<commit_before>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::cmp;
use std::collections::HashMap;
use std::collections::hash_map::Entry;
use std::error::Error;
use std::mem;
use std::sync::Arc;
use smallvec::SmallVec;

use buffer::Buffer;
use command_buffer::cb::CommandsListBuildPrimaryPool;
use command_buffer::cb::Flags;
use command_buffer::cb::Kind;
use command_buffer::cb::UnsyncedCommandBuffer;
use command_buffer::pool::CommandPool;
use command_buffer::submit::Submit;
use command_buffer::submit::SubmitBuilder;
use command_buffer::CommandsList;
use command_buffer::CommandsListSink;
use command_buffer::CommandsListSinkCaller;
use command_buffer::PipelineBarrierBuilder;
use command_buffer::SecondaryCommandBuffer;
use device::Device;
use device::Queue;
use image::Layout;
use image::Image;
use sync::AccessFlagBits;
use sync::PipelineStages;
use VulkanObject;
use vk;

use OomError;

pub struct AutobarriersCommandBuffer<L, P> where P: CommandPool {
    // The actual command buffer.
    inner: UnsyncedCommandBuffer<WrappedCommandsList<L>, P>
}

impl<L, P> CommandsListBuildPrimaryPool<L, P> for AutobarriersCommandBuffer<L, P>
    where L: CommandsList, P: CommandPool
{
    fn build_primary_with_pool(pool: P, list: L)
                               -> Result<AutobarriersCommandBuffer<L, P>, OomError>
        where Self: Sized
    {
        let kind = Kind::primary();
        let flags = Flags::SimultaneousUse;

        let cmd = unsafe {
            let device = pool.device().clone();
            try!(UnsyncedCommandBuffer::new(WrappedCommandsList(list, device), pool, kind, flags))
        };

        Ok(AutobarriersCommandBuffer {
            inner: cmd,
        })
    }
}

unsafe impl<L, P> Submit for AutobarriersCommandBuffer<L, P>
    where L: CommandsList, P: CommandPool
{
    #[inline]
    fn device(&self) -> &Arc<Device> {
        self.inner.device()
    }

    unsafe fn append_submission<'a>(&'a self, base: SubmitBuilder<'a>, queue: &Arc<Queue>)
                                    -> Result<SubmitBuilder<'a>, Box<Error>>
    {
        // FIXME: totally unsynchronized here
        Ok(base.add_command_buffer(&self.inner))
    }
}

// TODO: we're not necessarily a secondary command buffer
unsafe impl<L, P> SecondaryCommandBuffer for AutobarriersCommandBuffer<L, P>
    where L: CommandsList, P: CommandPool
{
    #[inline]
    fn inner(&self) -> vk::CommandBuffer {
        self.inner.internal_object()
    }

    #[inline]
    fn device(&self) -> &Arc<Device> {
        self.inner.device()
    }

    #[inline]
    fn append<'a>(&'a self, builder: &mut CommandsListSink<'a>) {
        self.inner.commands_list().append(builder);
    }
}

struct WrappedCommandsList<L>(L, Arc<Device>);
unsafe impl<L> CommandsList for WrappedCommandsList<L> where L: CommandsList {
    #[inline]
    fn append<'a>(&'a self, builder: &mut CommandsListSink<'a>) {
        let mut sink = Sink {
            output: builder,
            device: &self.1,
            accesses: HashMap::new(),
            pending_accesses: HashMap::new(),
            pending_commands: Vec::new(),
        };

        self.0.append(&mut sink);
        sink.flush();
    }
}

// Helper object for AutobarriersCommandBuffer. Implementation detail.
//
// This object is created in a local scope when the command is built, and destroyed after all the
// commands have been passed through.
struct Sink<'c: 'o, 'o> {
    output: &'o mut CommandsListSink<'c>,
    device: &'o Arc<Device>,
    accesses: HashMap<u64, SmallVec<[Element<'c>; 2]>>,
    pending_accesses: HashMap<u64, SmallVec<[Element<'c>; 2]>>,
    pending_commands: Vec<Box<CommandsListSinkCaller<'c> + 'c>>,
}

impl<'c: 'o, 'o> Sink<'c, 'o> {
    fn flush(&mut self) {
        let mut pipeline_barrier = PipelineBarrierBuilder::new();

        for (key, accesses) in self.pending_accesses.drain() {
            let prev_accesses = match self.accesses.entry(key) {
                Entry::Occupied(e) => e.into_mut(),     // TODO: for images, need to transition from initial layout
                Entry::Vacant(e) => { e.insert(accesses); continue; }
            };

            for prev_access in mem::replace(prev_accesses, SmallVec::new()).into_iter() {
                let mut found_conflict = false;

                for access in accesses.iter() {
                    match (&prev_access.inner, &access.inner) {
                        (&ElementInner::Buffer { buffer: old_buffer, offset: old_offset,
                                                 size: old_size, write: old_write },
                         &ElementInner::Buffer { buffer: new_buffer, offset: new_offset,
                                                 size: new_size, write: new_write }) =>
                        {
                            if (!old_write && !new_write) ||
                                !old_buffer.conflicts_buffer(old_offset, old_size,
                                                             new_buffer, new_offset, new_size)
                            {
                                continue;
                            }

                            found_conflict = true;

                            if !old_write {
                                unsafe {
                                    pipeline_barrier.add_execution_dependency(prev_access.stages,
                                                                              access.stages, true);
                                }
                            } else {
                                let real_offset = cmp::min(old_offset, new_offset);
                                let real_size = if old_offset < new_offset {
                                    cmp::max(old_size, new_size + (new_offset - old_offset))
                                } else {
                                    cmp::max(new_size, old_size + (old_offset - new_offset))
                                };

                                unsafe {
                                    pipeline_barrier.add_buffer_memory_barrier(old_buffer, prev_access.stages,
                                                                               prev_access.access, access.stages,
                                                                               access.access, true, None,
                                                                               real_offset, real_size);
                                }
                            }
                        },

                        (&ElementInner::Image { image: self_image, first_layer: self_fl, num_layers: self_nl,
                                                first_mipmap: self_fm, num_mipmaps: self_nm,
                                                write: self_write, layout: self_layout },
                         &ElementInner::Image { image: other_image, first_layer: other_fl, num_layers: other_nl,
                                                first_mipmap: other_fm, num_mipmaps: other_nm,
                                                write: other_write, layout: other_layout }) =>
                        {
                            if (self_layout == other_layout && !self_write && !other_write) ||
                                !self_image.conflicts_image(self_fl, self_nl, self_fm, self_nm,
                                                            other_image, other_fl, other_nl,
                                                            other_fm, other_nm)
                            {
                                continue;
                            }

                            found_conflict = true;

                            if !self_write && self_layout == other_layout {
                                unsafe {
                                    pipeline_barrier.add_execution_dependency(prev_access.stages,
                                                                              access.stages, true);
                                }
                            } else {
                                let real_first_layer = cmp::min(self_fl, other_fl);
                                let real_num_layers = if self_fl < other_fl {
                                    cmp::max(self_nl, other_nl + (other_fl - self_fl))
                                } else {
                                    cmp::max(other_nl, self_nl + (self_fl - other_fl))
                                };

                                let real_first_mipmap = cmp::min(self_fm, other_fm);
                                let real_num_mipmaps = if self_fm < other_fm {
                                    cmp::max(self_nm, other_nm + (other_fm - self_fm))
                                } else {
                                    cmp::max(other_nm, self_nm + (self_fm - other_fm))
                                };

                                unsafe {
                                    pipeline_barrier.add_image_memory_barrier(self_image, real_first_layer .. real_first_layer + real_num_layers,
                                                                              real_first_mipmap .. real_first_mipmap + real_num_mipmaps, prev_access.stages,
                                                                              prev_access.access, access.stages,
                                                                              access.access, true, None,
                                                                              self_layout, other_layout);
                                }
                            }
                        },

                        (&ElementInner::Buffer { buffer, offset, size, write: self_write },
                         &ElementInner::Image { image, first_layer, num_layers, first_mipmap, num_mipmaps,
                                                write: other_write, .. }) |
                        (&ElementInner::Image { image, first_layer, num_layers, first_mipmap, num_mipmaps,
                                                write: other_write, .. },
                         &ElementInner::Buffer { buffer, offset, size, write: self_write }) =>
                        {
                            // TODO: think about this situation
                            /*if !buffer.conflicts_image(offset, size, self_write, image, first_layer, num_layers,
                                                       first_mipmap, num_mipmaps, other_write)
                            {
                                continue;
                            }*/

                            //found_conflict = true;    // there's a warning if we uncomment that
                            unimplemented!()        // TODO:
                        },
                    }
                }

                if !found_conflict {
                    prev_accesses.push(prev_access);
                }
            }

            for access in accesses.into_iter() {
                prev_accesses.push(access);
            }
        }

        pipeline_barrier.append_to(self.output);
        for cmd in self.pending_commands.drain(..) {
            self.output.add_command(cmd);
        }
    }
}

impl<'c: 'o, 'o> CommandsListSink<'c> for Sink<'c, 'o> {
    #[inline]
    fn device(&self) -> &Arc<Device> {
        self.device
    }

    #[inline]
    fn add_command(&mut self, f: Box<CommandsListSinkCaller<'c> + 'c>) {
        self.pending_commands.push(f);
    }

    #[inline]
    fn add_buffer_transition(&mut self, buffer: &'c Buffer, offset: usize, size: usize, write: bool,
                             stages: PipelineStages, access: AccessFlagBits)
    {
        let key = buffer.conflict_key(offset, size);

        let element = Element {
            stages: stages,
            access: access,
            inner: ElementInner::Buffer {
                buffer: buffer,
                offset: offset,
                size: size,
                write: write,
            },
        };

        if self.pending_accesses.get(&key).map(|l| l.iter().any(|e| e.conflicts(&element))).unwrap_or(false) {
            self.flush();
        }

        self.pending_accesses.entry(key).or_insert_with(|| SmallVec::new()).push(element);
    }

    #[inline]
    fn add_image_transition(&mut self, image: &'c Image, first_layer: u32, num_layers: u32,
                            first_mipmap: u32, num_mipmaps: u32, write: bool, layout: Layout,
                            stages: PipelineStages, access: AccessFlagBits)
    {
        let key = image.conflict_key(first_layer, num_layers, first_mipmap, num_mipmaps);

        let element = Element {
            stages: stages,
            access: access,
            inner: ElementInner::Image {
                image: image,
                first_layer: first_layer,
                num_layers: num_layers,
                first_mipmap: first_mipmap,
                num_mipmaps: num_mipmaps,
                write: write,
                layout: layout,
            },
        };

        if self.pending_accesses.get(&key).map(|l| l.iter().any(|e| e.conflicts(&element))).unwrap_or(false) {
            self.flush();
        }

        self.pending_accesses.entry(key).or_insert_with(|| SmallVec::new()).push(element);
    }

    #[inline]
    fn add_image_transition_notification(&mut self, _: &Image, _: u32, _: u32, _: u32,
                                         _: u32, _: Layout, _: PipelineStages, _: AccessFlagBits)
    {
        // FIXME: unimplemented
    }
}

#[derive(Clone)]
struct Element<'a> {
    stages: PipelineStages,
    access: AccessFlagBits,
    inner: ElementInner<'a>,
}

