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

//! Syntax extensions in the Rust compiler.

#![crate_name = "syntax_ext"]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]

#![feature(rustc_private)]
#![feature(str_char)]

extern crate fmt_macros;
extern crate syntax;

use syntax::ext::base::{MacroExpanderFn, NormalTT};
use syntax::ext::base::{SyntaxEnv, SyntaxExtension};
use syntax::parse::token::intern;

// A variant of 'try!' that panics on Err(FatalError). This is used as a
// crutch on the way towards a non-panic!-prone parser. It should be used
// for fatal parsing errors; eventually we plan to convert all code using
// panictry to just use normal try
macro_rules! panictry {
    ($e:expr) => ({
        use std::result::Result::{Ok, Err};
        use syntax::diagnostic::FatalError;
        match $e {
            Ok(e) => e,
            Err(FatalError) => panic!(FatalError)
        }
    })
}

mod asm;
mod cfg;
mod concat;
mod concat_idents;
mod env;
mod format;
mod log_syntax;
mod trace_macros;

// for custom_derive
pub mod deriving;

pub fn register_builtins(env: &mut SyntaxEnv) {
    // utility function to simplify creating NormalTT syntax extensions
    fn builtin_normal_expander(f: MacroExpanderFn) -> SyntaxExtension {
        NormalTT(Box::new(f), None, false)
    }

    env.insert(intern("asm"),
               builtin_normal_expander(asm::expand_asm));
    env.insert(intern("cfg"),
               builtin_normal_expander(cfg::expand_cfg));
    env.insert(intern("concat"),
               builtin_normal_expander(concat::expand_syntax_ext));
    env.insert(intern("concat_idents"),
               builtin_normal_expander(concat_idents::expand_syntax_ext));
    env.insert(intern("env"),
               builtin_normal_expander(env::expand_env));
    env.insert(intern("option_env"),
               builtin_normal_expander(env::expand_option_env));
    env.insert(intern("format_args"),
               // format_args uses `unstable` things internally.
               NormalTT(Box::new(format::expand_format_args), None, true));
    env.insert(intern("log_syntax"),
               builtin_normal_expander(log_syntax::expand_syntax_ext));
    env.insert(intern("trace_macros"),
               builtin_normal_expander(trace_macros::expand_trace_macros));

    deriving::register_all(env);
}
<commit_msg>Mark libsyntax_ext unstable<commit_after>// Copyright 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.

//! Syntax extensions in the Rust compiler.

#![crate_name = "syntax_ext"]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]

#![cfg_attr(stage0, feature(custom_attribute))]
#![cfg_attr(stage0, staged_api)]
#![unstable(feature = "rustc_private", issue = "27812")]

#![feature(rustc_private)]
#![feature(staged_api)]
#![feature(str_char)]

extern crate fmt_macros;
extern crate syntax;

use syntax::ext::base::{MacroExpanderFn, NormalTT};
use syntax::ext::base::{SyntaxEnv, SyntaxExtension};
use syntax::parse::token::intern;

// A variant of 'try!' that panics on Err(FatalError). This is used as a
// crutch on the way towards a non-panic!-prone parser. It should be used
// for fatal parsing errors; eventually we plan to convert all code using
// panictry to just use normal try
macro_rules! panictry {
    ($e:expr) => ({
        use std::result::Result::{Ok, Err};
        use syntax::diagnostic::FatalError;
        match $e {
            Ok(e) => e,
            Err(FatalError) => panic!(FatalError)
        }
    })
}

mod asm;
mod cfg;
mod concat;
mod concat_idents;
mod env;
mod format;
mod log_syntax;
mod trace_macros;

// for custom_derive
pub mod deriving;

pub fn register_builtins(env: &mut SyntaxEnv) {
    // utility function to simplify creating NormalTT syntax extensions
    fn builtin_normal_expander(f: MacroExpanderFn) -> SyntaxExtension {
        NormalTT(Box::new(f), None, false)
    }

    env.insert(intern("asm"),
               builtin_normal_expander(asm::expand_asm));
    env.insert(intern("cfg"),
               builtin_normal_expander(cfg::expand_cfg));
    env.insert(intern("concat"),
               builtin_normal_expander(concat::expand_syntax_ext));
    env.insert(intern("concat_idents"),
               builtin_normal_expander(concat_idents::expand_syntax_ext));
    env.insert(intern("env"),
               builtin_normal_expander(env::expand_env));
    env.insert(intern("option_env"),
               builtin_normal_expander(env::expand_option_env));
    env.insert(intern("format_args"),
               // format_args uses `unstable` things internally.
               NormalTT(Box::new(format::expand_format_args), None, true));
    env.insert(intern("log_syntax"),
               builtin_normal_expander(log_syntax::expand_syntax_ext));
    env.insert(intern("trace_macros"),
               builtin_normal_expander(trace_macros::expand_trace_macros));

    deriving::register_all(env);
}
<|endoftext|>


<commit_before>use byteorder::{ReadBytesExt, LittleEndian};
use lnkpkg::errors::{LnkError};
use lnkpkg::utils;
use rwinstructs::guid::{Guid};
use std::io::SeekFrom;
use std::io::Read;
use std::io::Seek;

#[derive(Debug)]
pub struct DistributedTracker {
    size: u32,
    version: u32,
    machine_id: String, // 16 bytes (ascii)
    droid_volume: Guid,
    droid_file: Guid,
    birth_droid_volume: Guid,
    birth_droid_file: Guid
}
impl DistributedTracker {
    pub fn new<R: Read>(mut reader: R) -> Result<DistributedTracker,LnkError> {
        let size = reader.read_u32::<LittleEndian>()?;
        let version = reader.read_u32::<LittleEndian>()?;

        let mut buff_machine_id = vec![0; 16];
        reader.read_exact(buff_machine_id.as_mut_slice())?;
        let machine_id = utils::read_string_u8_till_null(
            buff_machine_id.as_slice()
        )?;

        let droid_volume = Guid::new(&mut reader)?;
        let droid_file = Guid::new(&mut reader)?;
        let birth_droid_volume = Guid::new(&mut reader)?;
        let birth_droid_file = Guid::new(&mut reader)?;

        Ok (
            DistributedTracker {
                size: size,
                version: version,
                machine_id: machine_id,
                droid_volume: droid_volume,
                droid_file: droid_file,
                birth_droid_volume: birth_droid_volume,
                birth_droid_file: birth_droid_file
            }
        )
    }
}

#[derive(Debug)]
pub struct EnvironmentVars {
    location: String, //size is 260 bytes (Unicode string terminated by an end-of-string character)
    location_unicode: String //size is 520 bytes (Unicode string terminated by an end-of-string character)
}
impl EnvironmentVars {
    pub fn new<R: Read>(mut reader: R) -> Result<EnvironmentVars,LnkError> {
        let mut buff_location = vec![0; 260];
        reader.read_exact(buff_location.as_mut_slice())?;
        let location = utils::read_string_u8_till_null(
            buff_location.as_slice()
        )?;

        let mut buff_location_unicode = vec![0; 520];
        reader.read_exact(buff_location_unicode.as_mut_slice())?;
        let location_unicode = utils::read_string_u16_till_null(
            buff_location_unicode.as_slice()
        )?;

        Ok(
            EnvironmentVars {
                location: location,
                location_unicode: location_unicode
            }
        )
    }
}

#[derive(Debug)]
pub struct ConsoleProperties {
    color_flags: u16,
    popup_attribs: u16,
    screen_width_buff_size: u16,
    screen_height_buff_size: u16,
    window_width: u16,
    window_height: u16,
    window_x: u16,
    window_y: u16,
    unknown1: u32,
    unknown2: u32,
    font_size: u32,
    font_family_value: u32,
    font_weight: u32,
    face_name: String, //size is 64 bytes (Unicode string terminated by an end-of-string character)
    cursor_size: u32,
    full_screen: u32,
    insert_mode: u32,
    auto_positioning: u32,
    history_buff_size: u32,
    history_buff_count: u32,
    duplicates_allowed: u32,
    color_table: utils::ByteArray
}
impl ConsoleProperties {
    pub fn new<R: Read>(mut reader: R) -> Result<ConsoleProperties,LnkError> {
        let color_flags = reader.read_u16::<LittleEndian>()?;
        let popup_attribs = reader.read_u16::<LittleEndian>()?;
        let screen_width_buff_size = reader.read_u16::<LittleEndian>()?;
        let screen_height_buff_size = reader.read_u16::<LittleEndian>()?;
        let window_width = reader.read_u16::<LittleEndian>()?;
        let window_height = reader.read_u16::<LittleEndian>()?;
        let window_x = reader.read_u16::<LittleEndian>()?;
        let window_y = reader.read_u16::<LittleEndian>()?;
        let unknown1 = reader.read_u32::<LittleEndian>()?;
        let unknown2 = reader.read_u32::<LittleEndian>()?;
        let font_size = reader.read_u32::<LittleEndian>()?;
        let font_family_value = reader.read_u32::<LittleEndian>()?;
        let font_weight = reader.read_u32::<LittleEndian>()?;

        // Read string
        let mut face_buff = vec![0; 64];
        reader.read_exact(face_buff.as_mut_slice())?;
        let face_name = utils::read_string_u16_till_null(face_buff.as_slice())?;

        let cursor_size = reader.read_u32::<LittleEndian>()?;
        let full_screen = reader.read_u32::<LittleEndian>()?;
        let insert_mode = reader.read_u32::<LittleEndian>()?;
        let auto_positioning = reader.read_u32::<LittleEndian>()?;
        let history_buff_size = reader.read_u32::<LittleEndian>()?;
        let history_buff_count = reader.read_u32::<LittleEndian>()?;
        let duplicates_allowed = reader.read_u32::<LittleEndian>()?;

        let mut color_buff = vec![0; 64];
        reader.read_exact(color_buff.as_mut_slice())?;
        let color_table = utils::ByteArray(color_buff);

        Ok (
            ConsoleProperties {
                color_flags: color_flags,
                popup_attribs: popup_attribs,
                screen_width_buff_size: screen_width_buff_size,
                screen_height_buff_size: screen_height_buff_size,
                window_width: window_width,
                window_height: window_height,
                window_x: window_x,
                window_y: window_y,
                unknown1: unknown1,
                unknown2: unknown2,
                font_size: font_size,
                font_family_value: font_family_value,
                font_weight: font_weight,
                face_name: face_name,
                cursor_size: cursor_size,
                full_screen: full_screen,
                insert_mode: insert_mode,
                auto_positioning: auto_positioning,
                history_buff_size: history_buff_size,
                history_buff_count: history_buff_count,
                duplicates_allowed: duplicates_allowed,
                color_table: color_table
            }
        )
    }
}

