<commit_before>//! Utilities module.

use crate::aabb::AABB;
use crate::bounding_hierarchy::BHShape;

/// Concatenates the list of vectors into a single vector.
/// Drains the elements from the source `vectors`.
pub fn concatenate_vectors<T: Sized>(vectors: &mut [Vec<T>]) -> Vec<T> {
    let mut result = Vec::new();
    for mut vector in vectors.iter_mut() {
        result.append(&mut vector);
    }
    result
}

/// Defines a Bucket utility object. Used to store the properties of shape-partitions
/// in the BVH build procedure using SAH.
#[derive(Copy, Clone)]
pub struct Bucket {
    /// The number of shapes in this `Bucket`.
    pub size: usize,

    /// The joint `AABB` of the shapes in this `Bucket`.
    pub aabb: AABB,
}

impl Bucket {
    /// Returns an empty bucket.
    pub fn empty() -> Bucket {
        Bucket {
            size: 0,
            aabb: AABB::empty(),
        }
    }

    /// Extend this `Bucket` by a shape with the given `AABB`.
    pub fn add_aabb(&mut self, aabb: &AABB) {
        self.size += 1;
        self.aabb = self.aabb.join(aabb);
    }

    /// Join the contents of two `Bucket`s.
    pub fn join_bucket(a: Bucket, b: &Bucket) -> Bucket {
        Bucket {
            size: a.size + b.size,
            aabb: a.aabb.join(&b.aabb),
        }
    }
}

pub fn joint_aabb_of_shapes<Shape: BHShape>(indices: &[usize], shapes: &[Shape]) -> AABB {
    let mut aabb = AABB::empty();
    for index in indices {
        let shape = &shapes[*index];
        aabb.join_mut(&shape.aabb());
    }
    aabb
}

#[cfg(test)]
mod tests {
    use crate::utils::concatenate_vectors;

    #[test]
    /// Test if concatenating no `Vec`s yields an empty `Vec`.
    fn test_concatenate_empty() {
        let mut vectors: Vec<Vec<usize>> = vec![];
        let expected = vec![];
        assert_eq!(concatenate_vectors(vectors.as_mut_slice()), expected);
        let expected_remainder: Vec<Vec<usize>> = vec![];
        assert_eq!(vectors, expected_remainder);
    }

    #[test]
    /// Test if concatenating some `Vec`s yields the concatenation of the vectors.
    fn test_concatenate_vectors() {
        let mut vectors = vec![vec![1, 2, 3], vec![], vec![4, 5, 6], vec![7, 8], vec![9]];
        let result = concatenate_vectors(vectors.as_mut_slice());
        let expected = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
        assert_eq!(result, expected);
        assert_eq!(vectors, vec![vec![], vec![], vec![], vec![], vec![]]);
    }
}
<commit_msg>Fix lint<commit_after>//! Utilities module.

use crate::aabb::AABB;
use crate::bounding_hierarchy::BHShape;

/// Concatenates the list of vectors into a single vector.
/// Drains the elements from the source `vectors`.
pub fn concatenate_vectors<T: Sized>(vectors: &mut [Vec<T>]) -> Vec<T> {
    let mut result = Vec::new();
    for vector in vectors.iter_mut() {
        result.append(vector);
    }
    result
}

/// Defines a Bucket utility object. Used to store the properties of shape-partitions
/// in the BVH build procedure using SAH.
#[derive(Copy, Clone)]
pub struct Bucket {
    /// The number of shapes in this `Bucket`.
    pub size: usize,

    /// The joint `AABB` of the shapes in this `Bucket`.
    pub aabb: AABB,
}

impl Bucket {
    /// Returns an empty bucket.
    pub fn empty() -> Bucket {
        Bucket {
            size: 0,
            aabb: AABB::empty(),
        }
    }

    /// Extend this `Bucket` by a shape with the given `AABB`.
    pub fn add_aabb(&mut self, aabb: &AABB) {
        self.size += 1;
        self.aabb = self.aabb.join(aabb);
    }

    /// Join the contents of two `Bucket`s.
    pub fn join_bucket(a: Bucket, b: &Bucket) -> Bucket {
        Bucket {
            size: a.size + b.size,
            aabb: a.aabb.join(&b.aabb),
        }
    }
}

pub fn joint_aabb_of_shapes<Shape: BHShape>(indices: &[usize], shapes: &[Shape]) -> AABB {
    let mut aabb = AABB::empty();
    for index in indices {
        let shape = &shapes[*index];
        aabb.join_mut(&shape.aabb());
    }
    aabb
}

#[cfg(test)]
mod tests {
    use crate::utils::concatenate_vectors;

    #[test]
    /// Test if concatenating no `Vec`s yields an empty `Vec`.
    fn test_concatenate_empty() {
        let mut vectors: Vec<Vec<usize>> = vec![];
        let expected = vec![];
        assert_eq!(concatenate_vectors(vectors.as_mut_slice()), expected);
        let expected_remainder: Vec<Vec<usize>> = vec![];
        assert_eq!(vectors, expected_remainder);
    }

    #[test]
    /// Test if concatenating some `Vec`s yields the concatenation of the vectors.
    fn test_concatenate_vectors() {
        let mut vectors = vec![vec![1, 2, 3], vec![], vec![4, 5, 6], vec![7, 8], vec![9]];
        let result = concatenate_vectors(vectors.as_mut_slice());
        let expected = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
        assert_eq!(result, expected);
        assert_eq!(vectors, vec![vec![], vec![], vec![], vec![], vec![]]);
    }
}
<|endoftext|>


<commit_before>use std::cmp::Ordering;

/// This function performs a binary search in a **sorted** vector
/// and returns the index of the closest element.
///
/// Returns None if it encounter an invalid value (NAN) or an empty vector
pub fn search_closest_idx(values: &Vec<f64>, target_value: &f64) -> Option<usize> {
    // avoid invalid inputs
    if values.len() == 0 || target_value.is_nan() {
        return None;
    }
    let mut step: usize = values.len() / 2;
    let mut idx: usize = step;
    // Perform a binary search (i.e dichotomie)
    loop {
        step /= 2;
        match (values[idx]).partial_cmp(target_value) {
            Some(Ordering::Less) => {
                if step > 0 {
                    idx += step;
                } else {
                    // if idx is the vec boundary
                    if idx == values.len() - 1 {
                        return Some(idx);
                    }
                    // Return closest between `values[idx]` and `values[idx+1]`
                    if (values[idx] - target_value).abs() < (values[idx+1] - target_value).abs() {
                        return Some(idx);
                    }
                    return Some(idx + 1);
                }
            },
            Some(Ordering::Greater) => {
                if step > 0 {
                    idx -= step;
                } else {
                    // if idx is the vec boundary
                    if idx == 0 {
                        return Some(idx);
                    }
                    // Return closest between `values[idx]` and `values[idx-1]`
                    if (values[idx] - target_value).abs() < (values[idx-1] - target_value).abs() {
                        return Some(idx);
                    }
                    return Some(idx - 1);
                }
            },
            // return the index if found
            Some(Ordering::Equal) => { return Some(idx); },
            // If values[idx] is NAN, abort
            None => { return None; },
        }
    }
}

#[test]
fn test_binary_search() {
    let values: Vec<f64> = vec![1., 3., 3.5, 5., 5.1, 6., 8., 11.];
    // search a value exactly equals to one of element
    assert_eq!(search_closest_idx(&values, &3_f64), Some(1_usize));
    // search a value not in the set
    assert_eq!(search_closest_idx(&values, &5.2), Some(4_usize));
    // search values outside the set ranges
    assert_eq!(search_closest_idx(&values, &-3.), Some(0_usize));
    assert_eq!(search_closest_idx(&values, &100.), Some(values.len() -1));
}
<commit_msg>Fix binary search bug<commit_after>use std::cmp::Ordering;

/// This function performs a binary search in a **sorted** vector
/// and returns the index of the closest element.
///
/// Returns None if it encounter an invalid value (NAN) or an empty vector
pub fn search_closest_idx(values: &Vec<f64>, target_value: &f64) -> Option<usize> {
    // avoid invalid inputs
    if values.len() == 0 || target_value.is_nan() {
        return None;
    }
    let max_idx = values.len() -1;
    // size of the dichotomie interval
    let mut step: usize = values.len() / 2;
    // current index
    let mut idx: usize = step;
    // Perform a binary search (i.e dichotomie)
	loop {
        // update the interval length
        step = (1 + step) / 2;
		match (values[idx]).partial_cmp(target_value) {
			Some(Ordering::Less) => {
                if idx < max_idx - step {
                    idx += step;
                } else {
                    idx = max_idx;
                }
            },
			Some(Ordering::Greater) => {
                if idx > step {
                    idx -= step;
                } else {
                    idx = 0;
                }
            },
			// return the index if found
			Some(Ordering::Equal) => { return Some(idx); },
			// If values[idx] is NAN, abort
			None => { return None; },
		}
        // If step == 1, we can't get any better
        // EXIT the loop
        if step == 1 {
            // Return closest between `values[idx]` and `values[idx+1]`
            if idx < max_idx && (values[idx] - target_value).abs() > (values[idx+1] - target_value).abs() {
                return Some(idx+1);
            }
            // Return closest between `values[idx]` and `values[idx-1]`
            if idx > 0 && (values[idx] - target_value).abs() > (values[idx-1] - target_value).abs() {
                return Some(idx -1);
            }
            return Some(idx);
        }
    }
}

#[test]
fn test_binary_search() {
    let values: Vec<f64> = vec![1., 3., 3.5, 5., 5.1, 6., 8., 11.];
    // search a value exactly equals to one of element
    assert_eq!(search_closest_idx(&values, &3_f64), Some(1_usize));
    // search a value not in the set
    assert_eq!(search_closest_idx(&values, &5.2), Some(4_usize));
    // search values outside the set ranges
    assert_eq!(search_closest_idx(&values, &-3.), Some(0_usize));
    assert_eq!(search_closest_idx(&values, &100.), Some(values.len() -1));
}
<|endoftext|>


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

use num::Float;

use {math, Seed};

/// Linearly interpolate values.
fn lerp<T: Float>(a: T, b: T, x: T) -> T {
    a + x * (b - a)
}

/// Map value between `0.0` and `1.0` to a Cubic Hermite curve.
fn smoothstep<T: Float>(x: T) -> T {
    let _3: T = math::cast(3.0);
    let _2: T = math::cast(2.0);
    x * x * (_3 - _2 * x)
}

/// 2-dimensional value noise
pub fn value2<T: Float>(seed: &Seed, point: &math::Point2<T>) -> T {
    #[inline(always)]
    fn get<T: Float>(seed: &Seed, corner: math::Point2<isize>) -> T {
        math::cast::<_, T>(seed.get2(corner)) * math::cast(1.0 / 255.0)
    }

    let floored = math::map2(*point, Float::floor);
    let near_corner = math::map2(floored, math::cast);
    let far_corner = math::add2(near_corner, math::one2());
    let weight = math::map2(math::sub2(*point, floored), smoothstep);

    let f00 = get(seed, [near_corner[0], near_corner[1]]);
    let f10 = get(seed, [far_corner[0], near_corner[1]]);
    let f01 = get(seed, [near_corner[0], far_corner[1]]);
    let f11 = get(seed, [far_corner[0], far_corner[1]]);

    let d0 = lerp(f00, f10, weight[0]);
    let d1 = lerp(f01, f11, weight[0]);
    let d = lerp(d0, d1, weight[1]);

    d * math::cast(2) - math::cast(1)
}

// 3-dimensional value noise
pub fn value3<T: Float>(seed: &Seed, point: &math::Point3<T>) -> T {
    #[inline(always)]
    fn get<T: Float>(seed: &Seed, corner: math::Point3<isize>) -> T {
        math::cast::<_, T>(seed.get3(corner)) * math::cast(1.0 / 255.0)
    }

    let floored = math::map3(*point, Float::floor);
    let near_corner = math::map3(floored, math::cast);
    let far_corner = math::add3(near_corner, math::one3());
    let weight = math::map3(math::sub3(*point, floored), smoothstep);

    let f000: T = get(seed, [near_corner[0], near_corner[1], near_corner[2]]);
    let f100: T = get(seed, [far_corner[0], near_corner[1], near_corner[2]]);
    let f010: T = get(seed, [near_corner[0], far_corner[1], near_corner[2]]);
    let f110: T = get(seed, [far_corner[0], far_corner[1], near_corner[2]]);
    let f001: T = get(seed, [near_corner[0], near_corner[1], far_corner[2]]);
    let f101: T = get(seed, [far_corner[0], near_corner[1], far_corner[2]]);
    let f011: T = get(seed, [near_corner[0], far_corner[1], far_corner[2]]);
    let f111: T = get(seed, [far_corner[0], far_corner[1], far_corner[2]]);

    let d00 = lerp(f000, f100, weight[0]);
    let d01 = lerp(f001, f101, weight[0]);
    let d10 = lerp(f010, f110, weight[0]);
    let d11 = lerp(f011, f111, weight[0]);
    let d0 = lerp(d00, d10, weight[1]);
    let d1 = lerp(d01, d11, weight[1]);
    let d = lerp(d0, d1, weight[2]);

    d * math::cast(2) - math::cast(1)
}