impl<'a> Element<'a> {
    fn conflicts(&self, other: &Element<'a>) -> bool {
        match (&self.inner, &other.inner) {
            (&ElementInner::Buffer { buffer: self_buffer, offset: self_offset, size: self_size,
                                     write: self_write },
             &ElementInner::Buffer { buffer: other_buffer, offset: other_offset, size: other_size,
                                     write: other_write }) =>
            {
                (self_write || other_write) &&
                    self_buffer.conflicts_buffer(self_offset, self_size, other_buffer,
                                                 other_offset, other_size)
            },

            (&ElementInner::Buffer { buffer, offset, size, write: self_write },
             &ElementInner::Image { image, first_layer, num_layers, first_mipmap, num_mipmaps,
                                    write: other_write, .. }) |
            (&ElementInner::Image { image, first_layer, num_layers, first_mipmap, num_mipmaps,
                                    write: other_write, .. },
             &ElementInner::Buffer { buffer, offset, size, write: self_write }) =>
            {
                (self_write || other_write) &&
                    buffer.conflicts_image(offset, size, image, first_layer, num_layers,
                                           first_mipmap, num_mipmaps)
            },

            (&ElementInner::Image { image: self_image, first_layer: self_fl, num_layers: self_nl,
                                    first_mipmap: self_fm, num_mipmaps: self_nm,
                                    write: self_write, layout: self_layout },
             &ElementInner::Image { image: other_image, first_layer: other_fl, num_layers: other_nl,
                                    first_mipmap: other_fm, num_mipmaps: other_nm,
                                    write: other_write, layout: other_layout }) =>
            {
                (self_layout != other_layout || self_write || other_write) &&
                    self_image.conflicts_image(self_fl, self_nl, self_fm, self_nm,
                                               other_image, other_fl, other_nl, other_fm, other_nm)
            },
        }
    }
}

#[derive(Clone)]
enum ElementInner<'a> {
    Buffer {
        buffer: &'a Buffer,
        offset: usize,
        size: usize,
        write: bool,
    },
    Image {
        image: &'a Image,
        first_layer: u32,
        num_layers: u32,
        first_mipmap: u32,
        num_mipmaps: u32,
        write: bool,
        layout: Layout,
    },
}
<commit_msg>Remove deleteme file<commit_after><|endoftext|>


<commit_before>#![warn(clippy::all, rust_2018_idioms)]

use cargo_registry::{db, models::Crate, schema::crates};
use std::io::{self, prelude::*};

use clap::Clap;
use diesel::prelude::*;

#[derive(Clap, Debug)]
#[clap(
    name = "delete-crate",
    about = "Purge all references to a crate from the database.\n\nPlease be super sure you want to do this before running this."
)]
struct Opts {
    /// Name of the crate
    crate_name: String,
}

fn main() {
    let conn = db::connect_now().unwrap();
    conn.transaction::<_, diesel::result::Error, _>(|| {
        delete(&conn);
        Ok(())
    })
    .unwrap()
}

fn delete(conn: &PgConnection) {
    let opts: Opts = Opts::parse();

    let krate: Crate = Crate::by_name(&opts.crate_name).first(conn).unwrap();
    print!(
        "Are you sure you want to delete {} ({}) [y/N]: ",
        opts.crate_name, krate.id
    );
    io::stdout().flush().unwrap();
    let mut line = String::new();
    io::stdin().read_line(&mut line).unwrap();
    if !line.starts_with('y') {
        return;
    }

    println!("deleting the crate");
    let n = diesel::delete(crates::table.find(krate.id))
        .execute(conn)
        .unwrap();
    println!("  {} deleted", n);

    print!("commit? [y/N]: ");
    io::stdout().flush().unwrap();
    let mut line = String::new();
    io::stdin().read_line(&mut line).unwrap();
    if !line.starts_with('y') {
        panic!("aborting transaction");
    }
}
<commit_msg>bin/delete-crate: Use `dialoguer` for command line prompts<commit_after>#![warn(clippy::all, rust_2018_idioms)]

use cargo_registry::{db, models::Crate, schema::crates};

use clap::Clap;
use dialoguer::Confirm;
use diesel::prelude::*;

#[derive(Clap, Debug)]
#[clap(
    name = "delete-crate",
    about = "Purge all references to a crate from the database.\n\nPlease be super sure you want to do this before running this."
)]
struct Opts {
    /// Name of the crate
    crate_name: String,
}

fn main() {
    let conn = db::connect_now().unwrap();
    conn.transaction::<_, diesel::result::Error, _>(|| {
        delete(&conn);
        Ok(())
    })
    .unwrap()
}

fn delete(conn: &PgConnection) {
    let opts: Opts = Opts::parse();

    let krate: Crate = Crate::by_name(&opts.crate_name).first(conn).unwrap();

    let prompt = format!(
        "Are you sure you want to delete {} ({})?",
        opts.crate_name, krate.id
    );
    if !Confirm::new()
        .with_prompt(prompt)
        .default(false)
        .wait_for_newline(true)
        .interact()
        .unwrap()
    {
        return;
    }

    println!("deleting the crate");
    let n = diesel::delete(crates::table.find(krate.id))
        .execute(conn)
        .unwrap();
    println!("  {} deleted", n);

    if !Confirm::new()
        .with_prompt("commit?")
        .default(false)
        .wait_for_newline(true)
        .interact()
        .unwrap()
    {
        panic!("aborting transaction");
    }
}
<|endoftext|>


<commit_before>/// Description for new columns
#[derive(Debug, Clone)]
pub struct ColumnDescription {
    pub name: String,

    // TODO: make this use one of the enums
    /// Type of the data, see the cfitsio documentation
    pub data_type: String,
}
<commit_msg>Add implementations of data description types<commit_after>/// Description for new columns
#[derive(Debug, Clone)]
pub struct ColumnDescription {
    pub name: String,

    // TODO: make this use one of the enums
    /// Type of the data, see the cfitsio documentation
    pub data_type: String,
}

#[derive(Debug, Clone)]
pub struct ColumnDataDescription {
    pub repeat: usize,
    pub width: usize,
    pub typ: ColumnDataType,
}

impl ColumnDataDescription {
    pub fn new(typ: ColumnDataType) -> Self {
        ColumnDataDescription {
            repeat: 1,
            width: 1,
            typ: typ,
        }
    }

    /* XXX These two methods force a call to clone which is wasteful of memory. I do not know if
     * this means that memory is leaked, or that destructors are needlessly called (I suspect the
     * latter) but it is fairly wasteful. On the other hand, it's unlikely this sort of thing will
     * be called in performance-critical code, and is more likely a one-dime definition. I will
     * leave it for now - SRW 2017-03-07
     * */
    pub fn repeats(&mut self, repeat: usize) -> Self {
        // TODO check that repeat >= 1
        self.repeat = repeat;
        self.clone()
    }

    pub fn width(&mut self, width: usize) -> Self {
        // TODO check that width >= 1
        self.width = width;
        self.clone()
    }
}

#[derive(Debug, Clone, Copy)]
pub enum ColumnDataType {
    Int,
}

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

    #[test]
    fn test_column_data_descriptions_builder_pattern() {
        let desc = ColumnDataDescription::new(ColumnDataType::Int)
            .width(100)
            .repeats(5);
        assert_eq!(desc.repeat, 5);
        assert_eq!(desc.width, 100);
    }
}
<|endoftext|>


<commit_before>use auto_enums::auto_enum;
use glob::{glob_with, MatchOptions};
use ion_shell::{
    expansion::{unescape, Expander},
    Shell,
};
use liner::{Completer, CursorPosition, Event, EventKind};
use std::{env, iter, path::PathBuf, str};

pub struct IonCompleter<'a, 'b> {
    shell:      &'b Shell<'a>,
    completion: CompletionType,
}

/// Escapes filenames from the completer so that special characters will be properly escaped.
///
/// NOTE: Perhaps we should submit a PR to Liner to add a &'static [u8] field to
/// `FilenameCompleter` so that we don't have to perform the escaping ourselves?
fn escape(input: &str) -> String {
    let mut output = Vec::with_capacity(input.len());
    for character in input.bytes() {
        match character {
            b'(' | b')' | b'[' | b']' | b'&' | b'$' | b'@' | b'{' | b'}' | b'<' | b'>' | b';'
            | b'"' | b'\'' | b'#' | b'^' | b'*' | b' ' => output.push(b'\\'),
            _ => (),
        }
        output.push(character);
    }
    unsafe { String::from_utf8_unchecked(output) }
}

enum CompletionType {
    Nothing,
    Command,
    VariableAndFiles,
}

impl<'a, 'b> IonCompleter<'a, 'b> {
    pub fn new(shell: &'b Shell<'a>) -> Self {
        IonCompleter { shell, completion: CompletionType::Nothing }
    }
}

impl<'a, 'b> Completer for IonCompleter<'a, 'b> {
    fn completions(&mut self, start: &str) -> Vec<String> {
        let mut completions = IonFileCompleter::new(None, &self.shell).completions(start);
        let vars = self.shell.variables();

        match self.completion {
            CompletionType::VariableAndFiles => {
                // Initialize a new completer from the definitions collected.
                // Creates a list of definitions from the shell environment that
                // will be used
                // in the creation of a custom completer.
                if start.is_empty() {
                    completions.extend(vars.string_vars().map(|(s, _)| format!("${}", s)));
                    completions.extend(vars.arrays().map(|(s, _)| format!("@{}", s)));
                } else if start.starts_with('$') {
                    completions.extend(
                        // Add the list of available variables to the completer's
                        // definitions. TODO: We should make
                        // it free to do String->SmallString
                        //       and mostly free to go back (free if allocated)
                        vars.string_vars()
                            .filter(|(s, _)| s.starts_with(&start[1..]))
                            .map(|(s, _)| format!("${}", &s)),
                    );
                } else if start.starts_with('@') {
                    completions.extend(
                        vars.arrays()
                            .filter(|(s, _)| s.starts_with(&start[1..]))
                            .map(|(s, _)| format!("@{}", &s)),
                    );
                }
            }
            CompletionType::Command => {
                // Initialize a new completer from the definitions collected.
                // Creates a list of definitions from the shell environment that
                // will be used
                // in the creation of a custom completer.
                completions.extend(
                    self.shell
                        .builtins()
                        .keys()
                        // Add built-in commands to the completer's definitions.
                        .map(ToString::to_string)
                        // Add the aliases to the completer's definitions.
                        .chain(vars.aliases().map(|(key, _)| key.to_string()))
                        // Add the list of available functions to the completer's
                        // definitions.
                        .chain(vars.functions().map(|(key, _)| key.to_string()))
                        .filter(|s| s.starts_with(start)),
                );
                // Creates completers containing definitions from all directories
                // listed
                // in the environment's **$PATH** variable.
                let file_completers: Vec<_> = if let Some(paths) = env::var_os("PATH") {
                    env::split_paths(&paths)
                        .map(|s| IonFileCompleter::new(Some(s), &self.shell))
                        .collect()
                } else {
                    vec![IonFileCompleter::new(Some("/bin/".into()), &self.shell)]
                };
                // Merge the collected definitions with the file path definitions.
                completions.extend(MultiCompleter::new(file_completers).completions(start));
            }
            CompletionType::Nothing => (),
        }
        completions
    }

