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

trait Nat {
    const VALUE: usize;
}

struct Zero;
struct Succ<N>(N);

impl Nat for Zero {
    const VALUE: usize = 0;
}

impl<N: Nat> Nat for Succ<N> {
    const VALUE: usize = N::VALUE + 1;
}

fn main() {
    let x: [i32; <Succ<Succ<Succ<Succ<Zero>>>>>::VALUE] = [1, 2, 3, 4];
}
<|endoftext|>


<commit_before><commit_msg>Re-added test for Issue 935 -- not sure what happened to it<commit_after>// xfail-pretty

fn id(x: bool) -> bool { x }

fn call_id() {
    let c <- fail;
    id(c);
}

fn call_id_2() { id(true) && id(ret); }

fn call_id_3() { id(ret) && id(ret); }

fn log_fail() { log(error, fail); }

fn log_ret() { log(error, ret); }

fn log_break() { loop { log(error, break); } }

fn log_again() { loop { log(error, again); } }

fn ret_ret() -> int { ret (ret 2) + 3; }

fn ret_guard() {
    alt 2 {
      x if (ret) { x; }
      _ {}
    }
}

fn main() {}
<|endoftext|>


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

/// Creates a `Vec` containing the arguments.
///
/// `vec!` allows `Vec`s to be defined with the same syntax as array expressions.
/// There are two forms of this macro:
///
/// - Create a `Vec` containing a given list of elements:
///
/// ```
/// let v = vec![1, 2, 3];
/// assert_eq!(v[0], 1);
/// assert_eq!(v[1], 2);
/// assert_eq!(v[2], 3);
/// ```
///
/// - Create a `Vec` from a given element and size:
///
/// ```
/// let v = vec![1; 3];
/// assert_eq!(v, [1, 1, 1]);
/// ```
///
/// Note that unlike array expressions this syntax supports all elements
/// which implement `Clone` and the number of elements doesn't have to be
/// a constant.
#[cfg(not(test))]
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! vec {
    ($elem:expr; $n:expr) => (
        $crate::vec::from_elem($elem, $n)
    );
    ($($x:expr),*) => (
        <[_]>::into_vec($crate::boxed::Box::new([$($x),*]))
    );
    ($($x:expr,)*) => (vec![$($x),*])
}

// HACK(japaric): with cfg(test) the inherent `[T]::into_vec` method, which is
// required for this macro definition, is not available. Instead use the
// `slice::into_vec`  function which is only available with cfg(test)
// NB see the slice::hack module in slice.rs for more information
#[cfg(test)]
macro_rules! vec {
    ($elem:expr; $n:expr) => (
        $crate::vec::from_elem($elem, $n)
    );
    ($($x:expr),*) => (
        $crate::slice::into_vec($crate::boxed::Box::new([$($x),*]))
    );
    ($($x:expr,)*) => (vec![$($x),*])
}

/// Use the syntax described in `std::fmt` to create a value of type `String`.
/// See `std::fmt` for more information.
///
/// # Examples
///
/// ```
/// format!("test");
/// format!("hello {}", "world!");
/// format!("x = {}, y = {y}", 10, y = 30);
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! format {
    ($($arg:tt)*) => ($crate::fmt::format(format_args!($($arg)*)))
}
<commit_msg>Auto merge of #28272 - Manishearth:improve_vec_docs, r=steveklabnik<commit_after>// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/// Creates a `Vec` containing the arguments.
///
/// `vec!` allows `Vec`s to be defined with the same syntax as array expressions.
/// There are two forms of this macro:
///
/// - Create a `Vec` containing a given list of elements:
///
/// ```
/// let v = vec![1, 2, 3];
/// assert_eq!(v[0], 1);
/// assert_eq!(v[1], 2);
/// assert_eq!(v[2], 3);
/// ```
///
/// - Create a `Vec` from a given element and size:
///
/// ```
/// let v = vec![1; 3];
/// assert_eq!(v, [1, 1, 1]);
/// ```
///
/// Note that unlike array expressions this syntax supports all elements
/// which implement `Clone` and the number of elements doesn't have to be
/// a constant.
///
/// This will use `clone()` to duplicate an expression, so one should be careful
/// using this with types having a nonstandard `Clone` implementation. For
/// example, `vec![Rc::new(1); 5]` will create a vector of five references
/// to the same boxed integer value, not five references pointing to independently
/// boxed integers.
#[cfg(not(test))]
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! vec {
    ($elem:expr; $n:expr) => (
        $crate::vec::from_elem($elem, $n)
    );
    ($($x:expr),*) => (
        <[_]>::into_vec($crate::boxed::Box::new([$($x),*]))
    );
    ($($x:expr,)*) => (vec![$($x),*])
}