// 4-dimensional value noise
pub fn value4<T: Float>(seed: &Seed, point: &math::Point4<T>) -> T {
    #[inline(always)]
    fn get<T: Float>(seed: &Seed, corner: math::Point4<isize>) -> T {
        math::cast::<_, T>(seed.get4(corner)) * math::cast(1.0 / 255.0)
    }

    let floored = math::map4(*point, Float::floor);
    let near_corner = math::map4(floored, math::cast);
    let far_corner = math::add4(near_corner, math::one4());
    let weight = math::map4(math::sub4(*point, floored), smoothstep);

    let f0000: T = get(seed, [near_corner[0], near_corner[1], near_corner[2], near_corner[3]]);
    let f1000: T = get(seed, [far_corner[0], near_corner[1], near_corner[2], near_corner[3]]);
    let f0100: T = get(seed, [near_corner[0], far_corner[1], near_corner[2], near_corner[3]]);
    let f1100: T = get(seed, [far_corner[0], far_corner[1], near_corner[2], near_corner[3]]);
    let f0010: T = get(seed, [near_corner[0], near_corner[1], far_corner[2], near_corner[3]]);
    let f1010: T = get(seed, [far_corner[0], near_corner[1], far_corner[2], near_corner[3]]);
    let f0110: T = get(seed, [near_corner[0], far_corner[1], far_corner[2], near_corner[3]]);
    let f1110: T = get(seed, [far_corner[0], far_corner[1], far_corner[2], near_corner[3]]);
    let f0001: T = get(seed, [near_corner[0], near_corner[1], near_corner[2], far_corner[3]]);
    let f1001: T = get(seed, [far_corner[0], near_corner[1], near_corner[2], far_corner[3]]);
    let f0101: T = get(seed, [near_corner[0], far_corner[1], near_corner[2], far_corner[3]]);
    let f1101: T = get(seed, [far_corner[0], far_corner[1], near_corner[2], far_corner[3]]);
    let f0011: T = get(seed, [near_corner[0], near_corner[1], far_corner[2], far_corner[3]]);
    let f1011: T = get(seed, [far_corner[0], near_corner[1], far_corner[2], far_corner[3]]);
    let f0111: T = get(seed, [near_corner[0], far_corner[1], far_corner[2], far_corner[3]]);
    let f1111: T = get(seed, [far_corner[0], far_corner[1], far_corner[2], far_corner[3]]);

    let d000 = lerp(f0000, f1000, weight[0]);
    let d010 = lerp(f0010, f1010, weight[0]);
    let d100 = lerp(f0100, f1100, weight[0]);
    let d110 = lerp(f0110, f1110, weight[0]);
    let d001 = lerp(f0001, f1001, weight[0]);
    let d011 = lerp(f0011, f1011, weight[0]);
    let d101 = lerp(f0101, f1101, weight[0]);
    let d111 = lerp(f0111, f1111, weight[0]);
    let d00 = lerp(d000, d100, weight[1]);
    let d10 = lerp(d010, d110, weight[1]);
    let d01 = lerp(d001, d101, weight[1]);
    let d11 = lerp(d011, d111, weight[1]);
    let d0 = lerp(d00, d10, weight[2]);
    let d1 = lerp(d01, d11, weight[2]);
    let d = lerp(d0, d1, weight[3]);

    d * math::cast(2) - math::cast(1)
}
<commit_msg>Fix doc-comments<commit_after>// Copyright 2015 The Noise-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use num::Float;

use {math, Seed};

/// Linearly interpolate values.
fn lerp<T: Float>(a: T, b: T, x: T) -> T {
    a + x * (b - a)
}

/// Map value between `0.0` and `1.0` to a Cubic Hermite curve.
fn smoothstep<T: Float>(x: T) -> T {
    let _3: T = math::cast(3.0);
    let _2: T = math::cast(2.0);
    x * x * (_3 - _2 * x)
}

/// 2-dimensional value noise
pub fn value2<T: Float>(seed: &Seed, point: &math::Point2<T>) -> T {
    #[inline(always)]
    fn get<T: Float>(seed: &Seed, corner: math::Point2<isize>) -> T {
        math::cast::<_, T>(seed.get2(corner)) * math::cast(1.0 / 255.0)
    }

    let floored = math::map2(*point, Float::floor);
    let near_corner = math::map2(floored, math::cast);
    let far_corner = math::add2(near_corner, math::one2());
    let weight = math::map2(math::sub2(*point, floored), smoothstep);

    let f00 = get(seed, [near_corner[0], near_corner[1]]);
    let f10 = get(seed, [far_corner[0], near_corner[1]]);
    let f01 = get(seed, [near_corner[0], far_corner[1]]);
    let f11 = get(seed, [far_corner[0], far_corner[1]]);

    let d0 = lerp(f00, f10, weight[0]);
    let d1 = lerp(f01, f11, weight[0]);
    let d = lerp(d0, d1, weight[1]);

    d * math::cast(2) - math::cast(1)
}

/// 3-dimensional value noise
pub fn value3<T: Float>(seed: &Seed, point: &math::Point3<T>) -> T {
    #[inline(always)]
    fn get<T: Float>(seed: &Seed, corner: math::Point3<isize>) -> T {
        math::cast::<_, T>(seed.get3(corner)) * math::cast(1.0 / 255.0)
    }

    let floored = math::map3(*point, Float::floor);
    let near_corner = math::map3(floored, math::cast);
    let far_corner = math::add3(near_corner, math::one3());
    let weight = math::map3(math::sub3(*point, floored), smoothstep);

    let f000: T = get(seed, [near_corner[0], near_corner[1], near_corner[2]]);
    let f100: T = get(seed, [far_corner[0], near_corner[1], near_corner[2]]);
    let f010: T = get(seed, [near_corner[0], far_corner[1], near_corner[2]]);
    let f110: T = get(seed, [far_corner[0], far_corner[1], near_corner[2]]);
    let f001: T = get(seed, [near_corner[0], near_corner[1], far_corner[2]]);
    let f101: T = get(seed, [far_corner[0], near_corner[1], far_corner[2]]);
    let f011: T = get(seed, [near_corner[0], far_corner[1], far_corner[2]]);
    let f111: T = get(seed, [far_corner[0], far_corner[1], far_corner[2]]);

    let d00 = lerp(f000, f100, weight[0]);
    let d01 = lerp(f001, f101, weight[0]);
    let d10 = lerp(f010, f110, weight[0]);
    let d11 = lerp(f011, f111, weight[0]);
    let d0 = lerp(d00, d10, weight[1]);
    let d1 = lerp(d01, d11, weight[1]);
    let d = lerp(d0, d1, weight[2]);

    d * math::cast(2) - math::cast(1)
}

/// 4-dimensional value noise
pub fn value4<T: Float>(seed: &Seed, point: &math::Point4<T>) -> T {
    #[inline(always)]
    fn get<T: Float>(seed: &Seed, corner: math::Point4<isize>) -> T {
        math::cast::<_, T>(seed.get4(corner)) * math::cast(1.0 / 255.0)
    }

    let floored = math::map4(*point, Float::floor);
    let near_corner = math::map4(floored, math::cast);
    let far_corner = math::add4(near_corner, math::one4());
    let weight = math::map4(math::sub4(*point, floored), smoothstep);

    let f0000: T = get(seed, [near_corner[0], near_corner[1], near_corner[2], near_corner[3]]);
    let f1000: T = get(seed, [far_corner[0], near_corner[1], near_corner[2], near_corner[3]]);
    let f0100: T = get(seed, [near_corner[0], far_corner[1], near_corner[2], near_corner[3]]);
    let f1100: T = get(seed, [far_corner[0], far_corner[1], near_corner[2], near_corner[3]]);
    let f0010: T = get(seed, [near_corner[0], near_corner[1], far_corner[2], near_corner[3]]);
    let f1010: T = get(seed, [far_corner[0], near_corner[1], far_corner[2], near_corner[3]]);
    let f0110: T = get(seed, [near_corner[0], far_corner[1], far_corner[2], near_corner[3]]);
    let f1110: T = get(seed, [far_corner[0], far_corner[1], far_corner[2], near_corner[3]]);
    let f0001: T = get(seed, [near_corner[0], near_corner[1], near_corner[2], far_corner[3]]);
    let f1001: T = get(seed, [far_corner[0], near_corner[1], near_corner[2], far_corner[3]]);
    let f0101: T = get(seed, [near_corner[0], far_corner[1], near_corner[2], far_corner[3]]);
    let f1101: T = get(seed, [far_corner[0], far_corner[1], near_corner[2], far_corner[3]]);
    let f0011: T = get(seed, [near_corner[0], near_corner[1], far_corner[2], far_corner[3]]);
    let f1011: T = get(seed, [far_corner[0], near_corner[1], far_corner[2], far_corner[3]]);
    let f0111: T = get(seed, [near_corner[0], far_corner[1], far_corner[2], far_corner[3]]);
    let f1111: T = get(seed, [far_corner[0], far_corner[1], far_corner[2], far_corner[3]]);

    let d000 = lerp(f0000, f1000, weight[0]);
    let d010 = lerp(f0010, f1010, weight[0]);
    let d100 = lerp(f0100, f1100, weight[0]);
    let d110 = lerp(f0110, f1110, weight[0]);
    let d001 = lerp(f0001, f1001, weight[0]);
    let d011 = lerp(f0011, f1011, weight[0]);
    let d101 = lerp(f0101, f1101, weight[0]);
    let d111 = lerp(f0111, f1111, weight[0]);
    let d00 = lerp(d000, d100, weight[1]);
    let d10 = lerp(d010, d110, weight[1]);
    let d01 = lerp(d001, d101, weight[1]);
    let d11 = lerp(d011, d111, weight[1]);
    let d0 = lerp(d00, d10, weight[2]);
    let d1 = lerp(d01, d11, weight[2]);
    let d = lerp(d0, d1, weight[3]);

    d * math::cast(2) - math::cast(1)
}
<|endoftext|>


<commit_before>
use ::std;
use ::std::ffi::OsString;
use ::std::os::windows::ffi::OsStringExt;

use ::WCString;
use ::NoNulError;
use ::error;

/// Representation of a borrowed Win32 style "wide" string.
#[derive(PartialEq, PartialOrd, Eq, Ord, Hash)]
pub struct WCStr {
    inner: [u16]
}

impl WCStr {
    /// Create a ```&WCStr``` from a raw pointer and a length.
    ///
    /// This function is unsafe for the reasons mentioned below.
    ///
    /// This function assumes that the pointer passed in has these properties:
    ///
    /// * It is not null.
    /// * It is a valid pointer.
    /// * It points to an array of ```u16```'s that does not contain any ```nul``` values.
    /// * It points to an array of ```u16```'s that is terminated with a ```nul``` at exactly the offset "```len```".
    ///
    /// This function will assert/panic when ```nul``` is not found at offset "```len```".
    ///
    /// The lifetime of the ```&WCStr``` returned from this function is not guranteed to be correct and
    /// it is up to the caller to determine the appropriate lifetime.
    ///
    /// # ```from_raw_parts()``` example
    ///
    ///     use wcstr::WCStr;
    ///     static a : &'static [u16] = &[116u16, 101u16, 115u16, 116u16, 0];
    ///     let s = unsafe { WCStr::from_raw_parts(a.as_ptr(), a.len() - 1) };
    ///     assert!(s.len() == (a.len() - 1));
    pub unsafe fn from_raw_parts<'a>(ptr: *const u16, len: usize) -> &'a WCStr {
        assert!(*ptr.offset(len as isize) == 0u16);
        std::mem::transmute(std::slice::from_raw_parts(ptr, len + 1))
    }