    fn on_event<W: std::io::Write>(&mut self, event: Event<'_, '_, W>) {
        if let EventKind::BeforeComplete = event.kind {
            let (words, pos) = event.editor.get_words_and_cursor_position();

            self.completion = match (words.len(), pos) {
                (0, _) => CompletionType::Nothing,
                (1, CursorPosition::InSpace(..)) => CompletionType::VariableAndFiles,
                (1, _) => CompletionType::Command,
                _ => CompletionType::VariableAndFiles,
            };
        }
    }
}

/// Performs escaping to an inner `FilenameCompleter` to enable a handful of special cases
/// needed by the shell, such as expanding '~' to a home directory, or adding a backslash
/// when a special character is contained within an expanded filename.
pub struct IonFileCompleter<'a, 'b> {
    shell: &'b Shell<'a>,
    /// The directory the expansion takes place in
    path: PathBuf,
}

impl<'a, 'b> IonFileCompleter<'a, 'b> {
    pub fn new(path: Option<PathBuf>, shell: &'b Shell<'a>) -> Self {
        let path = path.unwrap_or_default();
        IonFileCompleter { shell, path }
    }
}

impl<'a, 'b> Completer for IonFileCompleter<'a, 'b> {
    /// When the tab key is pressed, **Liner** will use this method to perform completions of
    /// filenames. As our `IonFileCompleter` is a wrapper around **Liner**'s
    /// `FilenameCompleter`,
    /// the purpose of our custom `Completer` is to expand possible `~` characters in the
    /// `start`
    /// value that we receive from the prompt, grab completions from the inner
    /// `FilenameCompleter`,
    /// and then escape the resulting filenames, as well as remove the expanded form of the `~`
    /// character and re-add the `~` character in it's place.
    fn completions(&mut self, start: &str) -> Vec<String> {
        // Dereferencing the raw pointers here should be entirely safe, theoretically,
        // because no changes will occur to either of the underlying references in the
        // duration between creation of the completers and execution of their
        // completions.
        let expanded = match self.shell.tilde(start) {
            Ok(expanded) => expanded,
            Err(why) => {
                eprintln!("ion: {}", why);
                return vec![start.into()];
            }
        };
        // Now we obtain completions for the `expanded` form of the `start` value.
        let completions = filename_completion(&expanded, &self.path);
        if expanded == start {
            return completions.collect();
        }
        // We can do that by obtaining the index position where the tilde character
        // ends. We don't search with `~` because we also want to
        // handle other tilde variants.
        let t_index = start.find('/').unwrap_or(1);
        // `tilde` is the tilde pattern, and `search` is the pattern that follows.
        let (tilde, search) = start.split_at(t_index);

        if search.len() < 2 {
            // If the length of the search pattern is less than 2, the search pattern is
            // empty, and thus the completions actually contain files and directories in
            // the home directory.

            // The tilde pattern will actually be our `start` command in itself,
            // and the completed form will be all of the characters beyond the length of
            // the expanded form of the tilde pattern.
            completions.map(|completion| [start, &completion[expanded.len()..]].concat()).collect()
        // To save processing time, we should get obtain the index position where our
        // search pattern begins, and re-use that index to slice the completions so
        // that we may re-add the tilde character with the completion that follows.
        } else if let Some(e_index) = expanded.rfind(search) {
            // And then we will need to take those completions and remove the expanded form
            // of the tilde pattern and replace it with that pattern yet again.
            completions
                .map(|completion| escape(&[tilde, &completion[e_index..]].concat()))
                .collect()
        } else {
            Vec::new()
        }
    }
}

#[auto_enum]
fn filename_completion<'a>(start: &'a str, path: &'a PathBuf) -> impl Iterator<Item = String> + 'a {
    let unescaped_start = unescape(start);

    let mut split_start = unescaped_start.split('/');
    let mut string = String::with_capacity(128);

    // When 'start' is an absolute path, "/..." gets split to ["", "..."]
    // So we skip the first element and add "/" to the start of the string
    if unescaped_start.starts_with('/') {
        split_start.next();
        string.push('/');
    } else {
        string.push_str(&path.to_string_lossy());
    }

    for element in split_start {
        string.push_str(element);
        if element != "." && element != ".." {
            string.push('*');
        }
        string.push('/');
    }

    string.pop(); // pop out the last '/' character
    if string.ends_with('.') {
        string.push('*')
    }

    let globs = glob_with(
        &string,
        MatchOptions {
            case_sensitive:              true,
            require_literal_separator:   true,
            require_literal_leading_dot: false,
        },
    )
    .ok()
    .map(|completions| {
        completions.filter_map(Result::ok).filter_map(move |file| {
            let out = file.to_str()?;
            let mut joined = String::with_capacity(out.len() + 3); // worst case senario
            if unescaped_start.starts_with("./") {
                joined.push_str("./");
            }
            joined.push_str(out);
            if file.is_dir() {
                joined.push('/');
            }
            Some(escape(&joined))
        })
    });

    #[auto_enum(Iterator)]
    match globs {
        Some(iter) => iter,
        None => iter::once(escape(start)),
    }
}

/// A completer that combines suggestions from multiple completers.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct MultiCompleter<A>(Vec<A>);

impl<A> MultiCompleter<A> {
    pub fn new(completions: Vec<A>) -> Self { MultiCompleter(completions) }
}

impl<A> Completer for MultiCompleter<A>
where
    A: Completer,
{
    fn completions(&mut self, start: &str) -> Vec<String> {
        self.0.iter_mut().flat_map(|comp| comp.completions(start)).collect()
    }
}

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

    #[test]
    fn filename_completion() {
        let shell = Shell::default();
        let mut completer = IonFileCompleter::new(None, &shell);
        assert_eq!(completer.completions("testing"), vec!["testing/"]);
        assert_eq!(completer.completions("testing/file"), vec!["testing/file_with_text"]);
        assert_eq!(completer.completions("~"), vec!["~/"]);
        assert_eq!(completer.completions("tes/fil"), vec!["testing/file_with_text"]);
    }
}
<commit_msg>Take into account backtracking at the prompt<commit_after>use auto_enums::auto_enum;
use glob::{glob_with, MatchOptions};
use ion_shell::{
    expansion::{unescape, Expander},
    Shell,
};
use liner::{Completer, CursorPosition, Event, EventKind};
use std::{env, iter, path::PathBuf, str};

pub struct IonCompleter<'a, 'b> {
    shell:      &'b Shell<'a>,
    completion: CompletionType,
}

/// Escapes filenames from the completer so that special characters will be properly escaped.
///
/// NOTE: Perhaps we should submit a PR to Liner to add a &'static [u8] field to
/// `FilenameCompleter` so that we don't have to perform the escaping ourselves?
fn escape(input: &str) -> String {
    let mut output = Vec::with_capacity(input.len());
    for character in input.bytes() {
        match character {
            b'(' | b')' | b'[' | b']' | b'&' | b'$' | b'@' | b'{' | b'}' | b'<' | b'>' | b';'
            | b'"' | b'\'' | b'#' | b'^' | b'*' | b' ' => output.push(b'\\'),
            _ => (),
        }
        output.push(character);
    }
    unsafe { String::from_utf8_unchecked(output) }
}

enum CompletionType {
    Nothing,
    Command,
    VariableAndFiles,
}

impl<'a, 'b> IonCompleter<'a, 'b> {
    pub fn new(shell: &'b Shell<'a>) -> Self {
        IonCompleter { shell, completion: CompletionType::Nothing }
    }
}

impl<'a, 'b> Completer for IonCompleter<'a, 'b> {
    fn completions(&mut self, start: &str) -> Vec<String> {
        let mut completions = IonFileCompleter::new(None, &self.shell).completions(start);
        let vars = self.shell.variables();

        match self.completion {
            CompletionType::VariableAndFiles => {
                // Initialize a new completer from the definitions collected.
                // Creates a list of definitions from the shell environment that
                // will be used
                // in the creation of a custom completer.
                if start.is_empty() {
                    completions.extend(vars.string_vars().map(|(s, _)| format!("${}", s)));
                    completions.extend(vars.arrays().map(|(s, _)| format!("@{}", s)));
                } else if start.starts_with('$') {
                    completions.extend(
                        // Add the list of available variables to the completer's
                        // definitions. TODO: We should make
                        // it free to do String->SmallString
                        //       and mostly free to go back (free if allocated)
                        vars.string_vars()
                            .filter(|(s, _)| s.starts_with(&start[1..]))
                            .map(|(s, _)| format!("${}", &s)),
                    );
                } else if start.starts_with('@') {
                    completions.extend(
                        vars.arrays()
                            .filter(|(s, _)| s.starts_with(&start[1..]))
                            .map(|(s, _)| format!("@{}", &s)),
                    );
                }
            }
            CompletionType::Command => {
                // Initialize a new completer from the definitions collected.
                // Creates a list of definitions from the shell environment that
                // will be used
                // in the creation of a custom completer.
                completions.extend(
                    self.shell
                        .builtins()
                        .keys()
                        // Add built-in commands to the completer's definitions.
                        .map(ToString::to_string)
                        // Add the aliases to the completer's definitions.
                        .chain(vars.aliases().map(|(key, _)| key.to_string()))
                        // Add the list of available functions to the completer's
                        // definitions.
                        .chain(vars.functions().map(|(key, _)| key.to_string()))
                        .filter(|s| s.starts_with(start)),
                );
                // Creates completers containing definitions from all directories
                // listed
                // in the environment's **$PATH** variable.
                let file_completers: Vec<_> = if let Some(paths) = env::var_os("PATH") {
                    env::split_paths(&paths)
                        .map(|s| IonFileCompleter::new(Some(s), &self.shell))
                        .collect()
                } else {
                    vec![IonFileCompleter::new(Some("/bin/".into()), &self.shell)]
                };
                // Merge the collected definitions with the file path definitions.
                completions.extend(MultiCompleter::new(file_completers).completions(start));
            }
            CompletionType::Nothing => (),
        }
        completions
    }

    fn on_event<W: std::io::Write>(&mut self, event: Event<'_, '_, W>) {
        if let EventKind::BeforeComplete = event.kind {
            let (words, pos) = event.editor.get_words_and_cursor_position();

            self.completion = match pos {
                _ if words.is_empty() => CompletionType::Nothing,
                CursorPosition::InWord(0) | CursorPosition::OnWordRightEdge(0) => {
                    CompletionType::Command
                }
                _ => CompletionType::VariableAndFiles,
            };
        }
    }
}

/// Performs escaping to an inner `FilenameCompleter` to enable a handful of special cases
/// needed by the shell, such as expanding '~' to a home directory, or adding a backslash
/// when a special character is contained within an expanded filename.
pub struct IonFileCompleter<'a, 'b> {
    shell: &'b Shell<'a>,
    /// The directory the expansion takes place in
    path: PathBuf,
}

impl<'a, 'b> IonFileCompleter<'a, 'b> {
    pub fn new(path: Option<PathBuf>, shell: &'b Shell<'a>) -> Self {
        let path = path.unwrap_or_default();
        IonFileCompleter { shell, path }
    }
}