// HACK(japaric): with cfg(test) the inherent `[T]::into_vec` method, which is
// required for this macro definition, is not available. Instead use the
// `slice::into_vec`  function which is only available with cfg(test)
// NB see the slice::hack module in slice.rs for more information
#[cfg(test)]
macro_rules! vec {
    ($elem:expr; $n:expr) => (
        $crate::vec::from_elem($elem, $n)
    );
    ($($x:expr),*) => (
        $crate::slice::into_vec($crate::boxed::Box::new([$($x),*]))
    );
    ($($x:expr,)*) => (vec![$($x),*])
}

/// Use the syntax described in `std::fmt` to create a value of type `String`.
/// See `std::fmt` for more information.
///
/// # Examples
///
/// ```
/// format!("test");
/// format!("hello {}", "world!");
/// format!("x = {}, y = {y}", 10, y = 30);
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! format {
    ($($arg:tt)*) => ($crate::fmt::format(format_args!($($arg)*)))
}
<|endoftext|>


<commit_before>// Copyright 2015 The Gfx-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.

#[macro_use]
extern crate gfx;
extern crate gfx_window_glutin;
extern crate glutin;

pub use gfx::format::{Srgb8, Depth};

gfx_vertex_struct!( Vertex {
    pos: [f32; 2] = "a_Pos",
    uv: [f32; 2] = "a_Uv",
});

impl Vertex {
    fn new(p: [f32; 2], u: [f32; 2]) -> Vertex {
        Vertex {
            pos: p,
            uv: u,
        }
    }
}

gfx_pipeline!(pipe {
    vbuf: gfx::VertexBuffer<Vertex> = (),
    tex: gfx::TextureSampler<[f32; 3]> = "t_Tex",
    out: gfx::RenderTarget<Srgb8> = "o_Color",
});

// Larger red dots
const L0_DATA: [[u8; 3]; 16] = [
    [ 0x00, 0x00, 0x00 ], [ 0x00, 0x00, 0x00 ], [ 0x00, 0x00, 0x00 ], [ 0x00, 0x00, 0x00 ],
    [ 0x00, 0x00, 0x00 ], [ 0xc0, 0x00, 0x00 ], [ 0xc0, 0x00, 0x00 ], [ 0x00, 0x00, 0x00 ],
    [ 0x00, 0x00, 0x00 ], [ 0xc0, 0x00, 0x00 ], [ 0xc0, 0x00, 0x00 ], [ 0x00, 0x00, 0x00 ],
    [ 0x00, 0x00, 0x00 ], [ 0x00, 0x00, 0x00 ], [ 0x00, 0x00, 0x00 ], [ 0x00, 0x00, 0x00 ],
];

// Uniform green
const L1_DATA: [[u8; 3]; 4] = [
    [ 0x00, 0xc0, 0x00 ], [ 0x00, 0xc0, 0x00 ],
    [ 0x00, 0xc0, 0x00 ], [ 0x00, 0xc0, 0x00 ],
];

// Uniform blue
const L2_DATA: [[u8; 3]; 1] = [ [ 0x00, 0x00, 0xc0 ] ];

fn make_texture<R, F>(factory: &mut F) -> gfx::handle::ShaderResourceView<R, [f32; 3]>
        where R: gfx::Resources,
              F: gfx::Factory<R>
{
    let kind = gfx::tex::Kind::D2(4, 4, gfx::tex::AaMode::Single);
    let tex = factory.create_texture(kind, 3, gfx::SHADER_RESOURCE,
        Some(gfx::format::ChannelType::Unorm)).unwrap();

    type Rgb8 = (gfx::format::R8_G8_B8, gfx::format::Unorm);

    factory.update_texture::<Rgb8>(&tex, &tex.get_info().to_image_info(0),
        gfx::cast_slice(&L0_DATA), None).unwrap();
    factory.update_texture::<Rgb8>(&tex, &tex.get_info().to_image_info(1),
        gfx::cast_slice(&L1_DATA), None).unwrap();
    factory.update_texture::<Rgb8>(&tex, &tex.get_info().to_image_info(2),
        gfx::cast_slice(&L2_DATA), None).unwrap();

    factory.view_texture_as_shader_resource::<Rgb8>(
        &tex, (0, 2), gfx::format::Swizzle::new()).unwrap()
}