    /// Create a ```&WCStr``` from a slice of ```u16```'s.
    /// This function will scan the slice for ```nul``` and assume that ```nul``` terminates the string.
    /// If no ```nul``` is found in the slice, it will return ```Err(NoNulError(None))```
    /// # ```frm_slice_with_nul()``` example
    ///
    ///     use wcstr::WCStr;
    ///     static a : &'static [u16] = &[116u16, 101u16, 115u16, 116u16, 0];
    ///     let s = WCStr::from_slice_with_nul(a).unwrap();
    ///     assert!(s.len() == (a.len() - 1));
    pub fn from_slice_with_nul<'a>(slice: &'a [u16]) -> Result<&'a WCStr, NoNulError> {
        match slice.iter().position(|x| *x == 0) {
            None => Err(error::no_nul(None)),
            Some(i) => Ok(unsafe { std::mem::transmute(&slice[..i + 1]) }),
        }
    }

    /// length of the string in u16 units
    pub fn len(&self) -> usize {
        self.inner.len() - 1
    }

    /// Return a raw pointer to this "wide" string.
    ///
    ///  * The pointer remains valid only as long as this string is valid.
    ///  * The pointer points to a contiguous region of memory terminated with ```nul```.
    pub fn as_ptr(&self) -> *const u16 {
        self.inner.as_ptr()
    }

    /// Return this "wide" string as a slice of ```u16```s without a ```nul``` terminator.
    pub fn to_slice(&self) -> &[u16] {
        &self.inner[..self.len()]
    }

    /// Return this "wide" string as a slice of ```u16```s with a ```nul``` terminator.
    pub fn to_slice_with_nul(&self) -> &[u16] {
        &self.inner
    }

    /// Convert this "wide" string to a ```String``` by using ```String::from_utf16```
    pub fn to_string(&self) -> Result<String, std::string::FromUtf16Error> {
        String::from_utf16(&self.inner)
    }

    /// Convert this "wide" string to a ```String``` by using ```String::from_utf16_lossy```
    pub fn to_string_lossy(&self) -> String {
        String::from_utf16_lossy(&self.inner)
    }

    /// Convert this "wide" string to an ```OsString``` by using ```OsString::from_wide```
    pub fn to_os_string(&self) -> OsString {
        OsString::from_wide(self.to_slice())
    }
}

impl std::fmt::Debug for WCStr {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        try!(write!(f, "\""));
        for &w in self.to_slice().iter() {
            if w < 0xD800 || w >= 0xE000 {
                for c in std::char::from_u32(w as u32).unwrap().escape_default() {
                    use std::fmt::Write;
                    try!(f.write_char(c));
                }
            }
            else {
                try!(write!(f, "\\u{{{:X}}}", w));
            }
        }
        write!(f, "\"")
    }
}

impl AsRef<WCStr> for WCStr {
    fn as_ref(&self) -> &WCStr {
        self
    }
}

impl AsRef<[u16]> for WCStr {
    fn as_ref(&self) -> &[u16] {
        &self.inner[..self.len()]
    }
}

impl ToOwned for WCStr {
    type Owned = WCString;
    fn to_owned(&self) -> WCString {
        unsafe {
            WCString::from_vec_with_nul_unchecked(self.inner.to_owned())
        }
    }
}

<commit_msg>fix string conversion<commit_after>
use ::std;
use ::std::ffi::OsString;
use ::std::os::windows::ffi::OsStringExt;

use ::WCString;
use ::NoNulError;
use ::error;

/// Representation of a borrowed Win32 style "wide" string.
#[derive(PartialEq, PartialOrd, Eq, Ord, Hash)]
pub struct WCStr {
    inner: [u16]
}

impl WCStr {
    /// Create a ```&WCStr``` from a raw pointer and a length.
    ///
    /// This function is unsafe for the reasons mentioned below.
    ///
    /// This function assumes that the pointer passed in has these properties:
    ///
    /// * It is not null.
    /// * It is a valid pointer.
    /// * It points to an array of ```u16```'s that does not contain any ```nul``` values.
    /// * It points to an array of ```u16```'s that is terminated with a ```nul``` at exactly the offset "```len```".
    ///
    /// This function will assert/panic when ```nul``` is not found at offset "```len```".
    ///
    /// The lifetime of the ```&WCStr``` returned from this function is not guranteed to be correct and
    /// it is up to the caller to determine the appropriate lifetime.
    ///
    /// # ```from_raw_parts()``` example
    ///
    ///     use wcstr::WCStr;
    ///     static a : &'static [u16] = &[116u16, 101u16, 115u16, 116u16, 0];
    ///     let s = unsafe { WCStr::from_raw_parts(a.as_ptr(), a.len() - 1) };
    ///     assert!(s.len() == (a.len() - 1));
    pub unsafe fn from_raw_parts<'a>(ptr: *const u16, len: usize) -> &'a WCStr {
        assert!(*ptr.offset(len as isize) == 0u16);
        std::mem::transmute(std::slice::from_raw_parts(ptr, len + 1))
    }

    /// Create a ```&WCStr``` from a slice of ```u16```'s.
    /// This function will scan the slice for ```nul``` and assume that ```nul``` terminates the string.
    /// If no ```nul``` is found in the slice, it will return ```Err(NoNulError(None))```
    /// # ```frm_slice_with_nul()``` example
    ///
    ///     use wcstr::WCStr;
    ///     static a : &'static [u16] = &[116u16, 101u16, 115u16, 116u16, 0];
    ///     let s = WCStr::from_slice_with_nul(a).unwrap();
    ///     assert!(s.len() == (a.len() - 1));
    pub fn from_slice_with_nul<'a>(slice: &'a [u16]) -> Result<&'a WCStr, NoNulError> {
        match slice.iter().position(|x| *x == 0) {
            None => Err(error::no_nul(None)),
            Some(i) => Ok(unsafe { std::mem::transmute(&slice[..i + 1]) }),
        }
    }

    /// length of the string in u16 units
    pub fn len(&self) -> usize {
        self.inner.len() - 1
    }

    /// Return a raw pointer to this "wide" string.
    ///
    ///  * The pointer remains valid only as long as this string is valid.
    ///  * The pointer points to a contiguous region of memory terminated with ```nul```.
    pub fn as_ptr(&self) -> *const u16 {
        self.inner.as_ptr()
    }

    /// Return this "wide" string as a slice of ```u16```s without a ```nul``` terminator.
    pub fn to_slice(&self) -> &[u16] {
        &self.inner[..self.len()]
    }

    /// Return this "wide" string as a slice of ```u16```s with a ```nul``` terminator.
    pub fn to_slice_with_nul(&self) -> &[u16] {
        &self.inner
    }

    /// Convert this "wide" string to a ```String``` by using ```String::from_utf16```
    pub fn to_string(&self) -> Result<String, std::string::FromUtf16Error> {
        String::from_utf16(&self.to_slice())
    }

    /// Convert this "wide" string to a ```String``` by using ```String::from_utf16_lossy```
    pub fn to_string_lossy(&self) -> String {
        String::from_utf16_lossy(&self.to_slice())
    }

    /// Convert this "wide" string to an ```OsString``` by using ```OsString::from_wide```
    pub fn to_os_string(&self) -> OsString {
        OsString::from_wide(self.to_slice())
    }
}

impl std::fmt::Debug for WCStr {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        try!(write!(f, "\""));
        for &w in self.to_slice().iter() {
            if w < 0xD800 || w >= 0xE000 {
                for c in std::char::from_u32(w as u32).unwrap().escape_default() {
                    use std::fmt::Write;
                    try!(f.write_char(c));
                }
            }
            else {
                try!(write!(f, "\\u{{{:X}}}", w));
            }
        }
        write!(f, "\"")
    }
}

impl AsRef<WCStr> for WCStr {
    fn as_ref(&self) -> &WCStr {
        self
    }
}

impl AsRef<[u16]> for WCStr {
    fn as_ref(&self) -> &[u16] {
        &self.inner[..self.len()]
    }
}

impl ToOwned for WCStr {
    type Owned = WCString;
    fn to_owned(&self) -> WCString {
        unsafe {
            WCString::from_vec_with_nul_unchecked(self.inner.to_owned())
        }
    }
}

<|endoftext|>


<commit_before>use std::path::{Display, PathBuf};
use std::process::{Command, ExitStatus};
use std::{env, mem};

use toml::Value;
use rustc_version::VersionMeta;

use CompilationMode;
use cargo::{Config, Root, Rustflags, Subcommand};
use cli::Args;
use errors::*;
use extensions::CommandExt;
use flock::{FileLock, Filesystem};
use {cargo, util};

pub fn run(args: &Args,
           cmode: &CompilationMode,
           rustflags: Rustflags,
           home: &Home,
           meta: &VersionMeta,
           config: Option<&Config>,
           verbose: bool)
           -> Result<ExitStatus> {
    let mut cmd = Command::new("cargo");
    cmd.args(args.all());

    if args.subcommand() == Some(Subcommand::Doc) {
        cmd.env("RUSTDOCFLAGS",
                cargo::rustdocflags(config, cmode.triple())?.for_xargo(home));
    }

    cmd.env("RUSTFLAGS", rustflags.for_xargo(home));

    let locks = (home.lock_ro(&meta.host),
                 home.lock_ro(cmode.triple()));

    let status = cmd.run_and_get_status(verbose)?;

    mem::drop(locks);

    Ok(status)
}

pub struct Home {
    path: Filesystem,
}

impl Home {
    pub fn display(&self) -> Display {
        self.path.display()
    }

    fn path(&self, triple: &str) -> Filesystem {
        self.path
            .join("lib/rustlib")
            .join(triple)
    }

    pub fn lock_ro(&self, triple: &str) -> Result<FileLock> {
        let fs = self.path(triple);

        fs.open_ro(".sentinel", &format!("{}'s sysroot", triple))
            .chain_err(|| {
                format!("couldn't lock {}'s sysroot as read-only", triple)
            })
    }

    pub fn lock_rw(&self, triple: &str) -> Result<FileLock> {
        let fs = self.path(triple);

        fs.open_rw(".sentinel", &format!("{}'s sysroot", triple))
            .chain_err(|| {
                format!("couldn't lock {}'s sysroot as read-only", triple)
            })
    }
}

pub fn home(cmode: &CompilationMode) -> Result<Home> {
    let p = if let Some(h) = env::var_os("XARGO_HOME") {
        PathBuf::from(h)
    } else {
        let mut p = env::home_dir()
            .ok_or_else(|| "couldn't find your home directory. Is $HOME set?")?
            .join(".xargo");

        if cmode.is_native() {
            p.push("HOST");
        }
        p
    };

    Ok(Home { path: Filesystem::new(p) })
}

pub struct Toml {
    table: Value,
}

impl Toml {
    /// Returns the `target.{}.dependencies` part of `Xargo.toml`
    pub fn dependencies(&self, target: &str) -> Option<&Value> {
        self.table.lookup(&format!("target.{}.dependencies", target))
    }
}

pub fn toml(root: &Root) -> Result<Option<Toml>> {
    let p = root.path().join("Xargo.toml");

    if p.exists() {
        util::parse(&p).map(|t| Some(Toml { table: t }))
    } else {
        Ok(None)
    }
}
<commit_msg>fix xargo::home logic<commit_after>use std::path::{Display, PathBuf};
use std::process::{Command, ExitStatus};
use std::{env, mem};

use toml::Value;
use rustc_version::VersionMeta;

use CompilationMode;
use cargo::{Config, Root, Rustflags, Subcommand};
use cli::Args;
use errors::*;
use extensions::CommandExt;
use flock::{FileLock, Filesystem};
use {cargo, util};

pub fn run(args: &Args,
           cmode: &CompilationMode,
           rustflags: Rustflags,
           home: &Home,
           meta: &VersionMeta,
           config: Option<&Config>,
           verbose: bool)
           -> Result<ExitStatus> {
    let mut cmd = Command::new("cargo");
    cmd.args(args.all());

    if args.subcommand() == Some(Subcommand::Doc) {
        cmd.env("RUSTDOCFLAGS",
                cargo::rustdocflags(config, cmode.triple())?.for_xargo(home));
    }

    cmd.env("RUSTFLAGS", rustflags.for_xargo(home));

    let locks = (home.lock_ro(&meta.host),
                 home.lock_ro(cmode.triple()));

    let status = cmd.run_and_get_status(verbose)?;

    mem::drop(locks);

    Ok(status)
}

pub struct Home {
    path: Filesystem,
}

impl Home {
    pub fn display(&self) -> Display {
        self.path.display()
    }