impl<'a, 'b> Completer for IonFileCompleter<'a, 'b> {
    /// When the tab key is pressed, **Liner** will use this method to perform completions of
    /// filenames. As our `IonFileCompleter` is a wrapper around **Liner**'s
    /// `FilenameCompleter`,
    /// the purpose of our custom `Completer` is to expand possible `~` characters in the
    /// `start`
    /// value that we receive from the prompt, grab completions from the inner
    /// `FilenameCompleter`,
    /// and then escape the resulting filenames, as well as remove the expanded form of the `~`
    /// character and re-add the `~` character in it's place.
    fn completions(&mut self, start: &str) -> Vec<String> {
        // Dereferencing the raw pointers here should be entirely safe, theoretically,
        // because no changes will occur to either of the underlying references in the
        // duration between creation of the completers and execution of their
        // completions.
        let expanded = match self.shell.tilde(start) {
            Ok(expanded) => expanded,
            Err(why) => {
                eprintln!("ion: {}", why);
                return vec![start.into()];
            }
        };
        // Now we obtain completions for the `expanded` form of the `start` value.
        let completions = filename_completion(&expanded, &self.path);
        if expanded == start {
            return completions.collect();
        }
        // We can do that by obtaining the index position where the tilde character
        // ends. We don't search with `~` because we also want to
        // handle other tilde variants.
        let t_index = start.find('/').unwrap_or(1);
        // `tilde` is the tilde pattern, and `search` is the pattern that follows.
        let (tilde, search) = start.split_at(t_index);

        if search.len() < 2 {
            // If the length of the search pattern is less than 2, the search pattern is
            // empty, and thus the completions actually contain files and directories in
            // the home directory.

            // The tilde pattern will actually be our `start` command in itself,
            // and the completed form will be all of the characters beyond the length of
            // the expanded form of the tilde pattern.
            completions.map(|completion| [start, &completion[expanded.len()..]].concat()).collect()
        // To save processing time, we should get obtain the index position where our
        // search pattern begins, and re-use that index to slice the completions so
        // that we may re-add the tilde character with the completion that follows.
        } else if let Some(e_index) = expanded.rfind(search) {
            // And then we will need to take those completions and remove the expanded form
            // of the tilde pattern and replace it with that pattern yet again.
            completions
                .map(|completion| escape(&[tilde, &completion[e_index..]].concat()))
                .collect()
        } else {
            Vec::new()
        }
    }
}

#[auto_enum]
fn filename_completion<'a>(start: &'a str, path: &'a PathBuf) -> impl Iterator<Item = String> + 'a {
    let unescaped_start = unescape(start);

    let mut split_start = unescaped_start.split('/');
    let mut string = String::with_capacity(128);

    // When 'start' is an absolute path, "/..." gets split to ["", "..."]
    // So we skip the first element and add "/" to the start of the string
    if unescaped_start.starts_with('/') {
        split_start.next();
        string.push('/');
    } else {
        string.push_str(&path.to_string_lossy());
    }

    for element in split_start {
        string.push_str(element);
        if element != "." && element != ".." {
            string.push('*');
        }
        string.push('/');
    }

    string.pop(); // pop out the last '/' character
    if string.ends_with('.') {
        string.push('*')
    }

    let globs = glob_with(
        &string,
        MatchOptions {
            case_sensitive:              true,
            require_literal_separator:   true,
            require_literal_leading_dot: false,
        },
    )
    .ok()
    .map(|completions| {
        completions.filter_map(Result::ok).filter_map(move |file| {
            let out = file.to_str()?;
            let mut joined = String::with_capacity(out.len() + 3); // worst case senario
            if unescaped_start.starts_with("./") {
                joined.push_str("./");
            }
            joined.push_str(out);
            if file.is_dir() {
                joined.push('/');
            }
            Some(escape(&joined))
        })
    });

    #[auto_enum(Iterator)]
    match globs {
        Some(iter) => iter,
        None => iter::once(escape(start)),
    }
}

/// A completer that combines suggestions from multiple completers.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct MultiCompleter<A>(Vec<A>);

impl<A> MultiCompleter<A> {
    pub fn new(completions: Vec<A>) -> Self { MultiCompleter(completions) }
}

impl<A> Completer for MultiCompleter<A>
where
    A: Completer,
{
    fn completions(&mut self, start: &str) -> Vec<String> {
        self.0.iter_mut().flat_map(|comp| comp.completions(start)).collect()
    }
}

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

    #[test]
    fn filename_completion() {
        let shell = Shell::default();
        let mut completer = IonFileCompleter::new(None, &shell);
        assert_eq!(completer.completions("testing"), vec!["testing/"]);
        assert_eq!(completer.completions("testing/file"), vec!["testing/file_with_text"]);
        assert_eq!(completer.completions("~"), vec!["~/"]);
        assert_eq!(completer.completions("tes/fil"), vec!["testing/file_with_text"]);
    }
}
<|endoftext|>


<commit_before>extern crate piston_window;
extern crate vecmath;
extern crate camera_controllers;
#[macro_use]
extern crate gfx;
extern crate gfx_device_gl;
extern crate sdl2_window;
extern crate piston_meta;

use std::fs::File;
use std::io::Read;
use sdl2_window::Sdl2Window;
use piston_window::*;
use camera_controllers::{
    FirstPersonSettings,
    FirstPerson,
    CameraPerspective,
    model_view_projection
};
use gfx::traits::*;
use piston_meta::*;

//----------------------------------------
// Cube associated data

gfx_vertex!( Vertex {
    a_pos@ a_pos: [f32; 3],
    a_tex_coord@ a_tex_coord: [f32; 2],
});

impl Vertex {
    fn new(pos: [f32; 3], tc: [f32; 2]) -> Vertex {
        Vertex {
            a_pos: pos,
            a_tex_coord: tc,
        }
    }
}

gfx_parameters!( Params {
    u_model_view_proj@ u_model_view_proj: [[f32; 4]; 4],
    t_color@ t_color: gfx::shade::TextureParam<R>,
});

//----------------------------------------

fn main() {
    let mut events: PistonWindow<Sdl2Window> =
        WindowSettings::new("piston: cube", [640, 480])
        .exit_on_esc(true)
        .samples(4)
        .into();
    events.set_capture_cursor(true);

    let ref mut factory = events.factory.borrow().clone();

    // Read OpenGEX meta rules.
    let mut file_h = File::open("assets/opengex-syntax.txt").unwrap();
    let mut source = String::new();
    file_h.read_to_string(&mut source).unwrap();
    let rules = stderr_unwrap(&source, syntax(&source));

    // Read cube.ogex.
    let mut file_h = File::open("assets/cube.ogex").unwrap();
    let mut source = String::new();
    file_h.read_to_string(&mut source).unwrap();
    let data = stderr_unwrap(&source, parse(&rules, &source));

    let v3 = |mut s: &mut Search| Ok([
        try!(s.f64("x")) as f32,
        try!(s.f64("y")) as f32,
        try!(s.f64("z")) as f32
    ]);

    let tx = vec![
        [0.0, 0.0],
        [1.0, 0.0],
        [1.0, 1.0],
        [0.0, 1.0],
        //bottom (0, 0, -1)
        [0.0, 0.0],
        [1.0, 0.0],
        [1.0, 1.0],
        [0.0, 1.0],
        //right (1, 0, 0)
        [0.0, 0.0],
        [1.0, 0.0],
        [1.0, 1.0],
        [0.0, 1.0],
        //left (-1, 0, 0)
        [0.0, 0.0],
        [1.0, 0.0],
        [1.0, 1.0],
        [0.0, 1.0],
        //front (0, 1, 0)
        [0.0, 0.0],
        [1.0, 0.0],
        [1.0, 1.0],
        [0.0, 1.0],
        //back (0, -1, 0)
        [0.0, 0.0],
        [1.0, 0.0],
        [1.0, 1.0],
        [0.0, 1.0],
    ];

    let s = Search::new(&data);
    let vertex_data: Vec<Vertex> = stderr_unwrap(&source, s.for_bool("position", true,
        |ref mut s| {
            let mut vs = Vec::with_capacity(24);
            for t in &tx {
                vs.push(Vertex::new(try!(v3(s)), *t));
            }
            Ok(vs)
        }));

    let mesh = factory.create_mesh(&vertex_data);

    let index_data: &[u8] = &[
         0,  1,  2,  2,  3,  0, // top
         4,  6,  5,  6,  4,  7, // bottom
         8,  9, 10, 10, 11,  8, // right
        12, 14, 13, 14, 12, 16, // left
        16, 18, 17, 18, 16, 19, // front
        20, 21, 22, 22, 23, 20, // back
    ];

    let slice = index_data.to_slice(factory, gfx::PrimitiveType::TriangleList);

    let texture = factory.create_texture_rgba8_static(1, 1, &[0x00_C0_A0_20]).unwrap();

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

    let program = {
        let vertex = gfx::ShaderSource {
            glsl_120: Some(include_bytes!("../assets/cube_120.glslv")),
            glsl_150: Some(include_bytes!("../assets/cube_150.glslv")),
            .. gfx::ShaderSource::empty()
        };
        let fragment = gfx::ShaderSource {
            glsl_120: Some(include_bytes!("../assets/cube_120.glslf")),
            glsl_150: Some(include_bytes!("../assets/cube_150.glslf")),
            .. gfx::ShaderSource::empty()
        };
        factory.link_program_source(vertex, fragment).unwrap()
    };

    let mut data = Params {
        u_model_view_proj: vecmath::mat4_id(),
        t_color: (texture, Some(sampler)),
        _r: std::marker::PhantomData,
    };

    let get_projection = |w: &PistonWindow<Sdl2Window>| {
        let draw_size = w.window.borrow().draw_size();
        CameraPerspective {
            fov: 90.0, near_clip: 0.1, far_clip: 1000.0,
            aspect_ratio: (draw_size.width as f32) / (draw_size.height as f32)
        }.projection()
    };

    let model = vecmath::mat4_id();
    let mut projection = get_projection(&events);
    let mut first_person = FirstPerson::new(
        [0.5, 0.5, 4.0],
        FirstPersonSettings::keyboard_wasd()
    );
    let state = gfx::DrawState::new().depth(gfx::state::Comparison::LessEqual, true);

    for e in events {
        first_person.event(&e);

        e.draw_3d(|stream| {
            let args = e.render_args().unwrap();
            stream.clear(
                gfx::ClearData {
                    color: [0.3, 0.3, 0.3, 1.0],
                    depth: 1.0,
                    stencil: 0,
                }
            );
            data.u_model_view_proj = model_view_projection(
                model,
                first_person.camera(args.ext_dt).orthogonal(),
                projection
            );
            stream.draw(&(&mesh, slice.clone(), &program, &data, &state)).unwrap();
        });

        if let Some(_) = e.resize_args() {
            projection = get_projection(&e);
        }
    }
}
<commit_msg>Read index_data from cube.ogex<commit_after>extern crate piston_window;
extern crate vecmath;
extern crate camera_controllers;
#[macro_use]
extern crate gfx;
extern crate gfx_device_gl;
extern crate sdl2_window;
extern crate piston_meta;

use std::fs::File;
use std::io::Read;
use sdl2_window::Sdl2Window;
use piston_window::*;
use camera_controllers::{
    FirstPersonSettings,
    FirstPerson,
    CameraPerspective,
    model_view_projection
};
use gfx::traits::*;
use piston_meta::*;

