<commit_before>#![cfg_attr(
    not(any(feature = "vulkan", feature = "dx12", feature = "metal")),
    allow(dead_code, unused_extern_crates, unused_imports)
)]

extern crate env_logger;
extern crate gfx_hal as hal;
#[cfg(feature = "dx12")]
extern crate gfx_backend_dx12 as back;
#[cfg(feature = "vulkan")]
extern crate gfx_backend_vulkan as back;
#[cfg(feature = "metal")]
extern crate gfx_backend_metal as back;

use std::str::FromStr;

use hal::{
    Backend, Compute, Device, DescriptorPool, Instance, PhysicalDevice, QueueFamily,
};
use hal::{queue, pso, memory, buffer, pool, command};

extern crate glsl_to_spirv;

use std::fs;
use std::io::Read;

#[cfg(any(feature = "vulkan", feature = "dx12", feature = "metal"))]
fn main() {
    env_logger::init();

    // For now this just panics if you didn't pass numbers. Could add proper error handling.
    if std::env::args().len() == 1 { panic!("You must pass a list of positive integers!") }
    let numbers: Vec<u32> = std::env::args()
        .skip(1)
        .map(|s| u32::from_str(&s).expect("You must pass a list of positive integers!"))
        .collect();
    let stride = std::mem::size_of::<u32>() as u64;

    #[cfg(any(feature = "vulkan", feature = "dx12", feature = "metal"))]
    let instance = back::Instance::create("gfx-rs compute", 1);

    let mut adapter = instance.enumerate_adapters().into_iter()
        .find(|a| a.queue_families
            .iter()
            .any(|family| family.supports_compute())
        )
        .expect("Failed to find a GPU with compute support!");

    let memory_properties = adapter.physical_device.memory_properties();
    let (mut device, mut queue_group) = adapter
        .open_with::<_, Compute>(1, |_family| true)
        .unwrap();

    let glsl = fs::read_to_string("compute/shader/collatz.comp").unwrap();
    let spirv: Vec<u8> = glsl_to_spirv::compile(&glsl, glsl_to_spirv::ShaderType::Compute)
        .unwrap()
        .bytes()
        .map(|b| b.unwrap())
        .collect();
    let shader = device.create_shader_module(&spirv).unwrap();

    let (pipeline_layout, pipeline, set_layout, mut desc_pool) = {
        let set_layout = device.create_descriptor_set_layout(
            &[
                pso::DescriptorSetLayoutBinding {
                    binding: 0,
                    ty: pso::DescriptorType::StorageBuffer,
                    count: 1,
                    stage_flags: pso::ShaderStageFlags::COMPUTE,
                    immutable_samplers: false,
                }
            ],
            &[],
        ).expect("Can't create descriptor set layout");

        let pipeline_layout = device
            .create_pipeline_layout(Some(&set_layout), &[])
            .expect("Can't create pipeline layout");
        let entry_point = pso::EntryPoint {
            entry: "main",
            module: &shader,
            specialization: pso::Specialization::default(),
        };
        let pipeline = device
            .create_compute_pipeline(&pso::ComputePipelineDesc::new(entry_point, &pipeline_layout), None)
            .expect("Error creating compute pipeline!");

        let desc_pool = device.create_descriptor_pool(
            1,
            &[
                pso::DescriptorRangeDesc {
                    ty: pso::DescriptorType::StorageBuffer,
                    count: 1,
                },
            ],
        ).expect("Can't create descriptor pool");
        (pipeline_layout, pipeline, set_layout, desc_pool)
    };

    let (staging_memory, staging_buffer, staging_size) = create_buffer::<back::Backend>(
        &mut device,
        &memory_properties.memory_types,
        memory::Properties::CPU_VISIBLE | memory::Properties::COHERENT,
        buffer::Usage::TRANSFER_SRC | buffer::Usage::TRANSFER_DST,
        stride,
        numbers.len() as u64,
    );

    {
        let mut writer = device.acquire_mapping_writer::<u32>(&staging_memory, 0..staging_size).unwrap();
        writer[0..numbers.len()].copy_from_slice(&numbers);
        device.release_mapping_writer(writer).expect("Can't relase mapping writer");
    }

    let (device_memory, device_buffer, _device_buffer_size) = create_buffer::<back::Backend>(
        &mut device,
        &memory_properties.memory_types,
        memory::Properties::DEVICE_LOCAL,
        buffer::Usage::TRANSFER_SRC | buffer::Usage::TRANSFER_DST | buffer::Usage::STORAGE,
        stride,
        numbers.len() as u64,
    );

    let desc_set = desc_pool.allocate_set(&set_layout).unwrap();
    device.write_descriptor_sets(Some(
        pso::DescriptorSetWrite {
            set: &desc_set,
            binding: 0,
            array_offset: 0,
            descriptors: Some(
                pso::Descriptor::Buffer(&device_buffer, None .. None)
            ),
        }
    ));

    let mut command_pool = device
        .create_command_pool_typed(&queue_group, pool::CommandPoolCreateFlags::empty(), 16)
        .expect("Can't create command pool");
    let fence = device
        .create_fence(false)
        .expect("Can't create fence");
    let submission = queue::Submission::new().submit(Some({
        let mut command_buffer = command_pool.acquire_command_buffer(false);
        command_buffer.copy_buffer(&staging_buffer, &device_buffer, &[command::BufferCopy { src: 0, dst: 0, size: stride * numbers.len() as u64}]);
        command_buffer.pipeline_barrier(
            pso::PipelineStage::TRANSFER .. pso::PipelineStage::COMPUTE_SHADER,
            memory::Dependencies::empty(),
            Some(memory::Barrier::Buffer {
                states: buffer::Access::TRANSFER_WRITE .. buffer::Access::SHADER_READ | buffer::Access::SHADER_WRITE,
                target: &device_buffer
            }),
        );
        command_buffer.bind_compute_pipeline(&pipeline);
        command_buffer.bind_compute_descriptor_sets(&pipeline_layout, 0, &[desc_set], &[]);
        command_buffer.dispatch([numbers.len() as u32, 1, 1]);
        command_buffer.pipeline_barrier(
            pso::PipelineStage::COMPUTE_SHADER .. pso::PipelineStage::TRANSFER,
            memory::Dependencies::empty(),
            Some(memory::Barrier::Buffer {
                states: buffer::Access::SHADER_READ | buffer::Access::SHADER_WRITE .. buffer::Access::TRANSFER_READ,
                target: &device_buffer
            }),
        );
        command_buffer.copy_buffer(&device_buffer, &staging_buffer, &[command::BufferCopy { src: 0, dst: 0, size: stride * numbers.len() as u64}]);
        command_buffer.finish()
    }));
    queue_group.queues[0].submit(submission, Some(&fence));
    device.wait_for_fence(&fence, !0).unwrap();

    {
        let reader = device.acquire_mapping_reader::<u32>(&staging_memory, 0..staging_size).unwrap();
        println!("Times: {:?}", reader[0..numbers.len()].into_iter().map(|n| *n).collect::<Vec<u32>>());
        device.release_mapping_reader(reader);
    }

    device.destroy_command_pool(command_pool.into_raw());
    device.destroy_descriptor_pool(desc_pool);
    device.destroy_descriptor_set_layout(set_layout);
    device.destroy_shader_module(shader);
    device.destroy_buffer(device_buffer);
    device.destroy_buffer(staging_buffer);
    device.destroy_fence(fence);
    device.destroy_pipeline_layout(pipeline_layout);
    device.free_memory(device_memory);
    device.free_memory(staging_memory);
    device.destroy_compute_pipeline(pipeline);
}

fn create_buffer<B: Backend>(
    device: &mut B::Device,
    memory_types: &[hal::MemoryType],
    properties: memory::Properties,
    usage: buffer::Usage,
    stride: u64,
    len: u64,
) -> (B::Memory, B::Buffer, u64) {
    let buffer = device.create_buffer(stride * len, usage).unwrap();
    let requirements = device.get_buffer_requirements(&buffer);

    let ty = memory_types
        .into_iter()
        .enumerate()
        .position(|(id, memory_type)| {
            requirements.type_mask & (1 << id) != 0 &&
            memory_type.properties.contains(properties)
        })
        .unwrap()
        .into();

    let memory = device.allocate_memory(ty, requirements.size).unwrap();
    let buffer = device.bind_buffer_memory(&memory, 0, buffer).unwrap();

    (memory, buffer, requirements.size)
}

#[cfg(not(any(feature = "vulkan", feature = "dx12", feature = "metal")))]
fn main() {
    println!("You need to enable one of the next-gen API feature (vulkan, dx12, metal) to run this example.");
}
<commit_msg>fn main is attributed already<commit_after>#![cfg_attr(
    not(any(feature = "vulkan", feature = "dx12", feature = "metal")),
    allow(dead_code, unused_extern_crates, unused_imports)
)]

extern crate env_logger;
extern crate gfx_hal as hal;
#[cfg(feature = "dx12")]
extern crate gfx_backend_dx12 as back;
#[cfg(feature = "vulkan")]
extern crate gfx_backend_vulkan as back;
#[cfg(feature = "metal")]
extern crate gfx_backend_metal as back;

use std::str::FromStr;

use hal::{
    Backend, Compute, Device, DescriptorPool, Instance, PhysicalDevice, QueueFamily,
};
use hal::{queue, pso, memory, buffer, pool, command};

extern crate glsl_to_spirv;

use std::fs;
use std::io::Read;