#[derive(Debug)]
pub struct ExtraDataBlocks {
    pub console_properties: Option<ConsoleProperties>,
    pub environment_vars: Option<EnvironmentVars>,
    pub distributed_tracker: Option<DistributedTracker>
}
impl ExtraDataBlocks {
    pub fn new<Rs: Read+Seek>(mut reader: Rs) -> Result<ExtraDataBlocks,LnkError> {
        let mut console_properties = None;
        let mut environment_vars = None;
        let mut distributed_tracker = None;

        let mut _offset = reader.seek(
            SeekFrom::Current(0)
        )?;

        loop {
            let size = reader.read_u32::<LittleEndian>()?;
            if size != 0 {
                let signature = reader.read_u32::<LittleEndian>()?;
                match signature {
                    0xa0000001 => {
                        environment_vars = Some(EnvironmentVars::new(&mut reader)?);
                    },
                    0xa0000002 => {
                        console_properties = Some(ConsoleProperties::new(&mut reader)?);
                    },
                    0xa0000003 => {
                        distributed_tracker = Some(DistributedTracker::new(&mut reader)?);
                    },
                    _ => {
                        println!(
                            "Unhandled data block with signature {} at offset {}",
                            signature,
                            _offset
                        );
                    }
                }

                _offset += size as u64;

                reader.seek(
                    SeekFrom::Start(_offset)
                )?;
            } else {
                break
            }
        }

        Ok(
            ExtraDataBlocks {
                console_properties: console_properties,
                environment_vars: environment_vars,
                distributed_tracker: distributed_tracker
            }
        )
    }
}
<commit_msg>Added Codepage and SpecialFolder block parsing<commit_after>use byteorder::{ReadBytesExt, LittleEndian};
use lnkpkg::errors::{LnkError};
use lnkpkg::utils;
use rwinstructs::guid::{Guid};
use std::io::SeekFrom;
use std::io::Read;
use std::io::Seek;

#[derive(Debug)]
pub struct SpecialFolder {
    special_folder_id: u32,
    first_child_segment_offset: u32
}
impl SpecialFolder {
    pub fn new<R: Read>(mut reader: R) -> Result<SpecialFolder,LnkError> {
        let special_folder_id = reader.read_u32::<LittleEndian>()?;
        let first_child_segment_offset = reader.read_u32::<LittleEndian>()?;

        Ok (
            SpecialFolder {
                special_folder_id: special_folder_id,
                first_child_segment_offset: first_child_segment_offset
            }
        )
    }
}

#[derive(Debug)]
pub struct Codepage {
    codepage: u32
}
impl Codepage {
    pub fn new<R: Read>(mut reader: R) -> Result<Codepage,LnkError> {
        let codepage = reader.read_u32::<LittleEndian>()?;

        Ok (
            Codepage {
                codepage: codepage
            }
        )
    }
}

#[derive(Debug)]
pub struct DistributedTracker {
    size: u32,
    version: u32,
    machine_id: String, // 16 bytes (ascii)
    droid_volume: Guid,
    droid_file: Guid,
    birth_droid_volume: Guid,
    birth_droid_file: Guid
}
impl DistributedTracker {
    pub fn new<R: Read>(mut reader: R) -> Result<DistributedTracker,LnkError> {
        let size = reader.read_u32::<LittleEndian>()?;
        let version = reader.read_u32::<LittleEndian>()?;

        let mut buff_machine_id = vec![0; 16];
        reader.read_exact(buff_machine_id.as_mut_slice())?;
        let machine_id = utils::read_string_u8_till_null(
            buff_machine_id.as_slice()
        )?;

        let droid_volume = Guid::new(&mut reader)?;
        let droid_file = Guid::new(&mut reader)?;
        let birth_droid_volume = Guid::new(&mut reader)?;
        let birth_droid_file = Guid::new(&mut reader)?;

        Ok (
            DistributedTracker {
                size: size,
                version: version,
                machine_id: machine_id,
                droid_volume: droid_volume,
                droid_file: droid_file,
                birth_droid_volume: birth_droid_volume,
                birth_droid_file: birth_droid_file
            }
        )
    }
}

#[derive(Debug)]
pub struct EnvironmentVars {
    location: String, //size is 260 bytes (Unicode string terminated by an end-of-string character)
    location_unicode: String //size is 520 bytes (Unicode string terminated by an end-of-string character)
}
impl EnvironmentVars {
    pub fn new<R: Read>(mut reader: R) -> Result<EnvironmentVars,LnkError> {
        let mut buff_location = vec![0; 260];
        reader.read_exact(buff_location.as_mut_slice())?;
        let location = utils::read_string_u8_till_null(
            buff_location.as_slice()
        )?;

        let mut buff_location_unicode = vec![0; 520];
        reader.read_exact(buff_location_unicode.as_mut_slice())?;
        let location_unicode = utils::read_string_u16_till_null(
            buff_location_unicode.as_slice()
        )?;

        Ok(
            EnvironmentVars {
                location: location,
                location_unicode: location_unicode
            }
        )
    }
}

#[derive(Debug)]
pub struct ConsoleProperties {
    color_flags: u16,
    popup_attribs: u16,
    screen_width_buff_size: u16,
    screen_height_buff_size: u16,
    window_width: u16,
    window_height: u16,
    window_x: u16,
    window_y: u16,
    unknown1: u32,
    unknown2: u32,
    font_size: u32,
    font_family_value: u32,
    font_weight: u32,
    face_name: String, //size is 64 bytes (Unicode string terminated by an end-of-string character)
    cursor_size: u32,
    full_screen: u32,
    insert_mode: u32,
    auto_positioning: u32,
    history_buff_size: u32,
    history_buff_count: u32,
    duplicates_allowed: u32,
    color_table: utils::ByteArray
}
impl ConsoleProperties {
    pub fn new<R: Read>(mut reader: R) -> Result<ConsoleProperties,LnkError> {
        let color_flags = reader.read_u16::<LittleEndian>()?;
        let popup_attribs = reader.read_u16::<LittleEndian>()?;
        let screen_width_buff_size = reader.read_u16::<LittleEndian>()?;
        let screen_height_buff_size = reader.read_u16::<LittleEndian>()?;
        let window_width = reader.read_u16::<LittleEndian>()?;
        let window_height = reader.read_u16::<LittleEndian>()?;
        let window_x = reader.read_u16::<LittleEndian>()?;
        let window_y = reader.read_u16::<LittleEndian>()?;
        let unknown1 = reader.read_u32::<LittleEndian>()?;
        let unknown2 = reader.read_u32::<LittleEndian>()?;
        let font_size = reader.read_u32::<LittleEndian>()?;
        let font_family_value = reader.read_u32::<LittleEndian>()?;
        let font_weight = reader.read_u32::<LittleEndian>()?;

        // Read string
        let mut face_buff = vec![0; 64];
        reader.read_exact(face_buff.as_mut_slice())?;
        let face_name = utils::read_string_u16_till_null(face_buff.as_slice())?;

        let cursor_size = reader.read_u32::<LittleEndian>()?;
        let full_screen = reader.read_u32::<LittleEndian>()?;
        let insert_mode = reader.read_u32::<LittleEndian>()?;
        let auto_positioning = reader.read_u32::<LittleEndian>()?;
        let history_buff_size = reader.read_u32::<LittleEndian>()?;
        let history_buff_count = reader.read_u32::<LittleEndian>()?;
        let duplicates_allowed = reader.read_u32::<LittleEndian>()?;

        let mut color_buff = vec![0; 64];
        reader.read_exact(color_buff.as_mut_slice())?;
        let color_table = utils::ByteArray(color_buff);

        Ok (
            ConsoleProperties {
                color_flags: color_flags,
                popup_attribs: popup_attribs,
                screen_width_buff_size: screen_width_buff_size,
                screen_height_buff_size: screen_height_buff_size,
                window_width: window_width,
                window_height: window_height,
                window_x: window_x,
                window_y: window_y,
                unknown1: unknown1,
                unknown2: unknown2,
                font_size: font_size,
                font_family_value: font_family_value,
                font_weight: font_weight,
                face_name: face_name,
                cursor_size: cursor_size,
                full_screen: full_screen,
                insert_mode: insert_mode,
                auto_positioning: auto_positioning,
                history_buff_size: history_buff_size,
                history_buff_count: history_buff_count,
                duplicates_allowed: duplicates_allowed,
                color_table: color_table
            }
        )
    }
}

#[derive(Debug)]
pub struct ExtraDataBlocks {
    pub console_properties: Option<ConsoleProperties>,
    pub environment_vars: Option<EnvironmentVars>,
    pub distributed_tracker: Option<DistributedTracker>,
    pub codepage: Option<Codepage>,
    pub special_folder: Option<SpecialFolder>
}
impl ExtraDataBlocks {
    pub fn new<Rs: Read+Seek>(mut reader: Rs) -> Result<ExtraDataBlocks,LnkError> {
        let mut console_properties = None;
        let mut environment_vars = None;
        let mut distributed_tracker = None;
        let mut codepage = None;
        let mut special_folder = None;

        let mut _offset = reader.seek(
            SeekFrom::Current(0)
        )?;

        loop {
            let size = reader.read_u32::<LittleEndian>()?;
            if size != 0 {
                let signature = reader.read_u32::<LittleEndian>()?;
                match signature {
                    0xa0000001 => {
                        environment_vars = Some(EnvironmentVars::new(&mut reader)?);
                    },
                    0xa0000002 => {
                        console_properties = Some(ConsoleProperties::new(&mut reader)?);
                    },
                    0xa0000003 => {
                        distributed_tracker = Some(DistributedTracker::new(&mut reader)?);
                    },
                    0xa0000004 => {
                        codepage = Some(Codepage::new(&mut reader)?);
                    },
                    0xa0000005 => {
                        special_folder = Some(SpecialFolder::new(&mut reader)?);
                    },
                    _ => {
                        println!(
                            "Unhandled data block with signature {} at offset {}",
                            signature,
                            _offset
                        );
                    }
                }

                _offset += size as u64;

                reader.seek(
                    SeekFrom::Start(_offset)
                )?;
            } else {
                break
            }
        }

        Ok(
            ExtraDataBlocks {
                console_properties: console_properties,
                environment_vars: environment_vars,
                distributed_tracker: distributed_tracker,
                codepage: codepage,
                special_folder: special_folder
            }
        )
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The vulkano developers
// 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. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use smallvec::SmallVec;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering;
use std::iter;

use buffer::BufferAccess;
use buffer::BufferUsage;
use buffer::CpuAccessibleBuffer;
use buffer::TypedBufferAccess;
use command_buffer::AutoCommandBuffer;
use command_buffer::AutoCommandBufferBuilder;
use command_buffer::CommandBuffer;
use command_buffer::CommandBufferExecFuture;
use device::Device;
use device::Queue;
use format::AcceptsPixels;
use format::FormatDesc;
use image::Dimensions;
use image::ImageInner;
use image::ImageLayout;
use image::ImageUsage;
use image::MipmapsCount;
use image::sys::ImageCreationError;
use image::sys::UnsafeImage;
use image::sys::UnsafeImageView;
use image::traits::ImageAccess;
use image::traits::ImageContent;
use image::traits::ImageViewAccess;
use instance::QueueFamily;
use memory::pool::AllocLayout;
use memory::pool::MemoryPool;
use memory::pool::MemoryPoolAlloc;
use memory::pool::StdMemoryPoolAlloc;
use sync::AccessError;
use sync::Sharing;
use sync::NowFuture;

/// Image whose purpose is to be used for read-only purposes. You can write to the image once,
/// but then you must only ever read from it.
// TODO: type (2D, 3D, array, etc.) as template parameter
#[derive(Debug)]
pub struct ImmutableImage<F, A = StdMemoryPoolAlloc> {
    image: UnsafeImage,
    view: UnsafeImageView,
    dimensions: Dimensions,
    memory: A,
    format: F,
    initialized: AtomicBool,
    layout: ImageLayout,
}

// Must not implement Clone, as that would lead to multiple `used` values.
pub struct ImmutableImageInitialization<F, A = StdMemoryPoolAlloc> {
    image: Arc<ImmutableImage<F, A>>,
    used: AtomicBool,
}

impl<F> ImmutableImage<F> {
    /// Builds an uninitialized immutable image.
    ///
    /// Returns two things: the image, and a special access that should be used for the initial upload to the image.
    pub fn uninitialized<'a, I, M>(device: Arc<Device>, dimensions: Dimensions, format: F,
                                   mipmaps: M, usage: ImageUsage, layout: ImageLayout, queue_families: I)
                                   -> Result<(Arc<ImmutableImage<F>>, ImmutableImageInitialization<F>), ImageCreationError>
        where F: FormatDesc,
              I: IntoIterator<Item = QueueFamily<'a>>,
              M: Into<MipmapsCount>
    {
        let queue_families = queue_families
            .into_iter()
            .map(|f| f.id())
            .collect::<SmallVec<[u32; 4]>>();

        let (image, mem_reqs) = unsafe {
            let sharing = if queue_families.len() >= 2 {
                Sharing::Concurrent(queue_families.iter().cloned())
            } else {
                Sharing::Exclusive
            };

            UnsafeImage::new(device.clone(),
                             usage,
                             format.format(),
                             dimensions.to_image_dimensions(),
                             1,
                             mipmaps,
                             sharing,
                             false,
                             false)?
        };

        let mem_ty = {
            let device_local = device
                .physical_device()
                .memory_types()
                .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0)
                .filter(|t| t.is_device_local());
            let any = device
                .physical_device()
                .memory_types()
                .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0);
            device_local.chain(any).next().unwrap()
        };