    fn path(&self, triple: &str) -> Filesystem {
        self.path
            .join("lib/rustlib")
            .join(triple)
    }

    pub fn lock_ro(&self, triple: &str) -> Result<FileLock> {
        let fs = self.path(triple);

        fs.open_ro(".sentinel", &format!("{}'s sysroot", triple))
            .chain_err(|| {
                format!("couldn't lock {}'s sysroot as read-only", triple)
            })
    }

    pub fn lock_rw(&self, triple: &str) -> Result<FileLock> {
        let fs = self.path(triple);

        fs.open_rw(".sentinel", &format!("{}'s sysroot", triple))
            .chain_err(|| {
                format!("couldn't lock {}'s sysroot as read-only", triple)
            })
    }
}

pub fn home(cmode: &CompilationMode) -> Result<Home> {
    let mut p = if let Some(h) = env::var_os("XARGO_HOME") {
        PathBuf::from(h)
    } else {
        env::home_dir()
            .ok_or_else(|| "couldn't find your home directory. Is $HOME set?")?
            .join(".xargo")
    };

    if cmode.is_native() {
        p.push("HOST");
    }

    Ok(Home { path: Filesystem::new(p) })
}

pub struct Toml {
    table: Value,
}

impl Toml {
    /// Returns the `target.{}.dependencies` part of `Xargo.toml`
    pub fn dependencies(&self, target: &str) -> Option<&Value> {
        self.table.lookup(&format!("target.{}.dependencies", target))
    }
}

pub fn toml(root: &Root) -> Result<Option<Toml>> {
    let p = root.path().join("Xargo.toml");

    if p.exists() {
        util::parse(&p).map(|t| Some(Toml { table: t }))
    } else {
        Ok(None)
    }
}
<|endoftext|>


<commit_before>use std;
use std::error::Error;
use std::fmt::{self, Formatter, Display};
use std::io::ErrorKind;
use std::io::prelude::*;
use std::process::{Command, ExitStatus};
use std::string::String;

struct Shim {
    command: String,
    arguments: Vec<String>,
}

impl Shim {
    fn load() -> std::io::Result<Shim> {
        let exe = try! { std::env::current_exe() };
        let p = exe.with_extension("shim");
        let f = try! { std::fs::File::open(&p) };
        let reader = std::io::BufReader::new(&f);

        let mut lines = reader.lines();
        let command = try! { match lines.next() {
            Some(result) => result,
            None => { return Err(std::io::Error::new(
                    ErrorKind::InvalidData, "Could not read command"));
            },
        } };

        let mut arguments = Vec::new();
        for result in lines {
            let arg = match result {
                Ok(line) => line,
                Err(_) => { continue; },
            };
            arguments.push(arg);
        }

        Ok(Shim {
            command: command,
            arguments: arguments,
        })
    }
}

impl Display for Shim {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{} {}", self.command, self.arguments.join(" "))
    }
}

pub fn run() -> Result<ExitStatus, String> {
    let shim = match Shim::load() {
        Ok(shim) => shim,
        Err(err) => { return Err(String::from(err.description())); },
    };
    match Command::new(&shim.command).args(&shim.arguments).status() {
        Ok(status) => Ok(status),
        Err(_) => {
            let mut s = String::from("failed to launch \"");
            s.push_str(&shim.command);
            s.push_str("\"");
            return Err(s);
        },
    }
}
<commit_msg>Shim should forward its arguments to child<commit_after>use std;
use std::error::Error;
use std::fmt::{self, Formatter, Display};
use std::io::ErrorKind;
use std::io::prelude::*;
use std::process::{Command, ExitStatus};
use std::string::String;

struct Shim {
    command: String,
    arguments: Vec<String>,
}

impl Shim {
    fn load() -> std::io::Result<Shim> {
        let exe = try! { std::env::current_exe() };
        let p = exe.with_extension("shim");
        let f = try! { std::fs::File::open(&p) };
        let reader = std::io::BufReader::new(&f);

        let mut lines = reader.lines();
        let command = try! { match lines.next() {
            Some(result) => result,
            None => { return Err(std::io::Error::new(
                    ErrorKind::InvalidData, "Could not read command"));
            },
        } };

        let mut arguments = Vec::new();
        for result in lines {
            let arg = match result {
                Ok(line) => line,
                Err(_) => { continue; },
            };
            arguments.push(arg);
        }

        let mut envargs = std::env::args();
        envargs.next();     // Skip args[0].
        for arg in envargs {
            arguments.push(arg);
        }

        Ok(Shim {
            command: command,
            arguments: arguments,
        })
    }
}

impl Display for Shim {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{} {}", self.command, self.arguments.join(" "))
    }
}

pub fn run() -> Result<ExitStatus, String> {
    let shim = match Shim::load() {
        Ok(shim) => shim,
        Err(err) => { return Err(String::from(err.description())); },
    };
    match Command::new(&shim.command).args(&shim.arguments).status() {
        Ok(status) => Ok(status),
        Err(_) => {
            let mut s = String::from("failed to launch \"");
            s.push_str(&shim.command);
            s.push_str("\"");
            return Err(s);
        },
    }
}
<|endoftext|>


<commit_before><commit_msg>fix: fix benchmarks<commit_after><|endoftext|>


<commit_before><commit_msg>temporarily disable test `lto::test_profile`<commit_after><|endoftext|>


<commit_before><commit_msg>Add basic auction testing<commit_after><|endoftext|>


<commit_before>use crate::util::check_builtin_macro_attribute;

use rustc_ast::mut_visit::{self, MutVisitor};
use rustc_ast::ptr::P;
use rustc_ast::{self as ast, AstLike};
use rustc_data_structures::map_in_place::MapInPlace;
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_expand::config::StripUnconfigured;
use rustc_expand::configure;
use rustc_span::symbol::sym;
use rustc_span::Span;
use smallvec::SmallVec;

crate fn expand(
    ecx: &mut ExtCtxt<'_>,
    _span: Span,
    meta_item: &ast::MetaItem,
    item: Annotatable,
) -> Vec<Annotatable> {
    check_builtin_macro_attribute(ecx, meta_item, sym::cfg_eval);

    let mut visitor = CfgEval {
        cfg: StripUnconfigured { sess: ecx.sess, features: ecx.ecfg.features, modified: false },
    };
    let mut item = visitor.fully_configure(item);
    if visitor.cfg.modified {
        // Erase the tokens if cfg-stripping modified the item
        // This will cause us to synthesize fake tokens
        // when `nt_to_tokenstream` is called on this item.
        if let Some(tokens) = item.tokens_mut() {
            *tokens = None;
        }
    }
    vec![item]
}

crate struct CfgEval<'a> {
    pub cfg: StripUnconfigured<'a>,
}

impl CfgEval<'_> {
    fn configure<T: AstLike>(&mut self, node: T) -> Option<T> {
        self.cfg.configure(node)
    }

    fn configure_foreign_mod(&mut self, foreign_mod: &mut ast::ForeignMod) {
        let ast::ForeignMod { unsafety: _, abi: _, items } = foreign_mod;
        items.flat_map_in_place(|item| self.configure(item));
    }

    fn configure_variant_data(&mut self, vdata: &mut ast::VariantData) {
        match vdata {
            ast::VariantData::Struct(fields, ..) | ast::VariantData::Tuple(fields, _) => {
                fields.flat_map_in_place(|field| self.configure(field))
            }
            ast::VariantData::Unit(_) => {}
        }
    }

    fn configure_item_kind(&mut self, item: &mut ast::ItemKind) {
        match item {
            ast::ItemKind::Struct(def, _generics) | ast::ItemKind::Union(def, _generics) => {
                self.configure_variant_data(def)
            }
            ast::ItemKind::Enum(ast::EnumDef { variants }, _generics) => {
                variants.flat_map_in_place(|variant| self.configure(variant));
                for variant in variants {
                    self.configure_variant_data(&mut variant.data);
                }
            }
            _ => {}
        }
    }

    fn configure_expr_kind(&mut self, expr_kind: &mut ast::ExprKind) {
        match expr_kind {
            ast::ExprKind::Match(_m, arms) => {
                arms.flat_map_in_place(|arm| self.configure(arm));
            }
            ast::ExprKind::Struct(_path, fields, _base) => {
                fields.flat_map_in_place(|field| self.configure(field));
            }
            _ => {}
        }
    }

    fn configure_pat(&mut self, pat: &mut P<ast::Pat>) {
        if let ast::PatKind::Struct(_path, fields, _etc) = &mut pat.kind {
            fields.flat_map_in_place(|field| self.configure(field));
        }
    }

    fn configure_fn_decl(&mut self, fn_decl: &mut ast::FnDecl) {
        fn_decl.inputs.flat_map_in_place(|arg| self.configure(arg));
    }

    crate fn fully_configure(&mut self, item: Annotatable) -> Annotatable {
        // Since the item itself has already been configured by the InvocationCollector,
        // we know that fold result vector will contain exactly one element
        match item {
            Annotatable::Item(item) => Annotatable::Item(self.flat_map_item(item).pop().unwrap()),
            Annotatable::TraitItem(item) => {
                Annotatable::TraitItem(self.flat_map_trait_item(item).pop().unwrap())
            }
            Annotatable::ImplItem(item) => {
                Annotatable::ImplItem(self.flat_map_impl_item(item).pop().unwrap())
            }
            Annotatable::ForeignItem(item) => {
                Annotatable::ForeignItem(self.flat_map_foreign_item(item).pop().unwrap())
            }
            Annotatable::Stmt(stmt) => {
                Annotatable::Stmt(stmt.map(|stmt| self.flat_map_stmt(stmt).pop().unwrap()))
            }
            Annotatable::Expr(mut expr) => Annotatable::Expr({
                self.visit_expr(&mut expr);
                expr
            }),
            Annotatable::Arm(arm) => Annotatable::Arm(self.flat_map_arm(arm).pop().unwrap()),
            Annotatable::Field(field) => {
                Annotatable::Field(self.flat_map_field(field).pop().unwrap())
            }
            Annotatable::FieldPat(fp) => {
                Annotatable::FieldPat(self.flat_map_field_pattern(fp).pop().unwrap())
            }
            Annotatable::GenericParam(param) => {
                Annotatable::GenericParam(self.flat_map_generic_param(param).pop().unwrap())
            }
            Annotatable::Param(param) => {
                Annotatable::Param(self.flat_map_param(param).pop().unwrap())
            }
            Annotatable::StructField(sf) => {
                Annotatable::StructField(self.flat_map_struct_field(sf).pop().unwrap())
            }
            Annotatable::Variant(v) => {
                Annotatable::Variant(self.flat_map_variant(v).pop().unwrap())
            }
        }
    }
}

impl MutVisitor for CfgEval<'_> {
    fn visit_foreign_mod(&mut self, foreign_mod: &mut ast::ForeignMod) {
        self.configure_foreign_mod(foreign_mod);
        mut_visit::noop_visit_foreign_mod(foreign_mod, self);
    }

    fn visit_item_kind(&mut self, item: &mut ast::ItemKind) {
        self.configure_item_kind(item);
        mut_visit::noop_visit_item_kind(item, self);
    }

    fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
        self.cfg.configure_expr(expr);
        self.configure_expr_kind(&mut expr.kind);
        mut_visit::noop_visit_expr(expr, self);
    }

    fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
        let mut expr = configure!(self, expr);
        self.configure_expr_kind(&mut expr.kind);
        mut_visit::noop_visit_expr(&mut expr, self);
        Some(expr)
    }

    fn flat_map_generic_param(
        &mut self,
        param: ast::GenericParam,
    ) -> SmallVec<[ast::GenericParam; 1]> {
        mut_visit::noop_flat_map_generic_param(configure!(self, param), self)
    }

    fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
        mut_visit::noop_flat_map_stmt(configure!(self, stmt), self)
    }

    fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
        mut_visit::noop_flat_map_item(configure!(self, item), self)
    }

    fn flat_map_impl_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
        mut_visit::noop_flat_map_assoc_item(configure!(self, item), self)
    }

    fn flat_map_trait_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
        mut_visit::noop_flat_map_assoc_item(configure!(self, item), self)
    }

    fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
        self.configure_pat(pat);
        mut_visit::noop_visit_pat(pat, self)
    }

    fn visit_fn_decl(&mut self, mut fn_decl: &mut P<ast::FnDecl>) {
        self.configure_fn_decl(&mut fn_decl);
        mut_visit::noop_visit_fn_decl(fn_decl, self);
    }
}
<commit_msg>cfg_eval: Configure everything through mutable visitor methods<commit_after>use crate::util::check_builtin_macro_attribute;