#[cfg(any(feature = "vulkan", feature = "dx12", feature = "metal"))]
fn main() {
    env_logger::init();

    // For now this just panics if you didn't pass numbers. Could add proper error handling.
    if std::env::args().len() == 1 { panic!("You must pass a list of positive integers!") }
    let numbers: Vec<u32> = std::env::args()
        .skip(1)
        .map(|s| u32::from_str(&s).expect("You must pass a list of positive integers!"))
        .collect();
    let stride = std::mem::size_of::<u32>() as u64;

    let instance = back::Instance::create("gfx-rs compute", 1);

    let mut adapter = instance.enumerate_adapters().into_iter()
        .find(|a| a.queue_families
            .iter()
            .any(|family| family.supports_compute())
        )
        .expect("Failed to find a GPU with compute support!");

    let memory_properties = adapter.physical_device.memory_properties();
    let (mut device, mut queue_group) = adapter
        .open_with::<_, Compute>(1, |_family| true)
        .unwrap();

    let glsl = fs::read_to_string("compute/shader/collatz.comp").unwrap();
    let spirv: Vec<u8> = glsl_to_spirv::compile(&glsl, glsl_to_spirv::ShaderType::Compute)
        .unwrap()
        .bytes()
        .map(|b| b.unwrap())
        .collect();
    let shader = device.create_shader_module(&spirv).unwrap();

    let (pipeline_layout, pipeline, set_layout, mut desc_pool) = {
        let set_layout = device.create_descriptor_set_layout(
            &[
                pso::DescriptorSetLayoutBinding {
                    binding: 0,
                    ty: pso::DescriptorType::StorageBuffer,
                    count: 1,
                    stage_flags: pso::ShaderStageFlags::COMPUTE,
                    immutable_samplers: false,
                }
            ],
            &[],
        ).expect("Can't create descriptor set layout");

        let pipeline_layout = device
            .create_pipeline_layout(Some(&set_layout), &[])
            .expect("Can't create pipeline layout");
        let entry_point = pso::EntryPoint {
            entry: "main",
            module: &shader,
            specialization: pso::Specialization::default(),
        };
        let pipeline = device
            .create_compute_pipeline(&pso::ComputePipelineDesc::new(entry_point, &pipeline_layout), None)
            .expect("Error creating compute pipeline!");

        let desc_pool = device.create_descriptor_pool(
            1,
            &[
                pso::DescriptorRangeDesc {
                    ty: pso::DescriptorType::StorageBuffer,
                    count: 1,
                },
            ],
        ).expect("Can't create descriptor pool");
        (pipeline_layout, pipeline, set_layout, desc_pool)
    };

    let (staging_memory, staging_buffer, staging_size) = create_buffer::<back::Backend>(
        &mut device,
        &memory_properties.memory_types,
        memory::Properties::CPU_VISIBLE | memory::Properties::COHERENT,
        buffer::Usage::TRANSFER_SRC | buffer::Usage::TRANSFER_DST,
        stride,
        numbers.len() as u64,
    );

    {
        let mut writer = device.acquire_mapping_writer::<u32>(&staging_memory, 0..staging_size).unwrap();
        writer[0..numbers.len()].copy_from_slice(&numbers);
        device.release_mapping_writer(writer).expect("Can't relase mapping writer");
    }

    let (device_memory, device_buffer, _device_buffer_size) = create_buffer::<back::Backend>(
        &mut device,
        &memory_properties.memory_types,
        memory::Properties::DEVICE_LOCAL,
        buffer::Usage::TRANSFER_SRC | buffer::Usage::TRANSFER_DST | buffer::Usage::STORAGE,
        stride,
        numbers.len() as u64,
    );

    let desc_set = desc_pool.allocate_set(&set_layout).unwrap();
    device.write_descriptor_sets(Some(
        pso::DescriptorSetWrite {
            set: &desc_set,
            binding: 0,
            array_offset: 0,
            descriptors: Some(
                pso::Descriptor::Buffer(&device_buffer, None .. None)
            ),
        }
    ));

    let mut command_pool = device
        .create_command_pool_typed(&queue_group, pool::CommandPoolCreateFlags::empty(), 16)
        .expect("Can't create command pool");
    let fence = device
        .create_fence(false)
        .expect("Can't create fence");
    let submission = queue::Submission::new().submit(Some({
        let mut command_buffer = command_pool.acquire_command_buffer(false);
        command_buffer.copy_buffer(&staging_buffer, &device_buffer, &[command::BufferCopy { src: 0, dst: 0, size: stride * numbers.len() as u64}]);
        command_buffer.pipeline_barrier(
            pso::PipelineStage::TRANSFER .. pso::PipelineStage::COMPUTE_SHADER,
            memory::Dependencies::empty(),
            Some(memory::Barrier::Buffer {
                states: buffer::Access::TRANSFER_WRITE .. buffer::Access::SHADER_READ | buffer::Access::SHADER_WRITE,
                target: &device_buffer
            }),
        );
        command_buffer.bind_compute_pipeline(&pipeline);
        command_buffer.bind_compute_descriptor_sets(&pipeline_layout, 0, &[desc_set], &[]);
        command_buffer.dispatch([numbers.len() as u32, 1, 1]);
        command_buffer.pipeline_barrier(
            pso::PipelineStage::COMPUTE_SHADER .. pso::PipelineStage::TRANSFER,
            memory::Dependencies::empty(),
            Some(memory::Barrier::Buffer {
                states: buffer::Access::SHADER_READ | buffer::Access::SHADER_WRITE .. buffer::Access::TRANSFER_READ,
                target: &device_buffer
            }),
        );
        command_buffer.copy_buffer(&device_buffer, &staging_buffer, &[command::BufferCopy { src: 0, dst: 0, size: stride * numbers.len() as u64}]);
        command_buffer.finish()
    }));
    queue_group.queues[0].submit(submission, Some(&fence));
    device.wait_for_fence(&fence, !0).unwrap();

    {
        let reader = device.acquire_mapping_reader::<u32>(&staging_memory, 0..staging_size).unwrap();
        println!("Times: {:?}", reader[0..numbers.len()].into_iter().map(|n| *n).collect::<Vec<u32>>());
        device.release_mapping_reader(reader);
    }

    device.destroy_command_pool(command_pool.into_raw());
    device.destroy_descriptor_pool(desc_pool);
    device.destroy_descriptor_set_layout(set_layout);
    device.destroy_shader_module(shader);
    device.destroy_buffer(device_buffer);
    device.destroy_buffer(staging_buffer);
    device.destroy_fence(fence);
    device.destroy_pipeline_layout(pipeline_layout);
    device.free_memory(device_memory);
    device.free_memory(staging_memory);
    device.destroy_compute_pipeline(pipeline);
}

fn create_buffer<B: Backend>(
    device: &mut B::Device,
    memory_types: &[hal::MemoryType],
    properties: memory::Properties,
    usage: buffer::Usage,
    stride: u64,
    len: u64,
) -> (B::Memory, B::Buffer, u64) {
    let buffer = device.create_buffer(stride * len, usage).unwrap();
    let requirements = device.get_buffer_requirements(&buffer);

    let ty = memory_types
        .into_iter()
        .enumerate()
        .position(|(id, memory_type)| {
            requirements.type_mask & (1 << id) != 0 &&
            memory_type.properties.contains(properties)
        })
        .unwrap()
        .into();

    let memory = device.allocate_memory(ty, requirements.size).unwrap();
    let buffer = device.bind_buffer_memory(&memory, 0, buffer).unwrap();

    (memory, buffer, requirements.size)
}

#[cfg(not(any(feature = "vulkan", feature = "dx12", feature = "metal")))]
fn main() {
    println!("You need to enable one of the next-gen API feature (vulkan, dx12, metal) to run this example.");
}
<|endoftext|>


<commit_before>//! Example of logger with custom formatting
extern crate iron;
extern crate logger;
extern crate term;

use std::io::net::ip::Ipv4Addr;

use iron::{Chain, ChainBuilder, Iron, IronResult, Request, Response};

use logger::Logger;
use logger::format::{Format, FunctionAttrs};

use term::attr;

// This is an example of using a format string that can specify colors and attributes
// to specific words that are printed out to the console.
fn main() {
    let format_str =
        "@[red A]URI: {uri}@@, @[blue blink underline]Method: {method}@@, @[yellow standout]Status: {status}@@, @[brightgreen]Time: {response_time}@@";
    fn attrs(req: &Request, _res: &Response) -> Vec<attr::Attr> {
        match format!("{}", req.url).as_slice() {
            "/" => vec![attr::Blink],
            _ => vec![]
        }
    }
    let mut chain = ChainBuilder::new(no_op_handler);
    chain.link(Logger::new(Format::from_format_string(format_str, &mut vec![], &mut vec![FunctionAttrs(attrs)])));
    Iron::new(chain).listen(Ipv4Addr(127, 0, 0, 1), 3000);
}

fn no_op_handler(_: &mut Request) -> IronResult<Response> {
    Ok(Response::with(iron::status::Ok, ""))
}
<commit_msg>(fix) Use the new format for format strings.<commit_after>//! Example of logger with custom formatting
extern crate iron;
extern crate logger;
extern crate term;

use std::io::net::ip::Ipv4Addr;

use iron::{Chain, ChainBuilder, Iron, IronResult, Request, Response};

use logger::Logger;
use logger::format::{Format, FunctionAttrs};

use term::attr;

static FORMAT: &'static str =
    "@[red A]Uri: {uri}@, @[blue blink underline]Method: {method}@, @[yellow standout]Status: {status}@, @[brightgreen]Time: {response-time}@";

// This is an example of using a format string that can specify colors and attributes
// to specific words that are printed out to the console.
fn main() {
    fn attrs(req: &Request, _res: &Response) -> Vec<attr::Attr> {
        match format!("{}", req.url).as_slice() {
            "/" => vec![attr::Blink],
            _ => vec![]
        }
    }

    let mut chain = ChainBuilder::new(no_op_handler);
    let format = Format::new(FORMAT, vec![], vec![FunctionAttrs(attrs)]);
    chain.link(Logger::new(Some(format.unwrap())));
    Iron::new(chain).listen(Ipv4Addr(127, 0, 0, 1), 3000);
}