//----------------------------------------
// Cube associated data

gfx_vertex!( Vertex {
    a_pos@ a_pos: [f32; 3],
    a_tex_coord@ a_tex_coord: [f32; 2],
});

impl Vertex {
    fn new(pos: [f32; 3], tc: [f32; 2]) -> Vertex {
        Vertex {
            a_pos: pos,
            a_tex_coord: tc,
        }
    }
}

gfx_parameters!( Params {
    u_model_view_proj@ u_model_view_proj: [[f32; 4]; 4],
    t_color@ t_color: gfx::shade::TextureParam<R>,
});

//----------------------------------------

fn main() {
    let mut events: PistonWindow<Sdl2Window> =
        WindowSettings::new("piston: cube", [640, 480])
        .exit_on_esc(true)
        .samples(4)
        .into();
    events.set_capture_cursor(true);

    let ref mut factory = events.factory.borrow().clone();

    // Read OpenGEX meta rules.
    let mut file_h = File::open("assets/opengex-syntax.txt").unwrap();
    let mut source = String::new();
    file_h.read_to_string(&mut source).unwrap();
    let rules = stderr_unwrap(&source, syntax(&source));

    // Read cube.ogex.
    let mut file_h = File::open("assets/cube.ogex").unwrap();
    let mut source = String::new();
    file_h.read_to_string(&mut source).unwrap();
    let data = stderr_unwrap(&source, parse(&rules, &source));

    let v3 = |mut s: &mut Search| Ok([
        try!(s.f64("x")) as f32,
        try!(s.f64("y")) as f32,
        try!(s.f64("z")) as f32
    ]);

    let tx = vec![
        [0.0, 0.0],
        [1.0, 0.0],
        [1.0, 1.0],
        [0.0, 1.0],
        //bottom (0, 0, -1)
        [0.0, 0.0],
        [1.0, 0.0],
        [1.0, 1.0],
        [0.0, 1.0],
        //right (1, 0, 0)
        [0.0, 0.0],
        [1.0, 0.0],
        [1.0, 1.0],
        [0.0, 1.0],
        //left (-1, 0, 0)
        [0.0, 0.0],
        [1.0, 0.0],
        [1.0, 1.0],
        [0.0, 1.0],
        //front (0, 1, 0)
        [0.0, 0.0],
        [1.0, 0.0],
        [1.0, 1.0],
        [0.0, 1.0],
        //back (0, -1, 0)
        [0.0, 0.0],
        [1.0, 0.0],
        [1.0, 1.0],
        [0.0, 1.0],
    ];

    let s = Search::new(&data);
    let vertex_data: Vec<Vertex> = stderr_unwrap(&source, s.for_bool("position", true,
        |ref mut s| {
            let mut vs = Vec::with_capacity(24);
            for t in &tx {
                vs.push(Vertex::new(try!(v3(s)), *t));
            }
            Ok(vs)
        }));

    let mesh = factory.create_mesh(&vertex_data);

    let index_data: Vec<u8> = stderr_unwrap(&source, s.for_node("IndexArray",
        |ref mut s| {
            let mut is = Vec::with_capacity(36);
            for _ in 0 .. 12 {
                is.push(try!(s.f64("a")) as u8);
                is.push(try!(s.f64("b")) as u8);
                is.push(try!(s.f64("c")) as u8);
            }
            Ok(is)
        }));

    let slice = index_data.to_slice(factory, gfx::PrimitiveType::TriangleList);

    let texture = factory.create_texture_rgba8_static(1, 1, &[0x00_C0_A0_20]).unwrap();

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

    let program = {
        let vertex = gfx::ShaderSource {
            glsl_120: Some(include_bytes!("../assets/cube_120.glslv")),
            glsl_150: Some(include_bytes!("../assets/cube_150.glslv")),
            .. gfx::ShaderSource::empty()
        };
        let fragment = gfx::ShaderSource {
            glsl_120: Some(include_bytes!("../assets/cube_120.glslf")),
            glsl_150: Some(include_bytes!("../assets/cube_150.glslf")),
            .. gfx::ShaderSource::empty()
        };
        factory.link_program_source(vertex, fragment).unwrap()
    };

    let mut data = Params {
        u_model_view_proj: vecmath::mat4_id(),
        t_color: (texture, Some(sampler)),
        _r: std::marker::PhantomData,
    };

    let get_projection = |w: &PistonWindow<Sdl2Window>| {
        let draw_size = w.window.borrow().draw_size();
        CameraPerspective {
            fov: 90.0, near_clip: 0.1, far_clip: 1000.0,
            aspect_ratio: (draw_size.width as f32) / (draw_size.height as f32)
        }.projection()
    };

    let model = vecmath::mat4_id();
    let mut projection = get_projection(&events);
    let mut first_person = FirstPerson::new(
        [0.5, 0.5, 4.0],
        FirstPersonSettings::keyboard_wasd()
    );
    let state = gfx::DrawState::new().depth(gfx::state::Comparison::LessEqual, true);

    for e in events {
        first_person.event(&e);

        e.draw_3d(|stream| {
            let args = e.render_args().unwrap();
            stream.clear(
                gfx::ClearData {
                    color: [0.3, 0.3, 0.3, 1.0],
                    depth: 1.0,
                    stencil: 0,
                }
            );
            data.u_model_view_proj = model_view_projection(
                model,
                first_person.camera(args.ext_dt).orthogonal(),
                projection
            );
            stream.draw(&(&mesh, slice.clone(), &program, &data, &state)).unwrap();
        });

        if let Some(_) = e.resize_args() {
            projection = get_projection(&e);
        }
    }
}
<|endoftext|>


<commit_before>pub use self::imp::read2;

#[cfg(unix)]
mod imp {
    use std::cmp;
    use std::io::prelude::*;
    use std::io;
    use std::mem;
    use std::os::unix::prelude::*;
    use std::process::{ChildStdout, ChildStderr};
    use libc;

    pub fn read2(mut out_pipe: ChildStdout,
                 mut err_pipe: ChildStderr,
                 mut data: &mut FnMut(bool, &mut Vec<u8>, bool)) -> io::Result<()> {
        unsafe {
            libc::fcntl(out_pipe.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK);
            libc::fcntl(err_pipe.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK);
        }

        let mut out_done = false;
        let mut err_done = false;
        let mut out = Vec::new();
        let mut err = Vec::new();

        let max = cmp::max(out_pipe.as_raw_fd(), err_pipe.as_raw_fd());
        loop {
            // wait for either pipe to become readable using `select`
            let r = unsafe {
                let mut read: libc::fd_set = mem::zeroed();
                if !out_done {
                    libc::FD_SET(out_pipe.as_raw_fd(), &mut read);
                }
                if !err_done {
                    libc::FD_SET(err_pipe.as_raw_fd(), &mut read);
                }
                libc::select(max + 1, &mut read, 0 as *mut _, 0 as *mut _,
                             0 as *mut _)
            };
            if r == -1 {
                let err = io::Error::last_os_error();
                if err.kind() == io::ErrorKind::Interrupted {
                    continue
                }
                return Err(err)
            }

            // Read as much as we can from each pipe, ignoring EWOULDBLOCK or
            // EAGAIN. If we hit EOF, then this will happen because the underlying
            // reader will return Ok(0), in which case we'll see `Ok` ourselves. In
            // this case we flip the other fd back into blocking mode and read
            // whatever's leftover on that file descriptor.
            let handle = |res: io::Result<_>| {
                match res {
                    Ok(_) => Ok(true),
                    Err(e) => {
                        if e.kind() == io::ErrorKind::WouldBlock {
                            Ok(false)
                        } else {
                            Err(e)
                        }
                    }
                }
            };
            if !out_done && handle(out_pipe.read_to_end(&mut out))? {
                out_done = true;
            }
            data(true, &mut out, out_done);
            if !err_done && handle(err_pipe.read_to_end(&mut err))? {
                err_done = true;
            }
            data(false, &mut err, err_done);

            if out_done && err_done {
                return Ok(())
            }
        }
    }
}

#[cfg(windows)]
mod imp {
    extern crate miow;
    extern crate winapi;

    use std::io;
    use std::os::windows::prelude::*;
    use std::process::{ChildStdout, ChildStderr};
    use std::slice;

    use self::miow::iocp::{CompletionPort, CompletionStatus};
    use self::miow::pipe::NamedPipe;
    use self::miow::Overlapped;
    use self::winapi::ERROR_BROKEN_PIPE;

    struct Pipe<'a> {
        dst: &'a mut Vec<u8>,
        overlapped: Overlapped,
        pipe: NamedPipe,
        done: bool,
    }

    macro_rules! try {
        ($e:expr) => (match $e {
            Ok(e) => e,
            Err(e) => {
                println!("{} failed with {}", stringify!($e), e);
                return Err(e)
            }
        })
    }

    pub fn read2(out_pipe: ChildStdout,
                 err_pipe: ChildStderr,
                 mut data: &mut FnMut(bool, &mut Vec<u8>, bool)) -> io::Result<()> {
        let mut out = Vec::new();
        let mut err = Vec::new();

        let port = CompletionPort::new(1)?;
        port.add_handle(0, &out_pipe)?;
        port.add_handle(1, &err_pipe)?;

        unsafe {
            let mut out_pipe = Pipe::new(out_pipe, &mut out);
            let mut err_pipe = Pipe::new(err_pipe, &mut err);

            out_pipe.read()?;
            err_pipe.read()?;

            let mut status = [CompletionStatus::zero(), CompletionStatus::zero()];

            while !out_pipe.done || !err_pipe.done {
                for status in port.get_many(&mut status, None)? {
                    if status.token() == 0 {
                        out_pipe.complete(status);
                        data(true, out_pipe.dst, out_pipe.done);
                        out_pipe.read()?;
                    } else {
                        err_pipe.complete(status);
                        data(false, err_pipe.dst, err_pipe.done);
                        err_pipe.read()?;
                    }
                }
            }

            Ok(())
        }
    }

    impl<'a> Pipe<'a> {
        unsafe fn new<P: IntoRawHandle>(p: P, dst: &'a mut Vec<u8>) -> Pipe<'a> {
            Pipe {
                dst: dst,
                pipe: NamedPipe::from_raw_handle(p.into_raw_handle()),
                overlapped: Overlapped::zero(),
                done: false,
            }
        }

        unsafe fn read(&mut self) -> io::Result<()> {
            let dst = slice_to_end(self.dst);
            match self.pipe.read_overlapped(dst, &mut self.overlapped) {
                Ok(_) => Ok(()),
                Err(e) => {
                    if e.raw_os_error() == Some(ERROR_BROKEN_PIPE as i32) {
                        self.done = true;
                        Ok(())
                    } else {
                        Err(e)
                    }
                }
            }
        }

        unsafe fn complete(&mut self, status: &CompletionStatus) {
            let prev = self.dst.len();
            self.dst.set_len(prev + status.bytes_transferred() as usize);
            if status.bytes_transferred() == 0 {
                self.done = true;
            }
        }
    }

    unsafe fn slice_to_end(v: &mut Vec<u8>) -> &mut [u8] {
        if v.capacity() == 0 {
            v.reserve(16);
        }
        if v.capacity() == v.len() {
            v.reserve(1);
        }
        slice::from_raw_parts_mut(v.as_mut_ptr().offset(v.len() as isize),
                                  v.capacity() - v.len())
    }
}
<commit_msg>delete unused try macro from read2.rs<commit_after>pub use self::imp::read2;