use rustc_ast::mut_visit::{self, MutVisitor};
use rustc_ast::ptr::P;
use rustc_ast::{self as ast, AstLike};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_expand::config::StripUnconfigured;
use rustc_expand::configure;
use rustc_span::symbol::sym;
use rustc_span::Span;
use smallvec::SmallVec;

crate fn expand(
    ecx: &mut ExtCtxt<'_>,
    _span: Span,
    meta_item: &ast::MetaItem,
    item: Annotatable,
) -> Vec<Annotatable> {
    check_builtin_macro_attribute(ecx, meta_item, sym::cfg_eval);

    let mut visitor = CfgEval {
        cfg: StripUnconfigured { sess: ecx.sess, features: ecx.ecfg.features, modified: false },
    };
    let mut item = visitor.fully_configure(item);
    if visitor.cfg.modified {
        // Erase the tokens if cfg-stripping modified the item
        // This will cause us to synthesize fake tokens
        // when `nt_to_tokenstream` is called on this item.
        if let Some(tokens) = item.tokens_mut() {
            *tokens = None;
        }
    }
    vec![item]
}

crate struct CfgEval<'a> {
    pub cfg: StripUnconfigured<'a>,
}

impl CfgEval<'_> {
    fn configure<T: AstLike>(&mut self, node: T) -> Option<T> {
        self.cfg.configure(node)
    }

    crate fn fully_configure(&mut self, item: Annotatable) -> Annotatable {
        // Since the item itself has already been configured by the InvocationCollector,
        // we know that fold result vector will contain exactly one element
        match item {
            Annotatable::Item(item) => Annotatable::Item(self.flat_map_item(item).pop().unwrap()),
            Annotatable::TraitItem(item) => {
                Annotatable::TraitItem(self.flat_map_trait_item(item).pop().unwrap())
            }
            Annotatable::ImplItem(item) => {
                Annotatable::ImplItem(self.flat_map_impl_item(item).pop().unwrap())
            }
            Annotatable::ForeignItem(item) => {
                Annotatable::ForeignItem(self.flat_map_foreign_item(item).pop().unwrap())
            }
            Annotatable::Stmt(stmt) => {
                Annotatable::Stmt(stmt.map(|stmt| self.flat_map_stmt(stmt).pop().unwrap()))
            }
            Annotatable::Expr(mut expr) => Annotatable::Expr({
                self.visit_expr(&mut expr);
                expr
            }),
            Annotatable::Arm(arm) => Annotatable::Arm(self.flat_map_arm(arm).pop().unwrap()),
            Annotatable::Field(field) => {
                Annotatable::Field(self.flat_map_field(field).pop().unwrap())
            }
            Annotatable::FieldPat(fp) => {
                Annotatable::FieldPat(self.flat_map_field_pattern(fp).pop().unwrap())
            }
            Annotatable::GenericParam(param) => {
                Annotatable::GenericParam(self.flat_map_generic_param(param).pop().unwrap())
            }
            Annotatable::Param(param) => {
                Annotatable::Param(self.flat_map_param(param).pop().unwrap())
            }
            Annotatable::StructField(sf) => {
                Annotatable::StructField(self.flat_map_struct_field(sf).pop().unwrap())
            }
            Annotatable::Variant(v) => {
                Annotatable::Variant(self.flat_map_variant(v).pop().unwrap())
            }
        }
    }
}

impl MutVisitor for CfgEval<'_> {
    fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
        self.cfg.configure_expr(expr);
        mut_visit::noop_visit_expr(expr, self);
    }

    fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
        let mut expr = configure!(self, expr);
        mut_visit::noop_visit_expr(&mut expr, self);
        Some(expr)
    }

    fn flat_map_generic_param(
        &mut self,
        param: ast::GenericParam,
    ) -> SmallVec<[ast::GenericParam; 1]> {
        mut_visit::noop_flat_map_generic_param(configure!(self, param), self)
    }

    fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
        mut_visit::noop_flat_map_stmt(configure!(self, stmt), self)
    }

    fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
        mut_visit::noop_flat_map_item(configure!(self, item), self)
    }

    fn flat_map_impl_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
        mut_visit::noop_flat_map_assoc_item(configure!(self, item), self)
    }

    fn flat_map_trait_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
        mut_visit::noop_flat_map_assoc_item(configure!(self, item), self)
    }

    fn flat_map_foreign_item(
        &mut self,
        foreign_item: P<ast::ForeignItem>,
    ) -> SmallVec<[P<ast::ForeignItem>; 1]> {
        mut_visit::noop_flat_map_foreign_item(configure!(self, foreign_item), self)
    }

    fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> {
        mut_visit::noop_flat_map_arm(configure!(self, arm), self)
    }

    fn flat_map_field(&mut self, field: ast::Field) -> SmallVec<[ast::Field; 1]> {
        mut_visit::noop_flat_map_field(configure!(self, field), self)
    }

    fn flat_map_field_pattern(&mut self, fp: ast::FieldPat) -> SmallVec<[ast::FieldPat; 1]> {
        mut_visit::noop_flat_map_field_pattern(configure!(self, fp), self)
    }

    fn flat_map_param(&mut self, p: ast::Param) -> SmallVec<[ast::Param; 1]> {
        mut_visit::noop_flat_map_param(configure!(self, p), self)
    }

    fn flat_map_struct_field(&mut self, sf: ast::StructField) -> SmallVec<[ast::StructField; 1]> {
        mut_visit::noop_flat_map_struct_field(configure!(self, sf), self)
    }

    fn flat_map_variant(&mut self, variant: ast::Variant) -> SmallVec<[ast::Variant; 1]> {
        mut_visit::noop_flat_map_variant(configure!(self, variant), self)
    }
}
<|endoftext|>


<commit_before>use std::sync::Arc;

#[derive(Debug)]
enum Value {
    Nil,
    Integer(i64),
    List(Cons),
}

#[derive(Debug)]
struct Cons {
    car: Arc<Value>,
    cdr: Arc<Value>,
}

fn cons(a: Value, b: Value) -> Value {
    Value::List(Cons {
        car: Arc::new(a),
        cdr: Arc::new(b),
    })
}

fn main() {
    let a = cons(Value::Integer(1), cons(Value::Integer(2), Value::Nil));
    println!("{:?}", a);
}
<commit_msg>delete<commit_after><|endoftext|>


<commit_before><commit_msg>Add utility methods to DicomValue<commit_after><|endoftext|>


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

use exonum::{
    blockchain::{GenesisConfig, ValidatorKeys},
    node::{Node, NodeApiConfig, NodeConfig},
};
use exonum_cryptocurrency::contracts::ServiceFactoryImpl;

fn node_config() -> NodeConfig {
    let (consensus_public_key, consensus_secret_key) = exonum::crypto::gen_keypair();
    let (service_public_key, service_secret_key) = exonum::crypto::gen_keypair();

    let validator_keys = ValidatorKeys {
        consensus_key: consensus_public_key,
        service_key: service_public_key,
    };
    let genesis = GenesisConfig::new(vec![validator_keys].into_iter());

    let api_address = "0.0.0.0:8000".parse().unwrap();
    let api_cfg = NodeApiConfig {
        public_api_address: Some(api_address),
        ..Default::default()
    };

    let peer_address = "0.0.0.0:2000";

    NodeConfig {
        listen_address: peer_address.parse().unwrap(),
        service_public_key,
        service_secret_key,
        consensus_public_key,
        consensus_secret_key,
        genesis,
        external_address: peer_address.to_owned(),
        network: Default::default(),
        connect_list: Default::default(),
        api: api_cfg,
        mempool: Default::default(),
        services_configs: Default::default(),
        database: Default::default(),
        thread_pool_size: Default::default(),
    }
}

fn main() {
    exonum::helpers::init_logger().unwrap();

    println!("Creating in-memory database...");
    let node = Node::new(
        TemporaryDB::new(),
        vec![Box::new(ServiceFactoryImpl)],
        node_config(),
        None,
    );
    println!("Starting a single node...");
    println!("Blockchain is ready for transactions!");
    node.run().unwrap();
}
<commit_msg>Fix demo<commit_after>// Copyright 2019 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use exonum_merkledb::TemporaryDB;

use exonum::{
    blockchain::{GenesisConfig, ValidatorKeys},
    node::{Node, NodeApiConfig, NodeConfig},
};
use exonum_cryptocurrency::contracts::CryptocurrencyService;

fn node_config() -> NodeConfig {
    let (consensus_public_key, consensus_secret_key) = exonum::crypto::gen_keypair();
    let (service_public_key, service_secret_key) = exonum::crypto::gen_keypair();

    let validator_keys = ValidatorKeys {
        consensus_key: consensus_public_key,
        service_key: service_public_key,
    };
    let genesis = GenesisConfig::new(vec![validator_keys].into_iter());

    let api_address = "0.0.0.0:8000".parse().unwrap();
    let api_cfg = NodeApiConfig {
        public_api_address: Some(api_address),
        ..Default::default()
    };

    let peer_address = "0.0.0.0:2000";

    NodeConfig {
        listen_address: peer_address.parse().unwrap(),
        service_public_key,
        service_secret_key,
        consensus_public_key,
        consensus_secret_key,
        genesis,
        external_address: peer_address.to_owned(),
        network: Default::default(),
        connect_list: Default::default(),
        api: api_cfg,
        mempool: Default::default(),
        services_configs: Default::default(),
        database: Default::default(),
        thread_pool_size: Default::default(),
    }
}

fn main() {
    exonum::helpers::init_logger().unwrap();

    println!("Creating in-memory database...");
    let node = Node::new(
        TemporaryDB::new(),
        vec![Box::new(CryptocurrencyService)],
        node_config(),
        None,
    );
    println!("Starting a single node...");
    println!("Blockchain is ready for transactions!");
    node.run().unwrap();
}
<|endoftext|>


<commit_before>extern crate docopt;
extern crate flac;
extern crate rustc_serialize;

#[macro_use]
mod commands;

use std::env;

use commands::{streaminfo, comments, seektable, picture};
use docopt::Docopt;

const USAGE: &'static str = "
Usage: metadata <command> [<args>...]
       metadata [options]

Options:
  -h, --help  Show this message.

Commands:
  streaminfo  Display stream information.
  comments    Display or export comment tags.
  seektable   Display seek table.
  picture     Export picutes.
";

#[derive(Debug, RustcDecodable)]
struct Arguments {
  arg_command: Option<Command>,
  arg_args: Vec<String>,
}

#[derive(Clone, Copy, Debug, RustcDecodable)]
enum Command {
  StreamInfo,
  Comments,
  SeekTable,
  Picture,
}

fn handle_subcommand(command: Command) {
  match command {
    Command::StreamInfo => command!(streaminfo),
    Command::Comments   => command!(comments),
    Command::SeekTable  => command!(seektable),
    Command::Picture    => command!(picture),
  }
}

fn main() {
  let args: Arguments = Docopt::new(USAGE)
    .and_then(|d| d.options_first(true).decode())
    .unwrap_or_else(|e| e.exit());

  if let Some(command) = args.arg_command {
    handle_subcommand(command);
  } else {
    println!("{}", USAGE);
  }
}
<commit_msg>Fix typo for picture subcommand<commit_after>extern crate docopt;
extern crate flac;
extern crate rustc_serialize;

#[macro_use]
mod commands;

use std::env;

use commands::{streaminfo, comments, seektable, picture};
use docopt::Docopt;

const USAGE: &'static str = "
Usage: metadata <command> [<args>...]
       metadata [options]

Options:
  -h, --help  Show this message.

Commands:
  streaminfo  Display stream information.
  comments    Display or export comment tags.
  seektable   Display seek table.
  picture     Export pictures.
";

#[derive(Debug, RustcDecodable)]
struct Arguments {
  arg_command: Option<Command>,
  arg_args: Vec<String>,
}

#[derive(Clone, Copy, Debug, RustcDecodable)]
enum Command {
  StreamInfo,
  Comments,
  SeekTable,
  Picture,
}

fn handle_subcommand(command: Command) {
  match command {
    Command::StreamInfo => command!(streaminfo),
    Command::Comments   => command!(comments),
    Command::SeekTable  => command!(seektable),
    Command::Picture    => command!(picture),
  }
}