fn no_op_handler(_: &mut Request) -> IronResult<Response> {
    Ok(Response::with(iron::status::Ok, ""))
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use app_units::Au;
use fnv::FnvHasher;
use font::{Font, FontGroup, FontHandleMethods};
use font_cache_thread::FontCacheThread;
use font_template::FontTemplateDescriptor;
use heapsize::HeapSizeOf;
use platform::font::FontHandle;
use platform::font_context::FontContextHandle;
use platform::font_template::FontTemplateData;
use smallvec::SmallVec;
use std::cell::RefCell;
use std::collections::HashMap;
use std::default::Default;
use std::hash::{BuildHasherDefault, Hash, Hasher};
use std::rc::Rc;
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
use style::computed_values::{font_style, font_variant};
use style::properties::style_structs;
use webrender_traits;

static SMALL_CAPS_SCALE_FACTOR: f32 = 0.8;      // Matches FireFox (see gfxFont.h)

#[derive(Debug)]
struct LayoutFontCacheEntry {
    family: String,
    font: Option<Rc<RefCell<Font>>>,
}

#[derive(Debug)]
struct FallbackFontCacheEntry {
    font: Rc<RefCell<Font>>,
}

/// An epoch for the font context cache. The cache is flushed if the current epoch does not match
/// this one.
static FONT_CACHE_EPOCH: AtomicUsize = ATOMIC_USIZE_INIT;

/// The FontContext represents the per-thread/thread state necessary for
/// working with fonts. It is the public API used by the layout and
/// paint code. It talks directly to the font cache thread where
/// required.
#[derive(Debug)]
pub struct FontContext {
    platform_handle: FontContextHandle,
    font_cache_thread: FontCacheThread,

    /// TODO: See bug https://github.com/servo/servo/issues/3300.
    layout_font_cache: Vec<LayoutFontCacheEntry>,
    fallback_font_cache: Vec<FallbackFontCacheEntry>,

    layout_font_group_cache:
        HashMap<LayoutFontGroupCacheKey, Rc<FontGroup>, BuildHasherDefault<FnvHasher>>,

    epoch: usize,
}

impl FontContext {
    pub fn new(font_cache_thread: FontCacheThread) -> FontContext {
        let handle = FontContextHandle::new();
        FontContext {
            platform_handle: handle,
            font_cache_thread: font_cache_thread,
            layout_font_cache: vec!(),
            fallback_font_cache: vec!(),
            layout_font_group_cache: HashMap::with_hasher(Default::default()),
            epoch: 0,
        }
    }

    /// Create a font for use in layout calculations.
    fn create_layout_font(&self,
                          template: Arc<FontTemplateData>,
                          descriptor: FontTemplateDescriptor,
                          pt_size: Au,
                          variant: font_variant::T,
                          font_key: webrender_traits::FontKey) -> Result<Font, ()> {
        // TODO: (Bug #3463): Currently we only support fake small-caps
        // painting. We should also support true small-caps (where the
        // font supports it) in the future.
        let actual_pt_size = match variant {
            font_variant::T::small_caps => pt_size.scale_by(SMALL_CAPS_SCALE_FACTOR),
            font_variant::T::normal => pt_size,
        };

        let handle = try!(FontHandle::new_from_template(&self.platform_handle,
                                                        template,
                                                        Some(actual_pt_size)));

        Ok(Font::new(handle, variant, descriptor, pt_size, actual_pt_size, font_key))
    }

    fn expire_font_caches_if_necessary(&mut self) {
        let current_epoch = FONT_CACHE_EPOCH.load(Ordering::SeqCst);
        if current_epoch == self.epoch {
            return
        }

        self.layout_font_cache.clear();
        self.fallback_font_cache.clear();
        self.layout_font_group_cache.clear();
        self.epoch = current_epoch
    }

    /// Create a group of fonts for use in layout calculations. May return
    /// a cached font if this font instance has already been used by
    /// this context.
    pub fn layout_font_group_for_style(&mut self, style: Arc<style_structs::Font>)
                                       -> Rc<FontGroup> {
        self.expire_font_caches_if_necessary();

        let layout_font_group_cache_key = LayoutFontGroupCacheKey {
            pointer: style.clone(),
            size: style.font_size,
        };
        if let Some(ref cached_font_group) = self.layout_font_group_cache.get(
                &layout_font_group_cache_key) {
            return (*cached_font_group).clone()
        }

        // TODO: The font context holds a strong ref to the cached fonts
        // so they will never be released. Find out a good time to drop them.

        let desc = FontTemplateDescriptor::new(style.font_weight,
                                               style.font_stretch,
                                               style.font_style == font_style::T::italic ||
                                                style.font_style == font_style::T::oblique);

        let mut fonts: SmallVec<[Rc<RefCell<Font>>; 8]> = SmallVec::new();

        for family in &style.font_family.0 {
            // GWTODO: Check on real pages if this is faster as Vec() or HashMap().
            let mut cache_hit = false;
            for cached_font_entry in &self.layout_font_cache {
                if cached_font_entry.family == family.name() {
                    match cached_font_entry.font {
                        None => {
                            cache_hit = true;
                            break;
                        }
                        Some(ref cached_font_ref) => {
                            let cached_font = (*cached_font_ref).borrow();
                            if cached_font.descriptor == desc &&
                               cached_font.requested_pt_size == style.font_size &&
                               cached_font.variant == style.font_variant {
                                fonts.push((*cached_font_ref).clone());
                                cache_hit = true;
                                break;
                            }
                        }
                    }
                }
            }

            if !cache_hit {
                let template_info = self.font_cache_thread.find_font_template(family.clone(),
                                                                             desc.clone());
                match template_info {
                    Some(template_info) => {
                        let layout_font = self.create_layout_font(template_info.font_template,
                                                                  desc.clone(),
                                                                  style.font_size,
                                                                  style.font_variant,
                                                                  template_info.font_key
                                                                               .expect("No font key present!"));
                        let font = match layout_font {
                            Ok(layout_font) => {
                                let layout_font = Rc::new(RefCell::new(layout_font));
                                fonts.push(layout_font.clone());

                                Some(layout_font)
                            }
                            Err(_) => None
                        };

                        self.layout_font_cache.push(LayoutFontCacheEntry {
                            family: family.name().to_owned(),
                            font: font
                        });
                    }
                    None => {
                        self.layout_font_cache.push(LayoutFontCacheEntry {
                            family: family.name().to_owned(),
                            font: None,
                        });
                    }
                }
            }
        }

        // Add a last resort font as a fallback option.
        let mut cache_hit = false;
        for cached_font_entry in &self.fallback_font_cache {
            let cached_font = cached_font_entry.font.borrow();
            if cached_font.descriptor == desc &&
                        cached_font.requested_pt_size == style.font_size &&
                        cached_font.variant == style.font_variant {
                fonts.push(cached_font_entry.font.clone());
                cache_hit = true;
                break;
            }
        }

        if !cache_hit {
            let template_info = self.font_cache_thread.last_resort_font_template(desc.clone());
            let layout_font = self.create_layout_font(template_info.font_template,
                                                      desc.clone(),
                                                      style.font_size,
                                                      style.font_variant,
                                                      template_info.font_key.expect("No font key present!"));
            match layout_font {
                Ok(layout_font) => {
                    let layout_font = Rc::new(RefCell::new(layout_font));
                    self.fallback_font_cache.push(FallbackFontCacheEntry {
                        font: layout_font.clone(),
                    });
                    fonts.push(layout_font);
                }
                Err(_) => debug!("Failed to create fallback layout font!")
            }
        }

        let font_group = Rc::new(FontGroup::new(fonts));
        self.layout_font_group_cache.insert(layout_font_group_cache_key, font_group.clone());
        font_group
    }

    /// Returns a reference to the font cache thread.
    pub fn font_cache_thread(&self) -> FontCacheThread {
        self.font_cache_thread.clone()
    }
}

impl HeapSizeOf for FontContext {
    fn heap_size_of_children(&self) -> usize {
        // FIXME(njn): Measure other fields eventually.
        self.platform_handle.heap_size_of_children()
    }
}

#[derive(Debug)]
struct LayoutFontGroupCacheKey {
    pointer: Arc<style_structs::Font>,
    size: Au,
}

impl PartialEq for LayoutFontGroupCacheKey {
    fn eq(&self, other: &LayoutFontGroupCacheKey) -> bool {
        self.pointer == other.pointer && self.size == other.size
    }
}

impl Eq for LayoutFontGroupCacheKey {}

impl Hash for LayoutFontGroupCacheKey {
    fn hash<H>(&self, hasher: &mut H) where H: Hasher {
        self.pointer.hash.hash(hasher)
    }
}

#[inline]
pub fn invalidate_font_caches() {
    FONT_CACHE_EPOCH.fetch_add(1, Ordering::SeqCst);
}
<commit_msg>Remove unused FontContext::font_cache_thread().<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use app_units::Au;
use fnv::FnvHasher;
use font::{Font, FontGroup, FontHandleMethods};
use font_cache_thread::FontCacheThread;
use font_template::FontTemplateDescriptor;
use heapsize::HeapSizeOf;
use platform::font::FontHandle;
use platform::font_context::FontContextHandle;
use platform::font_template::FontTemplateData;
use smallvec::SmallVec;
use std::cell::RefCell;
use std::collections::HashMap;
use std::default::Default;
use std::hash::{BuildHasherDefault, Hash, Hasher};
use std::rc::Rc;
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
use style::computed_values::{font_style, font_variant};
use style::properties::style_structs;
use webrender_traits;

static SMALL_CAPS_SCALE_FACTOR: f32 = 0.8;      // Matches FireFox (see gfxFont.h)

#[derive(Debug)]
struct LayoutFontCacheEntry {
    family: String,
    font: Option<Rc<RefCell<Font>>>,
}

#[derive(Debug)]
struct FallbackFontCacheEntry {
    font: Rc<RefCell<Font>>,
}

/// An epoch for the font context cache. The cache is flushed if the current epoch does not match
/// this one.
static FONT_CACHE_EPOCH: AtomicUsize = ATOMIC_USIZE_INIT;

/// The FontContext represents the per-thread/thread state necessary for
/// working with fonts. It is the public API used by the layout and
/// paint code. It talks directly to the font cache thread where
/// required.
#[derive(Debug)]
pub struct FontContext {
    platform_handle: FontContextHandle,
    font_cache_thread: FontCacheThread,

    /// TODO: See bug https://github.com/servo/servo/issues/3300.
    layout_font_cache: Vec<LayoutFontCacheEntry>,
    fallback_font_cache: Vec<FallbackFontCacheEntry>,

    layout_font_group_cache:
        HashMap<LayoutFontGroupCacheKey, Rc<FontGroup>, BuildHasherDefault<FnvHasher>>,

    epoch: usize,
}

impl FontContext {
    pub fn new(font_cache_thread: FontCacheThread) -> FontContext {
        let handle = FontContextHandle::new();
        FontContext {
            platform_handle: handle,
            font_cache_thread: font_cache_thread,
            layout_font_cache: vec!(),
            fallback_font_cache: vec!(),
            layout_font_group_cache: HashMap::with_hasher(Default::default()),
            epoch: 0,
        }
    }

    /// Create a font for use in layout calculations.
    fn create_layout_font(&self,
                          template: Arc<FontTemplateData>,
                          descriptor: FontTemplateDescriptor,
                          pt_size: Au,
                          variant: font_variant::T,
                          font_key: webrender_traits::FontKey) -> Result<Font, ()> {
        // TODO: (Bug #3463): Currently we only support fake small-caps
        // painting. We should also support true small-caps (where the
        // font supports it) in the future.
        let actual_pt_size = match variant {
            font_variant::T::small_caps => pt_size.scale_by(SMALL_CAPS_SCALE_FACTOR),
            font_variant::T::normal => pt_size,
        };

        let handle = try!(FontHandle::new_from_template(&self.platform_handle,
                                                        template,
                                                        Some(actual_pt_size)));

        Ok(Font::new(handle, variant, descriptor, pt_size, actual_pt_size, font_key))
    }

    fn expire_font_caches_if_necessary(&mut self) {
        let current_epoch = FONT_CACHE_EPOCH.load(Ordering::SeqCst);
        if current_epoch == self.epoch {
            return
        }

        self.layout_font_cache.clear();
        self.fallback_font_cache.clear();
        self.layout_font_group_cache.clear();
        self.epoch = current_epoch
    }

    /// Create a group of fonts for use in layout calculations. May return
    /// a cached font if this font instance has already been used by
    /// this context.
    pub fn layout_font_group_for_style(&mut self, style: Arc<style_structs::Font>)
                                       -> Rc<FontGroup> {
        self.expire_font_caches_if_necessary();

        let layout_font_group_cache_key = LayoutFontGroupCacheKey {
            pointer: style.clone(),
            size: style.font_size,
        };
        if let Some(ref cached_font_group) = self.layout_font_group_cache.get(
                &layout_font_group_cache_key) {
            return (*cached_font_group).clone()
        }

        // TODO: The font context holds a strong ref to the cached fonts
        // so they will never be released. Find out a good time to drop them.

        let desc = FontTemplateDescriptor::new(style.font_weight,
                                               style.font_stretch,
                                               style.font_style == font_style::T::italic ||
                                                style.font_style == font_style::T::oblique);

        let mut fonts: SmallVec<[Rc<RefCell<Font>>; 8]> = SmallVec::new();

        for family in &style.font_family.0 {
            // GWTODO: Check on real pages if this is faster as Vec() or HashMap().
            let mut cache_hit = false;
            for cached_font_entry in &self.layout_font_cache {
                if cached_font_entry.family == family.name() {
                    match cached_font_entry.font {
                        None => {
                            cache_hit = true;
                            break;
                        }
                        Some(ref cached_font_ref) => {
                            let cached_font = (*cached_font_ref).borrow();
                            if cached_font.descriptor == desc &&
                               cached_font.requested_pt_size == style.font_size &&
                               cached_font.variant == style.font_variant {
                                fonts.push((*cached_font_ref).clone());
                                cache_hit = true;
                                break;
                            }
                        }
                    }
                }
            }

            if !cache_hit {
                let template_info = self.font_cache_thread.find_font_template(family.clone(),
                                                                             desc.clone());
                match template_info {
                    Some(template_info) => {
                        let layout_font = self.create_layout_font(template_info.font_template,
                                                                  desc.clone(),
                                                                  style.font_size,
                                                                  style.font_variant,
                                                                  template_info.font_key
                                                                               .expect("No font key present!"));
                        let font = match layout_font {
                            Ok(layout_font) => {
                                let layout_font = Rc::new(RefCell::new(layout_font));
                                fonts.push(layout_font.clone());

                                Some(layout_font)
                            }
                            Err(_) => None
                        };

                        self.layout_font_cache.push(LayoutFontCacheEntry {
                            family: family.name().to_owned(),
                            font: font
                        });
                    }
                    None => {
                        self.layout_font_cache.push(LayoutFontCacheEntry {
                            family: family.name().to_owned(),
                            font: None,
                        });
                    }
                }
            }
        }

        // Add a last resort font as a fallback option.
        let mut cache_hit = false;
        for cached_font_entry in &self.fallback_font_cache {
            let cached_font = cached_font_entry.font.borrow();
            if cached_font.descriptor == desc &&
                        cached_font.requested_pt_size == style.font_size &&
                        cached_font.variant == style.font_variant {
                fonts.push(cached_font_entry.font.clone());
                cache_hit = true;
                break;
            }
        }

        if !cache_hit {
            let template_info = self.font_cache_thread.last_resort_font_template(desc.clone());
            let layout_font = self.create_layout_font(template_info.font_template,
                                                      desc.clone(),
                                                      style.font_size,
                                                      style.font_variant,
                                                      template_info.font_key.expect("No font key present!"));
            match layout_font {
                Ok(layout_font) => {
                    let layout_font = Rc::new(RefCell::new(layout_font));
                    self.fallback_font_cache.push(FallbackFontCacheEntry {
                        font: layout_font.clone(),
                    });
                    fonts.push(layout_font);
                }
                Err(_) => debug!("Failed to create fallback layout font!")
            }
        }

        let font_group = Rc::new(FontGroup::new(fonts));
        self.layout_font_group_cache.insert(layout_font_group_cache_key, font_group.clone());
        font_group
    }
}

impl HeapSizeOf for FontContext {
    fn heap_size_of_children(&self) -> usize {
        // FIXME(njn): Measure other fields eventually.
        self.platform_handle.heap_size_of_children()
    }
}

#[derive(Debug)]
struct LayoutFontGroupCacheKey {
    pointer: Arc<style_structs::Font>,
    size: Au,
}

impl PartialEq for LayoutFontGroupCacheKey {
    fn eq(&self, other: &LayoutFontGroupCacheKey) -> bool {
        self.pointer == other.pointer && self.size == other.size
    }
}

impl Eq for LayoutFontGroupCacheKey {}

impl Hash for LayoutFontGroupCacheKey {
    fn hash<H>(&self, hasher: &mut H) where H: Hasher {
        self.pointer.hash.hash(hasher)
    }
}

#[inline]
pub fn invalidate_font_caches() {
    FONT_CACHE_EPOCH.fetch_add(1, Ordering::SeqCst);
}
<|endoftext|>


<commit_before>#![crate_name = "mnemosyne"]
#![crate_type = "lib"]
#![feature(rustc_private)]
#![feature(cstr_memory)]

extern crate rustc;
extern crate combine;
extern crate seax_util as seax;

pub mod position;
pub mod ast;
pub mod compile;
<commit_msg>Versioning takes place now<commit_after>#![crate_name = "mnemosyne"]
#![crate_type = "lib"]
#![feature(rustc_private)]
#![feature(cstr_memory)]

extern crate rustc;
extern crate combine;
extern crate seax_util as seax;

pub mod position;
pub mod ast;
pub mod compile;

use rustc::lib::llvm::{LLVMVersionMajor, LLVMVersionMinor}

const VERSION_MAJOR: u32 = 0;
const VERSION_MINOR: u32 = 1;

pub fn llvm_version() -> String {
    format!("LLVM v{}.{}", LLVMVersionMajor(), LLVMVersionMinor())
}

pub fn mnemosyne_version() -> String {
    format!("Mnemosyne v{}.{}", VERSION_MAJOR, VERSION_MINOR)
}
<|endoftext|>


<commit_before>extern crate futures;
#[macro_use]
extern crate tokio_core;
extern crate tokio_process;
#[macro_use]
extern crate log;
extern crate env_logger;

use std::env;
use std::io;
use std::process::{Stdio, ExitStatus};

use futures::{Future, BoxFuture};
use futures::stream::{self, Stream};
use tokio_core::io::{read_until, write_all};
use tokio_core::reactor::{Core, Handle};
use tokio_process::{Command, Child};

fn cat(handle: &Handle) -> Command {
    let mut path = env::current_exe().unwrap();
    path.pop();
    path.push("cat");
    let mut cmd = Command::new(path, handle);
    cmd.stdin(Stdio::piped())
       .stdout(Stdio::piped());
    cmd
}

fn feed_cat(mut cat: Child, n: usize) -> BoxFuture<ExitStatus, io::Error> {
    let stdin = cat.stdin().take().unwrap();
    let stdout = cat.stdout().take().unwrap();

    debug!("starting to feed");
    // Produce n lines on the child's stdout.
    let numbers = stream::iter((0..n).into_iter().map(Ok));
    let write = numbers.fold(stdin, |stdin, i| {
        debug!("sending line {} to child", i);
        write_all(stdin, format!("line {}\n", i).into_bytes()).map(|p| p.0)
    }).map(|_| ());

    // Try to read `n + 1` lines, ensuring the last one is empty
    // (i.e. EOF is reached after `n` lines.
    let reader = io::BufReader::new(stdout);
    let expected_numbers = stream::iter((0..n + 1).map(Ok));
    let read = expected_numbers.fold((reader, 0), move |(reader, i), _| {
        let done = i >= n;
        debug!("starting read from child");
        read_until(reader, b'\n', Vec::new()).and_then(move |(reader, vec)| {
            debug!("read line {} from child ({} bytes, done: {})",
                   i, vec.len(), done);
            match (done, vec.len()) {
                (false, 0) => {
                    Err(io::Error::new(io::ErrorKind::BrokenPipe, "broken pipe"))
                },
                (true, n) if n != 0 => {
                    Err(io::Error::new(io::ErrorKind::Other, "extraneous data"))
                },
                _ => {
                    let s = std::str::from_utf8(&vec).unwrap();
                    let expected = format!("line {}\n", i);
                    if done || s == expected {
                        Ok((reader, i + 1))
                    } else {
                        Err(io::Error::new(io::ErrorKind::Other, "unexpected data"))
                    }
                }
            }
        })
    });

    // Compose reading and writing concurrently.
    write.join(read).and_then(|_| cat).boxed()
}

#[test]
/// Check for the following properties when feeding stdin and
/// consuming stdout of a cat-like process:
///
/// - A number of lines that amounts to a number of bytes exceeding a
///   typical OS buffer size can be fed to the child without
///   deadlock. This tests that we also consume the stdout
///   concurrently; otherwise this would deadlock.
///
/// - We read the same lines from the child that we fed it.
//
/// - The child does produce EOF on stdout after the last line.
fn feed_a_lot() {
    let _ = ::env_logger::init();

    let mut lp = Core::new().unwrap();
    let cmd = cat(&lp.handle());
    let child = cmd.spawn().and_then(|child| {
        feed_cat(child, 10000)
    });
    let status = lp.run(child).unwrap();
    assert_eq!(status.code(), Some(0));
}
<commit_msg>process: Fix nightly tests<commit_after>extern crate futures;
#[macro_use]
extern crate tokio_core;
extern crate tokio_process;
#[macro_use]
extern crate log;
extern crate env_logger;

use std::env;
use std::io;
use std::process::{Stdio, ExitStatus};

use futures::{Future, BoxFuture};
use futures::stream::{self, Stream};
use tokio_core::io::{read_until, write_all};
use tokio_core::reactor::{Core, Handle};
use tokio_process::{Command, Child};

fn cat(handle: &Handle) -> Command {
    let mut path = env::current_exe().unwrap();
    path.pop();
    if path.ends_with("deps") {
        path.pop();
    }
    path.push("cat");
    let mut cmd = Command::new(path, handle);
    cmd.stdin(Stdio::piped())
       .stdout(Stdio::piped());
    cmd
}

fn feed_cat(mut cat: Child, n: usize) -> BoxFuture<ExitStatus, io::Error> {
    let stdin = cat.stdin().take().unwrap();
    let stdout = cat.stdout().take().unwrap();

    debug!("starting to feed");
    // Produce n lines on the child's stdout.
    let numbers = stream::iter((0..n).into_iter().map(Ok));
    let write = numbers.fold(stdin, |stdin, i| {
        debug!("sending line {} to child", i);
        write_all(stdin, format!("line {}\n", i).into_bytes()).map(|p| p.0)
    }).map(|_| ());

    // Try to read `n + 1` lines, ensuring the last one is empty
    // (i.e. EOF is reached after `n` lines.
    let reader = io::BufReader::new(stdout);
    let expected_numbers = stream::iter((0..n + 1).map(Ok));
    let read = expected_numbers.fold((reader, 0), move |(reader, i), _| {
        let done = i >= n;
        debug!("starting read from child");
        read_until(reader, b'\n', Vec::new()).and_then(move |(reader, vec)| {
            debug!("read line {} from child ({} bytes, done: {})",
                   i, vec.len(), done);
            match (done, vec.len()) {
                (false, 0) => {
                    Err(io::Error::new(io::ErrorKind::BrokenPipe, "broken pipe"))
                },
                (true, n) if n != 0 => {
                    Err(io::Error::new(io::ErrorKind::Other, "extraneous data"))
                },
                _ => {
                    let s = std::str::from_utf8(&vec).unwrap();
                    let expected = format!("line {}\n", i);
                    if done || s == expected {
                        Ok((reader, i + 1))
                    } else {
                        Err(io::Error::new(io::ErrorKind::Other, "unexpected data"))
                    }
                }
            }
        })
    });

    // Compose reading and writing concurrently.
    write.join(read).and_then(|_| cat).boxed()
}

#[test]
/// Check for the following properties when feeding stdin and
/// consuming stdout of a cat-like process:
///
/// - A number of lines that amounts to a number of bytes exceeding a
///   typical OS buffer size can be fed to the child without
///   deadlock. This tests that we also consume the stdout
///   concurrently; otherwise this would deadlock.
///
/// - We read the same lines from the child that we fed it.
//
/// - The child does produce EOF on stdout after the last line.
fn feed_a_lot() {
    let _ = ::env_logger::init();

    let mut lp = Core::new().unwrap();
    let cmd = cat(&lp.handle());
    let child = cmd.spawn().and_then(|child| {
        feed_cat(child, 10000)
    });
    let status = lp.run(child).unwrap();
    assert_eq!(status.code(), Some(0));
}
<|endoftext|>


<commit_before>use std::error;
use std::fmt::{self, Debug, Display};
use std::io::{self, BufRead};

use {Grid, X, Y};

/// The type for errors occurring in reading puzrs data.
#[derive(Debug)]
pub enum ReadError {
    Io(io::Error),
    InvalidFormat,
    InvalidValue,
}

impl fmt::Display for ReadError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use std::error::Error;
        match *self {
            ReadError::Io(ref err) => Display::fmt(err, f),
            _ => write!(f, "{}", self.description()),
        }
    }
}