pub fn main() {
    use gfx::traits::{Device, Factory, FactoryExt};

    let builder = glutin::WindowBuilder::new()
        .with_title("Mipmap example".to_string())
        .with_dimensions(800, 600);
    let (window, mut device, mut factory, main_color, _) =
        gfx_window_glutin::init::<Srgb8, Depth>(builder);
    let mut encoder = factory.create_encoder();

    let pso = factory.create_pipeline_simple(
        include_bytes!("shader/120.glslv"),
        include_bytes!("shader/120.glslf"),
        gfx::state::CullFace::Nothing,
        pipe::new()
        ).unwrap();

    let vertex_data = [
        Vertex::new([ 0.0,  0.0], [ 0.0,  0.0]),
        Vertex::new([ 1.0,  0.0], [50.0,  0.0]),
        Vertex::new([ 1.0,  1.1], [50.0, 50.0]),

        Vertex::new([ 0.0,  0.0], [  0.0,   0.0]),
        Vertex::new([-1.0,  0.0], [800.0,   0.0]),
        Vertex::new([-1.0, -1.0], [800.0, 800.0]),
    ];
    let (vbuf, slice) = factory.create_vertex_buffer(&vertex_data);

    let texture_view = make_texture(&mut factory);

    let sampler = factory.create_sampler(gfx::tex::SamplerInfo::new(
        gfx::tex::FilterMethod::Trilinear,
        gfx::tex::WrapMode::Tile,
    ));

    let data = pipe::Data {
        vbuf: vbuf,
        tex: (texture_view, sampler),
        out: main_color,
    };

    'main: loop {
        // quit when Esc is pressed.
        for event in window.poll_events() {
            match event {
                glutin::Event::KeyboardInput(_, _, Some(glutin::VirtualKeyCode::Escape)) |
                glutin::Event::Closed => break 'main,
                _ => {},
            }
        }

        encoder.reset();
        encoder.clear(&data.out, [0.1, 0.2, 0.3]);
        encoder.draw(&slice, &pso, &data);

        device.submit(encoder.as_buffer());
        window.swap_buffers().unwrap();
        device.cleanup();
    }
}
<commit_msg>R8_G8_B8_A8 is even better supported.<commit_after>// Copyright 2015 The Gfx-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.

#[macro_use]
extern crate gfx;
extern crate gfx_window_glutin;
extern crate glutin;

pub use gfx::format::{Rgba8, Depth};

gfx_vertex_struct!( Vertex {
    pos: [f32; 2] = "a_Pos",
    uv: [f32; 2] = "a_Uv",
});

impl Vertex {
    fn new(p: [f32; 2], u: [f32; 2]) -> Vertex {
        Vertex {
            pos: p,
            uv: u,
        }
    }
}

gfx_pipeline!(pipe {
    vbuf: gfx::VertexBuffer<Vertex> = (),
    tex: gfx::TextureSampler<[f32; 4]> = "t_Tex",
    out: gfx::RenderTarget<Rgba8> = "o_Color",
});

// Larger red dots
const L0_DATA: [[u8; 4]; 16] = [
    [ 0x00, 0x00, 0x00, 0x00 ], [ 0x00, 0x00, 0x00, 0x00 ], [ 0x00, 0x00, 0x00, 0x00 ], [ 0x00, 0x00, 0x00, 0x00 ],
    [ 0x00, 0x00, 0x00, 0x00 ], [ 0xc0, 0x00, 0x00, 0x00 ], [ 0xc0, 0x00, 0x00, 0x00 ], [ 0x00, 0x00, 0x00, 0x00 ],
    [ 0x00, 0x00, 0x00, 0x00 ], [ 0xc0, 0x00, 0x00, 0x00 ], [ 0xc0, 0x00, 0x00, 0x00 ], [ 0x00, 0x00, 0x00, 0x00 ],
    [ 0x00, 0x00, 0x00, 0x00 ], [ 0x00, 0x00, 0x00, 0x00 ], [ 0x00, 0x00, 0x00, 0x00 ], [ 0x00, 0x00, 0x00, 0x00 ],
];

// Uniform green
const L1_DATA: [[u8; 4]; 4] = [
    [ 0x00, 0xc0, 0x00, 0x00 ], [ 0x00, 0xc0, 0x00, 0x00 ],
    [ 0x00, 0xc0, 0x00, 0x00 ], [ 0x00, 0xc0, 0x00, 0x00 ],
];