fn main() {
  let args: Arguments = Docopt::new(USAGE)
    .and_then(|d| d.options_first(true).decode())
    .unwrap_or_else(|e| e.exit());

  if let Some(command) = args.arg_command {
    handle_subcommand(command);
  } else {
    println!("{}", USAGE);
  }
}
<|endoftext|>


<commit_before>extern crate docopt;
extern crate flac;
extern crate rustc_serialize;

use docopt::Docopt;
use flac::{ReadStream, Stream, StreamProducer};

use std::env;
use std::fs::File;

const USAGE: &'static str = "
Usage: metadata streaminfo [options] <input>
       metadata --help

Options:
  --block-size       Show both the max and min block size from StreamInfo.
  --frame-size       Show both the max and min frame size from StreamInfo.
  --sample-rate      Show the sample rate from StreamInfo.
  --channels         Show the number of channels from StreamInfo.
  --bits-per-sample  Show the size in bits for each sample from StreamInfo.
  --total-samples    Show total number of samples from StreamInfo.
  --md5              Show the MD5 signature from StreamInfo.
  -h, --help         Show this message.
";

#[derive(Debug, RustcDecodable)]
struct Arguments {
  arg_input: String,
  cmd_streaminfo: bool,
  flag_block_size: bool,
  flag_frame_size: bool,
  flag_sample_rate: bool,
  flag_channels: bool,
  flag_bits_per_sample: bool,
  flag_total_samples: bool,
  flag_md5: bool,
}

fn print_stream_info<P>(stream: &Stream<P>, args: &Arguments)
 where P: StreamProducer {
  let info     = stream.info();
  let no_flags = (args.flag_block_size      || args.flag_frame_size    ||
                  args.flag_sample_rate     || args.flag_channels      ||
                  args.flag_bits_per_sample || args.flag_total_samples ||
                  args.flag_md5) == false;

  if no_flags || args.flag_block_size {
    println!("Minimum block size: {} samples", info.min_block_size);
    println!("Maximum block size: {} samples", info.max_block_size);
  }

  if no_flags || args.flag_frame_size {
    println!("Minimum frame size: {} bytes", info.min_frame_size);
    println!("Maximum frame size: {} bytes", info.max_frame_size);
  }

  if no_flags || args.flag_sample_rate {
    println!("Sample rate: {} Hz", info.sample_rate);
  }

  if no_flags || args.flag_channels {
    println!("Number of channels: {}", info.channels);
  }

  if no_flags || args.flag_bits_per_sample {
    println!("Bits per sample: {}", info.bits_per_sample);
  }

  if no_flags || args.flag_total_samples {
    println!("Total samples: {}", info.total_samples);
  }

  if no_flags || args.flag_md5 {
    let mut md5  = String::with_capacity(32);

    for byte in &info.md5_sum {
      let hex = format!("{:02x}", byte);

      md5.push_str(&hex);
    }

    println!("MD5 sum: {}", md5);
  }
}

fn main() {
  let args: Arguments = Docopt::new(USAGE)
    .and_then(|d| d.argv(env::args()).decode())
    .unwrap_or_else(|e| e.exit());

  let stream = Stream::<ReadStream<File>>::from_file(&args.arg_input)
                 .expect("Couldn't parse file");

  if args.cmd_streaminfo {
    print_stream_info(&stream, &args);
  }
}
<commit_msg>Add a comments subcommand<commit_after>extern crate docopt;
extern crate flac;
extern crate rustc_serialize;

use docopt::Docopt;
use flac::{ReadStream, Stream, StreamProducer};

use std::env;
use std::fs::File;

const USAGE: &'static str = "
Usage: metadata streaminfo [options] <input>
       metadata comments <input>
       metadata --help

Options:
  --block-size       Show both the max and min block size from StreamInfo.
  --frame-size       Show both the max and min frame size from StreamInfo.
  --sample-rate      Show the sample rate from StreamInfo.
  --channels         Show the number of channels from StreamInfo.
  --bits-per-sample  Show the size in bits for each sample from StreamInfo.
  --total-samples    Show total number of samples from StreamInfo.
  --md5              Show the MD5 signature from StreamInfo.
  -h, --help         Show this message.
";

#[derive(Debug, RustcDecodable)]
struct Arguments {
  arg_input: String,
  cmd_streaminfo: bool,
  cmd_comments: bool,
  flag_block_size: bool,
  flag_frame_size: bool,
  flag_sample_rate: bool,
  flag_channels: bool,
  flag_bits_per_sample: bool,
  flag_total_samples: bool,
  flag_md5: bool,
}

fn print_stream_info<P>(stream: &Stream<P>, args: &Arguments)
 where P: StreamProducer {
  let info     = stream.info();
  let no_flags = (args.flag_block_size      || args.flag_frame_size    ||
                  args.flag_sample_rate     || args.flag_channels      ||
                  args.flag_bits_per_sample || args.flag_total_samples ||
                  args.flag_md5) == false;

  if no_flags || args.flag_block_size {
    println!("Minimum block size: {} samples", info.min_block_size);
    println!("Maximum block size: {} samples", info.max_block_size);
  }

  if no_flags || args.flag_frame_size {
    println!("Minimum frame size: {} bytes", info.min_frame_size);
    println!("Maximum frame size: {} bytes", info.max_frame_size);
  }

  if no_flags || args.flag_sample_rate {
    println!("Sample rate: {} Hz", info.sample_rate);
  }

  if no_flags || args.flag_channels {
    println!("Number of channels: {}", info.channels);
  }

  if no_flags || args.flag_bits_per_sample {
    println!("Bits per sample: {}", info.bits_per_sample);
  }

  if no_flags || args.flag_total_samples {
    println!("Total samples: {}", info.total_samples);
  }

  if no_flags || args.flag_md5 {
    let mut md5  = String::with_capacity(32);

    for byte in &info.md5_sum {
      let hex = format!("{:02x}", byte);

      md5.push_str(&hex);
    }

    println!("MD5 sum: {}", md5);
  }
}

fn main() {
  let args: Arguments = Docopt::new(USAGE)
    .and_then(|d| d.argv(env::args()).decode())
    .unwrap_or_else(|e| e.exit());

  let stream = Stream::<ReadStream<File>>::from_file(&args.arg_input)
                 .expect("Couldn't parse file");

  if args.cmd_streaminfo {
    print_stream_info(&stream, &args);
  }
}
<|endoftext|>


<commit_before>//! # ACPI
//! Code to parse the ACPI tables

use core::intrinsics::{atomic_load, atomic_store};
use core::sync::atomic::Ordering;

use device::local_apic::LOCAL_APIC;
use interrupt;
use memory::{allocate_frames, Frame};
use paging::{entry, ActivePageTable, Page, PhysicalAddress, VirtualAddress};
use start::{kstart_ap, CPU_COUNT, AP_READY};

use self::dmar::{Dmar, DmarEntry};
use self::fadt::Fadt;
use self::madt::{Madt, MadtEntry};
use self::rsdt::Rsdt;
use self::sdt::Sdt;
use self::xsdt::Xsdt;

pub mod dmar;
pub mod fadt;
pub mod madt;
pub mod rsdt;
pub mod sdt;
pub mod xsdt;

const TRAMPOLINE: usize = 0x7E00;
const AP_STARTUP: usize = TRAMPOLINE + 512;

pub fn init_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) {
    print!("  ");
    for &c in sdt.signature.iter() {
        print!("{}", c as char);
    }

    if let Some(fadt) = Fadt::new(sdt) {
        println!(": {:#?}", fadt);
    } else if let Some(madt) = Madt::new(sdt) {
        println!(": {:>08X}: {}", madt.local_address, madt.flags);

        let mut local_apic = unsafe { &mut LOCAL_APIC };

        let me = local_apic.id() as u8;

        if local_apic.x2 {
            println!("    X2APIC {}", me);
        } else {
            println!("    XAPIC {}: {:>08X}", me, local_apic.address);
        }

        let trampoline_frame = Frame::containing_address(PhysicalAddress::new(TRAMPOLINE));
        let trampoline_page = Page::containing_address(VirtualAddress::new(TRAMPOLINE));

        // Map trampoline
        let result = active_table.map_to(trampoline_page, trampoline_frame, entry::PRESENT | entry::WRITABLE);
        result.flush(active_table);

        for madt_entry in madt.iter() {
            println!("      {:?}", madt_entry);
            match madt_entry {
                MadtEntry::LocalApic(ap_local_apic) => if ap_local_apic.id == me {
                    println!("        This is my local APIC");
                } else {
                    if ap_local_apic.flags & 1 == 1 {
                        // Increase CPU ID
                        CPU_COUNT.fetch_add(1, Ordering::SeqCst);

                        // Allocate a stack
                        let stack_start = allocate_frames(64).expect("no more frames in acpi stack_start").start_address().get() + ::KERNEL_OFFSET;
                        let stack_end = stack_start + 64 * 4096;

                        let ap_ready = TRAMPOLINE as *mut u64;
                        let ap_cpu_id = unsafe { ap_ready.offset(1) };
                        let ap_page_table = unsafe { ap_ready.offset(2) };
                        let ap_stack_start = unsafe { ap_ready.offset(3) };
                        let ap_stack_end = unsafe { ap_ready.offset(4) };
                        let ap_code = unsafe { ap_ready.offset(5) };

                        // Set the ap_ready to 0, volatile
                        unsafe { atomic_store(ap_ready, 0) };
                        unsafe { atomic_store(ap_cpu_id, ap_local_apic.id as u64) };
                        unsafe { atomic_store(ap_page_table, active_table.address() as u64) };
                        unsafe { atomic_store(ap_stack_start, stack_start as u64) };
                        unsafe { atomic_store(ap_stack_end, stack_end as u64) };
                        unsafe { atomic_store(ap_code, kstart_ap as u64) };
                        AP_READY.store(false, Ordering::SeqCst);

                        print!("        AP {}:", ap_local_apic.id);

                        // Send INIT IPI
                        {
                            let mut icr = 0x4500;
                            if local_apic.x2 {
                                icr |= (ap_local_apic.id as u64) << 32;
                            } else {
                                icr |= (ap_local_apic.id as u64) << 56;
                            }
                            print!(" IPI...");
                            local_apic.set_icr(icr);
                        }

                        // Send START IPI
                        {
                            //Start at 0x0800:0000 => 0x8000. Hopefully the bootloader code is still there
                            let ap_segment = (AP_STARTUP >> 12) & 0xFF;
                            let mut icr = 0x4600 | ap_segment as u64;

                            if local_apic.x2 {
                                icr |= (ap_local_apic.id as u64) << 32;
                            } else {
                                icr |= (ap_local_apic.id as u64) << 56;
                            }

                            print!(" SIPI...");
                            local_apic.set_icr(icr);
                        }

                        // Wait for trampoline ready
                        print!(" Wait...");
                        while unsafe { atomic_load(ap_ready) } == 0 {
                            interrupt::pause();
                        }
                        print!(" Trampoline...");
                        while ! AP_READY.load(Ordering::SeqCst) {
                            interrupt::pause();
                        }
                        println!(" Ready");

                        active_table.flush_all();
                    } else {
                        println!("        CPU Disabled");
                    }
                },
                _ => ()
            }
        }

        // Unmap trampoline
        let result = active_table.unmap(trampoline_page);
        result.flush(active_table);
    } else if let Some(dmar) = Dmar::new(sdt) {
        println!(": {}: {}", dmar.addr_width, dmar.flags);

        for dmar_entry in dmar.iter() {
            println!("      {:?}", dmar_entry);
            match dmar_entry {
                DmarEntry::Drhd(dmar_drhd) => {
                    let drhd = dmar_drhd.get(active_table);

                    println!("VER: {:X}", drhd.version);
                    println!("CAP: {:X}", drhd.cap);
                    println!("EXT_CAP: {:X}", drhd.ext_cap);
                    println!("GCMD: {:X}", drhd.gl_cmd);
                    println!("GSTS: {:X}", drhd.gl_sts);
                    println!("RT: {:X}", drhd.root_table);
                },
                _ => ()
            }
        }
    } else {
        println!(": Unknown");
    }
}