impl error::Error for ReadError {
    fn description(&self) -> &str {
        match *self {
            ReadError::Io(ref err) => err.description(),
            ReadError::InvalidFormat => "invalid format",
            ReadError::InvalidValue => "invalid value",
        }
    }
}

impl From<io::Error> for ReadError {
    fn from(err: io::Error) -> ReadError {
        ReadError::Io(err)
    }
}

fn is_comment(s: &String) -> bool {
    s.chars().next().unwrap() == '%'
}

pub fn next_valid_line(reader: &mut BufRead, buf: &mut String) -> io::Result<usize> {
    loop {
        buf.clear();
        let len = reader.read_line(buf)?;

        if len == 0 {
            return Err(io::Error::new(io::ErrorKind::UnexpectedEof, ""));
        }

        if !buf.trim().is_empty() && !is_comment(buf) {
            return Ok(len);
        }
    }
}

pub fn read_grid<R, F, T>(reader: &mut R, converter: F, default: T) -> Result<Grid<T>, ReadError>
where
    R: BufRead,
    F: Fn(&str) -> Result<T, ReadError>,
    T: Clone,
{
    let mut buffer = String::new();

    let height;
    let width;

    {
        next_valid_line(reader, &mut buffer)?;
        let mut header = buffer.split(' ');

        height = header
            .next()
            .ok_or(ReadError::InvalidFormat)?
            .trim()
            .parse::<i32>()
            .map_err(|_| ReadError::InvalidValue)?;
        width = header
            .next()
            .ok_or(ReadError::InvalidFormat)?
            .trim()
            .parse::<i32>()
            .map_err(|_| ReadError::InvalidValue)?;
    }

    let mut ret = Grid::new(height, width, default);

    for y in 0..height {
        next_valid_line(reader, &mut buffer)?;
        let mut row = buffer.split(' ');

        for x in 0..width {
            let elem = row.next().ok_or(ReadError::InvalidFormat)?;
            let converted_elem = converter(elem.as_ref())?;

            ret[(Y(y), X(x))] = converted_elem;
        }
    }

    Ok(ret)
}

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

    #[test]
    fn test_read_grid() {
        let mut src = "
3 4
% this line is a comment!
1 2 3 4
x y z w
p q r s
"
            .as_bytes();
        let grid = read_grid(&mut src, |s| Ok(s.to_string()), String::new()).unwrap();

        assert_eq!(grid.height(), 3);
        assert_eq!(grid.width(), 4);
        assert_eq!(grid[(Y(1), X(2))], "z".to_string());
    }
}
<commit_msg>Bug fix in io.rs<commit_after>use std::error;
use std::fmt::{self, Debug, Display};
use std::io::{self, BufRead};