// Uniform blue
const L2_DATA: [[u8; 4]; 1] = [ [ 0x00, 0x00, 0xc0, 0x00 ] ];

fn make_texture<R, F>(factory: &mut F) -> gfx::handle::ShaderResourceView<R, [f32; 4]>
        where R: gfx::Resources,
              F: gfx::Factory<R>
{
    let kind = gfx::tex::Kind::D2(4, 4, gfx::tex::AaMode::Single);
    let tex = factory.create_texture(kind, 3, gfx::SHADER_RESOURCE,
        Some(gfx::format::ChannelType::Unorm)).unwrap();

    factory.update_texture::<Rgba8>(&tex, &tex.get_info().to_image_info(0),
        gfx::cast_slice(&L0_DATA), None).unwrap();
    factory.update_texture::<Rgba8>(&tex, &tex.get_info().to_image_info(1),
        gfx::cast_slice(&L1_DATA), None).unwrap();
    factory.update_texture::<Rgba8>(&tex, &tex.get_info().to_image_info(2),
        gfx::cast_slice(&L2_DATA), None).unwrap();

    factory.view_texture_as_shader_resource::<Rgba8>(
        &tex, (0, 2), gfx::format::Swizzle::new()).unwrap()
}

pub fn main() {
    use gfx::traits::{Device, Factory, FactoryExt};

    let builder = glutin::WindowBuilder::new()
        .with_title("Mipmap example".to_string())
        .with_dimensions(800, 600);
    let (window, mut device, mut factory, main_color, _) =
        gfx_window_glutin::init::<Rgba8, Depth>(builder);
    let mut encoder = factory.create_encoder();

    let pso = factory.create_pipeline_simple(
        include_bytes!("shader/120.glslv"),
        include_bytes!("shader/120.glslf"),
        gfx::state::CullFace::Nothing,
        pipe::new()
        ).unwrap();

    let vertex_data = [
        Vertex::new([ 0.0,  0.0], [ 0.0,  0.0]),
        Vertex::new([ 1.0,  0.0], [50.0,  0.0]),
        Vertex::new([ 1.0,  1.1], [50.0, 50.0]),

        Vertex::new([ 0.0,  0.0], [  0.0,   0.0]),
        Vertex::new([-1.0,  0.0], [800.0,   0.0]),
        Vertex::new([-1.0, -1.0], [800.0, 800.0]),
    ];
    let (vbuf, slice) = factory.create_vertex_buffer(&vertex_data);

    let texture_view = make_texture(&mut factory);

    let sampler = factory.create_sampler(gfx::tex::SamplerInfo::new(
        gfx::tex::FilterMethod::Trilinear,
        gfx::tex::WrapMode::Tile,
    ));

    let data = pipe::Data {
        vbuf: vbuf,
        tex: (texture_view, sampler),
        out: main_color,
    };

    'main: loop {
        // quit when Esc is pressed.
        for event in window.poll_events() {
            match event {
                glutin::Event::KeyboardInput(_, _, Some(glutin::VirtualKeyCode::Escape)) |
                glutin::Event::Closed => break 'main,
                _ => {},
            }
        }

        encoder.reset();
        encoder.clear(&data.out, [0.1, 0.2, 0.3, 1.0]);
        encoder.draw(&slice, &pso, &data);

        device.submit(encoder.as_buffer());
        window.swap_buffers().unwrap();
        device.cleanup();
    }
}
<|endoftext|>


<commit_before><commit_msg>safer... but slower stack freelist<commit_after><|endoftext|>


<commit_before>/// Computing hashes for files.

use libc;

use std::ffi::OsString;
use std::fs::{OpenOptions};
use std::io::{self};
use std::io::prelude::*;
use std::os::unix::ffi::OsStringExt;
use std::fs::File;
use std::mem;
use std::path::Path;

use openssl::crypto::hash::{self, Hasher};

use rustc_serialize::hex::ToHex;

use super::Result;
use super::suretree::{SureFile, SureTree};
use super::escape::*;
use super::progress::Progress;

pub trait SureHash {
    /// Estimate how much work (files and bytes) need to be hashed.
    fn hash_estimate(&self) -> Estimate;

    /// Update the hashes on any files that are missing them.
    /// Note that this only logs errors, and tries to continue.
    fn hash_update(&mut self, path: &Path, meter: &mut Progress);
}