/// Parse the ACPI tables to gather CPU, interrupt, and timer information
pub unsafe fn init(active_table: &mut ActivePageTable) -> Option<Acpi> {
    let start_addr = 0xE0000;
    let end_addr = 0xFFFFF;

    // Map all of the ACPI RSDP space
    {
        let start_frame = Frame::containing_address(PhysicalAddress::new(start_addr));
        let end_frame = Frame::containing_address(PhysicalAddress::new(end_addr));
        for frame in Frame::range_inclusive(start_frame, end_frame) {
            let page = Page::containing_address(VirtualAddress::new(frame.start_address().get()));
            let result = active_table.map_to(page, frame, entry::PRESENT | entry::NO_EXECUTE);
            result.flush(active_table);
        }
    }

    // Search for RSDP
    if let Some(rsdp) = RSDP::search(start_addr, end_addr) {
        let get_sdt = |sdt_address: usize, active_table: &mut ActivePageTable| -> (&'static Sdt, bool) {
            let mapped = if active_table.translate_page(Page::containing_address(VirtualAddress::new(sdt_address))).is_none() {
                let sdt_frame = Frame::containing_address(PhysicalAddress::new(sdt_address));
                let sdt_page = Page::containing_address(VirtualAddress::new(sdt_address));
                let result = active_table.map_to(sdt_page, sdt_frame, entry::PRESENT | entry::NO_EXECUTE);
                result.flush(active_table);
                true
            } else {
                false
            };
            (&*(sdt_address as *const Sdt), mapped)
        };

        let drop_sdt = |sdt: &'static Sdt, mapped: bool, active_table: &mut ActivePageTable| {
            let sdt_address = sdt as *const Sdt as usize;
            drop(sdt);
            if mapped {
                let sdt_page = Page::containing_address(VirtualAddress::new(sdt_address));
                let result = active_table.unmap(sdt_page);
                result.flush(active_table);
            }
        };

        let (rxsdt, rxmapped) = get_sdt(rsdp.sdt_address(), active_table);

        for &c in rxsdt.signature.iter() {
            print!("{}", c as char);
        }
        println!(":");
        if let Some(rsdt) = Rsdt::new(rxsdt) {
            for sdt_address in rsdt.iter() {
                let (sdt, mapped) = get_sdt(sdt_address, active_table);
                init_sdt(sdt, active_table);
                drop_sdt(sdt, mapped, active_table);
            }
        } else if let Some(xsdt) = Xsdt::new(rxsdt) {
            for sdt_address in xsdt.iter() {
                let (sdt, mapped) = get_sdt(sdt_address, active_table);
                init_sdt(sdt, active_table);
                drop_sdt(sdt, mapped, active_table);
            }
        } else {
            println!("UNKNOWN RSDT OR XSDT SIGNATURE");
        }

        drop_sdt(rxsdt, rxmapped, active_table);
    } else {
        println!("NO RSDP FOUND");
    }

    // Unmap all of the ACPI RSDP space
    {
        let start_frame = Frame::containing_address(PhysicalAddress::new(start_addr));
        let end_frame = Frame::containing_address(PhysicalAddress::new(end_addr));
        for frame in Frame::range_inclusive(start_frame, end_frame) {
            let page = Page::containing_address(VirtualAddress::new(frame.start_address().get()));
            let result = active_table.unmap(page);
            result.flush(active_table);
        }
    }

    None
}

pub struct Acpi;

/// RSDP
#[derive(Copy, Clone, Debug)]
#[repr(packed)]
pub struct RSDP {
    signature: [u8; 8],
    checksum: u8,
    oemid: [u8; 6],
    revision: u8,
    rsdt_address: u32,
    length: u32,
    xsdt_address: u64,
    extended_checksum: u8,
    reserved: [u8; 3]
}

impl RSDP {
    /// Search for the RSDP
    pub fn search(start_addr: usize, end_addr: usize) -> Option<RSDP> {
        for i in 0 .. (end_addr + 1 - start_addr)/16 {
            let rsdp = unsafe { &*((start_addr + i * 16) as *const RSDP) };
            if &rsdp.signature == b"RSD PTR " {
                return Some(*rsdp);
            }
        }
        None
    }

    /// Get the RSDT or XSDT address
    pub fn sdt_address(&self) -> usize {
        if self.revision >= 2 {
            self.xsdt_address as usize
        } else {
            self.rsdt_address as usize
        }
    }
}
<commit_msg>Saved FADT in a pointer accessible elsewhere in the kernel<commit_after>//! # ACPI
//! Code to parse the ACPI tables

use core::intrinsics::{atomic_load, atomic_store};
use core::sync::atomic::Ordering;

use device::local_apic::LOCAL_APIC;
use interrupt;
use memory::{allocate_frames, Frame};
use paging::{entry, ActivePageTable, Page, PhysicalAddress, VirtualAddress};
use start::{kstart_ap, CPU_COUNT, AP_READY};

use self::dmar::{Dmar, DmarEntry};
use self::fadt::Fadt;
use self::madt::{Madt, MadtEntry};
use self::rsdt::Rsdt;
use self::sdt::Sdt;
use self::xsdt::Xsdt;

pub mod dmar;
pub mod fadt;
pub mod madt;
pub mod rsdt;
pub mod sdt;
pub mod xsdt;

const TRAMPOLINE: usize = 0x7E00;
const AP_STARTUP: usize = TRAMPOLINE + 512;

pub enum AcpiTable {
    fadt(Fadt),
    madt(Madt),
    dmar(Dmar)
}

pub fn init_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) -> Option<AcpiTable> {
    print!("  ");
    for &c in sdt.signature.iter() {
        print!("{}", c as char);
    }

    if let Some(fadt) = Fadt::new(sdt) {
        println!(": {:#?}", fadt);
        Some(AcpiTable::fadt(fadt))
    } else if let Some(madt) = Madt::new(sdt) {
        println!(": {:>08X}: {}", madt.local_address, madt.flags);

        let mut local_apic = unsafe { &mut LOCAL_APIC };

        let me = local_apic.id() as u8;

        if local_apic.x2 {
            println!("    X2APIC {}", me);
        } else {
            println!("    XAPIC {}: {:>08X}", me, local_apic.address);
        }

        let trampoline_frame = Frame::containing_address(PhysicalAddress::new(TRAMPOLINE));
        let trampoline_page = Page::containing_address(VirtualAddress::new(TRAMPOLINE));

        // Map trampoline
        let result = active_table.map_to(trampoline_page, trampoline_frame, entry::PRESENT | entry::WRITABLE);
        result.flush(active_table);

        for madt_entry in madt.iter() {
            println!("      {:?}", madt_entry);
            match madt_entry {
                MadtEntry::LocalApic(ap_local_apic) => if ap_local_apic.id == me {
                    println!("        This is my local APIC");
                } else {
                    if ap_local_apic.flags & 1 == 1 {
                        // Increase CPU ID
                        CPU_COUNT.fetch_add(1, Ordering::SeqCst);

                        // Allocate a stack
                        let stack_start = allocate_frames(64).expect("no more frames in acpi stack_start").start_address().get() + ::KERNEL_OFFSET;
                        let stack_end = stack_start + 64 * 4096;

                        let ap_ready = TRAMPOLINE as *mut u64;
                        let ap_cpu_id = unsafe { ap_ready.offset(1) };
                        let ap_page_table = unsafe { ap_ready.offset(2) };
                        let ap_stack_start = unsafe { ap_ready.offset(3) };
                        let ap_stack_end = unsafe { ap_ready.offset(4) };
                        let ap_code = unsafe { ap_ready.offset(5) };

                        // Set the ap_ready to 0, volatile
                        unsafe { atomic_store(ap_ready, 0) };
                        unsafe { atomic_store(ap_cpu_id, ap_local_apic.id as u64) };
                        unsafe { atomic_store(ap_page_table, active_table.address() as u64) };
                        unsafe { atomic_store(ap_stack_start, stack_start as u64) };
                        unsafe { atomic_store(ap_stack_end, stack_end as u64) };
                        unsafe { atomic_store(ap_code, kstart_ap as u64) };
                        AP_READY.store(false, Ordering::SeqCst);

                        print!("        AP {}:", ap_local_apic.id);

                        // Send INIT IPI
                        {
                            let mut icr = 0x4500;
                            if local_apic.x2 {
                                icr |= (ap_local_apic.id as u64) << 32;
                            } else {
                                icr |= (ap_local_apic.id as u64) << 56;
                            }
                            print!(" IPI...");
                            local_apic.set_icr(icr);
                        }

                        // Send START IPI
                        {
                            //Start at 0x0800:0000 => 0x8000. Hopefully the bootloader code is still there
                            let ap_segment = (AP_STARTUP >> 12) & 0xFF;
                            let mut icr = 0x4600 | ap_segment as u64;

                            if local_apic.x2 {
                                icr |= (ap_local_apic.id as u64) << 32;
                            } else {
                                icr |= (ap_local_apic.id as u64) << 56;
                            }

                            print!(" SIPI...");
                            local_apic.set_icr(icr);
                        }

                        // Wait for trampoline ready
                        print!(" Wait...");
                        while unsafe { atomic_load(ap_ready) } == 0 {
                            interrupt::pause();
                        }
                        print!(" Trampoline...");
                        while ! AP_READY.load(Ordering::SeqCst) {
                            interrupt::pause();
                        }
                        println!(" Ready");

                        active_table.flush_all();
                    } else {
                        println!("        CPU Disabled");
                    }
                },
                _ => ()
            }
        }

        // Unmap trampoline
        let result = active_table.unmap(trampoline_page);
        result.flush(active_table);
        Some(AcpiTable::madt(madt))
    } else if let Some(dmar) = Dmar::new(sdt) {
        println!(": {}: {}", dmar.addr_width, dmar.flags);

        for dmar_entry in dmar.iter() {
            println!("      {:?}", dmar_entry);
            match dmar_entry {
                DmarEntry::Drhd(dmar_drhd) => {
                    let drhd = dmar_drhd.get(active_table);

                    println!("VER: {:X}", drhd.version);
                    println!("CAP: {:X}", drhd.cap);
                    println!("EXT_CAP: {:X}", drhd.ext_cap);
                    println!("GCMD: {:X}", drhd.gl_cmd);
                    println!("GSTS: {:X}", drhd.gl_sts);
                    println!("RT: {:X}", drhd.root_table);
                },
                _ => ()
            }
        }
        Some(AcpiTable::dmar(dmar))
    } else {
        println!(": Unknown");
        None
    }
}

/// Parse the ACPI tables to gather CPU, interrupt, and timer information
pub unsafe fn init(active_table: &mut ActivePageTable) -> Option<Acpi> {
    let start_addr = 0xE0000;
    let end_addr = 0xFFFFF;

    let mut theFADT: Option<Fadt> = None;

    // Map all of the ACPI RSDP space
    {
        let start_frame = Frame::containing_address(PhysicalAddress::new(start_addr));
        let end_frame = Frame::containing_address(PhysicalAddress::new(end_addr));
        for frame in Frame::range_inclusive(start_frame, end_frame) {
            let page = Page::containing_address(VirtualAddress::new(frame.start_address().get()));
            let result = active_table.map_to(page, frame, entry::PRESENT | entry::NO_EXECUTE);
            result.flush(active_table);
        }
    }

    // Search for RSDP
    if let Some(rsdp) = RSDP::search(start_addr, end_addr) {
        let get_sdt = |sdt_address: usize, active_table: &mut ActivePageTable| -> (&'static Sdt, bool) {
            let mapped = if active_table.translate_page(Page::containing_address(VirtualAddress::new(sdt_address))).is_none() {
                let sdt_frame = Frame::containing_address(PhysicalAddress::new(sdt_address));
                let sdt_page = Page::containing_address(VirtualAddress::new(sdt_address));
                let result = active_table.map_to(sdt_page, sdt_frame, entry::PRESENT | entry::NO_EXECUTE);
                result.flush(active_table);
                true
            } else {
                false
            };
            (&*(sdt_address as *const Sdt), mapped)
        };

        let drop_sdt = |sdt: &'static Sdt, mapped: bool, active_table: &mut ActivePageTable| {
            let sdt_address = sdt as *const Sdt as usize;
            drop(sdt);
            if mapped {
                let sdt_page = Page::containing_address(VirtualAddress::new(sdt_address));
                let result = active_table.unmap(sdt_page);
                result.flush(active_table);
            }
        };

        let (rxsdt, rxmapped) = get_sdt(rsdp.sdt_address(), active_table);

        for &c in rxsdt.signature.iter() {
            print!("{}", c as char);
        }
        println!(":");
        if let Some(rsdt) = Rsdt::new(rxsdt) {
            for sdt_address in rsdt.iter() {
                let (sdt, mapped) = get_sdt(sdt_address, active_table);

                // If we find the FADT, rather than drop it, save a copy of the pointer, as this is needed elsewhere.
                // TODO: Eventually, save pointers to all tables containing pertinent information to other parts of
                // the kernel
                match init_sdt(sdt, active_table) {
                    Some(AcpiTable::fadt(fadt)) => theFADT = Some(fadt),
                    _ => drop_sdt(sdt, mapped, active_table)
                }
            }
        } else if let Some(xsdt) = Xsdt::new(rxsdt) {
            for sdt_address in xsdt.iter() {
                let (sdt, mapped) = get_sdt(sdt_address, active_table);

                // If we find the FADT, rather than drop it, save a copy of the pointer, as this is needed elsewhere.
                // TODO: Eventually, save pointers to all tables containing pertinent information to other parts of
                // the kernel
                match init_sdt(sdt, active_table) {
                    Some(AcpiTable::fadt(fadt)) => theFADT = Some(fadt),
                    _ => drop_sdt(sdt, mapped, active_table)
                }
            }
        } else {
            println!("UNKNOWN RSDT OR XSDT SIGNATURE");
        }

        drop_sdt(rxsdt, rxmapped, active_table);
    } else {
        println!("NO RSDP FOUND");
    }

    // Unmap all of the ACPI RSDP space
    {
        let start_frame = Frame::containing_address(PhysicalAddress::new(start_addr));
        let end_frame = Frame::containing_address(PhysicalAddress::new(end_addr));
        for frame in Frame::range_inclusive(start_frame, end_frame) {
            let page = Page::containing_address(VirtualAddress::new(frame.start_address().get()));
            let result = active_table.unmap(page);
            result.flush(active_table);
        }
    }

    if let Some(fadt) = theFADT {
        Some(Acpi { fadt: fadt })
    } else {
        None
    }
}