use {Grid, X, Y};

/// The type for errors occurring in reading puzrs data.
#[derive(Debug)]
pub enum ReadError {
    Io(io::Error),
    InvalidFormat,
    InvalidValue,
}

impl fmt::Display for ReadError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use std::error::Error;
        match *self {
            ReadError::Io(ref err) => Display::fmt(err, f),
            _ => write!(f, "{}", self.description()),
        }
    }
}

impl error::Error for ReadError {
    fn description(&self) -> &str {
        match *self {
            ReadError::Io(ref err) => err.description(),
            ReadError::InvalidFormat => "invalid format",
            ReadError::InvalidValue => "invalid value",
        }
    }
}

impl From<io::Error> for ReadError {
    fn from(err: io::Error) -> ReadError {
        ReadError::Io(err)
    }
}

fn is_comment(s: &String) -> bool {
    s.chars().next().unwrap() == '%'
}

pub fn next_valid_line(reader: &mut BufRead, buf: &mut String) -> io::Result<usize> {
    loop {
        buf.clear();
        let len = reader.read_line(buf)?;

        if len == 0 {
            return Err(io::Error::new(io::ErrorKind::UnexpectedEof, ""));
        }

        if !buf.trim().is_empty() && !is_comment(buf) {
            return Ok(len);
        }
    }
}

pub fn read_grid<R, F, T>(reader: &mut R, converter: F, default: T) -> Result<Grid<T>, ReadError>
where
    R: BufRead,
    F: Fn(&str) -> Result<T, ReadError>,
    T: Clone,
{
    let mut buffer = String::new();

    let height;
    let width;

    {
        next_valid_line(reader, &mut buffer)?;
        let mut header = buffer.split(' ');

        height = header
            .next()
            .ok_or(ReadError::InvalidFormat)?
            .trim()
            .parse::<i32>()
            .map_err(|_| ReadError::InvalidValue)?;
        width = header
            .next()
            .ok_or(ReadError::InvalidFormat)?
            .trim()
            .parse::<i32>()
            .map_err(|_| ReadError::InvalidValue)?;
    }

    let mut ret = Grid::new(height, width, default);

    for y in 0..height {
        next_valid_line(reader, &mut buffer)?;
        let mut row = buffer.trim_end().split(' ');

        for x in 0..width {
            let elem = row.next().ok_or(ReadError::InvalidFormat)?;
            let converted_elem = converter(elem.as_ref())?;

            ret[(Y(y), X(x))] = converted_elem;
        }
    }

    Ok(ret)
}

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

    #[test]
    fn test_read_grid() {
        let mut src = "
3 4
% this line is a comment!
1 2 3 4
x y z w
p q r s
"
            .as_bytes();
        let grid = read_grid(&mut src, |s| Ok(s.to_string()), String::new()).unwrap();

        assert_eq!(grid.height(), 3);
        assert_eq!(grid.width(), 4);
        assert_eq!(grid[(Y(1), X(2))], "z".to_string());
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use super::names::Name;

pub trait RecordType {
    fn name(&self) -> &str;
    fn value(&self) -> u16;
}

#[derive(Debug,PartialEq)]
pub enum RecordClass {
    IN,
}

pub trait ResourceRecord {
    type RType: RecordType;
    type DType;

    fn name(&self) -> &Name;
    fn rr_type(&self) -> Self::RType;
    fn rr_class(&self) -> &RecordClass;
    fn ttl(&self) -> i32;

    fn data(&self) -> &Self::DType;
}

impl fmt::Display for RecordClass {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            RecordClass::IN => write!(f, "IN"),
        }
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {}
}
<commit_msg>Fix "Copy not implemented" lint error<commit_after>use std::fmt;
use super::names::Name;

pub trait RecordType {
    fn name(&self) -> &str;
    fn value(&self) -> u16;
}

#[derive(Debug,PartialEq,Clone,Copy)]
pub enum RecordClass {
    IN,
}

pub trait ResourceRecord {
    type RType: RecordType;
    type DType;

    fn name(&self) -> &Name;
    fn rr_type(&self) -> Self::RType;
    fn rr_class(&self) -> &RecordClass;
    fn ttl(&self) -> i32;

    fn data(&self) -> &Self::DType;
}

impl fmt::Display for RecordClass {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            RecordClass::IN => write!(f, "IN"),
        }
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {}
}
<|endoftext|>


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

extern crate memmem;
use memmem::{Searcher, TwoWaySearcher};

macro_rules! search(
    ($name:ident, $needle:expr, $hay:expr, $result:expr) => (
        #[test]
        fn $name() {
            let searcher = TwoWaySearcher::new($needle.as_bytes());
            println!("searching for {:?} in {:?}", $needle, $hay);
            assert_eq!(searcher.search_in($hay.as_bytes()), $result);
        }
    );
);

search!(periodic_1, "aaaaaaaa", "aaaaaaabaaaaaaabaaaaaaabaaaaaaaa", Some(24));
search!(periodic_2, "aaaaaaaa", "aaaaaaabaaaaaaabaaaaaaabaaaaaaab", None);
search!(periodic_3, "abcabc", "abcabdabcabdabcabdabcabc", Some(18));
search!(periodic_4, "abcabc", "abcabdabcabdabcabdabcabd", None);

search!(aperiodic_1, "dog", "The quick brown fox jumped over the lazy dog.", Some(41));
search!(aperiodic_2, "doggy", "The quick brown fox jumped over the lazy dog.", None);
<commit_msg>Test memory.<commit_after>// Copyright 2015 Joe Neeman.
//
// 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.

extern crate memmem;
use memmem::{Searcher, TwoWaySearcher};

macro_rules! search(
    ($name:ident, $needle:expr, $hay:expr, $result:expr) => (
        #[test]
        fn $name() {
            let searcher = TwoWaySearcher::new($needle.as_bytes());
            println!("searching for {:?} in {:?}", $needle, $hay);
            assert_eq!(searcher.search_in($hay.as_bytes()), $result);
        }
    );
);

search!(periodic_1, "aaaaaaaa", "aaaaaabaaaaaabaaaaaabaaaaaaaa", Some(21));
search!(periodic_2, "aaaaaaaa", "aaaaaabaaaaaabaaaaaabaaaaaaab", None);
search!(periodic_3, "abcabc", "abcabaabcabaabcabaabcabc", Some(18));
search!(periodic_4, "abcabc", "abcabaabcabaabcabaabcabd", None);
search!(periodic_5, "abcabcabc", "bbcabcabcabc", Some(3));

search!(aperiodic_1, "dog", "The quick brown fox jumped over the lazy dog.", Some(41));
search!(aperiodic_2, "doggy", "The quick brown fox jumped over the lazy dog.", None);

search!(skip, "aaaaaaaa", "aaaaaaabaaaaaaabaaaaaaab", None);
<|endoftext|>


<commit_before>pub extern crate conrod;

pub use self::conrod::{backend, color, cursor, event, graph, image, input, scroll, text, theme,
                       utils, widget};
pub use self::conrod::{Bordering, Borderable, Colorable, Dimensions, FontSize, Labelable, Point,
                       Positionable, Range, Rect, Scalar, Sizeable, Theme, UiCell, Widget};
pub use self::conrod::event::Input;

/// Simplify inclusion of common traits with a `nannou::ui::prelude` module.
pub mod prelude {
    // Traits.
    pub use super::{Borderable, Colorable, Labelable, Positionable, Sizeable, Widget};
    // Types.
    pub use super::{Bordering, Dimensions, FontSize, Input, Point, Range, Rect, Scalar, Theme, Ui,
                    UiCell};
    // Modules.
    pub use super::{color, image, text, widget};
}

use App;
use frame::Frame;
use glium::{self, glutin};
use std::cell::RefCell;
use std::collections::HashMap;
use std::path::PathBuf;
use std::sync::{mpsc, Mutex};
use std::ops::Deref;
use window::{self, Window};

/// Owned by the `App`, the `Arrangement` handles the mapping between `Ui`s and their associated
/// windows.
pub(crate) struct Arrangement {
    pub(super) windows: RefCell<HashMap<window::Id, Vec<Handle>>>,
}

/// A handle to the `Ui` owned by the `App`.
pub(crate) struct Handle {
    /// A channel used for automatically submitting `Input` to the associated `Ui`.
    pub(crate) input_tx: Option<mpsc::SyncSender<Input>>,
}

/// A handle to the `Ui` for a specific window.
pub struct Ui {
    /// The `Id` of the window upon which this `Ui` is instantiated.
    window_id: window::Id,
    ui: conrod::Ui,
    input_rx: Option<mpsc::Receiver<Input>>,
    renderer: Mutex<conrod::backend::glium::Renderer>,
    pub image_map: conrod::image::Map<glium::texture::Texture2d>,
}

/// A type used for building a new `Ui`.
pub struct Builder<'a> {
    app: &'a App,
    window_id: window::Id,
    dimensions: Option<[Scalar; 2]>,
    theme: Option<Theme>,
    automatically_handle_input: bool,
    pending_input_limit: usize,
    default_font_path: Option<PathBuf>,
}

/// A map from `image::Id`s to their associatd `Texture2d`.
pub type Texture2dMap = conrod::image::Map<glium::texture::Texture2d>;

impl conrod::backend::winit::WinitWindow for Window {
    fn get_inner_size(&self) -> Option<(u32, u32)> {
        Some(self.inner_size_pixels())
    }
    fn hidpi_factor(&self) -> f32 {
        self.hidpi_factor()
    }
}

impl Arrangement {
    /// Initialise a new UI **Arrangement** (used by the App).
    pub(crate) fn new() -> Self {
        let windows = RefCell::new(HashMap::new());
        Arrangement { windows }
    }
}

impl<'a> Builder<'a> {
    /// Begin building a new `Ui`.
    pub(super) fn new(app: &'a App, window_id: window::Id) -> Self {
        Builder {
            app,
            window_id,
            dimensions: None,
            theme: None,
            automatically_handle_input: true,
            pending_input_limit: Ui::DEFAULT_PENDING_INPUT_LIMIT,
            default_font_path: None,
        }
    }