        let mem = MemoryPool::alloc(&Device::standard_pool(&device),
                                    mem_ty,
                                    mem_reqs.size,
                                    mem_reqs.alignment,
                                    AllocLayout::Optimal)?;
        debug_assert!((mem.offset() % mem_reqs.alignment) == 0);
        unsafe {
            image.bind_memory(mem.memory(), mem.offset())?;
        }

        let view = unsafe {
            UnsafeImageView::raw(&image,
                                 dimensions.to_view_type(),
                                 0 .. image.mipmap_levels(),
                                 0 .. image.dimensions().array_layers())?
        };

        let image = Arc::new(ImmutableImage {
            image: image,
            view: view,
            memory: mem,
            dimensions: dimensions,
            format: format,
            initialized: AtomicBool::new(false),
            layout: layout,
        });

        let init = ImmutableImageInitialization {
            image: image.clone(),
            used: AtomicBool::new(false),
        };

        Ok((image, init))
    }

    /// Construct an ImmutableImage from the contents of `iter`.
    ///
    /// TODO: Support mipmaps
    #[inline]
    pub fn from_iter<'a, P, I, J>(iter: I, dimensions: Dimensions, format: F, usage: ImageUsage, layout: ImageLayout,
                                  queue_families: J, queue: Arc<Queue>)
                                  -> Result<(Arc<Self>, CommandBufferExecFuture<NowFuture, AutoCommandBuffer>),
                                            ImageCreationError>
        where P: Send + Sync + Clone + 'static,
              F: FormatDesc + AcceptsPixels<P> + 'static + Send + Sync,
              I: ExactSizeIterator<Item = P>,
              J: IntoIterator<Item = QueueFamily<'a>>,
    {
        let source = CpuAccessibleBuffer::from_iter(queue.device().clone(),
                                                    BufferUsage::transfer_source(),
                                                    iter::once(queue.family()),
                                                    iter)?;
        ImmutableImage::from_buffer(source, dimensions, format, usage, layout, queue_families, queue)
    }

    /// Construct an ImmutableImage containing a copy of the data in `source`.
    ///
    /// TODO: Support mipmaps
    pub fn from_buffer<'a, B, P, I>(source: B, dimensions: Dimensions, format: F, usage: ImageUsage, layout: ImageLayout, queue_families: I, queue: Arc<Queue>)
                                    -> Result<(Arc<Self>, CommandBufferExecFuture<NowFuture, AutoCommandBuffer>),
                                              ImageCreationError>
        where B: BufferAccess + TypedBufferAccess<Content = [P]> + 'static + Clone + Send + Sync,
              P: Send + Sync + Clone + 'static,
              F: FormatDesc + AcceptsPixels<P> + 'static + Send + Sync,
              I: IntoIterator<Item = QueueFamily<'a>>,
    {
        let usage = ImageUsage { transfer_destination: true, ..usage }; // Ensure we can actually initialize the image
        // TODO: The following panics should be removed in favor of propagating errors from copy_buffer_to_image.
        format.ensure_accepts().unwrap();
        if source.len() % format.rate() as usize != 0 {
            panic!("cannot divide {} datums into an image with {} channels", source.len(), format.rate());
        }
        if dimensions.num_texels() as usize * format.rate() as usize != source.len() {
            panic!("image with {} texels cannot be initialized with {}", dimensions.num_texels(), source.len() / format.rate() as usize);
        }

        let (buffer, init) = ImmutableImage::uninitialized(source.device().clone(),
                                                           dimensions, format,
                                                           MipmapsCount::One, usage, layout,
                                                           queue_families)?;

        let cb = AutoCommandBufferBuilder::new(source.device().clone(), queue.family())?
            .copy_buffer_to_image_dimensions(source, init, [0, 0, 0], dimensions.width_height_depth(), 0, dimensions.array_layers_with_cube(), 0).unwrap()
            .build().unwrap();

        let future = match cb.execute(queue) {
            Ok(f) => f,
            Err(_) => unreachable!(),
        };

        Ok((buffer, future))
    }
}

impl<F, A> ImmutableImage<F, A> {
    /// Returns the dimensions of the image.
    #[inline]
    pub fn dimensions(&self) -> Dimensions {
        self.dimensions
    }

    /// Returns the number of mipmap levels of the image.
    #[inline]
    pub fn mipmap_levels(&self) -> u32 {
        self.image.mipmap_levels()
    }
}

unsafe impl<F, A> ImageAccess for ImmutableImage<F, A>
    where F: 'static + Send + Sync,
{
    #[inline]
    fn inner(&self) -> ImageInner {
        ImageInner {
            image: &self.image,
            first_layer: 0,
            num_layers: self.image.dimensions().array_layers() as usize,
            first_mipmap_level: 0,
            num_mipmap_levels: self.image.mipmap_levels() as usize,
        }
    }

    #[inline]
    fn initial_layout_requirement(&self) -> ImageLayout {
        self.layout
    }

    #[inline]
    fn final_layout_requirement(&self) -> ImageLayout {
        self.layout
    }

    #[inline]
    fn conflict_key(&self, _: u32, _: u32, _: u32, _: u32) -> u64 {
        self.image.key()
    }

    #[inline]
    fn try_gpu_lock(&self, exclusive_access: bool, queue: &Queue) -> Result<(), AccessError> {
        if exclusive_access {
            return Err(AccessError::ExclusiveDenied);
        }

        if !self.initialized.load(Ordering::Relaxed) {
            return Err(AccessError::BufferNotInitialized);
        }

        Ok(())
    }

    #[inline]
    unsafe fn increase_gpu_lock(&self) {}

    #[inline]
    unsafe fn unlock(&self) {}
}

unsafe impl<P, F, A> ImageContent<P> for ImmutableImage<F, A>
    where F: 'static + Send + Sync,
{
    #[inline]
    fn matches_format(&self) -> bool {
        true // FIXME:
    }
}

unsafe impl<F: 'static, A> ImageViewAccess for ImmutableImage<F, A>
    where F: 'static + Send + Sync,
{
    #[inline]
    fn parent(&self) -> &ImageAccess {
        self
    }

    #[inline]
    fn dimensions(&self) -> Dimensions {
        self.dimensions
    }

    #[inline]
    fn inner(&self) -> &UnsafeImageView {
        &self.view
    }

    #[inline]
    fn descriptor_set_storage_image_layout(&self) -> ImageLayout {
        self.layout
    }

    #[inline]
    fn descriptor_set_combined_image_sampler_layout(&self) -> ImageLayout {
        self.layout
    }

    #[inline]
    fn descriptor_set_sampled_image_layout(&self) -> ImageLayout {
        self.layout
    }

    #[inline]
    fn descriptor_set_input_attachment_layout(&self) -> ImageLayout {
        self.layout
    }

    #[inline]
    fn identity_swizzle(&self) -> bool {
        true
    }
}

unsafe impl<F, A> ImageAccess for ImmutableImageInitialization<F, A>
    where F: 'static + Send + Sync,
{
    #[inline]
    fn inner(&self) -> ImageInner {
        ImageAccess::inner(&self.image)
    }

    #[inline]
    fn initial_layout_requirement(&self) -> ImageLayout {
        ImageLayout::Undefined
    }

    #[inline]
    fn final_layout_requirement(&self) -> ImageLayout {
        self.image.layout
    }

    #[inline]
    fn conflict_key(&self, _: u32, _: u32, _: u32, _: u32) -> u64 {
        self.image.image.key()
    }

    #[inline]
    fn try_gpu_lock(&self, exclusive_access: bool, queue: &Queue) -> Result<(), AccessError> {
        if self.image.initialized.load(Ordering::Relaxed) {
            return Err(AccessError::AlreadyInUse);
        }

        // FIXME: Mipmapped textures require multiple writes to initialize
        if !self.used.compare_and_swap(false, true, Ordering::Relaxed) {
            Ok(())
        } else {
            Err(AccessError::AlreadyInUse)
        }
    }

    #[inline]
    unsafe fn increase_gpu_lock(&self) {
        debug_assert!(self.used.load(Ordering::Relaxed));
    }

    #[inline]
    unsafe fn unlock(&self) {
        self.image.initialized.store(true, Ordering::Relaxed);
    }
}
<commit_msg>Restore deprecated ImmutableImage constructors<commit_after>// Copyright (c) 2016 The vulkano developers
// 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. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use smallvec::SmallVec;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering;
use std::iter;

use buffer::BufferAccess;
use buffer::BufferUsage;
use buffer::CpuAccessibleBuffer;
use buffer::TypedBufferAccess;
use command_buffer::AutoCommandBuffer;
use command_buffer::AutoCommandBufferBuilder;
use command_buffer::CommandBuffer;
use command_buffer::CommandBufferExecFuture;
use device::Device;
use device::Queue;
use format::AcceptsPixels;
use format::FormatDesc;
use image::Dimensions;
use image::ImageInner;
use image::ImageLayout;
use image::ImageUsage;
use image::MipmapsCount;
use image::sys::ImageCreationError;
use image::sys::UnsafeImage;
use image::sys::UnsafeImageView;
use image::traits::ImageAccess;
use image::traits::ImageContent;
use image::traits::ImageViewAccess;
use instance::QueueFamily;
use memory::pool::AllocLayout;
use memory::pool::MemoryPool;
use memory::pool::MemoryPoolAlloc;
use memory::pool::StdMemoryPoolAlloc;
use sync::AccessError;
use sync::Sharing;
use sync::NowFuture;

/// Image whose purpose is to be used for read-only purposes. You can write to the image once,
/// but then you must only ever read from it.
// TODO: type (2D, 3D, array, etc.) as template parameter
#[derive(Debug)]
pub struct ImmutableImage<F, A = StdMemoryPoolAlloc> {
    image: UnsafeImage,
    view: UnsafeImageView,
    dimensions: Dimensions,
    memory: A,
    format: F,
    initialized: AtomicBool,
    layout: ImageLayout,
}

// Must not implement Clone, as that would lead to multiple `used` values.
pub struct ImmutableImageInitialization<F, A = StdMemoryPoolAlloc> {
    image: Arc<ImmutableImage<F, A>>,
    used: AtomicBool,
}