#[cfg(unix)]
mod imp {
    use std::cmp;
    use std::io::prelude::*;
    use std::io;
    use std::mem;
    use std::os::unix::prelude::*;
    use std::process::{ChildStdout, ChildStderr};
    use libc;

    pub fn read2(mut out_pipe: ChildStdout,
                 mut err_pipe: ChildStderr,
                 mut data: &mut FnMut(bool, &mut Vec<u8>, bool)) -> io::Result<()> {
        unsafe {
            libc::fcntl(out_pipe.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK);
            libc::fcntl(err_pipe.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK);
        }

        let mut out_done = false;
        let mut err_done = false;
        let mut out = Vec::new();
        let mut err = Vec::new();

        let max = cmp::max(out_pipe.as_raw_fd(), err_pipe.as_raw_fd());
        loop {
            // wait for either pipe to become readable using `select`
            let r = unsafe {
                let mut read: libc::fd_set = mem::zeroed();
                if !out_done {
                    libc::FD_SET(out_pipe.as_raw_fd(), &mut read);
                }
                if !err_done {
                    libc::FD_SET(err_pipe.as_raw_fd(), &mut read);
                }
                libc::select(max + 1, &mut read, 0 as *mut _, 0 as *mut _,
                             0 as *mut _)
            };
            if r == -1 {
                let err = io::Error::last_os_error();
                if err.kind() == io::ErrorKind::Interrupted {
                    continue
                }
                return Err(err)
            }

            // Read as much as we can from each pipe, ignoring EWOULDBLOCK or
            // EAGAIN. If we hit EOF, then this will happen because the underlying
            // reader will return Ok(0), in which case we'll see `Ok` ourselves. In
            // this case we flip the other fd back into blocking mode and read
            // whatever's leftover on that file descriptor.
            let handle = |res: io::Result<_>| {
                match res {
                    Ok(_) => Ok(true),
                    Err(e) => {
                        if e.kind() == io::ErrorKind::WouldBlock {
                            Ok(false)
                        } else {
                            Err(e)
                        }
                    }
                }
            };
            if !out_done && handle(out_pipe.read_to_end(&mut out))? {
                out_done = true;
            }
            data(true, &mut out, out_done);
            if !err_done && handle(err_pipe.read_to_end(&mut err))? {
                err_done = true;
            }
            data(false, &mut err, err_done);

            if out_done && err_done {
                return Ok(())
            }
        }
    }
}

#[cfg(windows)]
mod imp {
    extern crate miow;
    extern crate winapi;

    use std::io;
    use std::os::windows::prelude::*;
    use std::process::{ChildStdout, ChildStderr};
    use std::slice;

    use self::miow::iocp::{CompletionPort, CompletionStatus};
    use self::miow::pipe::NamedPipe;
    use self::miow::Overlapped;
    use self::winapi::ERROR_BROKEN_PIPE;

    struct Pipe<'a> {
        dst: &'a mut Vec<u8>,
        overlapped: Overlapped,
        pipe: NamedPipe,
        done: bool,
    }

    pub fn read2(out_pipe: ChildStdout,
                 err_pipe: ChildStderr,
                 mut data: &mut FnMut(bool, &mut Vec<u8>, bool)) -> io::Result<()> {
        let mut out = Vec::new();
        let mut err = Vec::new();

        let port = CompletionPort::new(1)?;
        port.add_handle(0, &out_pipe)?;
        port.add_handle(1, &err_pipe)?;

        unsafe {
            let mut out_pipe = Pipe::new(out_pipe, &mut out);
            let mut err_pipe = Pipe::new(err_pipe, &mut err);

            out_pipe.read()?;
            err_pipe.read()?;

            let mut status = [CompletionStatus::zero(), CompletionStatus::zero()];

            while !out_pipe.done || !err_pipe.done {
                for status in port.get_many(&mut status, None)? {
                    if status.token() == 0 {
                        out_pipe.complete(status);
                        data(true, out_pipe.dst, out_pipe.done);
                        out_pipe.read()?;
                    } else {
                        err_pipe.complete(status);
                        data(false, err_pipe.dst, err_pipe.done);
                        err_pipe.read()?;
                    }
                }
            }

            Ok(())
        }
    }

    impl<'a> Pipe<'a> {
        unsafe fn new<P: IntoRawHandle>(p: P, dst: &'a mut Vec<u8>) -> Pipe<'a> {
            Pipe {
                dst: dst,
                pipe: NamedPipe::from_raw_handle(p.into_raw_handle()),
                overlapped: Overlapped::zero(),
                done: false,
            }
        }

        unsafe fn read(&mut self) -> io::Result<()> {
            let dst = slice_to_end(self.dst);
            match self.pipe.read_overlapped(dst, &mut self.overlapped) {
                Ok(_) => Ok(()),
                Err(e) => {
                    if e.raw_os_error() == Some(ERROR_BROKEN_PIPE as i32) {
                        self.done = true;
                        Ok(())
                    } else {
                        Err(e)
                    }
                }
            }
        }

        unsafe fn complete(&mut self, status: &CompletionStatus) {
            let prev = self.dst.len();
            self.dst.set_len(prev + status.bytes_transferred() as usize);
            if status.bytes_transferred() == 0 {
                self.done = true;
            }
        }
    }

    unsafe fn slice_to_end(v: &mut Vec<u8>) -> &mut [u8] {
        if v.capacity() == 0 {
            v.reserve(16);
        }
        if v.capacity() == v.len() {
            v.reserve(1);
        }
        slice::from_raw_parts_mut(v.as_mut_ptr().offset(v.len() as isize),
                                  v.capacity() - v.len())
    }
}
<|endoftext|>


<commit_before>pub use self::imp::read2;

#[cfg(unix)]
mod imp {
    use std::cmp;
    use std::io::prelude::*;
    use std::io;
    use std::mem;
    use std::os::unix::prelude::*;
    use std::process::{ChildStdout, ChildStderr};
    use libc;

    pub fn read2(mut out_pipe: ChildStdout,
                 mut err_pipe: ChildStderr,
                 data: &mut FnMut(bool, &mut Vec<u8>, bool)) -> io::Result<()> {
        unsafe {
            libc::fcntl(out_pipe.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK);
            libc::fcntl(err_pipe.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK);
        }

        let mut out_done = false;
        let mut err_done = false;
        let mut out = Vec::new();
        let mut err = Vec::new();

        let max = cmp::max(out_pipe.as_raw_fd(), err_pipe.as_raw_fd());
        loop {
            // wait for either pipe to become readable using `select`
            let r = unsafe {
                let mut read: libc::fd_set = mem::zeroed();
                if !out_done {
                    libc::FD_SET(out_pipe.as_raw_fd(), &mut read);
                }
                if !err_done {
                    libc::FD_SET(err_pipe.as_raw_fd(), &mut read);
                }
                libc::select(max + 1, &mut read, 0 as *mut _, 0 as *mut _,
                             0 as *mut _)
            };
            if r == -1 {
                let err = io::Error::last_os_error();
                if err.kind() == io::ErrorKind::Interrupted {
                    continue
                }
                return Err(err)
            }

            // Read as much as we can from each pipe, ignoring EWOULDBLOCK or
            // EAGAIN. If we hit EOF, then this will happen because the underlying
            // reader will return Ok(0), in which case we'll see `Ok` ourselves. In
            // this case we flip the other fd back into blocking mode and read
            // whatever's leftover on that file descriptor.
            let handle = |res: io::Result<_>| {
                match res {
                    Ok(_) => Ok(true),
                    Err(e) => {
                        if e.kind() == io::ErrorKind::WouldBlock {
                            Ok(false)
                        } else {
                            Err(e)
                        }
                    }
                }
            };
            if !out_done && handle(out_pipe.read_to_end(&mut out))? {
                out_done = true;
            }
            data(true, &mut out, out_done);
            if !err_done && handle(err_pipe.read_to_end(&mut err))? {
                err_done = true;
            }
            data(false, &mut err, err_done);

            if out_done && err_done {
                return Ok(())
            }
        }
    }
}

#[cfg(windows)]
mod imp {
    extern crate miow;
    extern crate winapi;

    use std::io;
    use std::os::windows::prelude::*;
    use std::process::{ChildStdout, ChildStderr};
    use std::slice;

    use self::miow::iocp::{CompletionPort, CompletionStatus};
    use self::miow::pipe::NamedPipe;
    use self::miow::Overlapped;
    use self::winapi::ERROR_BROKEN_PIPE;

    struct Pipe<'a> {
        dst: &'a mut Vec<u8>,
        overlapped: Overlapped,
        pipe: NamedPipe,
        done: bool,
    }

    pub fn read2(out_pipe: ChildStdout,
                 err_pipe: ChildStderr,
                 mut data: &mut FnMut(bool, &mut Vec<u8>, bool)) -> io::Result<()> {
        let mut out = Vec::new();
        let mut err = Vec::new();

        let port = CompletionPort::new(1)?;
        port.add_handle(0, &out_pipe)?;
        port.add_handle(1, &err_pipe)?;

        unsafe {
            let mut out_pipe = Pipe::new(out_pipe, &mut out);
            let mut err_pipe = Pipe::new(err_pipe, &mut err);

            out_pipe.read()?;
            err_pipe.read()?;

            let mut status = [CompletionStatus::zero(), CompletionStatus::zero()];

            while !out_pipe.done || !err_pipe.done {
                for status in port.get_many(&mut status, None)? {
                    if status.token() == 0 {
                        out_pipe.complete(status);
                        data(true, out_pipe.dst, out_pipe.done);
                        out_pipe.read()?;
                    } else {
                        err_pipe.complete(status);
                        data(false, err_pipe.dst, err_pipe.done);
                        err_pipe.read()?;
                    }
                }
            }

            Ok(())
        }
    }

    impl<'a> Pipe<'a> {
        unsafe fn new<P: IntoRawHandle>(p: P, dst: &'a mut Vec<u8>) -> Pipe<'a> {
            Pipe {
                dst: dst,
                pipe: NamedPipe::from_raw_handle(p.into_raw_handle()),
                overlapped: Overlapped::zero(),
                done: false,
            }
        }

        unsafe fn read(&mut self) -> io::Result<()> {
            let dst = slice_to_end(self.dst);
            match self.pipe.read_overlapped(dst, self.overlapped.raw()) {
                Ok(_) => Ok(()),
                Err(e) => {
                    if e.raw_os_error() == Some(ERROR_BROKEN_PIPE as i32) {
                        self.done = true;
                        Ok(())
                    } else {
                        Err(e)
                    }
                }
            }
        }

        unsafe fn complete(&mut self, status: &CompletionStatus) {
            let prev = self.dst.len();
            self.dst.set_len(prev + status.bytes_transferred() as usize);
            if status.bytes_transferred() == 0 {
                self.done = true;
            }
        }
    }

    unsafe fn slice_to_end(v: &mut Vec<u8>) -> &mut [u8] {
        if v.capacity() == 0 {
            v.reserve(16);
        }
        if v.capacity() == v.len() {
            v.reserve(1);
        }
        slice::from_raw_parts_mut(v.as_mut_ptr().offset(v.len() as isize),
                                  v.capacity() - v.len())
    }
}
<commit_msg>Fixed instance in Windows cfg.<commit_after>pub use self::imp::read2;