    /// Build the `Ui` with the given dimensions.
    ///
    /// By default, the `Ui` will have  the dimensions of the specified window.
    pub fn with_dimensions(mut self, dimensions: [Scalar; 2]) -> Self {
        self.dimensions = Some(dimensions);
        self
    }

    /// Build the `Ui` with the given theme.
    ///
    /// By default, nannou uses conrod's default theme.
    pub fn with_theme(mut self, theme: Theme) -> Self {
        self.theme = Some(theme);
        self
    }

    /// Whether or not the `App` should automatically submit input to the `Ui`.
    ///
    /// When enabled, events that can be interpreted as UI `Input` will be passed to the `Ui` via
    /// the `conrod::Ui::handle_input` method.
    ///
    /// Note that `Input`s are not immediately submitted to the `Ui` when received by the `App`.
    /// Instead, they are enqueued for the `Ui` to be processed next time `Ui::set_widgets` is
    /// called. The max number of pending `Input`s before they become ignored can be specified via
    /// the `pending_input_limit` method.
    ///
    /// By default this is `true`. Users should set this to `false` if they wish to manually filter
    /// and submit events (e.g. if something is occluding the `Ui` and the user wishes to filter
    /// occluded input).
    pub fn automatically_handle_input(mut self, b: bool) -> Self {
        self.automatically_handle_input = b;
        self
    }

    /// Specify the max number of pending `Input`s that can be enqueued for processing by the `Ui`
    /// before `Input`s start being ignored.
    ///
    /// By default this is `Ui::DEFAULT_PENDING_INPUT_LIMIT`.
    ///
    /// This has no affect if `automatically_handle_input` is set to `false`.
    pub fn pending_input_limit(mut self, limit: usize) -> Self {
        self.pending_input_limit = limit;
        self
    }

    /// Specify the path to the default font.
    ///
    /// By default this is "fonts/NotoSans/NotoSans-Regular.ttf".
    ///
    /// Fonts can also be specified manually after `Ui` creation using the `fonts_mut` method.
    pub fn default_font_path(mut self, path: PathBuf) -> Self {
        self.default_font_path = Some(path);
        self
    }

    /// Build a `Ui` with the specified parameters.
    ///
    /// Returns `None` if the window at the given `Id` is closed or if the inner `Renderer` returns
    /// an error upon creation.
    pub fn build(self) -> Option<Ui> {
        let Builder {
            app,
            window_id,
            dimensions,
            theme,
            pending_input_limit,
            automatically_handle_input,
            default_font_path,
        } = self;
        let dimensions = match dimensions {
            None => match app.window(window_id) {
                None => return None,
                Some(window) => {
                    let (win_w, win_h) = window.inner_size_points();
                    [win_w as Scalar, win_h as Scalar]
                },
            },
            Some(dimensions) => dimensions,
        };
        let theme = theme.unwrap_or_else(Theme::default);
        let ui = conrod::UiBuilder::new(dimensions).theme(theme).build();

        let (input_rx, handle) = if automatically_handle_input {
            let (input_tx, input_rx) = mpsc::sync_channel(pending_input_limit);
            let input_tx = Some(input_tx);
            let input_rx = Some(input_rx);
            let handle = Handle { input_tx };
            (input_rx, handle)
        } else {
            let input_tx = None;
            let input_rx = None;
            let handle = Handle { input_tx };
            (input_rx, handle)
        };

        // Insert the handle into the app's UI arrangement.
        app.ui.windows.borrow_mut()
            .entry(window_id)
            .or_insert(Vec::new())
            .push(handle);

        // Initialise the renderer which draws conrod::render::Primitives to the frame..
        let renderer = match app.windows.borrow().get(&window_id) {
            None => return None,
            Some(window) => match conrod::backend::glium::Renderer::new(&window.display) {
                Ok(renderer) => Mutex::new(renderer),
                Err(_) => return None,
            },
        };

        // Initialise the image map.
        let image_map = image::Map::new();

        // Initialise the `Ui`.
        let mut ui = Ui { window_id, ui, input_rx, renderer, image_map };

        // If the default font is in the assets/fonts directory, load it into the UI font map.
        let default_font_path = default_font_path
            .or_else(|| app.assets_path().ok().map(|p| p.join(Ui::DEFAULT_FONT_PATH)));

        // If there is some font path to use for the default font, attempt to load it.
        if let Some(font_path) = default_font_path {
            ui.fonts_mut().insert_from_file(font_path).ok();
        }

        Some(ui)
    }
}

impl Deref for Ui {
    type Target = conrod::Ui;
    fn deref(&self) -> &Self::Target {
        &self.ui
    }
}

impl Ui {
    /// The default maximum number of `Input`s that a `Ui` will store in its pending `Input` queue
    /// before `Input`s start being ignored.
    pub const DEFAULT_PENDING_INPUT_LIMIT: usize = 1024;
    /// The path to the default font for the `Ui`.
    pub const DEFAULT_FONT_PATH: &'static str = "fonts/NotoSans/NotoSans-Regular.ttf";

    /// Generate a new, unique `widget::Id` into a Placeholder node within the widget graph. This
    /// should only be called once for each unique widget needed to avoid unnecessary bloat within
    /// the `Ui`'s internal widget graph.
    ///
    /// When using this method, be sure to store the returned `widget::Id` somewhere so that it can
    /// be re-used on next update.
    ///
    /// **Panics** if adding another node would exceed the maximum capacity for node indices.
    pub fn generate_widget_id(&mut self) -> widget::Id {
        self.widget_id_generator().next()
    }

    /// Produces the type that may be used to generate new unique `widget::Id`s.
    pub fn widget_id_generator(&mut self) -> widget::id::Generator {
        self.ui.widget_id_generator()
    }

    /// Handle a raw UI input event and update the **Ui** state accordingly.
    ///
    /// This method *drives* the **Ui** forward and interprets input into higher-level events (like
    /// clicks and drags) for widgets.
    pub fn handle_input(&mut self, input: Input) {
        self.ui.handle_event(input)
    }

    /// Processes all pending input.
    ///
    /// This is automatically called at the beginning of the `set_widgets` method, so the user
    /// should never need to call this manually, however the method is exposed for flexibility
    /// just in case.
    ///
    /// This has no effect if automatic input handling is disabled.
    pub fn handle_pending_input(&mut self) {
        let Ui { ref mut ui, ref input_rx, .. } = *self;
        if let Some(ref rx) = *input_rx {
            for input in rx.try_iter() {
                ui.handle_event(input);
            }
        }
    }

    /// Returns a context upon which UI widgets can be instantiated.
    ///
    /// The **UiCell** simply acts as a wrapper around the **Ui** for the period over which widgets
    /// are instantiated. Once the **UiCell** is dropped, it does some cleanup and sorting that is
    /// required after widget instantiation.
    pub fn set_widgets(&mut self) -> UiCell {
        // Process any pending inputs first.
        self.handle_pending_input();
        self.ui.set_widgets()
    }

    /// Mutable access to the `Ui`'s font map.
    ///
    /// This allows for adding and removing fonts to the UI.
    pub fn fonts_mut(&mut self) -> &mut text::font::Map {
        &mut self.ui.fonts
    }

    /// Mutable access to the `Ui`'s `Theme`.
    ///
    /// This allows for making changes to the active theme.
    pub fn theme_mut(&mut self) -> &mut Theme {
        &mut self.ui.theme
    }

    /// Draws the current state of the `Ui` to the given `Frame`.
    ///
    /// The `Ui` will automatically draw to its associated window within the given `Frame`.
    ///
    /// If you require more control over where the `Ui` is drawn within the `Frame`, the `draw`
    /// method offers more flexibility.
    ///
    /// This has no effect if the window originally associated with the `Ui` no longer exists.
    pub fn draw_to_frame(&self, app: &App, frame: &Frame)
        -> Result<(), conrod::backend::glium::DrawError>
    {
        let Ui { ref ui, ref renderer, ref image_map, window_id, .. } = *self;
        if let Some(window) = app.window(window_id) {
            if let Some(mut window_frame) = frame.window(window_id) {
                if let Ok(mut renderer) = renderer.lock() {
                    let primitives = ui.draw();
                    renderer.fill(&window.display, primitives, &image_map);
                    window_frame.clear_color(0.0, 0.0, 0.0, 1.0);
                    renderer.draw(&window.display, &mut window_frame.frame.frame, image_map)?;
                }
            }
        }
        Ok(())
    }
}

/// Convert the given window event to a UI Input.
///
/// Returns `None` if there's no associated UI Input for the given event.
pub fn glutin_window_event_to_input(event: glutin::WindowEvent, window: &Window) -> Option<Input> {
    conrod::backend::winit::convert_window_event(event, window)
}
<commit_msg>Add clear_with(Color) method to the Ui<commit_after>pub extern crate conrod;

pub use self::conrod::{backend, color, cursor, event, graph, image, input, scroll, text, theme,
                       utils, widget};
pub use self::conrod::{Bordering, Borderable, Color, Colorable, Dimensions, FontSize, Labelable,
                       Point, Positionable, Range, Rect, Scalar, Sizeable, Theme, UiCell, Widget};
pub use self::conrod::event::Input;

/// Simplify inclusion of common traits with a `nannou::ui::prelude` module.
pub mod prelude {
    // Traits.
    pub use super::{Borderable, Colorable, Labelable, Positionable, Sizeable, Widget};
    // Types.
    pub use super::{Bordering, Dimensions, FontSize, Input, Point, Range, Rect, Scalar, Theme, Ui,
                    UiCell};
    // Modules.
    pub use super::{color, image, text, widget};
}

use App;
use frame::Frame;
use glium::{self, glutin};
use std::cell::RefCell;
use std::collections::HashMap;
use std::path::PathBuf;
use std::sync::{mpsc, Mutex};
use std::ops::Deref;
use window::{self, Window};

/// Owned by the `App`, the `Arrangement` handles the mapping between `Ui`s and their associated
/// windows.
pub(crate) struct Arrangement {
    pub(super) windows: RefCell<HashMap<window::Id, Vec<Handle>>>,
}

/// A handle to the `Ui` owned by the `App`.
pub(crate) struct Handle {
    /// A channel used for automatically submitting `Input` to the associated `Ui`.
    pub(crate) input_tx: Option<mpsc::SyncSender<Input>>,
}

/// A handle to the `Ui` for a specific window.
pub struct Ui {
    /// The `Id` of the window upon which this `Ui` is instantiated.
    window_id: window::Id,
    ui: conrod::Ui,
    input_rx: Option<mpsc::Receiver<Input>>,
    renderer: Mutex<conrod::backend::glium::Renderer>,
    pub image_map: conrod::image::Map<glium::texture::Texture2d>,
}

/// A type used for building a new `Ui`.
pub struct Builder<'a> {
    app: &'a App,
    window_id: window::Id,
    dimensions: Option<[Scalar; 2]>,
    theme: Option<Theme>,
    automatically_handle_input: bool,
    pending_input_limit: usize,
    default_font_path: Option<PathBuf>,
}

/// A map from `image::Id`s to their associatd `Texture2d`.
pub type Texture2dMap = conrod::image::Map<glium::texture::Texture2d>;

impl conrod::backend::winit::WinitWindow for Window {
    fn get_inner_size(&self) -> Option<(u32, u32)> {
        Some(self.inner_size_pixels())
    }
    fn hidpi_factor(&self) -> f32 {
        self.hidpi_factor()
    }
}

impl Arrangement {
    /// Initialise a new UI **Arrangement** (used by the App).
    pub(crate) fn new() -> Self {
        let windows = RefCell::new(HashMap::new());
        Arrangement { windows }
    }
}