impl<F> ImmutableImage<F> {
    #[deprecated(note = "use ImmutableImage::uninitialized instead")]
    #[inline]
    pub fn new<'a, I>(device: Arc<Device>, dimensions: Dimensions, format: F, queue_families: I)
                      -> Result<Arc<ImmutableImage<F>>, ImageCreationError>
        where F: FormatDesc,
              I: IntoIterator<Item = QueueFamily<'a>>
    {
        #[allow(deprecated)]
        ImmutableImage::with_mipmaps(device,
                                     dimensions,
                                     format,
                                     MipmapsCount::One,
                                     queue_families)
    }

    #[deprecated(note = "use ImmutableImage::uninitialized instead")]
    #[inline]
    pub fn with_mipmaps<'a, I, M>(device: Arc<Device>, dimensions: Dimensions, format: F,
                                  mipmaps: M, queue_families: I)
                                  -> Result<Arc<ImmutableImage<F>>, ImageCreationError>
         where F: FormatDesc,
               I: IntoIterator<Item = QueueFamily<'a>>,
               M: Into<MipmapsCount>
    {
        let usage = ImageUsage {
            transfer_source: true, // for blits
            transfer_destination: true,
            sampled: true,
            ..ImageUsage::none()
        };

        let (image, _) = ImmutableImage::uninitialized(device, dimensions, format, mipmaps, usage, ImageLayout::ShaderReadOnlyOptimal, queue_families)?;
        image.initialized.store(true, Ordering::Relaxed); // Allow uninitialized access for backwards compatibility
        Ok(image)
    }

    /// Builds an uninitialized immutable image.
    ///
    /// Returns two things: the image, and a special access that should be used for the initial upload to the image.
    pub fn uninitialized<'a, I, M>(device: Arc<Device>, dimensions: Dimensions, format: F,
                                   mipmaps: M, usage: ImageUsage, layout: ImageLayout, queue_families: I)
                                   -> Result<(Arc<ImmutableImage<F>>, ImmutableImageInitialization<F>), ImageCreationError>
        where F: FormatDesc,
              I: IntoIterator<Item = QueueFamily<'a>>,
              M: Into<MipmapsCount>
    {
        let queue_families = queue_families
            .into_iter()
            .map(|f| f.id())
            .collect::<SmallVec<[u32; 4]>>();

        let (image, mem_reqs) = unsafe {
            let sharing = if queue_families.len() >= 2 {
                Sharing::Concurrent(queue_families.iter().cloned())
            } else {
                Sharing::Exclusive
            };

            UnsafeImage::new(device.clone(),
                             usage,
                             format.format(),
                             dimensions.to_image_dimensions(),
                             1,
                             mipmaps,
                             sharing,
                             false,
                             false)?
        };

        let mem_ty = {
            let device_local = device
                .physical_device()
                .memory_types()
                .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0)
                .filter(|t| t.is_device_local());
            let any = device
                .physical_device()
                .memory_types()
                .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0);
            device_local.chain(any).next().unwrap()
        };

        let mem = MemoryPool::alloc(&Device::standard_pool(&device),
                                    mem_ty,
                                    mem_reqs.size,
                                    mem_reqs.alignment,
                                    AllocLayout::Optimal)?;
        debug_assert!((mem.offset() % mem_reqs.alignment) == 0);
        unsafe {
            image.bind_memory(mem.memory(), mem.offset())?;
        }

        let view = unsafe {
            UnsafeImageView::raw(&image,
                                 dimensions.to_view_type(),
                                 0 .. image.mipmap_levels(),
                                 0 .. image.dimensions().array_layers())?
        };

        let image = Arc::new(ImmutableImage {
            image: image,
            view: view,
            memory: mem,
            dimensions: dimensions,
            format: format,
            initialized: AtomicBool::new(false),
            layout: layout,
        });

        let init = ImmutableImageInitialization {
            image: image.clone(),
            used: AtomicBool::new(false),
        };

        Ok((image, init))
    }

    /// Construct an ImmutableImage from the contents of `iter`.
    ///
    /// TODO: Support mipmaps
    #[inline]
    pub fn from_iter<'a, P, I, J>(iter: I, dimensions: Dimensions, format: F, usage: ImageUsage, layout: ImageLayout,
                                  queue_families: J, queue: Arc<Queue>)
                                  -> Result<(Arc<Self>, CommandBufferExecFuture<NowFuture, AutoCommandBuffer>),
                                            ImageCreationError>
        where P: Send + Sync + Clone + 'static,
              F: FormatDesc + AcceptsPixels<P> + 'static + Send + Sync,
              I: ExactSizeIterator<Item = P>,
              J: IntoIterator<Item = QueueFamily<'a>>,
    {
        let source = CpuAccessibleBuffer::from_iter(queue.device().clone(),
                                                    BufferUsage::transfer_source(),
                                                    iter::once(queue.family()),
                                                    iter)?;
        ImmutableImage::from_buffer(source, dimensions, format, usage, layout, queue_families, queue)
    }

    /// Construct an ImmutableImage containing a copy of the data in `source`.
    ///
    /// TODO: Support mipmaps
    pub fn from_buffer<'a, B, P, I>(source: B, dimensions: Dimensions, format: F, usage: ImageUsage, layout: ImageLayout, queue_families: I, queue: Arc<Queue>)
                                    -> Result<(Arc<Self>, CommandBufferExecFuture<NowFuture, AutoCommandBuffer>),
                                              ImageCreationError>
        where B: BufferAccess + TypedBufferAccess<Content = [P]> + 'static + Clone + Send + Sync,
              P: Send + Sync + Clone + 'static,
              F: FormatDesc + AcceptsPixels<P> + 'static + Send + Sync,
              I: IntoIterator<Item = QueueFamily<'a>>,
    {
        let usage = ImageUsage { transfer_destination: true, ..usage }; // Ensure we can actually initialize the image
        // TODO: The following panics should be removed in favor of propagating errors from copy_buffer_to_image.
        format.ensure_accepts().unwrap();
        if source.len() % format.rate() as usize != 0 {
            panic!("cannot divide {} datums into an image with {} channels", source.len(), format.rate());
        }
        if dimensions.num_texels() as usize * format.rate() as usize != source.len() {
            panic!("image with {} texels cannot be initialized with {}", dimensions.num_texels(), source.len() / format.rate() as usize);
        }

        let (buffer, init) = ImmutableImage::uninitialized(source.device().clone(),
                                                           dimensions, format,
                                                           MipmapsCount::One, usage, layout,
                                                           queue_families)?;

        let cb = AutoCommandBufferBuilder::new(source.device().clone(), queue.family())?
            .copy_buffer_to_image_dimensions(source, init, [0, 0, 0], dimensions.width_height_depth(), 0, dimensions.array_layers_with_cube(), 0).unwrap()
            .build().unwrap();

        let future = match cb.execute(queue) {
            Ok(f) => f,
            Err(_) => unreachable!(),
        };

        Ok((buffer, future))
    }
}

impl<F, A> ImmutableImage<F, A> {
    /// Returns the dimensions of the image.
    #[inline]
    pub fn dimensions(&self) -> Dimensions {
        self.dimensions
    }

    /// Returns the number of mipmap levels of the image.
    #[inline]
    pub fn mipmap_levels(&self) -> u32 {
        self.image.mipmap_levels()
    }
}

unsafe impl<F, A> ImageAccess for ImmutableImage<F, A>
    where F: 'static + Send + Sync,
{
    #[inline]
    fn inner(&self) -> ImageInner {
        ImageInner {
            image: &self.image,
            first_layer: 0,
            num_layers: self.image.dimensions().array_layers() as usize,
            first_mipmap_level: 0,
            num_mipmap_levels: self.image.mipmap_levels() as usize,
        }
    }

    #[inline]
    fn initial_layout_requirement(&self) -> ImageLayout {
        self.layout
    }

    #[inline]
    fn final_layout_requirement(&self) -> ImageLayout {
        self.layout
    }

    #[inline]
    fn conflict_key(&self, _: u32, _: u32, _: u32, _: u32) -> u64 {
        self.image.key()
    }

    #[inline]
    fn try_gpu_lock(&self, exclusive_access: bool, queue: &Queue) -> Result<(), AccessError> {
        if exclusive_access {
            return Err(AccessError::ExclusiveDenied);
        }

        if !self.initialized.load(Ordering::Relaxed) {
            return Err(AccessError::BufferNotInitialized);
        }

        Ok(())
    }

    #[inline]
    unsafe fn increase_gpu_lock(&self) {}

    #[inline]
    unsafe fn unlock(&self) {}
}

unsafe impl<P, F, A> ImageContent<P> for ImmutableImage<F, A>
    where F: 'static + Send + Sync,
{
    #[inline]
    fn matches_format(&self) -> bool {
        true // FIXME:
    }
}

unsafe impl<F: 'static, A> ImageViewAccess for ImmutableImage<F, A>
    where F: 'static + Send + Sync,
{
    #[inline]
    fn parent(&self) -> &ImageAccess {
        self
    }

    #[inline]
    fn dimensions(&self) -> Dimensions {
        self.dimensions
    }

    #[inline]
    fn inner(&self) -> &UnsafeImageView {
        &self.view
    }

    #[inline]
    fn descriptor_set_storage_image_layout(&self) -> ImageLayout {
        self.layout
    }

    #[inline]
    fn descriptor_set_combined_image_sampler_layout(&self) -> ImageLayout {
        self.layout
    }

    #[inline]
    fn descriptor_set_sampled_image_layout(&self) -> ImageLayout {
        self.layout
    }

    #[inline]
    fn descriptor_set_input_attachment_layout(&self) -> ImageLayout {
        self.layout
    }

    #[inline]
    fn identity_swizzle(&self) -> bool {
        true
    }
}

unsafe impl<F, A> ImageAccess for ImmutableImageInitialization<F, A>
    where F: 'static + Send + Sync,
{
    #[inline]
    fn inner(&self) -> ImageInner {
        ImageAccess::inner(&self.image)
    }

    #[inline]
    fn initial_layout_requirement(&self) -> ImageLayout {
        ImageLayout::Undefined
    }

    #[inline]
    fn final_layout_requirement(&self) -> ImageLayout {
        self.image.layout
    }

    #[inline]
    fn conflict_key(&self, _: u32, _: u32, _: u32, _: u32) -> u64 {
        self.image.image.key()
    }

    #[inline]
    fn try_gpu_lock(&self, exclusive_access: bool, queue: &Queue) -> Result<(), AccessError> {
        if self.image.initialized.load(Ordering::Relaxed) {
            return Err(AccessError::AlreadyInUse);
        }

        // FIXME: Mipmapped textures require multiple writes to initialize
        if !self.used.compare_and_swap(false, true, Ordering::Relaxed) {
            Ok(())
        } else {
            Err(AccessError::AlreadyInUse)
        }
    }

    #[inline]
    unsafe fn increase_gpu_lock(&self) {
        debug_assert!(self.used.load(Ordering::Relaxed));
    }

    #[inline]
    unsafe fn unlock(&self) {
        self.image.initialized.store(true, Ordering::Relaxed);
    }
}
<|endoftext|>


<commit_before>extern crate racer;
extern crate racer_testutils;

use racer_testutils::*;

#[test]
fn completes_pub_fn_from_local_package() {
    let src = "
    extern crate fixtures;

    use fixtures::foo;

    fn main() {
        let x = foo::~
    }
    ";

    with_test_project(|dir| {
        let srcdir = dir.nested_dir("src");
        let got = get_one_completion(src, Some(srcdir));
        assert_eq!("test", got.matchstr);
    })
}

#[test]
fn completes_pub_fn_from_local_submodule_package() {
    let src = "
    extern crate fixtures;

    use fixtures::bar;

    fn main() {
        let x = bar::~
    }
    ";

    with_test_project(|dir| {
        let srcdir = dir.nested_dir("src");
        let got = get_one_completion(src, Some(srcdir));
        assert_eq!("bartest", got.matchstr);
    })
}