#[derive(Debug)]
pub struct Estimate {
    pub files: u64,
    pub bytes: u64,
}

impl SureHash for SureTree {
    fn hash_estimate(&self) -> Estimate {
        let mut est = Estimate {
            files: 0,
            bytes: 0,
        };
        est.update(self);
        est
    }

    fn hash_update(&mut self, path: &Path, meter: &mut Progress) {
        for d in &mut self.children {
            let s: OsString = OsStringExt::from_vec(d.name.unescape().unwrap());
            let cpath = path.join(&s);
            d.hash_update(&cpath, meter);
        }

        for f in &mut self.files {
            if !f.needs_hash() {
                continue;
            }

            let s: OsString = OsStringExt::from_vec(f.name.unescape().unwrap());
            let fpath = path.join(&s);

            match noatime_open(&fpath) {
                Ok(mut fd) => {
                    match hash_file(&mut fd) {
                        Ok(h) => {
                            let hex = h.to_hex();
                            f.atts.insert("sha1".to_string(), hex);
                        },
                        Err(e) => {
                            error!("Unable to has file: '{:?}' ({})", fpath, e);
                        }
                    }
                },
                Err(e) => {
                    error!("Unable to open '{:?}' for hashing ({})", fpath, e);
                }
            }

            meter.update(1, f.atts["size"].parse().unwrap());
        }
    }
}

impl SureFile {
    fn needs_hash(&self) -> bool {
        match (self.atts.get("kind"), self.atts.get("sha1")) {
            (Some(k), None) if k == "file" => true,
            _ => false,
        }
    }
}

impl Estimate {
    fn update(&mut self, node: &SureTree) {
        for f in &node.files {
            if f.needs_hash() {
                self.files += 1;
                self.bytes += f.atts["size"].parse::<u64>().unwrap();
            }
            /*
            match (f.atts.get("kind"), f.atts.get("sha1")) {
                (Some(k), None) if k == "file" => {
                    self.files += 1;
                    self.bytes += f.atts["size"].parse::<u64>().unwrap();
                },
                _ => (),
            }
            */
        }

        for d in &node.children {
            self.update(d);
        }
    }
}

// TODO: Reuse buffer and hasher for a given thread.
fn hash_file<R: Read>(rd: &mut R) -> Result<Vec<u8>> {
    let mut h = Hasher::new(hash::Type::SHA1);
    let mut buf = vec![0u8; 8192];

    loop {
        let count = try!(rd.read(&mut buf));
        if count == 0 {
            break;
        }

        try!(h.write_all(&buf[0..count]));
    }
    Ok(h.finish())
}

/// Open the given file, trying to not update the atime if that is
/// possible.
/// Unfortunately, there isn't a clean way to do this with Rust's library,
/// so we hack.  This isn't completely safe, because we rely on the
/// structure being encoded the same way.
fn noatime_open(name: &Path) -> io::Result<File> {
    // Try opening it first with noatime, and if that fails, try the open
    // again without the option.
    match OpenOptions::new().read(true).noatime().open(name) {
        Ok(f) => Ok(f),
        Err(_) =>
            OpenOptions::new().read(true).open(name)
    }
}

trait HackNoAtime {
    fn noatime(&mut self) -> &mut Self;
}

impl HackNoAtime for OpenOptions {
    fn noatime(&mut self) -> &mut Self {
        unsafe {
            let ptr: *mut MyOpenOption = mem::transmute(self as *mut OpenOptions);
            (*ptr).0.flags |= 0o1000000;
        }
        self
    }
}

struct MyOpenOption(MyOpenOptionImp);
struct MyOpenOptionImp {
    flags: libc::c_int,
    // ...
}
<commit_msg>Allow build on non-linux platforms<commit_after>/// Computing hashes for files.

use std::ffi::OsString;
use std::io::prelude::*;
use std::os::unix::ffi::OsStringExt;
use std::path::Path;

use openssl::crypto::hash::{self, Hasher};

use rustc_serialize::hex::ToHex;

use super::Result;
use super::suretree::{SureFile, SureTree};
use super::escape::*;
use super::progress::Progress;

pub trait SureHash {
    /// Estimate how much work (files and bytes) need to be hashed.
    fn hash_estimate(&self) -> Estimate;

    /// Update the hashes on any files that are missing them.
    /// Note that this only logs errors, and tries to continue.
    fn hash_update(&mut self, path: &Path, meter: &mut Progress);
}