#[cfg(unix)]
mod imp {
    use std::cmp;
    use std::io::prelude::*;
    use std::io;
    use std::mem;
    use std::os::unix::prelude::*;
    use std::process::{ChildStdout, ChildStderr};
    use libc;

    pub fn read2(mut out_pipe: ChildStdout,
                 mut err_pipe: ChildStderr,
                 data: &mut FnMut(bool, &mut Vec<u8>, bool)) -> io::Result<()> {
        unsafe {
            libc::fcntl(out_pipe.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK);
            libc::fcntl(err_pipe.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK);
        }

        let mut out_done = false;
        let mut err_done = false;
        let mut out = Vec::new();
        let mut err = Vec::new();

        let max = cmp::max(out_pipe.as_raw_fd(), err_pipe.as_raw_fd());
        loop {
            // wait for either pipe to become readable using `select`
            let r = unsafe {
                let mut read: libc::fd_set = mem::zeroed();
                if !out_done {
                    libc::FD_SET(out_pipe.as_raw_fd(), &mut read);
                }
                if !err_done {
                    libc::FD_SET(err_pipe.as_raw_fd(), &mut read);
                }
                libc::select(max + 1, &mut read, 0 as *mut _, 0 as *mut _,
                             0 as *mut _)
            };
            if r == -1 {
                let err = io::Error::last_os_error();
                if err.kind() == io::ErrorKind::Interrupted {
                    continue
                }
                return Err(err)
            }

            // Read as much as we can from each pipe, ignoring EWOULDBLOCK or
            // EAGAIN. If we hit EOF, then this will happen because the underlying
            // reader will return Ok(0), in which case we'll see `Ok` ourselves. In
            // this case we flip the other fd back into blocking mode and read
            // whatever's leftover on that file descriptor.
            let handle = |res: io::Result<_>| {
                match res {
                    Ok(_) => Ok(true),
                    Err(e) => {
                        if e.kind() == io::ErrorKind::WouldBlock {
                            Ok(false)
                        } else {
                            Err(e)
                        }
                    }
                }
            };
            if !out_done && handle(out_pipe.read_to_end(&mut out))? {
                out_done = true;
            }
            data(true, &mut out, out_done);
            if !err_done && handle(err_pipe.read_to_end(&mut err))? {
                err_done = true;
            }
            data(false, &mut err, err_done);

            if out_done && err_done {
                return Ok(())
            }
        }
    }
}

#[cfg(windows)]
mod imp {
    extern crate miow;
    extern crate winapi;

    use std::io;
    use std::os::windows::prelude::*;
    use std::process::{ChildStdout, ChildStderr};
    use std::slice;

    use self::miow::iocp::{CompletionPort, CompletionStatus};
    use self::miow::pipe::NamedPipe;
    use self::miow::Overlapped;
    use self::winapi::ERROR_BROKEN_PIPE;