#[test]
fn follows_use_local_package() {
    let src = "
    extern crate fixtures;

    use fixtures::~
    ";

    with_test_project(|dir| {
        let srcdir = dir.nested_dir("src");
        let got = get_all_completions(src, Some(srcdir));
        assert!(got.into_iter().any(|ma| ma.matchstr == "foo"));
    })
}

#[test]
fn finds_extern_crate() {
    let src = "
    extern crate fixtures;
    f~ixtures
    ";

    with_test_project(|dir| {
        let srcdir = dir.nested_dir("src");
        let got = get_definition(src, Some(srcdir));
        assert_eq!(got.matchstr, "fixtures");
    })
}

// regression test for #800
#[test]
fn completes_typedef_in_external_crate() {
    let src = "
    extern crate fixtures;

    use fixtures::Usize~
    ";

    with_test_project(|dir| {
        let srcdir = dir.nested_dir("src");
        let got = get_only_completion(src, Some(srcdir));
        assert_eq!(got.matchstr, "UsizeVec");
        assert_eq!(got.contextstr, "pub type UsizeVec = Vec<usize>;");
    })
}

#[test]
fn follows_external_re_export() {
    let src = "
    extern crate rayon;
    fn main() {
        rayon::sco~
    }
    ";
    with_test_project(|dir| {
        let src_dir = dir.nested_dir("test-crate3").nested_dir("src");
        let got = get_only_completion(src, Some(src_dir));
        assert_eq!(got.matchstr, "scope");
    });
}

#[test]
fn follows_rand_crate() {
    let src = "
    extern crate rand;
    use rand::{Rng, thread_rng};
    fn main() {
        let mut rng: Box<Rng> = Box::new(thread_rng());
        rng.gen_rang~
    }
    ";
    with_test_project(|dir| {
        let src_dir = dir.nested_dir("test-crate3").nested_dir("src");
        let got = get_only_completion(src, Some(src_dir));
        assert_eq!(got.matchstr, "gen_range");
    });
}

// For issue 826
#[test]
fn find_crate_doc() {
    let src = "
    extern crate fixtures;
    use fixtur~
    ";
    let doc_str = r#"This is a test project for racer.

# Example:
Basic Usage.

```
extern crate fixtures;
use fixtures::foo;
fn main {
    println!("Racer")
}
```

## Notes:
- We should check racer can parse rust doc style comments
- and some comments..."#;
    with_test_project(|dir| {
        let srcdir = dir.nested_dir("src");
        let got = get_one_completion(src, Some(srcdir));
        assert_eq!(doc_str, got.docs);
    })
}

// test for re-export
#[test]
fn follows_use_for_reexport() {
    let src = "
    extern crate fixtures;

    use fixtures::use~;
    ";
    with_test_project(|dir| {
        let srcdir = dir.nested_dir("src");
        let got = get_only_completion(src, Some(srcdir));
        assert_eq!(got.matchstr, "useless_func");
    })
}

#[test]
fn completes_cratename_without_extern() {
    let src = "
    fn main() {
        rayon::sco~
    }
    ";
    with_test_project(|dir| {
        let src_dir = dir.nested_dir("test-crate4").nested_dir("src");
        let got = get_only_completion(src, Some(src_dir));
        assert_eq!(got.matchstr, "scope");
    });
}
<commit_msg>Add a test for edition checking<commit_after>extern crate racer;
extern crate racer_testutils;

use racer_testutils::*;

#[test]
fn completes_pub_fn_from_local_package() {
    let src = "
    extern crate fixtures;

    use fixtures::foo;

    fn main() {
        let x = foo::~
    }
    ";

    with_test_project(|dir| {
        let srcdir = dir.nested_dir("src");
        let got = get_one_completion(src, Some(srcdir));
        assert_eq!("test", got.matchstr);
    })
}

#[test]
fn completes_pub_fn_from_local_submodule_package() {
    let src = "
    extern crate fixtures;

    use fixtures::bar;

    fn main() {
        let x = bar::~
    }
    ";

    with_test_project(|dir| {
        let srcdir = dir.nested_dir("src");
        let got = get_one_completion(src, Some(srcdir));
        assert_eq!("bartest", got.matchstr);
    })
}

#[test]
fn follows_use_local_package() {
    let src = "
    extern crate fixtures;

    use fixtures::~
    ";

    with_test_project(|dir| {
        let srcdir = dir.nested_dir("src");
        let got = get_all_completions(src, Some(srcdir));
        assert!(got.into_iter().any(|ma| ma.matchstr == "foo"));
    })
}

#[test]
fn finds_extern_crate() {
    let src = "
    extern crate fixtures;
    f~ixtures
    ";

    with_test_project(|dir| {
        let srcdir = dir.nested_dir("src");
        let got = get_definition(src, Some(srcdir));
        assert_eq!(got.matchstr, "fixtures");
    })
}

// regression test for #800
#[test]
fn completes_typedef_in_external_crate() {
    let src = "
    extern crate fixtures;

    use fixtures::Usize~
    ";

    with_test_project(|dir| {
        let srcdir = dir.nested_dir("src");
        let got = get_only_completion(src, Some(srcdir));
        assert_eq!(got.matchstr, "UsizeVec");
        assert_eq!(got.contextstr, "pub type UsizeVec = Vec<usize>;");
    })
}

#[test]
fn follows_external_re_export() {
    let src = "
    extern crate rayon;
    fn main() {
        rayon::sco~
    }
    ";
    with_test_project(|dir| {
        let src_dir = dir.nested_dir("test-crate3").nested_dir("src");
        let got = get_only_completion(src, Some(src_dir));
        assert_eq!(got.matchstr, "scope");
    });
}

#[test]
fn follows_rand_crate() {
    let src = "
    extern crate rand;
    use rand::{Rng, thread_rng};
    fn main() {
        let mut rng: Box<Rng> = Box::new(thread_rng());
        rng.gen_rang~
    }
    ";
    with_test_project(|dir| {
        let src_dir = dir.nested_dir("test-crate3").nested_dir("src");
        let got = get_only_completion(src, Some(src_dir));
        assert_eq!(got.matchstr, "gen_range");
    });
}

// For issue 826
#[test]
fn find_crate_doc() {
    let src = "
    extern crate fixtures;
    use fixtur~
    ";
    let doc_str = r#"This is a test project for racer.

# Example:
Basic Usage.

```
extern crate fixtures;
use fixtures::foo;
fn main {
    println!("Racer")
}
```

## Notes:
- We should check racer can parse rust doc style comments
- and some comments..."#;
    with_test_project(|dir| {
        let srcdir = dir.nested_dir("src");
        let got = get_one_completion(src, Some(srcdir));
        assert_eq!(doc_str, got.docs);
    })
}

// test for re-export
#[test]
fn follows_use_for_reexport() {
    let src = "
    extern crate fixtures;

    use fixtures::use~;
    ";
    with_test_project(|dir| {
        let srcdir = dir.nested_dir("src");
        let got = get_only_completion(src, Some(srcdir));
        assert_eq!(got.matchstr, "useless_func");
    })
}

#[test]
fn completes_cratename_without_extern() {
    let src = "
    fn main() {
        rayon::sco~
    }
    ";
    with_test_project(|dir| {
        let src_dir = dir.nested_dir("test-crate4").nested_dir("src");
        let got = get_only_completion(src, Some(src_dir));
        assert_eq!(got.matchstr, "scope");
    });
}

#[test]
fn doesnt_complete_cratename_without_extern_in_2015() {
    let src = "
    fn main() {
        rayon::sco~
    }
    ";
    with_test_project(|dir| {
        let src_dir = dir.nested_dir("test-crate3").nested_dir("src");
        let got = get_all_completions(src, Some(src_dir));
        assert!(got.is_empty());
    });
}
<|endoftext|>


<commit_before>use rustc_serialize::json;

use std::path::{ Path, PathBuf };

use backend::download;
use package;

fn update_list<F>(url: &str, path: &Path, and: F) -> Result<bool, String>
    where F: Fn(u64) {
    let mut download_to = PathBuf::new();
        download_to.push(path);
        download_to.push(match url.split('/').last(){
            Some(x) => x,
            None => return Err("An error occured while getting package list filename.".to_string())
        });

    try!(download::download_file_and(url, path, and));
    Ok(true) // TODO: Return false if the package list is not updated.
}<commit_msg>Full function for update_list() implemented<commit_after>use rustc_serialize::json;

use std::error::Error;
use std::ffi::OsStr;
use std::fs;
use std::path::{ Path, PathBuf };

use backend::{ download, verify };
use package;

fn update_list<F>(url: &str, path: &Path, and: F) -> Result<bool, String>
    where F: Fn(u64) {
    let mut download_to = PathBuf::new();
        download_to.push(path);
        download_to.push(get_option!(url.split('/').last(), "An error occured while getting package list filename."));

    if download_to.exists() {
        let mut temporary_download_to = PathBuf::new();
            temporary_download_to.push(download_to.as_path());
            temporary_download_to.set_extension(".tmp");
        try!(download::download_file_and(url, temporary_download_to.as_path(), and));

        if try!(verify::verify_file_crc32(download_to.as_path())) == try!(verify::verify_file_crc32(temporary_download_to.as_path())) {
            get!(fs::remove_file(temporary_download_to.as_path()), "An error occured while removing unneeded package list.");
            Ok(false)
        } else {
            get!(fs::remove_file(download_to.as_path()), "An error occured while removing unneeded package list.");
            get!(fs::rename(temporary_download_to.as_path(), download_to.as_path()), "An error occured while renaming package list.");
            Ok(true)
        }
    // Indeed, this function is a giant clusterfuck. Apologies for code-gore.
    } else {
        try!(download::download_file_and(url, download_to.as_path(), and));
        Ok(true)
    }
}<|endoftext|>


<commit_before><commit_msg>Implement many1 combinator<commit_after><|endoftext|>


<commit_before>use super::control_register::IncrementAmount;
use errors::*;
use ppu::write_latch::LatchState;
use rom::NesRom;
use std::cell::Cell;

#[cfg(test)]
mod spec_tests;

pub trait Vram {
    fn new(rom: NesRom) -> Self;
    fn write_ppu_addr(&self, latch_state: LatchState);
    fn write_ppu_data(&mut self, val: u8, inc_amount: IncrementAmount) -> Result<()>;
    fn read_ppu_data(&self, inc_amount: IncrementAmount) -> Result<u8>;
    fn ppu_data(&self) -> Result<u8>;
    fn read(&self, addr: u16) -> Result<u8>;
}

pub struct VramBase {
    address: Cell<u16>,
    name_tables: [u8; 0x1000],
    palette: [u8; 0x20],
    rom: NesRom, // TODO: mapper
}

impl Vram for VramBase {
    fn new(rom: NesRom) -> Self {
        VramBase {
            address: Cell::new(0),
            name_tables: [0; 0x1000],
            palette: [0; 0x20],
            rom: rom,
        }
    }

    fn write_ppu_addr(&self, latch_state: LatchState) {
        // Addresses greater than 0x3fff are mirrored down
        match latch_state {
            LatchState::FirstWrite(val) => {
                let addr = self.address.get();
                self.address.set((addr & 0x80ff) | ((val as u16) & 0x3f) << 8);
            }
            LatchState::SecondWrite(val) => {
                let addr = self.address.get();
                let addr = (addr & 0xff00) | val as u16;
                self.address.set(addr);
            }
        }
    }