#[derive(Debug)]
pub struct Estimate {
    pub files: u64,
    pub bytes: u64,
}

impl SureHash for SureTree {
    fn hash_estimate(&self) -> Estimate {
        let mut est = Estimate {
            files: 0,
            bytes: 0,
        };
        est.update(self);
        est
    }

    fn hash_update(&mut self, path: &Path, meter: &mut Progress) {
        for d in &mut self.children {
            let s: OsString = OsStringExt::from_vec(d.name.unescape().unwrap());
            let cpath = path.join(&s);
            d.hash_update(&cpath, meter);
        }

        for f in &mut self.files {
            if !f.needs_hash() {
                continue;
            }

            let s: OsString = OsStringExt::from_vec(f.name.unescape().unwrap());
            let fpath = path.join(&s);

            match noatime_open(&fpath) {
                Ok(mut fd) => {
                    match hash_file(&mut fd) {
                        Ok(h) => {
                            let hex = h.to_hex();
                            f.atts.insert("sha1".to_string(), hex);
                        },
                        Err(e) => {
                            error!("Unable to has file: '{:?}' ({})", fpath, e);
                        }
                    }
                },
                Err(e) => {
                    error!("Unable to open '{:?}' for hashing ({})", fpath, e);
                }
            }

            meter.update(1, f.atts["size"].parse().unwrap());
        }
    }
}

impl SureFile {
    fn needs_hash(&self) -> bool {
        match (self.atts.get("kind"), self.atts.get("sha1")) {
            (Some(k), None) if k == "file" => true,
            _ => false,
        }
    }
}

impl Estimate {
    fn update(&mut self, node: &SureTree) {
        for f in &node.files {
            if f.needs_hash() {
                self.files += 1;
                self.bytes += f.atts["size"].parse::<u64>().unwrap();
            }
            /*
            match (f.atts.get("kind"), f.atts.get("sha1")) {
                (Some(k), None) if k == "file" => {
                    self.files += 1;
                    self.bytes += f.atts["size"].parse::<u64>().unwrap();
                },
                _ => (),
            }
            */
        }

        for d in &node.children {
            self.update(d);
        }
    }
}

// TODO: Reuse buffer and hasher for a given thread.
fn hash_file<R: Read>(rd: &mut R) -> Result<Vec<u8>> {
    let mut h = Hasher::new(hash::Type::SHA1);
    let mut buf = vec![0u8; 8192];

    loop {
        let count = try!(rd.read(&mut buf));
        if count == 0 {
            break;
        }

        try!(h.write_all(&buf[0..count]));
    }
    Ok(h.finish())
}

use self::atime_impl::noatime_open;

/// Open the given file, trying to not update the atime if that is
/// possible.
/// Unfortunately, there isn't a clean way to do this with Rust's library,
/// so we hack.  This isn't completely safe, because we rely on the
/// structure being encoded the same way.
#[cfg(target_os = "linux")]
mod atime_impl {
    use libc;
    use std::fs::{File, OpenOptions};
    use std::io;
    use std::mem;
    use std::path::Path;

    pub fn noatime_open(name: &Path) -> io::Result<File> {
        // Try opening it first with noatime, and if that fails, try the open
        // again without the option.
        match OpenOptions::new().read(true).noatime().open(name) {
            Ok(f) => Ok(f),
            Err(_) =>
                OpenOptions::new().read(true).open(name)
        }
    }

    trait HackNoAtime {
        fn noatime(&mut self) -> &mut Self;
    }

    impl HackNoAtime for OpenOptions {
        fn noatime(&mut self) -> &mut Self {
            unsafe {
                let ptr: *mut MyOpenOption = mem::transmute(self as *mut OpenOptions);
                (*ptr).0.flags |= 0o1000000;
            }
            self
        }
    }

    struct MyOpenOption(MyOpenOptionImp);
    struct MyOpenOptionImp {
        flags: libc::c_int,
        // ...
    }
}

// Other platforms, just use normal open.
#[cfg(not(target_os = "linux"))]
mod atime_impl {
    use std::fs::{File, OpenOptions};
    use std::path::Path;
    use std::io;

    pub fn noatime_open(name: &Path) -> io::Result<File> {
        OpenOptions::new().read(true).open(name)
    }
}
<|endoftext|>


<commit_before><commit_msg>Tighten up menu buttons<commit_after><|endoftext|>