    struct Pipe<'a> {
        dst: &'a mut Vec<u8>,
        overlapped: Overlapped,
        pipe: NamedPipe,
        done: bool,
    }

    pub fn read2(out_pipe: ChildStdout,
                 err_pipe: ChildStderr,
                 data: &mut FnMut(bool, &mut Vec<u8>, bool)) -> io::Result<()> {
        let mut out = Vec::new();
        let mut err = Vec::new();

        let port = CompletionPort::new(1)?;
        port.add_handle(0, &out_pipe)?;
        port.add_handle(1, &err_pipe)?;

        unsafe {
            let mut out_pipe = Pipe::new(out_pipe, &mut out);
            let mut err_pipe = Pipe::new(err_pipe, &mut err);

            out_pipe.read()?;
            err_pipe.read()?;

            let mut status = [CompletionStatus::zero(), CompletionStatus::zero()];

            while !out_pipe.done || !err_pipe.done {
                for status in port.get_many(&mut status, None)? {
                    if status.token() == 0 {
                        out_pipe.complete(status);
                        data(true, out_pipe.dst, out_pipe.done);
                        out_pipe.read()?;
                    } else {
                        err_pipe.complete(status);
                        data(false, err_pipe.dst, err_pipe.done);
                        err_pipe.read()?;
                    }
                }
            }

            Ok(())
        }
    }

    impl<'a> Pipe<'a> {
        unsafe fn new<P: IntoRawHandle>(p: P, dst: &'a mut Vec<u8>) -> Pipe<'a> {
            Pipe {
                dst: dst,
                pipe: NamedPipe::from_raw_handle(p.into_raw_handle()),
                overlapped: Overlapped::zero(),
                done: false,
            }
        }

        unsafe fn read(&mut self) -> io::Result<()> {
            let dst = slice_to_end(self.dst);
            match self.pipe.read_overlapped(dst, self.overlapped.raw()) {
                Ok(_) => Ok(()),
                Err(e) => {
                    if e.raw_os_error() == Some(ERROR_BROKEN_PIPE as i32) {
                        self.done = true;
                        Ok(())
                    } else {
                        Err(e)
                    }
                }
            }
        }

        unsafe fn complete(&mut self, status: &CompletionStatus) {
            let prev = self.dst.len();
            self.dst.set_len(prev + status.bytes_transferred() as usize);
            if status.bytes_transferred() == 0 {
                self.done = true;
            }
        }
    }

    unsafe fn slice_to_end(v: &mut Vec<u8>) -> &mut [u8] {
        if v.capacity() == 0 {
            v.reserve(16);
        }
        if v.capacity() == v.len() {
            v.reserve(1);
        }
        slice::from_raw_parts_mut(v.as_mut_ptr().offset(v.len() as isize),
                                  v.capacity() - v.len())
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

extern crate gj;
use std::net::ToSocketAddrs;
use gj::io::{AsyncRead, AsyncWrite};

fn echo<S,B>(stream: S, buf: B) -> gj::Promise<(), Box<::std::error::Error>>
    where S: AsyncRead + AsyncWrite, B: ::std::ops::DerefMut<Target=[u8]> + 'static
{
    stream.try_read(buf, 1).lift().then(move |(stream, buf, n)| {
        if n == 0 {
            // EOF
            Ok(gj::Promise::fulfilled(()))
        } else {
            Ok(stream.write(gj::io::Slice::new(buf, n)).lift().then(move |(stream, slice)| {
                Ok(echo(stream, slice.buf))
            }))
        }
    })
}

fn accept_loop(receiver: gj::io::tcp::Listener,
               mut task_set: gj::TaskSet) -> gj::Promise<(), Box<::std::error::Error>> {

    receiver.accept().lift().then(move |(receiver, stream)| {
        task_set.add(echo(stream, vec![0; 1024]).lift());
        Ok(accept_loop(receiver, task_set).lift())
    })
}

pub struct Reporter;

impl gj::ErrorHandler for Reporter {
    fn task_failed(&mut self, error: Box<::std::error::Error>) {
        println!("Task failed: {}", error);
    }
}

pub fn main() {
    let args : Vec<String> = ::std::env::args().collect();
    if args.len() != 2 {
        println!("usage: {} HOST:PORT", args[0]);
        return;
    }

    gj::EventLoop::top_level(move |wait_scope| {
        let addr = try!(args[1].to_socket_addrs()).next().expect("could not parse address");
        let listener = try!(::gj::io::tcp::Listener::bind(addr));
        return accept_loop(listener,
                           gj::TaskSet::new(Box::new(Reporter))).wait(wait_scope);
    }).unwrap();
}
<commit_msg>use more specific error<commit_after>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

extern crate gj;
use std::net::ToSocketAddrs;
use gj::io::{AsyncRead, AsyncWrite};

fn echo<S,B>(stream: S, buf: B) -> gj::Promise<(), ::std::io::Error>
    where S: AsyncRead + AsyncWrite, B: ::std::ops::DerefMut<Target=[u8]> + 'static
{
    stream.try_read(buf, 1).lift().then(move |(stream, buf, n)| {
        if n == 0 {
            // EOF
            Ok(gj::Promise::fulfilled(()))
        } else {
            Ok(stream.write(gj::io::Slice::new(buf, n)).lift().then(move |(stream, slice)| {
                Ok(echo(stream, slice.buf))
            }))
        }
    })
}

fn accept_loop(receiver: gj::io::tcp::Listener,
               mut task_set: gj::TaskSet) -> gj::Promise<(), Box<::std::error::Error>> {

    receiver.accept().lift().then(move |(receiver, stream)| {
        task_set.add(echo(stream, vec![0; 1024]).lift());
        Ok(accept_loop(receiver, task_set).lift())
    })
}

pub struct Reporter;

impl gj::ErrorHandler for Reporter {
    fn task_failed(&mut self, error: Box<::std::error::Error>) {
        println!("Task failed: {}", error);
    }
}

pub fn main() {
    let args : Vec<String> = ::std::env::args().collect();
    if args.len() != 2 {
        println!("usage: {} HOST:PORT", args[0]);
        return;
    }

    gj::EventLoop::top_level(move |wait_scope| {
        let addr = try!(args[1].to_socket_addrs()).next().expect("could not parse address");
        let listener = try!(::gj::io::tcp::Listener::bind(addr));
        return accept_loop(listener,
                           gj::TaskSet::new(Box::new(Reporter))).wait(wait_scope);
    }).unwrap();
}
<|endoftext|>


<commit_before>#[cfg(not(windows))]
compile_error!("This demo only runs on Windows.");

extern crate direct_composition;
extern crate gleam;
extern crate winit;

use direct_composition::{DirectComposition, D3DVisual};
use winit::os::windows::WindowExt;

fn main() {
    let mut events_loop = winit::EventsLoop::new();
    let window = winit::WindowBuilder::new()
        .with_title("Hello, world!")
        .with_dimensions(1024, 768)
        .build(&events_loop)
        .unwrap();

    let composition = direct_composition_from_window(&window);

    let visual1 = composition.create_d3d_visual(300, 200);
    visual1.set_offset_x(100.);
    visual1.set_offset_y(50.);

    let visual2 = composition.create_d3d_visual(400, 300);
    let mut offset_y = 100.;
    visual2.set_offset_x(200.);
    visual2.set_offset_y(offset_y);

    composition.commit();

    let mut rgba1 = [0., 0.2, 0.4, 1.];
    let mut rgba2 = [0., 0.5, 0., 0.5];
    render_plain_rgba_frame(&visual1, &rgba1);
    render_plain_rgba_frame(&visual2, &rgba2);

    let mut clicks: u32 = 0;

    events_loop.run_forever(|event| {
        if let winit::Event::WindowEvent { event, .. } = event {
            match event {
                winit::WindowEvent::Closed => {
                    return winit::ControlFlow::Break
                }
                winit::WindowEvent::MouseWheel { delta, .. } => {
                    let dy = match delta {
                        winit::MouseScrollDelta::LineDelta(_, dy) => dy,
                        winit::MouseScrollDelta::PixelDelta(_, dy) => dy,
                    };
                    offset_y = (offset_y - 10. * dy).max(0.).min(468.);

                    visual2.set_offset_y(offset_y);
                    composition.commit();
                }
                winit::WindowEvent::MouseInput {
                    button: winit::MouseButton::Left,
                    state: winit::ElementState::Pressed,
                    ..
                } => {
                    clicks += 1;
                    let (rgba, visual) = if clicks % 2 == 0 {
                        (&mut rgba1, &visual1)
                    } else {
                        (&mut rgba2, &visual2)
                    };
                    rgba[1] += 0.1;
                    rgba[1] %= 1.;
                    render_plain_rgba_frame(visual, rgba)
                }
                _ => {}
            }
        }
        winit::ControlFlow::Continue
    });
}

fn direct_composition_from_window(window: &winit::Window) -> DirectComposition {
    unsafe {
        DirectComposition::new(window.get_hwnd() as _)
    }
}

fn render_plain_rgba_frame(visual: &D3DVisual, rgba: &[f32; 4]) {
    visual.make_current();
    visual.gleam.clear_color(rgba[0], rgba[1], rgba[2], rgba[3]);
    visual.gleam.clear(gleam::gl::COLOR_BUFFER_BIT);
    assert_eq!(visual.gleam.get_error(), 0);
    visual.present();
}
<commit_msg>Use tuples for RGBA colors<commit_after>#[cfg(not(windows))]
compile_error!("This demo only runs on Windows.");

extern crate direct_composition;
extern crate gleam;
extern crate winit;

use direct_composition::{DirectComposition, D3DVisual};
use winit::os::windows::WindowExt;

fn main() {
    let mut events_loop = winit::EventsLoop::new();
    let window = winit::WindowBuilder::new()
        .with_title("Hello, world!")
        .with_dimensions(1024, 768)
        .build(&events_loop)
        .unwrap();

    let composition = direct_composition_from_window(&window);

    let visual1 = composition.create_d3d_visual(300, 200);
    visual1.set_offset_x(100.);
    visual1.set_offset_y(50.);

    let visual2 = composition.create_d3d_visual(400, 300);
    let mut offset_y = 100.;
    visual2.set_offset_x(200.);
    visual2.set_offset_y(offset_y);

    composition.commit();

    let mut rgba1 = (0., 0.2, 0.4, 1.);
    let mut rgba2 = (0., 0.5, 0., 0.5);
    render_plain_rgba_frame(&visual1, &rgba1);
    render_plain_rgba_frame(&visual2, &rgba2);

    let mut clicks: u32 = 0;

    events_loop.run_forever(|event| {
        if let winit::Event::WindowEvent { event, .. } = event {
            match event {
                winit::WindowEvent::Closed => {
                    return winit::ControlFlow::Break
                }
                winit::WindowEvent::MouseWheel { delta, .. } => {
                    let dy = match delta {
                        winit::MouseScrollDelta::LineDelta(_, dy) => dy,
                        winit::MouseScrollDelta::PixelDelta(_, dy) => dy,
                    };
                    offset_y = (offset_y - 10. * dy).max(0.).min(468.);

                    visual2.set_offset_y(offset_y);
                    composition.commit();
                }
                winit::WindowEvent::MouseInput {
                    button: winit::MouseButton::Left,
                    state: winit::ElementState::Pressed,
                    ..
                } => {
                    clicks += 1;
                    let (rgba, visual) = if clicks % 2 == 0 {
                        (&mut rgba1, &visual1)
                    } else {
                        (&mut rgba2, &visual2)
                    };
                    rgba.1 += 0.1;
                    rgba.1 %= 1.;
                    render_plain_rgba_frame(visual, rgba)
                }
                _ => {}
            }
        }
        winit::ControlFlow::Continue
    });
}

fn direct_composition_from_window(window: &winit::Window) -> DirectComposition {
    unsafe {
        DirectComposition::new(window.get_hwnd() as _)
    }
}

fn render_plain_rgba_frame(visual: &D3DVisual, &(r, g, b, a): &(f32, f32, f32, f32)) {
    visual.make_current();
    visual.gleam.clear_color(r, g, b, a);
    visual.gleam.clear(gleam::gl::COLOR_BUFFER_BIT);
    assert_eq!(visual.gleam.get_error(), 0);
    visual.present();
}
<|endoftext|>


<commit_before>// Copyright © 2011 Mozilla Foundation
//
// This program is made available under an ISC-style license.  See the
// accompanying file LICENSE for details.

//! libcubeb api/function test. Plays a simple tone.
extern crate cubeb;

use cubeb::SampleType;
use std::f32::consts::PI;
use std::thread;
use std::time::Duration;

const SAMPLE_FREQUENCY: u32 = 48000;
const STREAM_FORMAT: cubeb::SampleFormat = cubeb::SampleFormat::S16LE;

// store the phase of the generated waveform
struct Tone {
    position: isize
}

impl cubeb::StreamCallback for Tone {
    type Frame = cubeb::MonoFrame<i16>;

    fn data_callback(&mut self, _: &[cubeb::MonoFrame<i16>], output: &mut [cubeb::MonoFrame<i16>]) -> isize {

        // generate our test tone on the fly
        for f in output.iter_mut() {
            // North American dial tone
            let t1 = (2.0 * PI * 350.0 * self.position as f32 / SAMPLE_FREQUENCY as f32).sin();
            let t2 = (2.0 * PI * 440.0 * self.position as f32 / SAMPLE_FREQUENCY as f32).sin();

            f.m = i16::from_float(0.5 * (t1 + t2));

            self.position += 1;
        }

        output.len() as isize
    }

    fn state_callback(&mut self, state: cubeb::State) {
        println!("stream {:?}", state);
    }
}

fn main() {
    let ctx = cubeb::Context::init("Cubeb tone example", None).expect("Failed to create cubeb context");

    // std::unique_ptr<cb_user_data> user_data(new cb_user_data());
    // ASSERT_TRUE(!!user_data) << "Error allocating user data";

    // user_data->position = 0;

    let params = cubeb::StreamParamsBuilder::new()
        .format(STREAM_FORMAT)
        .rate(SAMPLE_FREQUENCY)
        .channels(1)
        .layout(cubeb::ChannelLayout::Mono)
        .take();

    let stream_init_opts = cubeb::StreamInitOptionsBuilder::new()
        .stream_name("Cubeb tone (mono)")
        .output_stream_param(&params)
        .latency(4096)
        .take();

    let stream = ctx.stream_init(
        &stream_init_opts,
        Tone {
            position: 0
        }
    ).expect("Failed to create cubeb stream");

    stream.start().unwrap();
    thread::sleep(Duration::from_millis(500));
    stream.stop().unwrap();
}
<commit_msg>cubeb-rs: Update tone example to use common::init.<commit_after>// Copyright © 2011 Mozilla Foundation
//
// This program is made available under an ISC-style license.  See the
// accompanying file LICENSE for details.

//! libcubeb api/function test. Plays a simple tone.
extern crate cubeb;

mod common;

use cubeb::SampleType;
use std::f32::consts::PI;
use std::thread;
use std::time::Duration;

const SAMPLE_FREQUENCY: u32 = 48000;
const STREAM_FORMAT: cubeb::SampleFormat = cubeb::SampleFormat::S16LE;

// store the phase of the generated waveform
struct Tone {
    position: isize
}

impl cubeb::StreamCallback for Tone {
    type Frame = cubeb::MonoFrame<i16>;

    fn data_callback(&mut self, _: &[cubeb::MonoFrame<i16>], output: &mut [cubeb::MonoFrame<i16>]) -> isize {

        // generate our test tone on the fly
        for f in output.iter_mut() {
            // North American dial tone
            let t1 = (2.0 * PI * 350.0 * self.position as f32 / SAMPLE_FREQUENCY as f32).sin();
            let t2 = (2.0 * PI * 440.0 * self.position as f32 / SAMPLE_FREQUENCY as f32).sin();

            f.m = i16::from_float(0.5 * (t1 + t2));

            self.position += 1;
        }

        output.len() as isize
    }

    fn state_callback(&mut self, state: cubeb::State) {
        println!("stream {:?}", state);
    }
}

fn main() {
    let ctx = common::init("Cubeb tone example").expect("Failed to create cubeb context");

    let params = cubeb::StreamParamsBuilder::new()
        .format(STREAM_FORMAT)
        .rate(SAMPLE_FREQUENCY)
        .channels(1)
        .layout(cubeb::ChannelLayout::Mono)
        .take();

    let stream_init_opts = cubeb::StreamInitOptionsBuilder::new()
        .stream_name("Cubeb tone (mono)")
        .output_stream_param(&params)
        .latency(4096)
        .take();

    let stream = ctx.stream_init(
        &stream_init_opts,
        Tone {
            position: 0
        }
    ).expect("Failed to create cubeb stream");

    stream.start().unwrap();
    thread::sleep(Duration::from_millis(500));
    stream.stop().unwrap();
}
<|endoftext|>


<commit_before>use crate::paging::ActivePageTable;

pub mod cpu;
pub mod ioapic;
pub mod local_apic;
pub mod pic;
pub mod pit;
pub mod rtc;
pub mod serial;
#[cfg(feature = "acpi")]
pub mod hpet;

pub unsafe fn init(active_table: &mut ActivePageTable) {
    pic::init();
    local_apic::init(active_table);
}
pub unsafe fn init_after_acpi(active_table: &mut ActivePageTable)  {
    // this will disable the IOAPIC if needed.
    ioapic::init(active_table);
}

#[cfg(feature = "acpi")]
unsafe fn init_hpet() -> bool {
    use crate::acpi::ACPI_TABLE;
    if let Some(ref mut hpet) = *ACPI_TABLE.hpet.write() {
        hpet::init(hpet)
    } else {
        false
    }
}

#[cfg(not(feature = "acpi"))]
unsafe fn init_hpet() -> bool {
    false
}

pub unsafe fn init_noncore() {
    if ! init_hpet() {
        pit::init();
    }

    rtc::init();
    serial::init();
}

pub unsafe fn init_ap() {
    local_apic::init_ap();
}
<commit_msg>Don't use the I/O APIC by default,<commit_after>use crate::paging::ActivePageTable;

pub mod cpu;
pub mod ioapic;
pub mod local_apic;
pub mod pic;
pub mod pit;
pub mod rtc;
pub mod serial;
#[cfg(feature = "acpi")]
pub mod hpet;

pub unsafe fn init(active_table: &mut ActivePageTable) {
    pic::init();
    local_apic::init(active_table);
}
pub unsafe fn init_after_acpi(active_table: &mut ActivePageTable)  {
    // this will disable the IOAPIC if needed.
    //ioapic::init(active_table);
}

#[cfg(feature = "acpi")]
unsafe fn init_hpet() -> bool {
    use crate::acpi::ACPI_TABLE;
    if let Some(ref mut hpet) = *ACPI_TABLE.hpet.write() {
        hpet::init(hpet)
    } else {
        false
    }
}

#[cfg(not(feature = "acpi"))]
unsafe fn init_hpet() -> bool {
    false
}

pub unsafe fn init_noncore() {
    if ! init_hpet() {
        pit::init();
    }

    rtc::init();
    serial::init();
}

pub unsafe fn init_ap() {
    local_apic::init_ap();
}
<|endoftext|>