    fn read_ppu_data(&self, inc_amount: IncrementAmount) -> Result<u8> {
        let val = self.ppu_data()?;
        match inc_amount {
            IncrementAmount::One => self.address.set(self.address.get() + 1),
            IncrementAmount::ThirtyTwo => self.address.set(self.address.get() + 32),
        }
        Ok(val)
    }

    fn ppu_data(&self) -> Result<u8> {
        let addr = self.address.get();
        self.read(addr)
    }

    fn write_ppu_data(&mut self, val: u8, inc_amount: IncrementAmount) -> Result<()> {
        let addr = self.address.get();

        if addr < 0x2000 {
            self.rom.chr[addr as usize] = val;
        } else if addr < 0x3f00 {
            self.name_tables[addr as usize & 0x0fff] = val;
        } else if addr < 0x4000 {
            let addr = addr as usize & 0x1f;
            // Certain sprite addresses are mirrored back into background addresses
            let addr = match addr & 0xf {
                0x0 => 0x0,
                0x4 => 0x4,
                0x8 => 0x8,
                0xc => 0xc,
                _ => addr,
            };
            self.palette[addr] = val;
        } else {
            let message = "Invalid write".to_owned();
            bail!(ErrorKind::Crash(CrashReason::InvalidVramAccess(message, addr)));
        }

        match inc_amount {
            IncrementAmount::One => self.address.set(self.address.get() + 1),
            IncrementAmount::ThirtyTwo => self.address.set(self.address.get() + 32),
        }
        Ok(())
    }

    fn read(&self, addr: u16) -> Result<u8> {
        let val = if addr < 0x2000 {
            self.rom.chr[addr as usize]
        } else if addr < 0x3f00 {
            self.name_tables[addr as usize & 0x0fff]
        } else if addr < 0x4000 {
            let addr = addr as usize & 0x1f;
            // Certain sprite addresses are mirrored back into background addresses
            let addr = match addr & 0xf {
                0x0 => 0x0,
                0x4 => 0x4,
                0x8 => 0x8,
                0xc => 0xc,
                _ => addr,
            };
            self.palette[addr]
        } else {
            let message = "Invalid read".to_owned();
            bail!(ErrorKind::Crash(CrashReason::InvalidVramAccess(message, addr)));
        };
        Ok(val)
    }
}
<commit_msg>Always inline vram read<commit_after>use super::control_register::IncrementAmount;
use errors::*;
use ppu::write_latch::LatchState;
use rom::NesRom;
use std::cell::Cell;

#[cfg(test)]
mod spec_tests;

pub trait Vram {
    fn new(rom: NesRom) -> Self;
    fn write_ppu_addr(&self, latch_state: LatchState);
    fn write_ppu_data(&mut self, val: u8, inc_amount: IncrementAmount) -> Result<()>;
    fn read_ppu_data(&self, inc_amount: IncrementAmount) -> Result<u8>;
    fn ppu_data(&self) -> Result<u8>;
    fn read(&self, addr: u16) -> Result<u8>;
}

pub struct VramBase {
    address: Cell<u16>,
    name_tables: [u8; 0x1000],
    palette: [u8; 0x20],
    rom: NesRom, // TODO: mapper
}

impl Vram for VramBase {
    fn new(rom: NesRom) -> Self {
        VramBase {
            address: Cell::new(0),
            name_tables: [0; 0x1000],
            palette: [0; 0x20],
            rom: rom,
        }
    }

    fn write_ppu_addr(&self, latch_state: LatchState) {
        // Addresses greater than 0x3fff are mirrored down
        match latch_state {
            LatchState::FirstWrite(val) => {
                let addr = self.address.get();
                self.address.set((addr & 0x80ff) | ((val as u16) & 0x3f) << 8);
            }
            LatchState::SecondWrite(val) => {
                let addr = self.address.get();
                let addr = (addr & 0xff00) | val as u16;
                self.address.set(addr);
            }
        }
    }

    fn read_ppu_data(&self, inc_amount: IncrementAmount) -> Result<u8> {
        let val = self.ppu_data()?;
        match inc_amount {
            IncrementAmount::One => self.address.set(self.address.get() + 1),
            IncrementAmount::ThirtyTwo => self.address.set(self.address.get() + 32),
        }
        Ok(val)
    }

    fn ppu_data(&self) -> Result<u8> {
        let addr = self.address.get();
        self.read(addr)
    }

    fn write_ppu_data(&mut self, val: u8, inc_amount: IncrementAmount) -> Result<()> {
        let addr = self.address.get();

        if addr < 0x2000 {
            self.rom.chr[addr as usize] = val;
        } else if addr < 0x3f00 {
            self.name_tables[addr as usize & 0x0fff] = val;
        } else if addr < 0x4000 {
            let addr = addr as usize & 0x1f;
            // Certain sprite addresses are mirrored back into background addresses
            let addr = match addr & 0xf {
                0x0 => 0x0,
                0x4 => 0x4,
                0x8 => 0x8,
                0xc => 0xc,
                _ => addr,
            };
            self.palette[addr] = val;
        } else {
            let message = "Invalid write".to_owned();
            bail!(ErrorKind::Crash(CrashReason::InvalidVramAccess(message, addr)));
        }

        match inc_amount {
            IncrementAmount::One => self.address.set(self.address.get() + 1),
            IncrementAmount::ThirtyTwo => self.address.set(self.address.get() + 32),
        }
        Ok(())
    }

    #[inline(always)]
    fn read(&self, addr: u16) -> Result<u8> {
        let val = if addr < 0x2000 {
            self.rom.chr[addr as usize]
        } else if addr < 0x3f00 {
            self.name_tables[addr as usize & 0x0fff]
        } else if addr < 0x4000 {
            let addr = addr as usize & 0x1f;
            // Certain sprite addresses are mirrored back into background addresses
            let addr = match addr & 0xf {
                0x0 => 0x0,
                0x4 => 0x4,
                0x8 => 0x8,
                0xc => 0xc,
                _ => addr,
            };
            self.palette[addr]
        } else {
            let message = "Invalid read".to_owned();
            bail!(ErrorKind::Crash(CrashReason::InvalidVramAccess(message, addr)));
        };
        Ok(val)
    }
}
<|endoftext|>


<commit_before>#[macro_export]
macro_rules! storage_value {
    ($name:ident {
        const SIZE = $body:expr;

        $($field_name:ident : $field_type:ty [$from:expr => $to:expr])*
    }) => (
        #[derive(Clone, PartialEq)]
        pub struct $name {
            raw: Vec<u8>
        }

        impl<'a> $crate::messages::Field<'a> for $name {
            fn read(buffer: &'a [u8], from: usize, to: usize) -> Self {
                let vec: Vec<u8> = $crate::messages::Field::read(buffer, from, to);
                $crate::storage::StorageValue::deserialize(vec)
            }

            fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize) {
                $crate::messages::Field::write(&self.raw, buffer, from, to);
            }

            fn field_size() -> usize {
                1
            }
        }

        impl $crate::storage::StorageValue for $name {
            fn serialize(self) -> Vec<u8> {
                self.raw
            }

            fn deserialize(v: Vec<u8>) -> Self {
                $name {
                    raw: v
                }
            }

            fn hash(&self) -> Hash {
                $name::hash(self)
            }
        }

        // TODO extract some fields like hash and from_raw into trait
        impl $name {
            pub fn new($($field_name: $field_type,)*) -> $name {
                use $crate::messages::{Field};
                let mut buf = vec![0; $body];
                $($field_name.write(&mut buf, $from, $to);)*
                $name { raw: buf }
            }

            pub fn from_raw(raw: Vec<u8>) -> $name {
                debug_assert_eq!(raw.len(), $body);
                $ name { raw: raw }
            }

            pub fn hash(&self) -> Hash {
                hash(self.raw.as_ref())
            }

            $(pub fn $field_name(&self) -> $field_type {
                use $crate::messages::Field;
                Field::read(&self.raw, $from, $to)
            })*
        }

        impl ::std::fmt::Debug for $name {
            fn fmt(&self, fmt: &mut ::std::fmt::Formatter)
                -> Result<(), ::std::fmt::Error> {
                fmt.debug_struct(stringify!($name))
                 $(.field(stringify!($field_name), &self.$field_name()))*
                   .finish()
            }
        }
    )
}
<commit_msg>Added checks for fields of storage_value!.<commit_after>#[macro_export]
macro_rules! storage_value {
    ($name:ident {
        const SIZE = $body:expr;

        $($field_name:ident : $field_type:ty [$from:expr => $to:expr])*
    }) => (
        #[derive(Clone, PartialEq)]
        pub struct $name {
            raw: Vec<u8>
        }

        impl<'a> $crate::messages::Field<'a> for $name {
            fn read(buffer: &'a [u8], from: usize, to: usize) -> Self {
                let vec: Vec<u8> = $crate::messages::Field::read(buffer, from, to);
                $crate::storage::StorageValue::deserialize(vec)
            }

            fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize) {
                $crate::messages::Field::write(&self.raw, buffer, from, to);
            }

            fn check(buffer: &'a [u8], from: usize, to: usize) -> Result<(), $crate::messages::Error> {

                let raw_message: $crate::messages::RawMessage = $crate::messages::Field::read(buffer, from, to);
                $(raw_message.check::<$field_type>($from, $to)?;)*
                Ok(())
            }

            fn field_size() -> usize {
                1
            }
        }

        impl $crate::storage::StorageValue for $name {
            fn serialize(self) -> Vec<u8> {
                self.raw
            }

            fn deserialize(v: Vec<u8>) -> Self {
                $name {
                    raw: v
                }
            }

            fn hash(&self) -> Hash {
                $name::hash(self)
            }
        }

        // TODO extract some fields like hash and from_raw into trait
        impl $name {
            pub fn new($($field_name: $field_type,)*) -> $name {
                use $crate::messages::{Field};
                let mut buf = vec![0; $body];
                $($field_name.write(&mut buf, $from, $to);)*
                $name { raw: buf }
            }

            pub fn from_raw(raw: Vec<u8>) -> $name {
                debug_assert_eq!(raw.len(), $body);
                $ name { raw: raw }
            }

            pub fn hash(&self) -> Hash {
                hash(self.raw.as_ref())
            }

            $(pub fn $field_name(&self) -> $field_type {
                use $crate::messages::Field;
                Field::read(&self.raw, $from, $to)
            })*
        }

        impl ::std::fmt::Debug for $name {
            fn fmt(&self, fmt: &mut ::std::fmt::Formatter)
                -> Result<(), ::std::fmt::Error> {
                fmt.debug_struct(stringify!($name))
                 $(.field(stringify!($field_name), &self.$field_name()))*
                   .finish()
            }
        }
    )
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::io::prelude::*;
use std::fs::{self, File};
use std::path::{Path, PathBuf};
use std::error::Error;
use std::rc::Rc;
use std::cell::RefCell;

use polygon::gl_render::{GLRender, GLMeshData, ShaderProgram};
use polygon::geometry::mesh::Mesh;

use wav::Wave;
use scene::Scene;
use ecs::Entity;
use component::{MeshManager, TransformManager};
use self::shader::*;

pub mod collada;
pub mod shader;

#[derive(Debug, Clone)]
pub struct ResourceManager {
    renderer: Rc<GLRender>,
    meshes: RefCell<HashMap<String, Mesh>>,
    gpu_meshes: RefCell<HashMap<String, GLMeshData>>,
    mesh_nodes: RefCell<HashMap<String, MeshNode>>,
    shaders: RefCell<HashMap<String, ShaderProgram>>,
    audio_clips: RefCell<HashMap<String, Rc<Wave>>>,