impl<'a> Builder<'a> {
    /// Begin building a new `Ui`.
    pub(super) fn new(app: &'a App, window_id: window::Id) -> Self {
        Builder {
            app,
            window_id,
            dimensions: None,
            theme: None,
            automatically_handle_input: true,
            pending_input_limit: Ui::DEFAULT_PENDING_INPUT_LIMIT,
            default_font_path: None,
        }
    }

    /// Build the `Ui` with the given dimensions.
    ///
    /// By default, the `Ui` will have  the dimensions of the specified window.
    pub fn with_dimensions(mut self, dimensions: [Scalar; 2]) -> Self {
        self.dimensions = Some(dimensions);
        self
    }

    /// Build the `Ui` with the given theme.
    ///
    /// By default, nannou uses conrod's default theme.
    pub fn with_theme(mut self, theme: Theme) -> Self {
        self.theme = Some(theme);
        self
    }

    /// Whether or not the `App` should automatically submit input to the `Ui`.
    ///
    /// When enabled, events that can be interpreted as UI `Input` will be passed to the `Ui` via
    /// the `conrod::Ui::handle_input` method.
    ///
    /// Note that `Input`s are not immediately submitted to the `Ui` when received by the `App`.
    /// Instead, they are enqueued for the `Ui` to be processed next time `Ui::set_widgets` is
    /// called. The max number of pending `Input`s before they become ignored can be specified via
    /// the `pending_input_limit` method.
    ///
    /// By default this is `true`. Users should set this to `false` if they wish to manually filter
    /// and submit events (e.g. if something is occluding the `Ui` and the user wishes to filter
    /// occluded input).
    pub fn automatically_handle_input(mut self, b: bool) -> Self {
        self.automatically_handle_input = b;
        self
    }

    /// Specify the max number of pending `Input`s that can be enqueued for processing by the `Ui`
    /// before `Input`s start being ignored.
    ///
    /// By default this is `Ui::DEFAULT_PENDING_INPUT_LIMIT`.
    ///
    /// This has no affect if `automatically_handle_input` is set to `false`.
    pub fn pending_input_limit(mut self, limit: usize) -> Self {
        self.pending_input_limit = limit;
        self
    }

    /// Specify the path to the default font.
    ///
    /// By default this is "fonts/NotoSans/NotoSans-Regular.ttf".
    ///
    /// Fonts can also be specified manually after `Ui` creation using the `fonts_mut` method.
    pub fn default_font_path(mut self, path: PathBuf) -> Self {
        self.default_font_path = Some(path);
        self
    }

    /// Build a `Ui` with the specified parameters.
    ///
    /// Returns `None` if the window at the given `Id` is closed or if the inner `Renderer` returns
    /// an error upon creation.
    pub fn build(self) -> Option<Ui> {
        let Builder {
            app,
            window_id,
            dimensions,
            theme,
            pending_input_limit,
            automatically_handle_input,
            default_font_path,
        } = self;
        let dimensions = match dimensions {
            None => match app.window(window_id) {
                None => return None,
                Some(window) => {
                    let (win_w, win_h) = window.inner_size_points();
                    [win_w as Scalar, win_h as Scalar]
                },
            },
            Some(dimensions) => dimensions,
        };
        let theme = theme.unwrap_or_else(Theme::default);
        let ui = conrod::UiBuilder::new(dimensions).theme(theme).build();

        let (input_rx, handle) = if automatically_handle_input {
            let (input_tx, input_rx) = mpsc::sync_channel(pending_input_limit);
            let input_tx = Some(input_tx);
            let input_rx = Some(input_rx);
            let handle = Handle { input_tx };
            (input_rx, handle)
        } else {
            let input_tx = None;
            let input_rx = None;
            let handle = Handle { input_tx };
            (input_rx, handle)
        };

        // Insert the handle into the app's UI arrangement.
        app.ui.windows.borrow_mut()
            .entry(window_id)
            .or_insert(Vec::new())
            .push(handle);

        // Initialise the renderer which draws conrod::render::Primitives to the frame..
        let renderer = match app.windows.borrow().get(&window_id) {
            None => return None,
            Some(window) => match conrod::backend::glium::Renderer::new(&window.display) {
                Ok(renderer) => Mutex::new(renderer),
                Err(_) => return None,
            },
        };

        // Initialise the image map.
        let image_map = image::Map::new();

        // Initialise the `Ui`.
        let mut ui = Ui { window_id, ui, input_rx, renderer, image_map };

        // If the default font is in the assets/fonts directory, load it into the UI font map.
        let default_font_path = default_font_path
            .or_else(|| app.assets_path().ok().map(|p| p.join(Ui::DEFAULT_FONT_PATH)));

        // If there is some font path to use for the default font, attempt to load it.
        if let Some(font_path) = default_font_path {
            ui.fonts_mut().insert_from_file(font_path).ok();
        }

        Some(ui)
    }
}

impl Deref for Ui {
    type Target = conrod::Ui;
    fn deref(&self) -> &Self::Target {
        &self.ui
    }
}

impl Ui {
    /// The default maximum number of `Input`s that a `Ui` will store in its pending `Input` queue
    /// before `Input`s start being ignored.
    pub const DEFAULT_PENDING_INPUT_LIMIT: usize = 1024;
    /// The path to the default font for the `Ui`.
    pub const DEFAULT_FONT_PATH: &'static str = "fonts/NotoSans/NotoSans-Regular.ttf";

    /// Generate a new, unique `widget::Id` into a Placeholder node within the widget graph. This
    /// should only be called once for each unique widget needed to avoid unnecessary bloat within
    /// the `Ui`'s internal widget graph.
    ///
    /// When using this method, be sure to store the returned `widget::Id` somewhere so that it can
    /// be re-used on next update.
    ///
    /// **Panics** if adding another node would exceed the maximum capacity for node indices.
    pub fn generate_widget_id(&mut self) -> widget::Id {
        self.widget_id_generator().next()
    }

    /// Produces the type that may be used to generate new unique `widget::Id`s.
    pub fn widget_id_generator(&mut self) -> widget::id::Generator {
        self.ui.widget_id_generator()
    }

    /// Handle a raw UI input event and update the **Ui** state accordingly.
    ///
    /// This method *drives* the **Ui** forward and interprets input into higher-level events (like
    /// clicks and drags) for widgets.
    pub fn handle_input(&mut self, input: Input) {
        self.ui.handle_event(input)
    }

    /// Processes all pending input.
    ///
    /// This is automatically called at the beginning of the `set_widgets` method, so the user
    /// should never need to call this manually, however the method is exposed for flexibility
    /// just in case.
    ///
    /// This has no effect if automatic input handling is disabled.
    pub fn handle_pending_input(&mut self) {
        let Ui { ref mut ui, ref input_rx, .. } = *self;
        if let Some(ref rx) = *input_rx {
            for input in rx.try_iter() {
                ui.handle_event(input);
            }
        }
    }

    /// Returns a context upon which UI widgets can be instantiated.
    ///
    /// The **UiCell** simply acts as a wrapper around the **Ui** for the period over which widgets
    /// are instantiated. Once the **UiCell** is dropped, it does some cleanup and sorting that is
    /// required after widget instantiation.
    pub fn set_widgets(&mut self) -> UiCell {
        // Process any pending inputs first.
        self.handle_pending_input();
        self.ui.set_widgets()
    }

    /// Mutable access to the `Ui`'s font map.
    ///
    /// This allows for adding and removing fonts to the UI.
    pub fn fonts_mut(&mut self) -> &mut text::font::Map {
        &mut self.ui.fonts
    }

    /// Mutable access to the `Ui`'s `Theme`.
    ///
    /// This allows for making changes to the active theme.
    pub fn theme_mut(&mut self) -> &mut Theme {
        &mut self.ui.theme
    }

    /// The first of the `Primitives` yielded by `Ui::draw` will always be a `Rectangle` the size
    /// of the window in which the Ui is instantiated.
    ///
    /// This method sets the colour with which this `Rectangle` is drawn (the default being
    /// `color::TRANSPARENT`).
    pub fn clear_with(&mut self, color: Color) {
        self.ui.clear_with(color)
    }

    /// Draws the current state of the `Ui` to the given `Frame`.
    ///
    /// The `Ui` will automatically draw to its associated window within the given `Frame`.
    ///
    /// If you require more control over where the `Ui` is drawn within the `Frame`, the `draw`
    /// method offers more flexibility.
    ///
    /// This has no effect if the window originally associated with the `Ui` no longer exists.
    pub fn draw_to_frame(&self, app: &App, frame: &Frame)
        -> Result<(), conrod::backend::glium::DrawError>
    {
        let Ui { ref ui, ref renderer, ref image_map, window_id, .. } = *self;
        if let Some(window) = app.window(window_id) {
            if let Some(mut window_frame) = frame.window(window_id) {
                if let Ok(mut renderer) = renderer.lock() {
                    let primitives = ui.draw();
                    renderer.fill(&window.display, primitives, &image_map);
                    window_frame.clear_color(0.0, 0.0, 0.0, 1.0);
                    renderer.draw(&window.display, &mut window_frame.frame.frame, image_map)?;
                }
            }
        }
        Ok(())
    }
}

/// Convert the given window event to a UI Input.
///
/// Returns `None` if there's no associated UI Input for the given event.
pub fn glutin_window_event_to_input(event: glutin::WindowEvent, window: &Window) -> Option<Input> {
    conrod::backend::winit::convert_window_event(event, window)
}
<|endoftext|>


<commit_before>extern crate cbindgen;

use cbindgen::*;
use std::path::Path;
use std::process::Command;
use std::{env, fs, str};

fn style_str(style: Style) -> &'static str {
    match style {
        Style::Both => "both",
        Style::Tag => "tag",
        Style::Type => "type",
    }
}

fn run_cbindgen(
    cbindgen_path: &'static str,
    path: &Path,
    output: &Path,
    language: Language,
    cpp_compat: bool,
    style: Option<Style>,
) {
    let program = Path::new(cbindgen_path);
    let mut command = Command::new(&program);
    match language {
        Language::Cxx => {}
        Language::C => {
            command.arg("--lang").arg("c");

            if cpp_compat {
                command.arg("--cpp-compat");
            }
        }
    }

    if let Some(style) = style {
        command.arg("--style").arg(style_str(style));
    }

    command.arg("-o").arg(output);

    if env::var("CBINDGEN_TEST_VERIFY").is_ok() {
        command.arg("--verify");
    }

    let mut config = path.clone().to_path_buf();
    config.set_extension("toml");
    if config.exists() {
        command.arg("--config").arg(config);
    }

    command.arg(path);

    println!("Running: {:?}", command);
    let cbindgen_output = command.output().expect("failed to execute process");
    assert!(
        cbindgen_output.status.success(),
        "cbindgen failed: {:?} with error: {}",
        output,
        str::from_utf8(&cbindgen_output.stderr).unwrap_or_default()
    );
}