pub struct Acpi {
    pub fadt: Fadt
}

/// RSDP
#[derive(Copy, Clone, Debug)]
#[repr(packed)]
pub struct RSDP {
    signature: [u8; 8],
    checksum: u8,
    oemid: [u8; 6],
    revision: u8,
    rsdt_address: u32,
    length: u32,
    xsdt_address: u64,
    extended_checksum: u8,
    reserved: [u8; 3]
}

impl RSDP {
    /// Search for the RSDP
    pub fn search(start_addr: usize, end_addr: usize) -> Option<RSDP> {
        for i in 0 .. (end_addr + 1 - start_addr)/16 {
            let rsdp = unsafe { &*((start_addr + i * 16) as *const RSDP) };
            if &rsdp.signature == b"RSD PTR " {
                return Some(*rsdp);
            }
        }
        None
    }

    /// Get the RSDT or XSDT address
    pub fn sdt_address(&self) -> usize {
        if self.revision >= 2 {
            self.xsdt_address as usize
        } else {
            self.rsdt_address as usize
        }
    }
}
<|endoftext|>


<commit_before>/* Copyright 2016 Jordan Miner
 *
 * Licensed under the MIT license <LICENSE or
 * http://opensource.org/licenses/MIT>. This file may not be copied,
 * modified, or distributed except according to those terms.
 */

#[macro_use]
extern crate clear_coat;
extern crate iup_sys;
extern crate smallvec;

use std::rc::Rc;
use iup_sys::*;
use smallvec::SmallVec;

use clear_coat::*;
use clear_coat::common_attrs_cbs::*;

struct CursorsCanvas {
    canvas: Canvas,
}

impl CursorsCanvas {
    pub fn new() -> Self {
        CursorsCanvas {
            canvas: Canvas::new(),
        }
    }
}

impl CursorAttribute for CursorsCanvas {}

unsafe impl Control for CursorsCanvas {
    fn handle(&self) -> *mut Ihandle {
        self.canvas.handle()
    }
}

fn create_cursors_page() -> Box<Control> {
    let cursors_canvas = Rc::new(CursorsCanvas::new());

    let radios_info = [
        ("None", Cursor::None),
        ("Arrow", Cursor::Arrow),
        ("Busy", Cursor::Busy),
        ("Cross", Cursor::Cross),
        ("Hand", Cursor::Hand),
        ("Help", Cursor::Help),
        ("Move", Cursor::Move),
        ("ResizeN", Cursor::ResizeN),
        ("ResizeS", Cursor::ResizeS),
        ("ResizeNS", Cursor::ResizeNS),
        ("ResizeW", Cursor::ResizeW),
        ("ResizeE", Cursor::ResizeE),
        ("ResizeWE", Cursor::ResizeWE),
        ("ResizeNE", Cursor::ResizeNE),
        ("ResizeSW", Cursor::ResizeSW),
        ("ResizeNW", Cursor::ResizeNW),
        ("ResizeSE", Cursor::ResizeSE),
        ("Text", Cursor::Text),
    ];

    let mut radios = SmallVec::<[Toggle; 32]>::new();
    for &(text, cur) in radios_info.iter() {
        let toggle = Toggle::new();
        toggle.set_title(text);
        let cursors_canvas2 = cursors_canvas.clone();
        toggle.action_event().add(move |checked| {
            if checked { cursors_canvas2.set_cursor(cur); }
        });
        radios.push(toggle);
    }

    let grid = grid_box!(
        &radios[0],
        &radios[1],
        &radios[2],
        &radios[3],
        &radios[4],
        &radios[5],
        &radios[6],
        &radios[7],
        &radios[8],
        &radios[9],
        &radios[10],
        &radios[11],
        &radios[12],
        &radios[13],
        &radios[14],
        &radios[15],
        &radios[16],
        &radios[17],
    );
    grid.set_num_div(NumDiv::Fixed(2));
    grid.fit_all_to_children();
    let page = vbox!(
        &cursors_canvas,
        hbox!(
            fill!(),
            Radio::with_child(&grid),
            fill!(),
        ),
    );
    Box::new(page)
}

fn create_file_dialog_page() -> Box<Control> {
    let dir_check_box = Toggle::new();
    dir_check_box.set_title("Directory:");

    let dir_text_box = Text::new();

    let show_dialog = Button::with_title("Show Dialog");
    let dir_check_box_capt = dir_check_box.clone();
    let dir_text_box_capt = dir_text_box.clone();
    show_dialog.action_event().add(move || {
        let dialog = FileDlg::new();
        if dir_check_box_capt.value() == ToggleState::On {
            dialog.set_directory(&dir_text_box_capt.value());
        }
        dialog.popup(ScreenPosition::CenterParent, ScreenPosition::CenterParent)
              .expect("couldn't show file dialog");
    });

    let grid = grid_box!(
        dir_check_box,
        dir_text_box,
        fill!(),
        show_dialog,
    );
    grid.set_num_div(NumDiv::Fixed(2));
    grid.fit_all_to_children();
    Box::new(grid)
}

fn main() {

    let dialog = Dialog::new();

    let tabs = Tabs::new();

    tabs.append_tabs(&[
        TabInfo::new(&*create_cursors_page()).title("Cursors"),
        TabInfo::new(&*create_file_dialog_page()).title("File Dialog"),
    ]);

    dialog.append(&tabs).expect("failed to build the window");
    dialog.set_title("Showcase");

    dialog.show_xy(ScreenPosition::Center, ScreenPosition::Center)
          .expect("failed to show the window");
    main_loop();
}
<commit_msg>Add the ability to change the file dialog type in Showcase<commit_after>/* Copyright 2016 Jordan Miner
 *
 * Licensed under the MIT license <LICENSE or
 * http://opensource.org/licenses/MIT>. This file may not be copied,
 * modified, or distributed except according to those terms.
 */

#[macro_use]
extern crate clear_coat;
extern crate iup_sys;
extern crate smallvec;

use std::rc::Rc;
use iup_sys::*;
use smallvec::SmallVec;

use clear_coat::*;
use clear_coat::common_attrs_cbs::*;

struct CursorsCanvas {
    canvas: Canvas,
}

impl CursorsCanvas {
    pub fn new() -> Self {
        CursorsCanvas {
            canvas: Canvas::new(),
        }
    }
}

impl CursorAttribute for CursorsCanvas {}

unsafe impl Control for CursorsCanvas {
    fn handle(&self) -> *mut Ihandle {
        self.canvas.handle()
    }
}

fn create_cursors_page() -> Box<Control> {
    let cursors_canvas = Rc::new(CursorsCanvas::new());

    let radios_info = [
        ("None", Cursor::None),
        ("Arrow", Cursor::Arrow),
        ("Busy", Cursor::Busy),
        ("Cross", Cursor::Cross),
        ("Hand", Cursor::Hand),
        ("Help", Cursor::Help),
        ("Move", Cursor::Move),
        ("ResizeN", Cursor::ResizeN),
        ("ResizeS", Cursor::ResizeS),
        ("ResizeNS", Cursor::ResizeNS),
        ("ResizeW", Cursor::ResizeW),
        ("ResizeE", Cursor::ResizeE),
        ("ResizeWE", Cursor::ResizeWE),
        ("ResizeNE", Cursor::ResizeNE),
        ("ResizeSW", Cursor::ResizeSW),
        ("ResizeNW", Cursor::ResizeNW),
        ("ResizeSE", Cursor::ResizeSE),
        ("Text", Cursor::Text),
    ];

    let mut radios = SmallVec::<[Toggle; 32]>::new();
    for &(text, cur) in radios_info.iter() {
        let toggle = Toggle::new();
        toggle.set_title(text);
        let cursors_canvas2 = cursors_canvas.clone();
        toggle.action_event().add(move |checked| {
            if checked { cursors_canvas2.set_cursor(cur); }
        });
        radios.push(toggle);
    }

    let grid = grid_box!(
        &radios[0],
        &radios[1],
        &radios[2],
        &radios[3],
        &radios[4],
        &radios[5],
        &radios[6],
        &radios[7],
        &radios[8],
        &radios[9],
        &radios[10],
        &radios[11],
        &radios[12],
        &radios[13],
        &radios[14],
        &radios[15],
        &radios[16],
        &radios[17],
    );
    grid.set_num_div(NumDiv::Fixed(2));
    grid.fit_all_to_children();
    let page = vbox!(
        &cursors_canvas,
        hbox!(
            fill!(),
            Radio::with_child(&grid),
            fill!(),
        ),
    );
    Box::new(page)
}

fn create_file_dialog_page() -> Box<Control> {

    let type_check_box = Toggle::new();
    type_check_box.set_title("Dialog Type:");

    let open_radio = Toggle::new();
    open_radio.set_title("Open");
    let save_radio = Toggle::new();
    save_radio.set_title("Save");
    let dir_radio = Toggle::new();
    dir_radio.set_title("Directory");
    let type_radio = Radio::with_child(&vbox!(
        &open_radio,
        &save_radio,
        &dir_radio,
    ));

    let dir_check_box = Toggle::new();
    dir_check_box.set_title("Directory:");

    let dir_text_box = Text::new();

    let show_dialog = Button::with_title("Show Dialog");
    let type_check_box_capt = type_check_box.clone();
    let open_radio_capt = open_radio.clone();
    let save_radio_capt = save_radio.clone();
    let dir_check_box_capt = dir_check_box.clone();
    let dir_text_box_capt = dir_text_box.clone();
    show_dialog.action_event().add(move || {
        let dialog = FileDlg::new();
        if type_check_box_capt.value() == ToggleState::On {
            dialog.set_dialog_type(if open_radio_capt.value() == ToggleState::On {
                FileDialogType::Open
            } else if save_radio_capt.value() == ToggleState::On {
                FileDialogType::Save
            } else {
                FileDialogType::Dir
            })
        }
        if dir_check_box_capt.value() == ToggleState::On {
            dialog.set_directory(&dir_text_box_capt.value());
        }
        dialog.popup(ScreenPosition::CenterParent, ScreenPosition::CenterParent)
              .expect("couldn't show file dialog");
    });

    let grid = grid_box!(
        type_check_box, type_radio,
        dir_check_box, dir_text_box,
        fill!(), show_dialog,
    );
    grid.set_alignment_lin_all(VAlignment::Top);
    grid.set_num_div(NumDiv::Fixed(2));
    grid.fit_all_to_children();
    Box::new(grid)
}

fn main() {

    let dialog = Dialog::new();

    let tabs = Tabs::new();

    tabs.append_tabs(&[
        TabInfo::new(&*create_cursors_page()).title("Cursors"),
        TabInfo::new(&*create_file_dialog_page()).title("File Dialog"),
    ]);

    dialog.append(&tabs).expect("failed to build the window");
    dialog.set_title("Showcase");

    dialog.show_xy(ScreenPosition::Center, ScreenPosition::Center)
          .expect("failed to show the window");
    main_loop();
}
<|endoftext|>