    resource_path: RefCell<PathBuf>,
}

impl ResourceManager {
    pub fn new(renderer: Rc<GLRender>) -> ResourceManager {
        ResourceManager {
            renderer: renderer,
            meshes: RefCell::new(HashMap::new()),
            gpu_meshes: RefCell::new(HashMap::new()),
            mesh_nodes: RefCell::new(HashMap::new()),
            shaders: RefCell::new(HashMap::new()),
            audio_clips: RefCell::new(HashMap::new()),

            resource_path: RefCell::new(PathBuf::new()),
        }
    }

    pub fn load_model<P: AsRef<Path>>(&self, path: P) -> Result<(), String> {

        let mut full_path = self.resource_path.borrow().clone();
        full_path.push(path);
        let metadata = match fs::metadata(&full_path) {
            Err(why) => return Err(format!(
                "Unable to read metadata for {}, either it doesn't exist or the user lacks permissions, {}",
                full_path.display(),
                &why)),
            Ok(metadata) => metadata,
        };

        if !metadata.is_file() {
            return Err(format!(
                "{} could not be loaded because it is not a file",
                full_path.display()));
        }

        collada::load_resources(full_path, self).unwrap(); // TODO: Don't panic?

        Ok(())
    }

    /// Sets the path to the resources directory.
    ///
    /// # Details
    ///
    /// The resource manager is configured to look in the specified directory when loading
    /// resources such as meshes and shaders.
    pub fn set_resource_path<P: AsRef<Path>>(&self, path: P) {
        let mut resource_path = self.resource_path.borrow_mut();
        *resource_path = PathBuf::new();
        resource_path.push(path);
    }

    pub fn get_gpu_mesh(&self, uri: &str) -> Option<GLMeshData> {
        // Use cached mesh data if possible.
        self.get_cached_mesh(uri)
        .or_else(|| {
            self.gen_gpu_mesh(uri)
        })
    }

    pub fn get_audio_clip(&self, path_text: &str) -> Rc<Wave> {
        let mut audio_clips = self.audio_clips.borrow_mut();

        if !audio_clips.contains_key(path_text) {
            let wave = Wave::from_file(path_text).unwrap();
            audio_clips.insert(path_text.into(), Rc::new(wave));
        }

        audio_clips.get(path_text).unwrap().clone()
    }

    pub fn instantiate_model(&self, resource: &str, scene: &Scene) -> Result<Entity, String> {
        if resource.contains(".") {
            println!("WARNING: ResourceManager::instantiate_model() doesn't yet support fully qualified URIs, only root assets may be instantiated.");
            unimplemented!();
        }

        let mesh_nodes = self.mesh_nodes.borrow();
        let root = try!(
            mesh_nodes
            .get(resource)
            .ok_or_else(|| format!("No mesh node is identified by the uri {}", resource)));

        self.instantiate_node(scene, root)
    }

    fn instantiate_node(&self, scene: &Scene, node: &MeshNode) -> Result<Entity, String> {
        let entity = scene.create_entity();
        {
            let mut transform_manager = scene.get_manager_mut::<TransformManager>();
            transform_manager.assign(entity);

            for mesh_id in &node.mesh_ids {
                let gpu_mesh = match self.get_gpu_mesh(&*mesh_id) {
                    Some(gpu_mesh) => gpu_mesh,
                    None => {
                        println!("WARNING: Unable to load gpu mesh for uri {}", mesh_id);
                        continue;
                    }
                };
                scene.get_manager_mut::<MeshManager>()
                    .give_mesh(entity, gpu_mesh);
            }
        }
        // TODO: Apply the node's transform to the entity transform.

        // Instantiate each of the children and set the current node as their parent.
        for node in &node.children {
            let child = try!(self.instantiate_node(scene, node));

            let mut transform_manager = scene.get_manager_mut::<TransformManager>();
            transform_manager.set_child(entity, child);
        }

        Ok(entity)
    }

    pub fn get_shader<P: AsRef<Path> + ::std::fmt::Debug>(
        &self,
        shader_path: P
    ) -> Result<ShaderProgram, ParseShaderError> {
        {
            let path_str = shader_path.as_ref().to_str().expect(&*format!(
                "shader path {:?} contains invalid unicode characters",
                shader_path));
            if let Some(shader) = self.shaders.borrow().get(path_str) {
                return Ok(shader.clone());
            }
        }

        // This should be an else block on the above if block, but that doesn't work until MIR has
        // dropped, so for now we have to settle for manual case analysis.
        {
            let path_string: String = shader_path.as_ref()
                .to_str()
                .expect(&*format!(
                    "shader path {:?} contains invalid unicode characters",
                    shader_path))
                .into();

            let mut full_path = self.resource_path.borrow().clone();
            full_path.push(shader_path);
            let program_src = load_file_text(full_path);

            let programs = try!(ShaderParser::parse(&*program_src));
            let vert_src = match programs.iter().find(|program| program.name == "vert") {
                None => return Err(ParseShaderError::NoVertProgram),
                Some(program) => program.src,
            };

            let frag_src = match programs.iter().find(|program| program.name == "frag") {
                None => return Err(ParseShaderError::NoFragProgram),
                Some(program) => program.src,
            };

            let shader = self.renderer.compile_shader_program(vert_src, frag_src);
            self.shaders.borrow_mut().insert(path_string, shader.clone());

            Ok(shader)
        }
    }

    pub fn add_mesh(&self, uri: String, mesh: Mesh) {
        let mut meshes = self.meshes.borrow_mut();

        if meshes.contains_key(&uri) {
            println!("WARNING: There is already a mesh node with uri {}, it will be overriden in the resource manager by the new node", uri);
        }

        meshes.insert(uri.clone(), mesh);
    }

    pub fn add_mesh_node(&self, uri: String, node: MeshNode) {
        let mut nodes = self.mesh_nodes.borrow_mut();

        if nodes.contains_key(&uri) {
            println!("WARNING: There is already a mesh node with uri {}, it will be overriden in the resource manager by the new node", uri);
        }

        nodes.insert(uri.clone(), node);
    }

    fn has_cached_mesh(&self, uri: &str) -> bool {
        self.gpu_meshes.borrow().contains_key(uri)
    }

    fn get_cached_mesh(&self, uri: &str) -> Option<GLMeshData> {
        self.gpu_meshes
        .borrow()
        .get(uri)
        .map(|mesh| *mesh)
    }

    fn gen_gpu_mesh(&self, uri: &str) -> Option<GLMeshData> {
        // TODO: Don't do this check in release builds.
        if self.has_cached_mesh(uri) {
            println!("WARNING: Attempting to create a new mesh for {} when the uri is already in the meshes map", uri);
        }

        let meshes = self.meshes.borrow();
        let mesh = match meshes.get(uri) {
            Some(mesh) => mesh,
            None => return None,
        };

        let mesh_data = self.renderer.gen_mesh(mesh);
        self.gpu_meshes
        .borrow_mut()
        .insert(uri.into(), mesh_data);

        Some(mesh_data)
    }
}

pub fn load_file_text<P: AsRef<Path>>(file_path: P) -> String {
    let mut file = match File::open(&file_path) {
        // The `desc` field of `IoError` is a string that describes the error
        Err(why) => panic!("couldn't open {}: {}", file_path.as_ref().display(), Error::description(&why)),
        Ok(file) => file,
    };
    let mut contents = String::new();
    match file.read_to_string(&mut contents) {
        Err(why) => panic!("couldn't read {}: {}", file_path.as_ref().display(), Error::description(&why)),
        Ok(_) => ()
    }
    contents
}

// TODO: Also include the node's local transform.
#[derive(Debug, Clone)]
pub struct MeshNode {
    pub mesh_ids: Vec<String>,
    pub children: Vec<MeshNode>,
}

impl MeshNode {
    pub fn new() -> MeshNode {
        MeshNode {
            mesh_ids: Vec::new(),
            children: Vec::new(),
        }
    }
}
<commit_msg>refactor(resource): rename load_model() to load_all_resources()<commit_after>use std::collections::HashMap;
use std::io::prelude::*;
use std::fs::{self, File};
use std::path::{Path, PathBuf};
use std::error::Error;
use std::rc::Rc;
use std::cell::RefCell;

use polygon::gl_render::{GLRender, GLMeshData, ShaderProgram};
use polygon::geometry::mesh::Mesh;

use wav::Wave;
use scene::Scene;
use ecs::Entity;
use component::{MeshManager, TransformManager};
use self::shader::*;

pub mod collada;
pub mod shader;

#[derive(Debug, Clone)]
pub struct ResourceManager {
    renderer: Rc<GLRender>,
    meshes: RefCell<HashMap<String, Mesh>>,
    gpu_meshes: RefCell<HashMap<String, GLMeshData>>,
    mesh_nodes: RefCell<HashMap<String, MeshNode>>,
    shaders: RefCell<HashMap<String, ShaderProgram>>,
    audio_clips: RefCell<HashMap<String, Rc<Wave>>>,

    resource_path: RefCell<PathBuf>,
}

impl ResourceManager {
    pub fn new(renderer: Rc<GLRender>) -> ResourceManager {
        ResourceManager {
            renderer: renderer,
            meshes: RefCell::new(HashMap::new()),
            gpu_meshes: RefCell::new(HashMap::new()),
            mesh_nodes: RefCell::new(HashMap::new()),
            shaders: RefCell::new(HashMap::new()),
            audio_clips: RefCell::new(HashMap::new()),

            resource_path: RefCell::new(PathBuf::new()),
        }
    }

    pub fn load_resource_file<P: AsRef<Path>>(&self, path: P) -> Result<(), String> {
        let mut full_path = self.resource_path.borrow().clone();
        full_path.push(path);
        let metadata = match fs::metadata(&full_path) {
            Err(why) => return Err(format!(
                "Unable to read metadata for {}, either it doesn't exist or the user lacks permissions, {}",
                full_path.display(),
                &why)),
            Ok(metadata) => metadata,
        };

        if !metadata.is_file() {
            return Err(format!(
                "{} could not be loaded because it is not a file",
                full_path.display()));
        }

        collada::load_resources(full_path, self).unwrap(); // TODO: Don't panic?

        Ok(())
    }

    /// Sets the path to the resources directory.
    ///
    /// # Details
    ///
    /// The resource manager is configured to look in the specified directory when loading
    /// resources such as meshes and shaders.
    pub fn set_resource_path<P: AsRef<Path>>(&self, path: P) {
        let mut resource_path = self.resource_path.borrow_mut();
        *resource_path = PathBuf::new();
        resource_path.push(path);
    }

    pub fn get_gpu_mesh(&self, uri: &str) -> Option<GLMeshData> {
        // Use cached mesh data if possible.
        self.get_cached_mesh(uri)
        .or_else(|| {
            self.gen_gpu_mesh(uri)
        })
    }

    pub fn get_audio_clip(&self, path_text: &str) -> Rc<Wave> {
        let mut audio_clips = self.audio_clips.borrow_mut();

        if !audio_clips.contains_key(path_text) {
            let wave = Wave::from_file(path_text).unwrap();
            audio_clips.insert(path_text.into(), Rc::new(wave));
        }

        audio_clips.get(path_text).unwrap().clone()
    }

    pub fn instantiate_model(&self, resource: &str, scene: &Scene) -> Result<Entity, String> {
        if resource.contains(".") {
            println!("WARNING: ResourceManager::instantiate_model() doesn't yet support fully qualified URIs, only root assets may be instantiated.");
            unimplemented!();
        }

        let mesh_nodes = self.mesh_nodes.borrow();
        let root = try!(
            mesh_nodes
            .get(resource)
            .ok_or_else(|| format!("No mesh node is identified by the uri {}", resource)));

        self.instantiate_node(scene, root)
    }