fn compile(
    cbindgen_output: &Path,
    tests_path: &Path,
    tmp_dir: &Path,
    language: Language,
    style: Option<Style>,
    skip_warning_as_error: bool,
) {
    let cc = match language {
        Language::Cxx => env::var("CXX").unwrap_or_else(|_| "g++".to_owned()),
        Language::C => env::var("CC").unwrap_or_else(|_| "gcc".to_owned()),
    };

    let file_name = cbindgen_output
        .file_name()
        .expect("cbindgen output should be a file");
    let mut object = tmp_dir.join(file_name);
    object.set_extension("o");

    let mut command = Command::new(cc);
    command.arg("-D").arg("DEFINED");
    command.arg("-I").arg(tests_path);
    command.arg("-Wall");
    if !skip_warning_as_error {
        command.arg("-Werror");
    }
    // `swift_name` is not recognzied by gcc.
    command.arg("-Wno-attributes");
    // clang warns about unused const variables.
    command.arg("-Wno-unused-const-variable");
    // clang also warns about returning non-instantiated templates (they could
    // be specialized, but they're not so it's fine).
    command.arg("-Wno-return-type-c-linkage");
    if let Language::Cxx = language {
        // enum class is a c++11 extension which makes g++ on macos 10.14 error out
        // inline variables are are a c++17 extension
        command.arg("-std=c++17");
        // Prevents warnings when compiling .c files as c++.
        command.arg("-x").arg("c++");
        if let Ok(extra_flags) = env::var("CXXFLAGS") {
            command.args(extra_flags.split_whitespace());
        }
    } else {
        if let Ok(extra_flags) = env::var("CFLAGS") {
            command.args(extra_flags.split_whitespace());
        }
    }

    if let Some(style) = style {
        command.arg("-D");
        command.arg(format!(
            "CBINDGEN_STYLE_{}",
            style_str(style).to_uppercase()
        ));
    }

    command.arg("-o").arg(&object);
    command.arg("-c").arg(cbindgen_output);

    println!("Running: {:?}", command);
    let out = command.output().expect("failed to compile");
    assert!(out.status.success(), "Output failed to compile: {:?}", out);

    if object.exists() {
        fs::remove_file(object).unwrap();
    }
}

const SKIP_WARNING_AS_ERROR_SUFFIX: &'static str = ".skip_warning_as_error";

fn run_compile_test(
    cbindgen_path: &'static str,
    name: &'static str,
    path: &Path,
    tmp_dir: &Path,
    language: Language,
    cpp_compat: bool,
    style: Option<Style>,
) {
    let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let tests_path = Path::new(&crate_dir).join("tests");
    let mut generated_file = tests_path.join("expectations");

    let style_ext = style
        .map(|style| match style {
            Style::Both => ".both",
            Style::Tag => ".tag",
            Style::Type => "",
        })
        .unwrap_or_default();
    let lang_ext = match language {
        Language::Cxx => ".cpp",
        Language::C if cpp_compat => ".compat.c",
        Language::C => ".c",
    };

    let skip_warning_as_error = name.rfind(SKIP_WARNING_AS_ERROR_SUFFIX).is_some();

    let source_file =
        format!("{}{}{}", name, style_ext, lang_ext).replace(SKIP_WARNING_AS_ERROR_SUFFIX, "");

    generated_file.push(source_file);

    run_cbindgen(
        cbindgen_path,
        path,
        &generated_file,
        language,
        cpp_compat,
        style,
    );

    compile(
        &generated_file,
        &tests_path,
        tmp_dir,
        language,
        style,
        skip_warning_as_error,
    );

    if language == Language::C && cpp_compat {
        compile(
            &generated_file,
            &tests_path,
            tmp_dir,
            Language::Cxx,
            style,
            skip_warning_as_error,
        );
    }
}

fn test_file(cbindgen_path: &'static str, name: &'static str, filename: &'static str) {
    let test = Path::new(filename);
    let tmp_dir = tempfile::Builder::new()
        .prefix("cbindgen-test-output")
        .tempdir()
        .expect("Creating tmp dir failed");
    let tmp_dir = tmp_dir.path();
    for style in &[Style::Type, Style::Tag, Style::Both] {
        for cpp_compat in &[true, false] {
            run_compile_test(
                cbindgen_path,
                name,
                &test,
                tmp_dir,
                Language::C,
                *cpp_compat,
                Some(*style),
            );
        }
    }

    run_compile_test(
        cbindgen_path,
        name,
        &test,
        tmp_dir,
        Language::Cxx,
        /* cpp_compat = */ false,
        None,
    );
}

macro_rules! test_file {
    ($cbindgen_path:expr, $test_function_name:ident, $name:expr, $file:tt) => {
        #[test]
        fn $test_function_name() {
            test_file($cbindgen_path, $name, $file);
        }
    };
}

// This file is generated by build.rs
include!(concat!(env!("OUT_DIR"), "/tests.rs"));
<commit_msg>test suite: Do not generate identical expectation files<commit_after>extern crate cbindgen;

use cbindgen::*;
use std::collections::HashSet;
use std::path::Path;
use std::process::Command;
use std::{env, fs, str};

fn style_str(style: Style) -> &'static str {
    match style {
        Style::Both => "both",
        Style::Tag => "tag",
        Style::Type => "type",
    }
}

fn run_cbindgen(
    cbindgen_path: &'static str,
    path: &Path,
    output: &Path,
    language: Language,
    cpp_compat: bool,
    style: Option<Style>,
) -> Vec<u8> {
    let program = Path::new(cbindgen_path);
    let mut command = Command::new(&program);
    match language {
        Language::Cxx => {}
        Language::C => {
            command.arg("--lang").arg("c");

            if cpp_compat {
                command.arg("--cpp-compat");
            }
        }
    }

    if let Some(style) = style {
        command.arg("--style").arg(style_str(style));
    }

    let mut config = path.clone().to_path_buf();
    config.set_extension("toml");
    if config.exists() {
        command.arg("--config").arg(config);
    }

    command.arg(path);

    println!("Running: {:?}", command);
    let cbindgen_output = command.output().expect("failed to execute process");
    assert!(
        cbindgen_output.status.success(),
        "cbindgen failed: {:?} with error: {}",
        output,
        str::from_utf8(&cbindgen_output.stderr).unwrap_or_default()
    );
    cbindgen_output.stdout
}

fn compile(
    cbindgen_output: &Path,
    tests_path: &Path,
    tmp_dir: &Path,
    language: Language,
    style: Option<Style>,
    skip_warning_as_error: bool,
) {
    let cc = match language {
        Language::Cxx => env::var("CXX").unwrap_or_else(|_| "g++".to_owned()),
        Language::C => env::var("CC").unwrap_or_else(|_| "gcc".to_owned()),
    };

    let file_name = cbindgen_output
        .file_name()
        .expect("cbindgen output should be a file");
    let mut object = tmp_dir.join(file_name);
    object.set_extension("o");

    let mut command = Command::new(cc);
    command.arg("-D").arg("DEFINED");
    command.arg("-I").arg(tests_path);
    command.arg("-Wall");
    if !skip_warning_as_error {
        command.arg("-Werror");
    }
    // `swift_name` is not recognzied by gcc.
    command.arg("-Wno-attributes");
    // clang warns about unused const variables.
    command.arg("-Wno-unused-const-variable");
    // clang also warns about returning non-instantiated templates (they could
    // be specialized, but they're not so it's fine).
    command.arg("-Wno-return-type-c-linkage");
    if let Language::Cxx = language {
        // enum class is a c++11 extension which makes g++ on macos 10.14 error out
        // inline variables are are a c++17 extension
        command.arg("-std=c++17");
        // Prevents warnings when compiling .c files as c++.
        command.arg("-x").arg("c++");
        if let Ok(extra_flags) = env::var("CXXFLAGS") {
            command.args(extra_flags.split_whitespace());
        }
    } else {
        if let Ok(extra_flags) = env::var("CFLAGS") {
            command.args(extra_flags.split_whitespace());
        }
    }

    if let Some(style) = style {
        command.arg("-D");
        command.arg(format!(
            "CBINDGEN_STYLE_{}",
            style_str(style).to_uppercase()
        ));
    }

    command.arg("-o").arg(&object);
    command.arg("-c").arg(cbindgen_output);

    println!("Running: {:?}", command);
    let out = command.output().expect("failed to compile");
    assert!(out.status.success(), "Output failed to compile: {:?}", out);

    if object.exists() {
        fs::remove_file(object).unwrap();
    }
}

const SKIP_WARNING_AS_ERROR_SUFFIX: &'static str = ".skip_warning_as_error";

fn run_compile_test(
    cbindgen_path: &'static str,
    name: &'static str,
    path: &Path,
    tmp_dir: &Path,
    language: Language,
    cpp_compat: bool,
    style: Option<Style>,
    cbindgen_outputs: &mut HashSet<Vec<u8>>,
) {
    let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let tests_path = Path::new(&crate_dir).join("tests");
    let mut generated_file = tests_path.join("expectations");
    fs::create_dir_all(&generated_file).unwrap();

    let style_ext = style
        .map(|style| match style {
            Style::Both => ".both",
            Style::Tag => ".tag",
            Style::Type => "",
        })
        .unwrap_or_default();
    let lang_ext = match language {
        Language::Cxx => ".cpp",
        Language::C if cpp_compat => ".compat.c",
        Language::C => ".c",
    };

    let skip_warning_as_error = name.rfind(SKIP_WARNING_AS_ERROR_SUFFIX).is_some();

    let source_file =
        format!("{}{}{}", name, style_ext, lang_ext).replace(SKIP_WARNING_AS_ERROR_SUFFIX, "");

    generated_file.push(source_file);

    let cbindgen_output = run_cbindgen(
        cbindgen_path,
        path,
        &generated_file,
        language,
        cpp_compat,
        style,
    );

    if cbindgen_outputs.contains(&cbindgen_output) {
        // We already generated an identical file previously.
        if env::var_os("CBINDGEN_TEST_VERIFY").is_some() {
            assert!(!generated_file.exists());
        } else {
            if generated_file.exists() {
                fs::remove_file(&generated_file).unwrap();
            }
        }
    } else {
        if env::var_os("CBINDGEN_TEST_VERIFY").is_some() {
            let prev_cbindgen_output = fs::read(&generated_file).unwrap();
            assert_eq!(cbindgen_output, prev_cbindgen_output);
        } else {
            fs::write(&generated_file, &cbindgen_output).unwrap();
        }

        cbindgen_outputs.insert(cbindgen_output);

        compile(
            &generated_file,
            &tests_path,
            tmp_dir,
            language,
            style,
            skip_warning_as_error,
        );

        if language == Language::C && cpp_compat {
            compile(
                &generated_file,
                &tests_path,
                tmp_dir,
                Language::Cxx,
                style,
                skip_warning_as_error,
            );
        }
    }
}

fn test_file(cbindgen_path: &'static str, name: &'static str, filename: &'static str) {
    let test = Path::new(filename);
    let tmp_dir = tempfile::Builder::new()
        .prefix("cbindgen-test-output")
        .tempdir()
        .expect("Creating tmp dir failed");
    let tmp_dir = tmp_dir.path();
    // Run tests in deduplication priority order. C++ compatibility tests are run first,
    // otherwise we would lose the C++ compiler run if they were deduplicated.
    let mut cbindgen_outputs = HashSet::new();
    for cpp_compat in &[true, false] {
        for style in &[Style::Type, Style::Tag, Style::Both] {
            run_compile_test(
                cbindgen_path,
                name,
                &test,
                tmp_dir,
                Language::C,
                *cpp_compat,
                Some(*style),
                &mut cbindgen_outputs,
            );
        }
    }

    run_compile_test(
        cbindgen_path,
        name,
        &test,
        tmp_dir,
        Language::Cxx,
        /* cpp_compat = */ false,
        None,
        &mut HashSet::new(),
    );
}

macro_rules! test_file {
    ($cbindgen_path:expr, $test_function_name:ident, $name:expr, $file:tt) => {
        #[test]
        fn $test_function_name() {
            test_file($cbindgen_path, $name, $file);
        }
    };
}

// This file is generated by build.rs
include!(concat!(env!("OUT_DIR"), "/tests.rs"));
<|endoftext|>