    fn instantiate_node(&self, scene: &Scene, node: &MeshNode) -> Result<Entity, String> {
        let entity = scene.create_entity();
        {
            let mut transform_manager = scene.get_manager_mut::<TransformManager>();
            transform_manager.assign(entity);

            for mesh_id in &node.mesh_ids {
                let gpu_mesh = match self.get_gpu_mesh(&*mesh_id) {
                    Some(gpu_mesh) => gpu_mesh,
                    None => {
                        println!("WARNING: Unable to load gpu mesh for uri {}", mesh_id);
                        continue;
                    }
                };
                scene.get_manager_mut::<MeshManager>()
                    .give_mesh(entity, gpu_mesh);
            }
        }
        // TODO: Apply the node's transform to the entity transform.

        // Instantiate each of the children and set the current node as their parent.
        for node in &node.children {
            let child = try!(self.instantiate_node(scene, node));

            let mut transform_manager = scene.get_manager_mut::<TransformManager>();
            transform_manager.set_child(entity, child);
        }

        Ok(entity)
    }

    pub fn get_shader<P: AsRef<Path> + ::std::fmt::Debug>(
        &self,
        shader_path: P
    ) -> Result<ShaderProgram, ParseShaderError> {
        {
            let path_str = shader_path.as_ref().to_str().expect(&*format!(
                "shader path {:?} contains invalid unicode characters",
                shader_path));
            if let Some(shader) = self.shaders.borrow().get(path_str) {
                return Ok(shader.clone());
            }
        }

        // This should be an else block on the above if block, but that doesn't work until MIR has
        // dropped, so for now we have to settle for manual case analysis.
        {
            let path_string: String = shader_path.as_ref()
                .to_str()
                .expect(&*format!(
                    "shader path {:?} contains invalid unicode characters",
                    shader_path))
                .into();

            let mut full_path = self.resource_path.borrow().clone();
            full_path.push(shader_path);
            let program_src = load_file_text(full_path);

            let programs = try!(ShaderParser::parse(&*program_src));
            let vert_src = match programs.iter().find(|program| program.name == "vert") {
                None => return Err(ParseShaderError::NoVertProgram),
                Some(program) => program.src,
            };

            let frag_src = match programs.iter().find(|program| program.name == "frag") {
                None => return Err(ParseShaderError::NoFragProgram),
                Some(program) => program.src,
            };

            let shader = self.renderer.compile_shader_program(vert_src, frag_src);
            self.shaders.borrow_mut().insert(path_string, shader.clone());

            Ok(shader)
        }
    }

    pub fn add_mesh(&self, uri: String, mesh: Mesh) {
        let mut meshes = self.meshes.borrow_mut();

        if meshes.contains_key(&uri) {
            println!("WARNING: There is already a mesh node with uri {}, it will be overriden in the resource manager by the new node", uri);
        }

        meshes.insert(uri.clone(), mesh);
    }

    pub fn add_mesh_node(&self, uri: String, node: MeshNode) {
        let mut nodes = self.mesh_nodes.borrow_mut();

        if nodes.contains_key(&uri) {
            println!("WARNING: There is already a mesh node with uri {}, it will be overriden in the resource manager by the new node", uri);
        }

        nodes.insert(uri.clone(), node);
    }

    fn has_cached_mesh(&self, uri: &str) -> bool {
        self.gpu_meshes.borrow().contains_key(uri)
    }

    fn get_cached_mesh(&self, uri: &str) -> Option<GLMeshData> {
        self.gpu_meshes
        .borrow()
        .get(uri)
        .map(|mesh| *mesh)
    }

    fn gen_gpu_mesh(&self, uri: &str) -> Option<GLMeshData> {
        // TODO: Don't do this check in release builds.
        if self.has_cached_mesh(uri) {
            println!("WARNING: Attempting to create a new mesh for {} when the uri is already in the meshes map", uri);
        }

        let meshes = self.meshes.borrow();
        let mesh = match meshes.get(uri) {
            Some(mesh) => mesh,
            None => return None,
        };

        let mesh_data = self.renderer.gen_mesh(mesh);
        self.gpu_meshes
        .borrow_mut()
        .insert(uri.into(), mesh_data);

        Some(mesh_data)
    }
}

pub fn load_file_text<P: AsRef<Path>>(file_path: P) -> String {
    let mut file = match File::open(&file_path) {
        // The `desc` field of `IoError` is a string that describes the error
        Err(why) => panic!("couldn't open {}: {}", file_path.as_ref().display(), Error::description(&why)),
        Ok(file) => file,
    };
    let mut contents = String::new();
    match file.read_to_string(&mut contents) {
        Err(why) => panic!("couldn't read {}: {}", file_path.as_ref().display(), Error::description(&why)),
        Ok(_) => ()
    }
    contents
}

// TODO: Also include the node's local transform.
#[derive(Debug, Clone)]
pub struct MeshNode {
    pub mesh_ids: Vec<String>,
    pub children: Vec<MeshNode>,
}

impl MeshNode {
    pub fn new() -> MeshNode {
        MeshNode {
            mesh_ids: Vec::new(),
            children: Vec::new(),
        }
    }
}
<|endoftext|>


<commit_before>use super::spc::Spc;
use super::timer::Timer;
use super::ring_buffer::RingBuffer;

pub const RAM_LEN: usize = 0x10000;

pub const IPL_ROM_LEN: usize = 64;
static DEFAULT_IPL_ROM: [u8; IPL_ROM_LEN] = [
    0xcd, 0xef, 0xbd, 0xe8, 0x00, 0xc6, 0x1d, 0xd0,
    0xfc, 0x8f, 0xaa, 0xf4, 0x8f, 0xbb, 0xf5, 0x78,
    0xcc, 0xf4, 0xd0, 0xfb, 0x2f, 0x19, 0xeb, 0xf4,
    0xd0, 0xfc, 0x7e, 0xf4, 0xd0, 0x0b, 0xe4, 0xf5,
    0xcb, 0xf4, 0xd7, 0x00, 0xfc, 0xd0, 0xf3, 0xab,
    0x01, 0x10, 0xef, 0x7e, 0xf4, 0x10, 0xeb, 0xba,
    0xf6, 0xda, 0x00, 0xba, 0xf4, 0xc4, 0xf4, 0xdd,
    0x5d, 0xd0, 0xdb, 0x1f, 0x00, 0x00, 0xc0, 0xff];

const SAMPLE_RATE: usize = 32000;
pub const BUFFER_LEN: usize = SAMPLE_RATE * 2;

pub struct Apu {
    ram: [u8; RAM_LEN],
    ipl_rom: [u8; IPL_ROM_LEN],

    timers: [Timer; 3],

    left_output_buffer: [i16; BUFFER_LEN],
    right_output_buffer: [i16; BUFFER_LEN],
    overflow_buffer: RingBuffer,

    is_ipl_rom_enabled: bool,
    dsp_reg_address: u8
}

impl Apu {
    pub fn new() -> Apu {
        let mut ret = Apu {
            ram: [0; RAM_LEN],
            ipl_rom: [0; IPL_ROM_LEN],

            timers: [Timer::new(256), Timer::new(256), Timer::new(32)],

            left_output_buffer: [0; BUFFER_LEN],
            right_output_buffer: [0; BUFFER_LEN],
            overflow_buffer: RingBuffer::new(),

            is_ipl_rom_enabled: true,
            dsp_reg_address: 0
        };
        ret.reset();
        ret
    }

    pub fn reset(&mut self) {
        // TODO: Randomize ram

        // TODO: Is there a better way to do this?
        for i in 0..IPL_ROM_LEN {
            self.ipl_rom[i] = DEFAULT_IPL_ROM[i];
        }

        for timer in self.timers.iter_mut() {
            timer.reset();
        }

        self.is_ipl_rom_enabled = true;
        self.dsp_reg_address = 0;
    }

    pub fn cpu_cycles_callback(&mut self, num_cycles: i32) {
        // TODO
    }

    pub fn read_byte(&mut self, address: u32) -> u8 {
        0 // TODO
    }

    pub fn write_byte(&mut self, address: u32, value: u8) {
        // TODO
    }
}
<commit_msg>hit a small bump in the road<commit_after>use super::spc::Spc;
use super::smp::Smp;
use super::timer::Timer;
use super::ring_buffer::RingBuffer;

pub const RAM_LEN: usize = 0x10000;

pub const IPL_ROM_LEN: usize = 64;
static DEFAULT_IPL_ROM: [u8; IPL_ROM_LEN] = [
    0xcd, 0xef, 0xbd, 0xe8, 0x00, 0xc6, 0x1d, 0xd0,
    0xfc, 0x8f, 0xaa, 0xf4, 0x8f, 0xbb, 0xf5, 0x78,
    0xcc, 0xf4, 0xd0, 0xfb, 0x2f, 0x19, 0xeb, 0xf4,
    0xd0, 0xfc, 0x7e, 0xf4, 0xd0, 0x0b, 0xe4, 0xf5,
    0xcb, 0xf4, 0xd7, 0x00, 0xfc, 0xd0, 0xf3, 0xab,
    0x01, 0x10, 0xef, 0x7e, 0xf4, 0x10, 0xeb, 0xba,
    0xf6, 0xda, 0x00, 0xba, 0xf4, 0xc4, 0xf4, 0xdd,
    0x5d, 0xd0, 0xdb, 0x1f, 0x00, 0x00, 0xc0, 0xff];

const SAMPLE_RATE: usize = 32000;
pub const BUFFER_LEN: usize = SAMPLE_RATE * 2;

pub struct Apu {
    ram: [u8; RAM_LEN],
    ipl_rom: [u8; IPL_ROM_LEN],

    smp: Smp,

    timers: [Timer; 3],

    left_output_buffer: [i16; BUFFER_LEN],
    right_output_buffer: [i16; BUFFER_LEN],
    overflow_buffer: RingBuffer,

    is_ipl_rom_enabled: bool,
    dsp_reg_address: u8
}

impl Apu {
    pub fn new() -> Apu {
        let mut ret = Apu {
            ram: [0; RAM_LEN],
            ipl_rom: [0; IPL_ROM_LEN],

            smp: Smp::new(/* TODO: Find some way to get ret in here, or rethink the architecture a bit */),

            timers: [Timer::new(256), Timer::new(256), Timer::new(32)],

            left_output_buffer: [0; BUFFER_LEN],
            right_output_buffer: [0; BUFFER_LEN],
            overflow_buffer: RingBuffer::new(),

            is_ipl_rom_enabled: true,
            dsp_reg_address: 0
        };
        ret.reset();
        ret
    }

    pub fn reset(&mut self) {
        // TODO: Randomize ram

        // TODO: Is there a better way to do this?
        for i in 0..IPL_ROM_LEN {
            self.ipl_rom[i] = DEFAULT_IPL_ROM[i];
        }

        for timer in self.timers.iter_mut() {
            timer.reset();
        }

        self.is_ipl_rom_enabled = true;
        self.dsp_reg_address = 0;
    }

    pub fn render(&mut self, /* TODO: Buffers */ num_samples: i32) {
        // TODO: Proper impl
        self.smp.run(num_samples * 64);
    }

    pub fn cpu_cycles_callback(&mut self, num_cycles: i32) {
        // TODO
    }

    pub fn read_byte(&mut self, address: u32) -> u8 {
        0 // TODO
    }

    pub fn write_byte(&mut self, address: u32, value: u8) {
        // TODO
    }
}
<|endoftext|>