<commit_before>use std;
use servo;

import result::{ok, err};
import std::test{test_opts, run_tests_console, test_desc};
import std::getopts::{getopts, reqopt, opt_opt, fail_str};
import std::path::connect;
import os::list_dir_path;

fn main(args: [str]) {
    let config = parse_config(args);
    let opts = test_options(config);
    let tests = find_tests(config);
    install_rasterize_js();
    run_tests_console(opts, tests);
}

type Config = {
    source_dir: str,
    work_dir: str
};

fn parse_config(args: [str]) -> Config {
    let args = args.tail();
    let opts = [reqopt("source-dir"), reqopt("work-dir")];
    let match = alt getopts(args, opts) {
      ok(m) { m }
      err(f) { fail fail_str(f) }
    }

    {
        source_dir: opt_str(match, "source-dir"),
        work_dir: opt_str(match, "work-dir"),
        filter: if match.free.is_empty() {
            none
        } else {
            some(match.head())
        }
    }
}

fn test_options(config: Config) -> test_opts {
    {
        filter: none,
        run_ignored: false,
        logfile: none
    }
}

fn find_tests(config: Config) -> [test_desc] {
    let html_files = list_dir_path(config.source_dir).filter({ |file| file.ends_with(".html") });
    ret html_files.map({ |file| make_test(config, file) });
}

fn make_test(config: Config, file: str) -> test_desc {
    {
        name: file,
        fn: { || run_test(config, file) },
        ignore: false,
        should_fail: false
    }
}

fn run_test(config: Config, file: str) {
    let servo_render = render_servo(config, file);
    let ref_render = render_ref(config, file);
    if !servo_render.eq(ref_render) {
        fail;
    }
}

type Render = [u8];

fn render_servo(config: Config, file: str) -> Render {
    let infile = connect(config.work_dir, file);
    let outfile = infile + ".png";
    run_pipeline_png(infile, outfile);
    fail;
}

fn render_ref(config: Config, file: str) -> Render {
    fail
}

fn install_rasterize_js() { fail }

// This is the script that uses phantom.js to render pages
fn rasterize_js() -> str { #include_str("rasterize.js") }
<commit_msg>Fix reftest build errors<commit_after>use std;
use servo;

import result::{ok, err};
import std::test::{test_opts, run_tests_console, test_desc};
import std::getopts::{getopts, reqopt, opt_str, fail_str};
import path::{connect, basename};
import os::list_dir_path;
import servo::run_pipeline_png;

fn main(args: [str]) {
    let config = parse_config(args);
    let opts = test_options(config);
    let tests = find_tests(config);
    install_rasterize_js();
    run_tests_console(opts, tests);
}

type Config = {
    source_dir: str,
    work_dir: str,
    filter: option<str>
};

fn parse_config(args: [str]) -> Config {
    let args = args.tail();
    let opts = [reqopt("source-dir"), reqopt("work-dir")];
    let match = alt getopts(args, opts) {
      ok(m) { m }
      err(f) { fail fail_str(f) }
    };

    {
        source_dir: opt_str(match, "source-dir"),
        work_dir: opt_str(match, "work-dir"),
        filter: if match.free.is_empty() {
            none
        } else {
            some(match.free.head())
        }
    }
}

fn test_options(config: Config) -> test_opts {
    {
        filter: config.filter,
        run_ignored: false,
        logfile: none
    }
}

fn find_tests(config: Config) -> [test_desc] {
    let html_files = list_dir_path(config.source_dir).filter({ |file| file.ends_with(".html") });
    ret html_files.map({ |file| make_test(config, file) });
}

fn make_test(config: Config, file: str) -> test_desc {
    {
        name: file,
        fn: fn~() { run_test(config, file) },
        ignore: false,
        should_fail: false
    }
}

fn run_test(config: Config, file: str) {
    let servo_render = render_servo(config, file);
    let ref_render = render_ref(config, file);
    if servo_render != ref_render {
        fail;
    }
}

type Render = [u8];

fn render_servo(config: Config, file: str) -> Render {
    let infile = file;
    let outfile = connect(config.work_dir, basename(file) + ".png");
    run_pipeline_png(infile, outfile);
    fail;
}

fn render_ref(config: Config, file: str) -> Render {
    fail
}

fn install_rasterize_js() { }

// This is the script that uses phantom.js to render pages
fn rasterize_js() -> str { #include_str("rasterize.js") }
<|endoftext|>


<commit_before>use std::fmt;
use rocksdb::{DB, Writable, Options, WriteBatch, WriteOptions};
use rocksdb::ffi::DBCFHandle;
use tempdir::TempDir;
use byteorder::{ByteOrder, BigEndian};
use spki_sexp;
use super::Operation;
use time::{Duration, PreciseTime};
use std::thread;
use std::sync::mpsc;
use std::sync::Arc;

pub struct Log {
    dir: TempDir,
    db: Arc<DB>,
    meta: DBCFHandle,
    data: DBCFHandle,
    flush_tx: mpsc::SyncSender<u64>,
}

const META: &'static str = "meta";
const DATA: &'static str = "data";
const META_PREPARED: &'static str = "prepared";
const META_COMMITTED: &'static str = "committed";

impl fmt::Debug for Log {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Log").field("dir", &self.dir.path()).finish()
    }
}

impl Log {
    pub fn new<F: Fn(u64) + Send + 'static>(committed: F) -> Log {
        let d = TempDir::new("rocksdb-log").expect("new log");
        info!("DB path: {:?}", d.path());
        let mut db = DB::open_default(&d.path().to_string_lossy()).expect("open db");
        let meta = db.create_cf(META, &Options::new()).expect("open meta cf");
        let data = db.create_cf(DATA, &Options::new()).expect("open data cf");
        let db = Arc::new(db);
        let (flush_tx, flush_rx) = mpsc::sync_channel(42);

        let flusher = {
            let db = db.clone();
            thread::Builder::new()
                .name("flusher".to_string())
                .spawn(move || Self::flush_thread_loop(db, flush_rx, committed))
                .expect("spawn flush thread")
        };
        Log {
            dir: d,
            db: db,
            meta: meta,
            data: data,
            flush_tx: flush_tx,
        }
    }

    fn flush_thread_loop<F: Fn(u64)>(db: Arc<DB>, rx: mpsc::Receiver<u64>, committed: F) {
        let meta = db.cf_handle(META).expect("open meta cf").clone();
        let data = db.cf_handle(DATA).expect("open data cf").clone();
        loop {
            debug!("Awaiting flush");
            let mut seqno = rx.recv().expect("recive flush seqno");
            loop {
                match rx.try_recv() {
                    Ok(n) => seqno = n,
                    Err(_) => break,
                }
            }
            debug!("Flushing: {:?}", seqno);
            Self::do_commit_to(db.clone(), meta, data, seqno);
            debug!("Flushed: {:?}", seqno);
            committed(seqno);
        }
    }

    fn tokey(seq: u64) -> [u8; 8] {
        let mut buf: [u8; 8] = [0, 0, 0, 0, 0, 0, 0, 0];
        BigEndian::write_u64(&mut buf, seq);
        buf
    }

    fn fromkey(key: &[u8]) -> u64 {
        BigEndian::read_u64(&key)
    }

    pub fn seqno(&self) -> u64 {
        let current = self.read_seqno(META_PREPARED);
        let next = current + 1;
        next
    }

    fn do_read_seqno(db: &DB, meta: DBCFHandle, name: &str) -> u64 {
        match db.get_cf(meta, name.as_bytes()) {
            Ok(Some(val)) => Self::fromkey(&val),
            Ok(None) => 0,
            Err(e) => panic!("Unexpected error getting commit point: {:?}", e),
        }
    }

    fn read_seqno(&self, name: &str) -> u64 {
        Self::do_read_seqno(&self.db, self.meta, name)
    }

    pub fn read(&self, seqno: u64) -> Option<Operation> {
        let key = Self::tokey(seqno);
        let ret = match self.db.get_cf(self.data, &key.as_ref()) {
            Ok(Some(val)) => Some(spki_sexp::from_bytes(&val).expect("decode operation")),
            Ok(None) => None,
            Err(e) => panic!("Unexpected error reading index: {:?}: {:?}", seqno, e),
        };
        debug!("Read: {:?} => {:?}", seqno, ret);
        ret
    }

    pub fn verify_sequential(&self, seqno: u64) -> bool {
        let current = self.seqno();
        if !(seqno == 0 || current <= seqno) {
            warn!("Hole in history: saw {}; have: {:?}", seqno, current);
            false
        } else {
            true
        }
    }

    pub fn prepare(&mut self, seqno: u64, op: &Operation) {
        let data_bytes = spki_sexp::as_bytes(op).expect("encode operation");
        debug!("Prepare {:?}", seqno);
        let key = Self::tokey(seqno);
        // match self.db.get_cf(self.data, &key.as_ref()) {
        // Ok(None) => (),
        // Err(e) => panic!("Unexpected error reading index: {:?}: {:?}", seqno, e),
        // Ok(_) => panic!("Unexpected entry at seqno: {:?}", seqno),
        // };

        let t0 = PreciseTime::now();
        let mut batch = WriteBatch::new();
        batch.put_cf(self.data, &key.as_ref(), &data_bytes).expect("Persist operation");
        batch.put_cf(self.meta, META_PREPARED.as_bytes(), &key.as_ref())
             .expect("Persist prepare point");
        self.db.write(batch).expect("Write batch");
        let t1 = PreciseTime::now();
        debug!("Prepare: {}", t0.to(t1));
        trace!("Watermarks: prepared: {:?}; committed: {:?}",
               self.read_seqno(META_PREPARED),
               self.read_seqno(META_COMMITTED));
    }

    pub fn commit_to(&mut self, seqno: u64) {
        debug!("Request commit upto: {:?}", seqno);
        self.flush_tx.send(seqno).expect("Send to flusher")
    }

    fn do_commit_to(db: Arc<DB>, meta: DBCFHandle, data: DBCFHandle, commit_seqno: u64) {
        debug!("Commit {:?}", commit_seqno);
        let key = Self::tokey(commit_seqno);

        let prepared = Self::do_read_seqno(&db, meta, META_PREPARED);
        let committed = Self::do_read_seqno(&db, meta, META_COMMITTED);

        debug!("Committing: {:?}, committed, {:?}, prepared: {:?}",
               committed,
               committed,
               prepared);
        assert!(prepared >= commit_seqno);

        if committed == commit_seqno {
            debug!("Skipping, commits up to date");
            return;
        }

        let t0 = PreciseTime::now();
        let mut opts = WriteOptions::new();
        opts.set_sync(true);
        db.put_cf_opt(meta, META_COMMITTED.as_bytes(), &key.as_ref(), &opts)
          .expect("Persist commit point");
        let t1 = PreciseTime::now();
        debug!("Committed {:?} in: {}", commit_seqno, t0.to(t1));
    }

    pub fn flush(&mut self) -> bool {
        let prepared = self.read_seqno(META_PREPARED);
        let committed = self.read_seqno(META_COMMITTED);
        if committed < prepared {
            info!("Flushing {} ({:?}->{:?})",
                  prepared - committed,
                  committed,
                  prepared);
            self.commit_to(prepared);
            true
        } else {
            false
        }
    }
}
<commit_msg>Note why my replication code is bad.<commit_after>use std::fmt;
use rocksdb::{DB, Writable, Options, WriteBatch, WriteOptions};
use rocksdb::ffi::DBCFHandle;
use tempdir::TempDir;
use byteorder::{ByteOrder, BigEndian};
use spki_sexp;
use super::Operation;
use time::{Duration, PreciseTime};
use std::thread;
use std::sync::mpsc;
use std::sync::Arc;

// Approximate structure of the log.
//
// The fun part is that each sequence number is Some(n) where n points to
// the *next* unwritten log slot. Unless it's unset, in which case we use
// None. This is ... suspect, and what happens when you just bang out code. It
// originally originated though, because at the time, the `Log#seqno` method
// was used solely to figure out the next slot that we should be writing to.

// However, we also use this very same logic to understand where we are in the
// replication stream. When we attempt to write say, two entries, we end up
// publishing the following messages:
//
// Prepare(0, "a")
// Prepare(1, "b")
// CommitTo(2)
//
// Which seems great, but we've just told the downstream replica to commit to
// an entry that hasn't been written yet. So've just told the downstream to
// commit an unwritten slot, triggers an `assert!` (the nearest I get to Hoare
// triples), and the whole castle comes tumbling down.

// Log Entries
//
//        R R R                        Replicas
//  ┌──┐  0 1 2
//  │  │        ◀─┐                    0   Head
//  │00│  X X O   │                    1 Middle
//  │ 1│  X X O   └───R2.Commit        2   Tail
//  │ 2│  X X O
//  │ 3│  X X O
//  │ 4│  X X   ◀─────R2.Prepare
//  │ 5│  X X
//  │ 6│  X X
//  │ 7│  X X
//  │ 8│  X O   ◀─────R1.Commit
//  │ 9│  X O
//  │10│  X O
//  │ 1│  X O
//  │ 2│  O O   ◀─────R0.Commit
//  │ 3│  O O
//  │ 4│  O O
//  │ 5│  O O
//  │ 6│  O     ◀─────R1.Prepare
//  │ 7│  O
//  │ 8│  O
//  │ 9│  O
//  └──┘        ◀─────R0.Prepare

pub struct Log {
    dir: TempDir,
    db: Arc<DB>,
    meta: DBCFHandle,
    data: DBCFHandle,
    flush_tx: mpsc::SyncSender<u64>,
}

const META: &'static str = "meta";
const DATA: &'static str = "data";
const META_PREPARED: &'static str = "prepared";
const META_COMMITTED: &'static str = "committed";

impl fmt::Debug for Log {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Log").field("dir", &self.dir.path()).finish()
    }
}

impl Log {
    pub fn new<F: Fn(u64) + Send + 'static>(committed: F) -> Log {
        let d = TempDir::new("rocksdb-log").expect("new log");
        info!("DB path: {:?}", d.path());
        let mut db = DB::open_default(&d.path().to_string_lossy()).expect("open db");
        let meta = db.create_cf(META, &Options::new()).expect("open meta cf");
        let data = db.create_cf(DATA, &Options::new()).expect("open data cf");
        let db = Arc::new(db);
        let (flush_tx, flush_rx) = mpsc::sync_channel(42);

        let flusher = {
            let db = db.clone();
            thread::Builder::new()
                .name("flusher".to_string())
                .spawn(move || Self::flush_thread_loop(db, flush_rx, committed))
                .expect("spawn flush thread")
        };
        Log {
            dir: d,
            db: db,
            meta: meta,
            data: data,
            flush_tx: flush_tx,
        }
    }

    fn flush_thread_loop<F: Fn(u64)>(db: Arc<DB>, rx: mpsc::Receiver<u64>, committed: F) {
        let meta = db.cf_handle(META).expect("open meta cf").clone();
        let data = db.cf_handle(DATA).expect("open data cf").clone();
        loop {
            debug!("Awaiting flush");
            let mut seqno = rx.recv().expect("recive flush seqno");
            loop {
                match rx.try_recv() {
                    Ok(n) => seqno = n,
                    Err(_) => break,
                }
            }
            debug!("Flushing: {:?}", seqno);
            Self::do_commit_to(db.clone(), meta, data, seqno);
            debug!("Flushed: {:?}", seqno);
            committed(seqno);
        }
    }

    fn tokey(seq: u64) -> [u8; 8] {
        let mut buf: [u8; 8] = [0, 0, 0, 0, 0, 0, 0, 0];
        BigEndian::write_u64(&mut buf, seq);
        buf
    }

    fn fromkey(key: &[u8]) -> u64 {
        BigEndian::read_u64(&key)
    }

    pub fn seqno(&self) -> u64 {
        let current = self.read_seqno(META_PREPARED);
        let next = current + 1;
        next
    }

    fn do_read_seqno(db: &DB, meta: DBCFHandle, name: &str) -> u64 {
        match db.get_cf(meta, name.as_bytes()) {
            Ok(Some(val)) => Self::fromkey(&val),
            Ok(None) => 0,
            Err(e) => panic!("Unexpected error getting commit point: {:?}", e),
        }
    }

    fn read_seqno(&self, name: &str) -> u64 {
        Self::do_read_seqno(&self.db, self.meta, name)
    }

    pub fn read(&self, seqno: u64) -> Option<Operation> {
        let key = Self::tokey(seqno);
        let ret = match self.db.get_cf(self.data, &key.as_ref()) {
            Ok(Some(val)) => Some(spki_sexp::from_bytes(&val).expect("decode operation")),
            Ok(None) => None,
            Err(e) => panic!("Unexpected error reading index: {:?}: {:?}", seqno, e),
        };
        debug!("Read: {:?} => {:?}", seqno, ret);
        ret
    }

    pub fn verify_sequential(&self, seqno: u64) -> bool {
        let current = self.seqno();
        if !(seqno == 0 || current <= seqno) {
            warn!("Hole in history: saw {}; have: {:?}", seqno, current);
            false
        } else {
            true
        }
    }

    pub fn prepare(&mut self, seqno: u64, op: &Operation) {
        let data_bytes = spki_sexp::as_bytes(op).expect("encode operation");
        debug!("Prepare {:?}", seqno);
        let key = Self::tokey(seqno);
        // match self.db.get_cf(self.data, &key.as_ref()) {
        // Ok(None) => (),
        // Err(e) => panic!("Unexpected error reading index: {:?}: {:?}", seqno, e),
        // Ok(_) => panic!("Unexpected entry at seqno: {:?}", seqno),
        // };

        let t0 = PreciseTime::now();
        let mut batch = WriteBatch::new();
        batch.put_cf(self.data, &key.as_ref(), &data_bytes).expect("Persist operation");
        batch.put_cf(self.meta, META_PREPARED.as_bytes(), &key.as_ref())
             .expect("Persist prepare point");
        self.db.write(batch).expect("Write batch");
        let t1 = PreciseTime::now();
        debug!("Prepare: {}", t0.to(t1));
        trace!("Watermarks: prepared: {:?}; committed: {:?}",
               self.read_seqno(META_PREPARED),
               self.read_seqno(META_COMMITTED));
    }

    pub fn commit_to(&mut self, seqno: u64) {
        debug!("Request commit upto: {:?}", seqno);
        self.flush_tx.send(seqno).expect("Send to flusher")
    }

    fn do_commit_to(db: Arc<DB>, meta: DBCFHandle, data: DBCFHandle, commit_seqno: u64) {
        debug!("Commit {:?}", commit_seqno);
        let key = Self::tokey(commit_seqno);

        let prepared = Self::do_read_seqno(&db, meta, META_PREPARED);
        let committed = Self::do_read_seqno(&db, meta, META_COMMITTED);

        debug!("Committing: {:?}, committed, {:?}, prepared: {:?}",
               committed,
               committed,
               prepared);
        assert!(prepared >= commit_seqno);

        if committed == commit_seqno {
            debug!("Skipping, commits up to date");
            return;
        }

        let t0 = PreciseTime::now();
        let mut opts = WriteOptions::new();
        opts.set_sync(true);
        db.put_cf_opt(meta, META_COMMITTED.as_bytes(), &key.as_ref(), &opts)
          .expect("Persist commit point");
        let t1 = PreciseTime::now();
        debug!("Committed {:?} in: {}", commit_seqno, t0.to(t1));
    }

    pub fn flush(&mut self) -> bool {
        let prepared = self.read_seqno(META_PREPARED);
        let committed = self.read_seqno(META_COMMITTED);
        if committed < prepared {
            info!("Flushing {} ({:?}->{:?})",
                  prepared - committed,
                  committed,
                  prepared);
            self.commit_to(prepared);
            true
        } else {
            false
        }
    }
}
<|endoftext|>


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

use std::cmp::Ordering;

use super::symbol_range::*;

///
/// A symbol map maps from one set of symbol ranges to another
///
pub struct SymbolMap<Symbol: PartialOrd+Clone> {
    // Ranges in this symbol map
    ranges: Vec<SymbolRange<Symbol>>,
}

impl<Symbol: PartialOrd+Clone> SymbolMap<Symbol> {
    ///
    /// Creates a new symbol map
    ///
    pub fn new() -> SymbolMap<Symbol> {
        SymbolMap { ranges: vec![] }
    }

    ///
    /// Orders two symbols (makes unordered symbols equal)
    ///
    #[inline]
    fn order_symbols(a: &Symbol, b: &Symbol) -> Ordering {
        if let Some(order) = a.partial_cmp(b) {
            order
        } else {
            Ordering::Equal
        }
    }

    ///
    /// Orders two symbol ranges
    ///
    #[inline]
    fn order_ranges(a: &SymbolRange<Symbol>, b: &SymbolRange<Symbol>) -> Ordering {
        let ordering = SymbolMap::order_symbols(&a.lowest, &b.lowest);

        if ordering == Ordering::Equal {
            SymbolMap::order_symbols(&a.highest, &b.highest)
        } else {
            ordering
        }
    }

    ///
    /// Adds a range to those that are known about by this object
    ///
    pub fn add_range(&mut self, range: &SymbolRange<Symbol>) {
        let existing = self.ranges.binary_search_by(|test_range| { SymbolMap::order_ranges(range, test_range) });

        // Insert the range if it is not already in the map
        if let Err(insertion_pos) = existing {
            self.ranges.insert(insertion_pos, range.clone());
        }
    }

    ///
    /// Finds the ranges in this map that overlap the target ranges
    ///
    pub fn find_overlapping_ranges(&self, range: &SymbolRange<Symbol>) -> Vec<&SymbolRange<Symbol>> {
        let mut result = vec![];

        // Find the first range that matches (or the insertion position, which should be the first range wit a lowest value higher than the target range)
        let existing = self.ranges.binary_search_by(|test_range| { SymbolMap::order_ranges(range, test_range) });

        // Start returning values from here
        let mut pos = match existing {
            Ok(found_position) => found_position,
            Err(insert_position) => insert_position
        };

        // TODO: can we construct a set of ranges such that one is missed here? Think maybe we can
        while pos < self.ranges.len() && self.ranges[pos].lowest <= range.highest {
            result.push(&self.ranges[pos]);
            pos += 1;
        }

        result
    }

    ///
    /// Creates a non-overlapping range from an overlapping one
    ///
    pub fn to_non_overlapping_map(&self) -> SymbolMap<Symbol> {
        // Create a vector of all the range symbols
        let mut range_symbols: Vec<Symbol> = self.ranges.iter()
            .map(|r| r.lowest.clone())
            .chain(self.ranges.iter().map(|r| r.highest.clone()))
            .collect();

        // Sort and dedupe (we'll get pairs of ranges)
        range_symbols.sort_by(SymbolMap::order_symbols);
        range_symbols.dedup();

        // Generate a new symbol map with these ranges
        // They'll overlap with the last value, which should be OK if following the rules for adjacent ranges in symbol_range.rs
        let mut result = vec![];
        for index in 0..range_symbols.len()-1 {
            result.push(SymbolRange::new(range_symbols[index].clone(), range_symbols[index+1].clone()));
        }

        // We already sorted everything, so bypass the usual 'add' method (which sorts as it goes)
        SymbolMap { ranges: result }
    }
}

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

    #[test]
    fn can_lookup_overlapping_ranges() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 4));
        map.add_range(&SymbolRange::new(2, 5));
        map.add_range(&SymbolRange::new(3, 6));

        let bottom = map.find_overlapping_ranges(&SymbolRange::new(0, 1));
        let all    = map.find_overlapping_ranges(&SymbolRange::new(1, 3));
        let top    = map.find_overlapping_ranges(&SymbolRange::new(6, 6));

        println!("All is: {:?}", all);

        assert!(bottom == vec![&SymbolRange::new(0, 4)]);
        assert!(all == vec![&SymbolRange::new(0, 4), &SymbolRange::new(2, 5), &SymbolRange::new(3, 6)]);
        assert!(top == vec![&SymbolRange::new(6, 6)]);
    }

    #[test]
    fn works_with_duplicate_lower_values() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 2));
        map.add_range(&SymbolRange::new(0, 3));

        let all    = map.find_overlapping_ranges(&SymbolRange::new(0, 1));

        println!("With duplicate lower values is: {:?}", all);

        assert!(all == vec![&SymbolRange::new(0, 2), &SymbolRange::new(0, 3)]);
    }

    #[test]
    fn obeys_adjacency_rule() {
        let mut map = SymbolMap::new();

        // By the adjacency rule for symbol ranges (in symbol_range.rs), '4' here is only in the upper range
        map.add_range(&SymbolRange::new(0, 4));
        map.add_range(&SymbolRange::new(4, 8));

        let top = map.find_overlapping_ranges(&SymbolRange::new(4, 4));

        assert!(top == vec![&SymbolRange::new(4, 8)]);
    }

    #[test]
    fn can_get_non_overlapping_map() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 4));
        map.add_range(&SymbolRange::new(2, 5));
        map.add_range(&SymbolRange::new(3, 6));

        let non_overlapping = map.to_non_overlapping_map();

        let all = non_overlapping.find_overlapping_ranges(&SymbolRange::new(0, 6));

        assert!(all == vec![&SymbolRange::new(0, 2), &SymbolRange::new(2, 3), &SymbolRange::new(3, 6)]);
    }
}
<commit_msg>Whoops, was ordering the ranges in reverse<commit_after>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

use std::cmp::Ordering;

use super::symbol_range::*;

///
/// A symbol map maps from one set of symbol ranges to another
///
pub struct SymbolMap<Symbol: PartialOrd+Clone> {
    // Ranges in this symbol map
    ranges: Vec<SymbolRange<Symbol>>,
}

impl<Symbol: PartialOrd+Clone> SymbolMap<Symbol> {
    ///
    /// Creates a new symbol map
    ///
    pub fn new() -> SymbolMap<Symbol> {
        SymbolMap { ranges: vec![] }
    }

    ///
    /// Orders two symbols (makes unordered symbols equal)
    ///
    #[inline]
    fn order_symbols(a: &Symbol, b: &Symbol) -> Ordering {
        if let Some(order) = a.partial_cmp(b) {
            order
        } else {
            Ordering::Equal
        }
    }

    ///
    /// Orders two symbol ranges
    ///
    #[inline]
    fn order_ranges(a: &SymbolRange<Symbol>, b: &SymbolRange<Symbol>) -> Ordering {
        let ordering = SymbolMap::order_symbols(&a.lowest, &b.lowest);

        if ordering == Ordering::Equal {
            SymbolMap::order_symbols(&a.highest, &b.highest)
        } else {
            ordering
        }
    }

    ///
    /// Adds a range to those that are known about by this object
    ///
    pub fn add_range(&mut self, range: &SymbolRange<Symbol>) {
        let existing = self.ranges.binary_search_by(|test_range| { SymbolMap::order_ranges(test_range, range) });

        // Insert the range if it is not already in the map
        if let Err(insertion_pos) = existing {
            self.ranges.insert(insertion_pos, range.clone());
        }
    }

    ///
    /// Finds the ranges in this map that overlap the target ranges
    ///
    pub fn find_overlapping_ranges(&self, range: &SymbolRange<Symbol>) -> Vec<&SymbolRange<Symbol>> {
        let mut result = vec![];

        // Find the first range that matches (or the insertion position, which should be the first range wit a lowest value higher than the target range)
        let existing = self.ranges.binary_search_by(|test_range| { SymbolMap::order_ranges(test_range, range) });

        // Start returning values from here
        let mut pos = match existing {
            Ok(found_position) => found_position,
            Err(insert_position) => insert_position
        };

        // TODO: can we construct a set of ranges such that one is missed here? Think maybe we can
        while pos < self.ranges.len() && self.ranges[pos].lowest <= range.highest {
            result.push(&self.ranges[pos]);
            pos += 1;
        }

        result
    }

    ///
    /// Creates a non-overlapping range from an overlapping one
    ///
    pub fn to_non_overlapping_map(&self) -> SymbolMap<Symbol> {
        // Create a vector of all the range symbols
        let mut range_symbols: Vec<Symbol> = self.ranges.iter()
            .map(|r| r.lowest.clone())
            .chain(self.ranges.iter().map(|r| r.highest.clone()))
            .collect();

        // Sort and dedupe (we'll get pairs of ranges)
        range_symbols.sort_by(SymbolMap::order_symbols);
        range_symbols.dedup();

        // Generate a new symbol map with these ranges
        // They'll overlap with the last value, which should be OK if following the rules for adjacent ranges in symbol_range.rs
        let mut result = vec![];
        for index in 0..range_symbols.len()-1 {
            result.push(SymbolRange::new(range_symbols[index].clone(), range_symbols[index+1].clone()));
        }

        // We already sorted everything, so bypass the usual 'add' method (which sorts as it goes)
        SymbolMap { ranges: result }
    }
}

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

    #[test]
    fn can_lookup_overlapping_ranges() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 4));
        map.add_range(&SymbolRange::new(2, 5));
        map.add_range(&SymbolRange::new(3, 6));

        let bottom = map.find_overlapping_ranges(&SymbolRange::new(0, 1));
        let all    = map.find_overlapping_ranges(&SymbolRange::new(1, 3));
        let top    = map.find_overlapping_ranges(&SymbolRange::new(6, 6));

        println!("All is: {:?}", all);

        assert!(bottom == vec![&SymbolRange::new(0, 4)]);
        assert!(all == vec![&SymbolRange::new(0, 4), &SymbolRange::new(2, 5), &SymbolRange::new(3, 6)]);
        assert!(top == vec![&SymbolRange::new(6, 6)]);
    }

    #[test]
    fn can_lookup_mid_range() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 4));
        map.add_range(&SymbolRange::new(5, 10));
        map.add_range(&SymbolRange::new(11, 15));

        let bottom = map.find_overlapping_ranges(&SymbolRange::new(1, 3));

        assert!(bottom == vec![&SymbolRange::new(0, 4)]);
    }

    #[test]
    fn works_with_duplicate_lower_values() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 2));
        map.add_range(&SymbolRange::new(0, 3));

        let all    = map.find_overlapping_ranges(&SymbolRange::new(0, 1));

        println!("With duplicate lower values is: {:?}", all);

        assert!(all == vec![&SymbolRange::new(0, 2), &SymbolRange::new(0, 3)]);
    }

    #[test]
    fn obeys_adjacency_rule() {
        let mut map = SymbolMap::new();

        // By the adjacency rule for symbol ranges (in symbol_range.rs), '4' here is only in the upper range
        map.add_range(&SymbolRange::new(0, 4));
        map.add_range(&SymbolRange::new(4, 8));

        let top = map.find_overlapping_ranges(&SymbolRange::new(4, 4));

        assert!(top == vec![&SymbolRange::new(4, 8)]);
    }

    #[test]
    fn can_get_non_overlapping_map() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 4));
        map.add_range(&SymbolRange::new(2, 5));
        map.add_range(&SymbolRange::new(3, 6));

        let non_overlapping = map.to_non_overlapping_map();

        let all = non_overlapping.find_overlapping_ranges(&SymbolRange::new(0, 6));

        assert!(all == vec![&SymbolRange::new(0, 2), &SymbolRange::new(2, 3), &SymbolRange::new(3, 6)]);
    }
}
<|endoftext|>


<commit_before>//! Interleaving and deinterleaving for data packet payloads.

use std;
use bits;

/// Interleaves a dibit buffer with an iterator interface.
pub type Interleaver = Redirect<InterleaveRedirector>;

/// Deinterleaves a dibit buffer with an iterator interface.
pub type Deinterleaver = Redirect<DeinterleaveRedirector>;

trait Redirector {
    /// Redirector the given index to another within the buffer.
    fn redirect(idx: usize) -> usize;
}

/// Redirects for interleaving.
struct InterleaveRedirector;

impl Redirector for InterleaveRedirector {
    fn redirect(idx: usize) -> usize {
        const REDIRECTS: [usize; 98] = [
            0,
            1,
            8,
            9,
            16,
            17,
            24,
            25,
            32,
            33,
            40,
            41,
            48,
            49,
            56,
            57,
            64,
            65,
            72,
            73,
            80,
            81,
            88,
            89,
            96,
            97,
            2,
            3,
            10,
            11,
            18,
            19,
            26,
            27,
            34,
            35,
            42,
            43,
            50,
            51,
            58,
            59,
            66,
            67,
            74,
            75,
            82,
            83,
            90,
            91,
            4,
            5,
            12,
            13,
            20,
            21,
            28,
            29,
            36,
            37,
            44,
            45,
            52,
            53,
            60,
            61,
            68,
            69,
            76,
            77,
            84,
            85,
            92,
            93,
            6,
            7,
            14,
            15,
            22,
            23,
            30,
            31,
            38,
            39,
            46,
            47,
            54,
            55,
            62,
            63,
            70,
            71,
            78,
            79,
            86,
            87,
            94,
            95,
        ];

        REDIRECTS[idx]
    }
}

/// Redirects to undo interleaving.
struct DeinterleaveRedirector;

impl Redirector for DeinterleaveRedirector {
    fn redirect(idx: usize) -> usize {
        const REDIRECTS: [usize; 98] = [
            0,
            1,
            26,
            27,
            50,
            51,
            74,
            75,
            2,
            3,
            28,
            29,
            52,
            53,
            76,
            77,
            4,
            5,
            30,
            31,
            54,
            55,
            78,
            79,
            6,
            7,
            32,
            33,
            56,
            57,
            80,
            81,
            8,
            9,
            34,
            35,
            58,
            59,
            82,
            83,
            10,
            11,
            36,
            37,
            60,
            61,
            84,
            85,
            12,
            13,
            38,
            39,
            62,
            63,
            86,
            87,
            14,
            15,
            40,
            41,
            64,
            65,
            88,
            89,
            16,
            17,
            42,
            43,
            66,
            67,
            90,
            91,
            18,
            19,
            44,
            45,
            68,
            69,
            92,
            93,
            20,
            21,
            46,
            47,
            70,
            71,
            94,
            95,
            22,
            23,
            48,
            49,
            72,
            73,
            96,
            97,
            24,
            25,
        ];

        REDIRECTS[idx]
    }
}

/// Wraps a buffer, redirecting sequential indexes with the given redirector.
struct Redirect<T: Redirector> {
    redirector: std::marker::PhantomData<T>,
    /// Wrapped buffer.
    dibits: [bits::Dibit; 98],
    /// Index into `dibits`.
    pos: std::ops::Range<usize>,
}

impl<T: Redirector> Redirect<T> {
    /// Construct a new `Redirect` over the given buffer.
    pub fn new(dibits: [bits::Dibit; 98]) -> Redirect<T> {
        Redirect {
            redirector: std::marker::PhantomData,
            dibits: dibits,
            pos: 0..98,
        }
    }
}

impl<T: Redirector> Iterator for Redirect<T> {
    type Item = bits::Dibit;

    fn next(&mut self) -> Option<Self::Item> {
        match self.pos.next() {
            Some(idx) => Some(self.dibits[T::redirect(idx)]),
            None => None
        }
    }
}

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

    #[test]
    fn test_interleave() {
        let mut buf = [Dibit::default(); 98];

        for i in 0..98 {
            buf[i] = Dibit::new(i as u8 % 4);
        }

        let mut int = Interleaver::new(buf);

        for _ in 0..13 {
            assert_eq!(int.next().unwrap().bits(), 0b00);
            assert_eq!(int.next().unwrap().bits(), 0b01);
        }

        for _ in 0..12 {
            assert_eq!(int.next().unwrap().bits(), 0b10);
            assert_eq!(int.next().unwrap().bits(), 0b11);
        }

        for _ in 0..12 {
            assert_eq!(int.next().unwrap().bits(), 0b00);
            assert_eq!(int.next().unwrap().bits(), 0b01);
        }

        for _ in 0..12 {
            assert_eq!(int.next().unwrap().bits(), 0b10);
            assert_eq!(int.next().unwrap().bits(), 0b11);
        }

        assert!(int.next().is_none());
    }

    #[test]
    fn test_deinterleave() {
        let mut buf = [Dibit::default(); 98];

        for i in 0..98 {
            buf[i] = Dibit::new(i as u8 % 4);
        }

        let mut out = [Dibit::default(); 98];

        for (i, dibit) in Interleaver::new(buf).enumerate() {
            out[i] = dibit;
        }

        let mut deint = Deinterleaver::new(out);

        for _ in 0..24 {
            assert_eq!(deint.next().unwrap().bits(), 0b00);
            assert_eq!(deint.next().unwrap().bits(), 0b01);
            assert_eq!(deint.next().unwrap().bits(), 0b10);
            assert_eq!(deint.next().unwrap().bits(), 0b11);
        }

        assert_eq!(deint.next().unwrap().bits(), 0b00);
        assert_eq!(deint.next().unwrap().bits(), 0b01);

        assert!(deint.next().is_none());
    }
}
<commit_msg>Rearrange interleave module so Deinterleaver can take array reference<commit_after>//! Interleaving and deinterleaving for data packet payloads.

use std;

use bits;
use data::consts;

trait Redirector {
    /// Redirector the given index to another within the buffer.
    fn redirect(idx: usize) -> usize;
}

/// Redirects for interleaving.
struct InterleaveRedirector;

impl Redirector for InterleaveRedirector {
    fn redirect(idx: usize) -> usize {
        const REDIRECTS: [usize; consts::CODING_DIBITS] = [
            0,
            1,
            8,
            9,
            16,
            17,
            24,
            25,
            32,
            33,
            40,
            41,
            48,
            49,
            56,
            57,
            64,
            65,
            72,
            73,
            80,
            81,
            88,
            89,
            96,
            97,
            2,
            3,
            10,
            11,
            18,
            19,
            26,
            27,
            34,
            35,
            42,
            43,
            50,
            51,
            58,
            59,
            66,
            67,
            74,
            75,
            82,
            83,
            90,
            91,
            4,
            5,
            12,
            13,
            20,
            21,
            28,
            29,
            36,
            37,
            44,
            45,
            52,
            53,
            60,
            61,
            68,
            69,
            76,
            77,
            84,
            85,
            92,
            93,
            6,
            7,
            14,
            15,
            22,
            23,
            30,
            31,
            38,
            39,
            46,
            47,
            54,
            55,
            62,
            63,
            70,
            71,
            78,
            79,
            86,
            87,
            94,
            95,
        ];

        REDIRECTS[idx]
    }
}

/// Redirects to undo interleaving.
struct DeinterleaveRedirector;

impl Redirector for DeinterleaveRedirector {
    fn redirect(idx: usize) -> usize {
        const REDIRECTS: [usize; consts::CODING_DIBITS] = [
            0,
            1,
            26,
            27,
            50,
            51,
            74,
            75,
            2,
            3,
            28,
            29,
            52,
            53,
            76,
            77,
            4,
            5,
            30,
            31,
            54,
            55,
            78,
            79,
            6,
            7,
            32,
            33,
            56,
            57,
            80,
            81,
            8,
            9,
            34,
            35,
            58,
            59,
            82,
            83,
            10,
            11,
            36,
            37,
            60,
            61,
            84,
            85,
            12,
            13,
            38,
            39,
            62,
            63,
            86,
            87,
            14,
            15,
            40,
            41,
            64,
            65,
            88,
            89,
            16,
            17,
            42,
            43,
            66,
            67,
            90,
            91,
            18,
            19,
            44,
            45,
            68,
            69,
            92,
            93,
            20,
            21,
            46,
            47,
            70,
            71,
            94,
            95,
            22,
            23,
            48,
            49,
            72,
            73,
            96,
            97,
            24,
            25,
        ];

        REDIRECTS[idx]
    }
}

struct Indexes<R: Redirector>(std::ops::Range<usize>, std::marker::PhantomData<R>);

impl<R: Redirector> Indexes<R> {
    pub fn new() -> Indexes<R> {
        Indexes(0..consts::CODING_DIBITS, std::marker::PhantomData)
    }
}

impl<R: Redirector> Iterator for Indexes<R> {
    type Item = usize;

    fn next(&mut self) -> Option<Self::Item> {
        match self.0.next() {
            Some(idx) => Some(R::redirect(idx)),
            None => None,
        }
    }
}

/// Takes ownership of a dibit buffer, yielding deinterleaved dibits.
pub struct Interleaver {
    /// Wrapped buffer.
    dibits: [bits::Dibit; consts::CODING_DIBITS],
    /// Redirected indexes.
    idx: Indexes<InterleaveRedirector>,
}

impl Interleaver {
    /// Construct a new `Interleaver` over the given buffer.
    pub fn new(dibits: [bits::Dibit; consts::CODING_DIBITS]) -> Interleaver {
        Interleaver {
            dibits: dibits,
            idx: Indexes::new(),
        }
    }
}

impl Iterator for Interleaver {
    type Item = bits::Dibit;

    fn next(&mut self) -> Option<Self::Item> {
        match self.idx.next() {
            Some(idx) => Some(self.dibits[idx]),
            None => None
        }
    }
}

pub struct Deinterleaver<'a> {
    dibits: &'a [bits::Dibit; consts::CODING_DIBITS],
    idx: Indexes<DeinterleaveRedirector>,
}

impl<'a> Deinterleaver<'a> {
    pub fn new(dibits: &'a [bits::Dibit; consts::CODING_DIBITS]) -> Deinterleaver<'a> {
        Deinterleaver {
            dibits: dibits,
            idx: Indexes::new(),
        }
    }
}

impl<'a> Iterator for Deinterleaver<'a> {
    type Item = bits::Dibit;

    fn next(&mut self) -> Option<Self::Item> {
        match self.idx.next() {
            Some(idx) => Some(self.dibits[idx]),
            None => None,
        }
    }
}

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

    #[test]
    fn test_interleave() {
        let mut buf = [Dibit::default(); 98];

        for i in 0..98 {
            buf[i] = Dibit::new(i as u8 % 4);
        }

        let mut int = Interleaver::new(buf);

        for _ in 0..13 {
            assert_eq!(int.next().unwrap().bits(), 0b00);
            assert_eq!(int.next().unwrap().bits(), 0b01);
        }

        for _ in 0..12 {
            assert_eq!(int.next().unwrap().bits(), 0b10);
            assert_eq!(int.next().unwrap().bits(), 0b11);
        }

        for _ in 0..12 {
            assert_eq!(int.next().unwrap().bits(), 0b00);
            assert_eq!(int.next().unwrap().bits(), 0b01);
        }

        for _ in 0..12 {
            assert_eq!(int.next().unwrap().bits(), 0b10);
            assert_eq!(int.next().unwrap().bits(), 0b11);
        }

        assert!(int.next().is_none());
    }

    #[test]
    fn test_deinterleave() {
        let mut buf = [Dibit::default(); 98];

        for i in 0..98 {
            buf[i] = Dibit::new(i as u8 % 4);
        }

        let mut out = [Dibit::default(); 98];

        for (i, dibit) in Interleaver::new(buf).enumerate() {
            out[i] = dibit;
        }

        let mut deint = Deinterleaver::new(&out);

        for _ in 0..24 {
            assert_eq!(deint.next().unwrap().bits(), 0b00);
            assert_eq!(deint.next().unwrap().bits(), 0b01);
            assert_eq!(deint.next().unwrap().bits(), 0b10);
            assert_eq!(deint.next().unwrap().bits(), 0b11);
        }

        assert_eq!(deint.next().unwrap().bits(), 0b00);
        assert_eq!(deint.next().unwrap().bits(), 0b01);

        assert!(deint.next().is_none());
    }
}
<|endoftext|>


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

#[macro_use]
extern crate log;

extern crate ash;
extern crate gfx_core as core;
#[macro_use]
extern crate lazy_static;

#[cfg(target_os = "windows")]
extern crate kernel32;

use ash::{Entry, LoadingError};
use ash::version::{EntryV1_0, DeviceV1_0, InstanceV1_0, V1_0};
use ash::vk;
use core::{command as com, handle, memory};
use core::{CommandBuffer, FrameSync, QueueType};
use std::{mem, ptr};
use std::ffi::{CStr, CString};
use std::sync::Arc;
use std::collections::VecDeque;

mod command;
pub mod data;
mod factory;
pub mod native;
mod pool;

const SURFACE_EXTENSIONS: &'static [&'static str] = &[
    vk::VK_KHR_SURFACE_EXTENSION_NAME,

    // Platform-specific WSI extensions
    vk::VK_KHR_XLIB_SURFACE_EXTENSION_NAME,
    vk::VK_KHR_XCB_SURFACE_EXTENSION_NAME,
    vk::VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME,
    vk::VK_KHR_MIR_SURFACE_EXTENSION_NAME,
    vk::VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
    vk::VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
];

lazy_static! {
    // Entry function pointers
    pub static ref VK_ENTRY: Result<Entry<V1_0>, LoadingError> = Entry::new();
}

pub struct Instance {
    pub raw: ash::Instance<ash::version::V1_0>,

    /// Supported surface extensions of this instance.
    pub surface_extensions: Vec<&'static str>,
}

fn map_queue_type(flags: vk::QueueFlags) -> QueueType {
    if flags.intersects(vk::QUEUE_GRAPHICS_BIT | vk::QUEUE_COMPUTE_BIT) { // TRANSER_BIT optional
        QueueType::General
    } else if flags.intersects(vk::QUEUE_GRAPHICS_BIT) { // TRANSER_BIT optional
        QueueType::Graphics
    } else if flags.intersects(vk::QUEUE_COMPUTE_BIT) { // TRANSER_BIT optional
        QueueType::Compute
    } else if flags.intersects(vk::QUEUE_TRANSFER_BIT) {
        QueueType::Transfer
    } else {
        // TODO: present only queues?
        unimplemented!()
    }
}

impl Instance {
    pub fn create() -> Instance {
        // TODO: return errors instead of panic
        let entry = VK_ENTRY.as_ref().expect("Unable to load vulkan entry points");

        let app_info = vk::ApplicationInfo {
            s_type: vk::StructureType::ApplicationInfo,
            p_next: ptr::null(),
            p_application_name: "vulkan_ll".as_ptr() as *const _, // TODO:
            application_version: 0,
            p_engine_name: "gfx-rs".as_ptr() as *const _,
            engine_version: 0, //TODO
            api_version: 0, //TODO
        };

        let instance_extensions = entry.enumerate_instance_extension_properties()
                                       .expect("Unable to enumerate instance extensions");

        // Check our surface extensions against the available extensions
        let surface_extensions = SURFACE_EXTENSIONS.iter().filter_map(|ext| {
            instance_extensions.iter().find(|inst_ext| {
                unsafe { CStr::from_ptr(inst_ext.extension_name.as_ptr()) == CStr::from_ptr(ext.as_ptr() as *const i8) }
            }).and_then(|_| Some(*ext))
        }).collect::<Vec<&str>>();

        let instance = {
            let cstrings = surface_extensions.iter()
                                    .map(|&s| CString::new(s).unwrap())
                                    .collect::<Vec<_>>();

            let str_pointers = cstrings.iter()
                                    .map(|s| s.as_ptr())
                                    .collect::<Vec<_>>();

            let create_info = vk::InstanceCreateInfo {
                s_type: vk::StructureType::InstanceCreateInfo,
                p_next: ptr::null(),
                flags: vk::InstanceCreateFlags::empty(),
                p_application_info: &app_info,
                enabled_layer_count: 0,
                pp_enabled_layer_names: ptr::null(),
                enabled_extension_count: str_pointers.len() as u32,
                pp_enabled_extension_names: str_pointers.as_ptr(),
            };

            entry.create_instance(&create_info, None).expect("Unable to create vulkan instance")
        };

        Instance {
            raw: instance,
            surface_extensions: surface_extensions,
        }
    }

    pub fn enumerate_adapters(instance: Arc<Instance>) -> Vec<Adapter> {
        instance.raw.enumerate_physical_devices()
            .expect("Unable to enumerate adapter")
            .iter()
            .map(|&device| {
                let properties = instance.raw.get_physical_device_properties(device);
                let name = unsafe {
                    CStr::from_ptr(properties.device_name.as_ptr())
                            .to_str()
                            .expect("Invalid UTF-8 string")
                            .to_owned()
                };

                let info = core::AdapterInfo {
                    name: name,
                    vendor: properties.vendor_id as usize,
                    device: properties.device_id as usize,
                    software_rendering: properties.device_type == vk::PhysicalDeviceType::Cpu,
                };

                let queue_families =
                    instance.raw.get_physical_device_queue_family_properties(device)
                        .iter()
                        .enumerate()
                        .map(|(i, queue_family)| {
                        (
                            QueueFamily {
                                device: device,
                                family_index: i as u32,
                                queue_type: queue_family.queue_flags,
                                queue_count: queue_family.queue_count,
                            },
                            map_queue_type(queue_family.queue_flags),
                        )
                        }).collect();

                Adapter {
                    instance: instance.clone(),
                    handle: device,
                    queue_families: queue_families,
                    info: info,
                }
            })
            .collect()
    }
}

pub struct QueueFamily {
    device: vk::PhysicalDevice,
    family_index: u32,
    queue_type: vk::QueueFlags,
    queue_count: u32,
}

impl QueueFamily {
    #[doc(hidden)]
    pub fn from_raw(device: vk::PhysicalDevice, index: u32, properties: &vk::QueueFamilyProperties) -> Self {
        QueueFamily {
            device: device,
            family_index: index,
            queue_type: properties.queue_flags,
            queue_count: properties.queue_count,
        }
    }

    #[doc(hidden)]
    pub fn device(&self) -> vk::PhysicalDevice {
        self.device
    }

    #[doc(hidden)]
    pub fn family_index(&self) -> u32 {
        self.family_index
    }

}

impl core::QueueFamily for QueueFamily {
    fn num_queues(&self) -> u32 {
        self.queue_count
    }
}

pub struct Adapter {
    instance: Arc<Instance>,
    handle: vk::PhysicalDevice,
    queue_families: Vec<(QueueFamily, QueueType)>,
    info: core::AdapterInfo,
}

impl core::Adapter<Backend> for Adapter {
    fn open(&self, queue_descs: &[(&QueueFamily, QueueType, u32)]) -> core::Device<Backend>
    {
        let mut queue_priorities = Vec::with_capacity(queue_descs.len());

        let queue_infos = queue_descs.iter().map(|&(family, _, queue_count)| {
                queue_priorities.push(vec![0.0f32; queue_count as usize]);

                vk::DeviceQueueCreateInfo {
                    s_type: vk::StructureType::DeviceQueueCreateInfo,
                    p_next: ptr::null(),
                    flags: vk::DeviceQueueCreateFlags::empty(),
                    queue_family_index: family.family_index,
                    queue_count: queue_count,
                    p_queue_priorities: queue_priorities.last().unwrap().as_ptr(),
                }
            }).collect::<Vec<_>>();

        // Create device
        let device_extensions = &[vk::VK_KHR_SWAPCHAIN_EXTENSION_NAME,];

        let device_raw = {
            let cstrings = device_extensions.iter()
                                    .map(|&s| CString::new(s).unwrap())
                                    .collect::<Vec<_>>();

            let str_pointers = cstrings.iter()
                                    .map(|s| s.as_ptr())
                                    .collect::<Vec<_>>();

            let features = unsafe { mem::zeroed() };
            let info = vk::DeviceCreateInfo {
                s_type: vk::StructureType::DeviceCreateInfo,
                p_next: ptr::null(),
                flags: vk::DeviceCreateFlags::empty(),
                queue_create_info_count: queue_infos.len() as u32,
                p_queue_create_infos: queue_infos.as_ptr(),
                enabled_layer_count: 0,
                pp_enabled_layer_names: ptr::null(),
                enabled_extension_count: str_pointers.len() as u32,
                pp_enabled_extension_names: str_pointers.as_ptr(),
                p_enabled_features: &features,
            };

            unsafe {
                self.instance.raw.create_device(self.handle, &info, None)
                    .expect("Error on device creation")
            }
        };

        let factory = Factory {
            device: Arc::new(RawDevice(device_raw)),
        };

        let mem_properties =  self.instance.raw.get_physical_device_memory_properties(self.handle);
        let memory_heaps = mem_properties.memory_heaps[..mem_properties.memory_heap_count as usize].iter()
                                .map(|mem| mem.size).collect::<Vec<_>>();
        let heap_types = mem_properties.memory_types[..mem_properties.memory_type_count as usize].iter().enumerate().map(|(i, mem)| {
            let mut type_flags = memory::HeapProperties::empty();

            if mem.property_flags.intersects(vk::MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
                type_flags |= memory::DEVICE_LOCAL;
            }
            if mem.property_flags.intersects(vk::MEMORY_PROPERTY_HOST_COHERENT_BIT) {
                type_flags |= memory::COHERENT;
            }
            if mem.property_flags.intersects(vk::MEMORY_PROPERTY_HOST_CACHED_BIT) {
                type_flags |= memory::CPU_CACHED;
            }
            if mem.property_flags.intersects(vk::MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
                type_flags |= memory::CPU_VISIBLE;
            }
            if mem.property_flags.intersects(vk::MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) {
                type_flags |= memory::LAZILY_ALLOCATED;
            }

            core::HeapType {
                id: i,
                properties: type_flags,
                heap_index: mem.heap_index as usize,
            }
        }).collect::<Vec<_>>();

        // Create associated command queues for each queue type
        let queues = queue_infos.iter().flat_map(|info| {
            (0..info.queue_count).map(|id| {
                let queue = unsafe {
                    factory.device.0.get_device_queue(info.queue_family_index, id)
                };
                unimplemented!()
                /*
                // TODO:
                unsafe {
                    core::GeneralQueue::new(CommandQueue {
                        inner: CommandQueueInner(Rc::new(RefCell::new(queue))),
                        device: factory.device.clone(),
                        family_index: info.queue_family_index,
                    })
                }
                */
            }).collect::<Vec<_>>()
        }).collect();

        core::Device {
            factory: factory,
            general_queues: queues,
            graphics_queues: Vec::new(),
            compute_queues: Vec::new(),
            transfer_queues: Vec::new(),
            heap_types: heap_types,
            memory_heaps: memory_heaps,

            _marker: std::marker::PhantomData,
        }
    }

    fn get_info(&self) -> &core::AdapterInfo {
        &self.info
    }

    fn get_queue_families(&self) -> &[(QueueFamily, QueueType)] {
        &self.queue_families
    }
}

#[doc(hidden)]
pub struct RawDevice(pub ash::Device<V1_0>);
impl Drop for RawDevice {
    fn drop(&mut self) {
        unsafe { self.0.destroy_device(None); }
    }
}

// Need to explicitly synchronize on submission and present.
pub type RawCommandQueue = Arc<vk::Queue>;

pub struct CommandQueue {
    raw: RawCommandQueue,
    device: Arc<RawDevice>,
    family_index: u32,

    frame_handles: handle::Manager<Resources>,
    max_resource_count: Option<usize>,
}

impl CommandQueue {
    #[doc(hidden)]
    pub fn raw(&self) -> RawCommandQueue {
        self.raw.clone()
    }

    #[doc(hidden)]
    pub fn device(&self) -> Arc<RawDevice> {
        self.device.clone()
    }

    #[doc(hidden)]
    pub fn device_handle(&self) -> vk::Device {
        self.device.0.handle()
    }
}

impl core::CommandQueue<Backend> for CommandQueue {
    unsafe fn submit(&mut self, submit_infos: &[core::QueueSubmit<Backend>],
        fence: Option<&handle::Fence<Resources>>, access: &com::AccessInfo<Resources>)
    {
        unimplemented!()
    }

    fn wait_idle(&mut self) {
        unsafe {
            self.device.0.queue_wait_idle(*self.raw);
        }
    }

    fn pin_submitted_resources(&mut self, man: &handle::Manager<Resources>) {
        self.frame_handles.extend(man);
        match self.max_resource_count {
            Some(c) if self.frame_handles.count() > c => {
                error!("Way too many resources in the current frame. Did you call Device::cleanup()?");
                self.max_resource_count = None;
            },
            _ => (),
        }
    }

    fn cleanup(&mut self) {
        use core::handle::Producer;

        self.frame_handles.clear();
        // TODO
    }
}

pub struct Factory {
    device: Arc<RawDevice>,
}

#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
pub enum Backend {}
impl core::Backend for Backend {
    type Adapter = Adapter;
    type Resources = Resources;
    type CommandQueue = CommandQueue;
    type RawCommandBuffer = command::CommandBuffer;
    type SubpassCommandBuffer = command::SubpassCommandBuffer;
    type SubmitInfo = command::SubmitInfo;
    type Factory = Factory;
    type QueueFamily = QueueFamily;

    type RawCommandPool = pool::RawCommandPool;
    type SubpassCommandPool = pool::SubpassCommandPool;
}

#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
pub enum Resources { }
impl core::Resources for Resources {
    type Buffer = ();
    type Shader = ();
    type Program = ();
    type PipelineStateObject = ();
    type Texture = ();
    type ShaderResourceView = ();
    type UnorderedAccessView = ();
    type RenderTargetView = ();
    type DepthStencilView = ();
    type Sampler = ();
    type Fence = native::Fence;
    type Semaphore = native::Semaphore;
    type Mapping = Mapping;
}

// TODO: temporary
#[derive(Debug, Eq, Hash, PartialEq)]
pub struct Mapping;

impl core::mapping::Gate<Resources> for Mapping {
    unsafe fn set<T>(&self, index: usize, val: T) {
        unimplemented!()
    }

    unsafe fn slice<'a, 'b, T>(&'a self, len: usize) -> &'b [T] {
        unimplemented!()
    }

    unsafe fn mut_slice<'a, 'b, T>(&'a self, len: usize) -> &'b mut [T] {
        unimplemented!()
    }
}

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

#[macro_use]
extern crate log;

extern crate ash;
extern crate gfx_core as core;
#[macro_use]
extern crate lazy_static;

#[cfg(target_os = "windows")]
extern crate kernel32;

use ash::{Entry, LoadingError};
use ash::version::{EntryV1_0, DeviceV1_0, InstanceV1_0, V1_0};
use ash::vk;
use core::{command as com, handle, memory};
use core::{CommandBuffer, FrameSync, QueueType};
use std::{mem, ptr};
use std::ffi::{CStr, CString};
use std::sync::Arc;
use std::collections::VecDeque;

mod command;
pub mod data;
mod factory;
pub mod native;
mod pool;

const SURFACE_EXTENSIONS: &'static [&'static str] = &[
    vk::VK_KHR_SURFACE_EXTENSION_NAME,

    // Platform-specific WSI extensions
    vk::VK_KHR_XLIB_SURFACE_EXTENSION_NAME,
    vk::VK_KHR_XCB_SURFACE_EXTENSION_NAME,
    vk::VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME,
    vk::VK_KHR_MIR_SURFACE_EXTENSION_NAME,
    vk::VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
    vk::VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
];

lazy_static! {
    // Entry function pointers
    pub static ref VK_ENTRY: Result<Entry<V1_0>, LoadingError> = Entry::new();
}

pub struct Instance {
    pub raw: ash::Instance<ash::version::V1_0>,

    /// Supported surface extensions of this instance.
    pub surface_extensions: Vec<&'static str>,
}

fn map_queue_type(flags: vk::QueueFlags) -> QueueType {
    if flags.subset(vk::QUEUE_GRAPHICS_BIT | vk::QUEUE_COMPUTE_BIT) { // TRANSER_BIT optional
        QueueType::General
    } else if flags.subset(vk::QUEUE_GRAPHICS_BIT) { // TRANSER_BIT optional
        QueueType::Graphics
    } else if flags.subset(vk::QUEUE_COMPUTE_BIT) { // TRANSER_BIT optional
        QueueType::Compute
    } else if flags.subset(vk::QUEUE_TRANSFER_BIT) {
        QueueType::Transfer
    } else {
        // TODO: present only queues?
        unimplemented!()
    }
}

impl Instance {
    pub fn create() -> Instance {
        // TODO: return errors instead of panic
        let entry = VK_ENTRY.as_ref().expect("Unable to load vulkan entry points");

        let app_info = vk::ApplicationInfo {
            s_type: vk::StructureType::ApplicationInfo,
            p_next: ptr::null(),
            p_application_name: "vulkan_ll".as_ptr() as *const _, // TODO:
            application_version: 0,
            p_engine_name: "gfx-rs".as_ptr() as *const _,
            engine_version: 0, //TODO
            api_version: 0, //TODO
        };

        let instance_extensions = entry.enumerate_instance_extension_properties()
                                       .expect("Unable to enumerate instance extensions");

        // Check our surface extensions against the available extensions
        let surface_extensions = SURFACE_EXTENSIONS.iter().filter_map(|ext| {
            instance_extensions.iter().find(|inst_ext| {
                unsafe { CStr::from_ptr(inst_ext.extension_name.as_ptr()) == CStr::from_ptr(ext.as_ptr() as *const i8) }
            }).and_then(|_| Some(*ext))
        }).collect::<Vec<&str>>();

        let instance = {
            let cstrings = surface_extensions.iter()
                                    .map(|&s| CString::new(s).unwrap())
                                    .collect::<Vec<_>>();

            let str_pointers = cstrings.iter()
                                    .map(|s| s.as_ptr())
                                    .collect::<Vec<_>>();

            let create_info = vk::InstanceCreateInfo {
                s_type: vk::StructureType::InstanceCreateInfo,
                p_next: ptr::null(),
                flags: vk::InstanceCreateFlags::empty(),
                p_application_info: &app_info,
                enabled_layer_count: 0,
                pp_enabled_layer_names: ptr::null(),
                enabled_extension_count: str_pointers.len() as u32,
                pp_enabled_extension_names: str_pointers.as_ptr(),
            };

            entry.create_instance(&create_info, None).expect("Unable to create vulkan instance")
        };

        Instance {
            raw: instance,
            surface_extensions: surface_extensions,
        }
    }

    pub fn enumerate_adapters(instance: Arc<Instance>) -> Vec<Adapter> {
        instance.raw.enumerate_physical_devices()
            .expect("Unable to enumerate adapter")
            .iter()
            .map(|&device| {
                let properties = instance.raw.get_physical_device_properties(device);
                let name = unsafe {
                    CStr::from_ptr(properties.device_name.as_ptr())
                            .to_str()
                            .expect("Invalid UTF-8 string")
                            .to_owned()
                };

                let info = core::AdapterInfo {
                    name: name,
                    vendor: properties.vendor_id as usize,
                    device: properties.device_id as usize,
                    software_rendering: properties.device_type == vk::PhysicalDeviceType::Cpu,
                };

                let queue_families =
                    instance.raw.get_physical_device_queue_family_properties(device)
                        .iter()
                        .enumerate()
                        .map(|(i, queue_family)| {
                        (
                            QueueFamily {
                                device: device,
                                family_index: i as u32,
                                queue_type: queue_family.queue_flags,
                                queue_count: queue_family.queue_count,
                            },
                            map_queue_type(queue_family.queue_flags),
                        )
                        }).collect();

                Adapter {
                    instance: instance.clone(),
                    handle: device,
                    queue_families: queue_families,
                    info: info,
                }
            })
            .collect()
    }
}

pub struct QueueFamily {
    device: vk::PhysicalDevice,
    family_index: u32,
    queue_type: vk::QueueFlags,
    queue_count: u32,
}

impl QueueFamily {
    #[doc(hidden)]
    pub fn from_raw(device: vk::PhysicalDevice, index: u32, properties: &vk::QueueFamilyProperties) -> Self {
        QueueFamily {
            device: device,
            family_index: index,
            queue_type: properties.queue_flags,
            queue_count: properties.queue_count,
        }
    }

    #[doc(hidden)]
    pub fn device(&self) -> vk::PhysicalDevice {
        self.device
    }

    #[doc(hidden)]
    pub fn family_index(&self) -> u32 {
        self.family_index
    }

}

impl core::QueueFamily for QueueFamily {
    fn num_queues(&self) -> u32 {
        self.queue_count
    }
}

pub struct Adapter {
    instance: Arc<Instance>,
    handle: vk::PhysicalDevice,
    queue_families: Vec<(QueueFamily, QueueType)>,
    info: core::AdapterInfo,
}

impl core::Adapter<Backend> for Adapter {
    fn open(&self, queue_descs: &[(&QueueFamily, QueueType, u32)]) -> core::Device<Backend>
    {
        let mut queue_priorities = Vec::with_capacity(queue_descs.len());

        let queue_infos = queue_descs.iter().map(|&(family, _, queue_count)| {
                queue_priorities.push(vec![0.0f32; queue_count as usize]);

                vk::DeviceQueueCreateInfo {
                    s_type: vk::StructureType::DeviceQueueCreateInfo,
                    p_next: ptr::null(),
                    flags: vk::DeviceQueueCreateFlags::empty(),
                    queue_family_index: family.family_index,
                    queue_count: queue_count,
                    p_queue_priorities: queue_priorities.last().unwrap().as_ptr(),
                }
            }).collect::<Vec<_>>();

        // Create device
        let device_extensions = &[vk::VK_KHR_SWAPCHAIN_EXTENSION_NAME,];

        let device_raw = {
            let cstrings = device_extensions.iter()
                                    .map(|&s| CString::new(s).unwrap())
                                    .collect::<Vec<_>>();

            let str_pointers = cstrings.iter()
                                    .map(|s| s.as_ptr())
                                    .collect::<Vec<_>>();

            let features = unsafe { mem::zeroed() };
            let info = vk::DeviceCreateInfo {
                s_type: vk::StructureType::DeviceCreateInfo,
                p_next: ptr::null(),
                flags: vk::DeviceCreateFlags::empty(),
                queue_create_info_count: queue_infos.len() as u32,
                p_queue_create_infos: queue_infos.as_ptr(),
                enabled_layer_count: 0,
                pp_enabled_layer_names: ptr::null(),
                enabled_extension_count: str_pointers.len() as u32,
                pp_enabled_extension_names: str_pointers.as_ptr(),
                p_enabled_features: &features,
            };

            unsafe {
                self.instance.raw.create_device(self.handle, &info, None)
                    .expect("Error on device creation")
            }
        };

        let factory = Factory {
            device: Arc::new(RawDevice(device_raw)),
        };

        let mem_properties =  self.instance.raw.get_physical_device_memory_properties(self.handle);
        let memory_heaps = mem_properties.memory_heaps[..mem_properties.memory_heap_count as usize].iter()
                                .map(|mem| mem.size).collect::<Vec<_>>();
        let heap_types = mem_properties.memory_types[..mem_properties.memory_type_count as usize].iter().enumerate().map(|(i, mem)| {
            let mut type_flags = memory::HeapProperties::empty();

            if mem.property_flags.intersects(vk::MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
                type_flags |= memory::DEVICE_LOCAL;
            }
            if mem.property_flags.intersects(vk::MEMORY_PROPERTY_HOST_COHERENT_BIT) {
                type_flags |= memory::COHERENT;
            }
            if mem.property_flags.intersects(vk::MEMORY_PROPERTY_HOST_CACHED_BIT) {
                type_flags |= memory::CPU_CACHED;
            }
            if mem.property_flags.intersects(vk::MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
                type_flags |= memory::CPU_VISIBLE;
            }
            if mem.property_flags.intersects(vk::MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) {
                type_flags |= memory::LAZILY_ALLOCATED;
            }

            core::HeapType {
                id: i,
                properties: type_flags,
                heap_index: mem.heap_index as usize,
            }
        }).collect::<Vec<_>>();

        // Create associated command queues for each queue type
        let queues = queue_infos.iter().flat_map(|info| {
            (0..info.queue_count).map(|id| {
                let queue = unsafe {
                    factory.device.0.get_device_queue(info.queue_family_index, id)
                };
                unimplemented!()
                /*
                // TODO:
                unsafe {
                    core::GeneralQueue::new(CommandQueue {
                        inner: CommandQueueInner(Rc::new(RefCell::new(queue))),
                        device: factory.device.clone(),
                        family_index: info.queue_family_index,
                    })
                }
                */
            }).collect::<Vec<_>>()
        }).collect();

        core::Device {
            factory: factory,
            general_queues: queues,
            graphics_queues: Vec::new(),
            compute_queues: Vec::new(),
            transfer_queues: Vec::new(),
            heap_types: heap_types,
            memory_heaps: memory_heaps,

            _marker: std::marker::PhantomData,
        }
    }

    fn get_info(&self) -> &core::AdapterInfo {
        &self.info
    }

    fn get_queue_families(&self) -> &[(QueueFamily, QueueType)] {
        &self.queue_families
    }
}

#[doc(hidden)]
pub struct RawDevice(pub ash::Device<V1_0>);
impl Drop for RawDevice {
    fn drop(&mut self) {
        unsafe { self.0.destroy_device(None); }
    }
}

// Need to explicitly synchronize on submission and present.
pub type RawCommandQueue = Arc<vk::Queue>;

pub struct CommandQueue {
    raw: RawCommandQueue,
    device: Arc<RawDevice>,
    family_index: u32,

    frame_handles: handle::Manager<Resources>,
    max_resource_count: Option<usize>,
}

impl CommandQueue {
    #[doc(hidden)]
    pub fn raw(&self) -> RawCommandQueue {
        self.raw.clone()
    }

    #[doc(hidden)]
    pub fn device(&self) -> Arc<RawDevice> {
        self.device.clone()
    }

    #[doc(hidden)]
    pub fn device_handle(&self) -> vk::Device {
        self.device.0.handle()
    }
}

impl core::CommandQueue<Backend> for CommandQueue {
    unsafe fn submit(&mut self, submit_infos: &[core::QueueSubmit<Backend>],
        fence: Option<&handle::Fence<Resources>>, access: &com::AccessInfo<Resources>)
    {
        unimplemented!()
    }

    fn wait_idle(&mut self) {
        unsafe {
            self.device.0.queue_wait_idle(*self.raw);
        }
    }

    fn pin_submitted_resources(&mut self, man: &handle::Manager<Resources>) {
        self.frame_handles.extend(man);
        match self.max_resource_count {
            Some(c) if self.frame_handles.count() > c => {
                error!("Way too many resources in the current frame. Did you call Device::cleanup()?");
                self.max_resource_count = None;
            },
            _ => (),
        }
    }

    fn cleanup(&mut self) {
        use core::handle::Producer;

        self.frame_handles.clear();
        // TODO
    }
}

pub struct Factory {
    device: Arc<RawDevice>,
}

#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
pub enum Backend {}
impl core::Backend for Backend {
    type Adapter = Adapter;
    type Resources = Resources;
    type CommandQueue = CommandQueue;
    type RawCommandBuffer = command::CommandBuffer;
    type SubpassCommandBuffer = command::SubpassCommandBuffer;
    type SubmitInfo = command::SubmitInfo;
    type Factory = Factory;
    type QueueFamily = QueueFamily;

    type RawCommandPool = pool::RawCommandPool;
    type SubpassCommandPool = pool::SubpassCommandPool;
}

#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
pub enum Resources { }
impl core::Resources for Resources {
    type Buffer = ();
    type Shader = ();
    type Program = ();
    type PipelineStateObject = ();
    type Texture = ();
    type ShaderResourceView = ();
    type UnorderedAccessView = ();
    type RenderTargetView = ();
    type DepthStencilView = ();
    type Sampler = ();
    type Fence = native::Fence;
    type Semaphore = native::Semaphore;
    type Mapping = Mapping;
}

// TODO: temporary
#[derive(Debug, Eq, Hash, PartialEq)]
pub struct Mapping;

impl core::mapping::Gate<Resources> for Mapping {
    unsafe fn set<T>(&self, index: usize, val: T) {
        unimplemented!()
    }

    unsafe fn slice<'a, 'b, T>(&'a self, len: usize) -> &'b [T] {
        unimplemented!()
    }

    unsafe fn mut_slice<'a, 'b, T>(&'a self, len: usize) -> &'b mut [T] {
        unimplemented!()
    }
}

<|endoftext|>


<commit_before>// Implements http://rosettacode.org/wiki/Prime_decomposition
fn factor(mut nb: i32)->~[i32]{
	let mut result = ~[];

	// First we take out all even factors.
	while nb%2==0 {
		result.push(2);
		nb /= 2;
	}

	// Then (if any left) we take out the odd ones.
	let mut cand = 3;
	let mut max_bound = (nb as f32).sqrt() as i32 + 1;

	while cand <= max_bound {
		while nb%cand == 0 {
			result.push(cand);
			nb /= cand;
		}
		max_bound = (nb as f32).sqrt() as i32 + 1;
		cand += 2;
	}

	if nb > 1 {
		result.push(nb);
	}

	result
}

fn main() {
	println!("{:?}", factor(5)==~[5]);
	println!("{:?}", factor(15)==~[3,5]);
	println!("{:?}", factor(16)==~[2,2,2,2]);
	println!("{:?}", factor(10287)==~[3,3,3,3,127]);
}
<commit_msg>Fixed prime decomposition<commit_after>// Implements http://rosettacode.org/wiki/Prime_decomposition

fn factor(mut nb: i32) -> Vec<i32> {
	let mut result = vec!();

	// First we take out all even factors.
	while nb % 2 == 0 {
		result.push(2);
		nb /= 2;
	}

	// Then (if any left) we take out the odd ones.
	let mut cand = 3;
	let mut max_bound = (nb as f32).sqrt() as i32 + 1;

	while cand <= max_bound {
		while nb % cand == 0 {
			result.push(cand);
			nb /= cand;
		}
		max_bound = (nb as f32).sqrt() as i32 + 1;
		cand += 2;
	}

	if nb > 1 {
		result.push(nb);
	}

	result
}

fn main() {
	println!("{:?}", factor(5) == vec!(5));
	println!("{:?}", factor(15) == vec!(3, 5));
	println!("{:?}", factor(16) == vec!(2, 2, 2, 2));
	println!("{:?}", factor(10287) == vec!(3, 3, 3, 3, 127));
}
<|endoftext|>


<commit_before>use crate::command_prelude::*;

use cargo::ops::{self, CompileFilter, FilterRule, LibRule};

pub fn cli() -> App {
    subcommand("fix")
        .about("Automatically fix lint warnings reported by rustc")
        .arg(opt("quiet", "No output printed to stdout").short("q"))
        .arg_package_spec(
            "Package(s) to fix",
            "Fix all packages in the workspace",
            "Exclude packages from the fixes",
        )
        .arg_jobs()
        .arg_targets_all(
            "Fix only this package's library",
            "Fix only the specified binary",
            "Fix all binaries",
            "Fix only the specified example",
            "Fix all examples",
            "Fix only the specified test target",
            "Fix all tests",
            "Fix only the specified bench target",
            "Fix all benches",
            "Fix all targets (default)",
        )
        .arg_release("Fix artifacts in release mode, with optimizations")
        .arg(opt("profile", "Profile to build the selected target for").value_name("PROFILE"))
        .arg_features()
        .arg_target_triple("Fix for the target triple")
        .arg_target_dir()
        .arg_manifest_path()
        .arg_message_format()
        .arg(
            Arg::with_name("broken-code")
                .long("broken-code")
                .help("Fix code even if it already has compiler errors"),
        )
        .arg(
            Arg::with_name("edition")
                .long("edition")
                .help("Fix in preparation for the next edition"),
        )
        .arg(
            // This is a deprecated argument, we'll want to phase it out
            // eventually.
            Arg::with_name("prepare-for")
                .long("prepare-for")
                .help("Fix warnings in preparation of an edition upgrade")
                .takes_value(true)
                .possible_values(&["2018"])
                .conflicts_with("edition")
                .hidden(true),
        )
        .arg(
            Arg::with_name("idioms")
                .long("edition-idioms")
                .help("Fix warnings to migrate to the idioms of an edition"),
        )
        .arg(
            Arg::with_name("allow-no-vcs")
                .long("allow-no-vcs")
                .help("Fix code even if a VCS was not detected"),
        )
        .arg(
            Arg::with_name("allow-dirty")
                .long("allow-dirty")
                .help("Fix code even if the working directory is dirty"),
        )
        .arg(
            Arg::with_name("allow-staged")
                .long("allow-staged")
                .help("Fix code even if the working directory has staged changes"),
        )
        .arg(
            Arg::with_name("clippy")
                .long("clippy")
                .help("Get fix suggestions from clippy instead of rustc")
                .hidden(true),
        )
        .after_help(
            "\
This Cargo subcommand will automatically take rustc's suggestions from
diagnostics like warnings and apply them to your source code. This is intended
to help automate tasks that rustc itself already knows how to tell you to fix!
The `cargo fix` subcommand is also being developed for the Rust 2018 edition
to provide code the ability to easily opt-in to the new edition without having
to worry about any breakage.

Executing `cargo fix` will under the hood execute `cargo check`. Any warnings
applicable to your crate will be automatically fixed (if possible) and all
remaining warnings will be displayed when the check process is finished. For
example if you'd like to prepare for the 2018 edition, you can do so by
executing:

    cargo fix --edition

which behaves the same as `cargo check --all-targets`. Similarly if you'd like
to fix code for different platforms you can do:

    cargo fix --edition --target x86_64-pc-windows-gnu

or if your crate has optional features:

    cargo fix --edition --no-default-features --features foo

If you encounter any problems with `cargo fix` or otherwise have any questions
or feature requests please don't hesitate to file an issue at
https://github.com/rust-lang/cargo
",
        )
}

pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
    let ws = args.workspace(config)?;
    let test = match args.value_of("profile") {
        Some("test") => true,
        None => false,
        Some(profile) => {
            let err = failure::format_err!(
                "unknown profile: `{}`, only `test` is \
                 currently supported",
                profile
            );
            return Err(CliError::new(err, 101));
        }
    };
    let mode = CompileMode::Check { test };

    // Unlike other commands default `cargo fix` to all targets to fix as much
    // code as we can.
    let mut opts = args.compile_options(config, mode, Some(&ws))?;

    let clippy_args = args
        .value_of("clippy") // always yields None
        .map(|s| s.split(' ').map(|s| s.to_string()).collect())
        .or_else(|| Some(vec![]));

    let use_clippy = args.is_present("clippy") || clippy_args.is_some();

    if use_clippy && !config.cli_unstable().unstable_options {
        return Err(failure::format_err!(
            "`cargo fix --clippy` is unstable, pass `-Z unstable-options` to enable it"
        )
        .into());
    }

    if let CompileFilter::Default { .. } = opts.filter {
        opts.filter = CompileFilter::Only {
            all_targets: true,
            lib: LibRule::Default,
            bins: FilterRule::All,
            examples: FilterRule::All,
            benches: FilterRule::All,
            tests: FilterRule::All,
        }
    }

    ops::fix(
        &ws,
        &mut ops::FixOptions {
            edition: args.is_present("edition"),
            prepare_for: args.value_of("prepare-for"),
            idioms: args.is_present("idioms"),
            compile_opts: opts,
            allow_dirty: args.is_present("allow-dirty"),
            allow_no_vcs: args.is_present("allow-no-vcs"),
            allow_staged: args.is_present("allow-staged"),
            broken_code: args.is_present("broken-code"),
            clippy_args,
        },
    )?;
    Ok(())
}
<commit_msg>it was still a little broken<commit_after>use crate::command_prelude::*;

use cargo::ops::{self, CompileFilter, FilterRule, LibRule};

pub fn cli() -> App {
    subcommand("fix")
        .about("Automatically fix lint warnings reported by rustc")
        .arg(opt("quiet", "No output printed to stdout").short("q"))
        .arg_package_spec(
            "Package(s) to fix",
            "Fix all packages in the workspace",
            "Exclude packages from the fixes",
        )
        .arg_jobs()
        .arg_targets_all(
            "Fix only this package's library",
            "Fix only the specified binary",
            "Fix all binaries",
            "Fix only the specified example",
            "Fix all examples",
            "Fix only the specified test target",
            "Fix all tests",
            "Fix only the specified bench target",
            "Fix all benches",
            "Fix all targets (default)",
        )
        .arg_release("Fix artifacts in release mode, with optimizations")
        .arg(opt("profile", "Profile to build the selected target for").value_name("PROFILE"))
        .arg_features()
        .arg_target_triple("Fix for the target triple")
        .arg_target_dir()
        .arg_manifest_path()
        .arg_message_format()
        .arg(
            Arg::with_name("broken-code")
                .long("broken-code")
                .help("Fix code even if it already has compiler errors"),
        )
        .arg(
            Arg::with_name("edition")
                .long("edition")
                .help("Fix in preparation for the next edition"),
        )
        .arg(
            // This is a deprecated argument, we'll want to phase it out
            // eventually.
            Arg::with_name("prepare-for")
                .long("prepare-for")
                .help("Fix warnings in preparation of an edition upgrade")
                .takes_value(true)
                .possible_values(&["2018"])
                .conflicts_with("edition")
                .hidden(true),
        )
        .arg(
            Arg::with_name("idioms")
                .long("edition-idioms")
                .help("Fix warnings to migrate to the idioms of an edition"),
        )
        .arg(
            Arg::with_name("allow-no-vcs")
                .long("allow-no-vcs")
                .help("Fix code even if a VCS was not detected"),
        )
        .arg(
            Arg::with_name("allow-dirty")
                .long("allow-dirty")
                .help("Fix code even if the working directory is dirty"),
        )
        .arg(
            Arg::with_name("allow-staged")
                .long("allow-staged")
                .help("Fix code even if the working directory has staged changes"),
        )
        .arg(
            Arg::with_name("clippy")
                .long("clippy")
                .help("Get fix suggestions from clippy instead of rustc")
                .hidden(true),
        )
        .after_help(
            "\
This Cargo subcommand will automatically take rustc's suggestions from
diagnostics like warnings and apply them to your source code. This is intended
to help automate tasks that rustc itself already knows how to tell you to fix!
The `cargo fix` subcommand is also being developed for the Rust 2018 edition
to provide code the ability to easily opt-in to the new edition without having
to worry about any breakage.

Executing `cargo fix` will under the hood execute `cargo check`. Any warnings
applicable to your crate will be automatically fixed (if possible) and all
remaining warnings will be displayed when the check process is finished. For
example if you'd like to prepare for the 2018 edition, you can do so by
executing:

    cargo fix --edition

which behaves the same as `cargo check --all-targets`. Similarly if you'd like
to fix code for different platforms you can do:

    cargo fix --edition --target x86_64-pc-windows-gnu

or if your crate has optional features:

    cargo fix --edition --no-default-features --features foo

If you encounter any problems with `cargo fix` or otherwise have any questions
or feature requests please don't hesitate to file an issue at
https://github.com/rust-lang/cargo
",
        )
}

pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
    let ws = args.workspace(config)?;
    let test = match args.value_of("profile") {
        Some("test") => true,
        None => false,
        Some(profile) => {
            let err = failure::format_err!(
                "unknown profile: `{}`, only `test` is \
                 currently supported",
                profile
            );
            return Err(CliError::new(err, 101));
        }
    };
    let mode = CompileMode::Check { test };

    // Unlike other commands default `cargo fix` to all targets to fix as much
    // code as we can.
    let mut opts = args.compile_options(config, mode, Some(&ws))?;

    let use_clippy = args.is_present("clippy");

    let clippy_args = args
        .value_of("clippy") // always yields None
        .map(|s| s.split(' ').map(|s| s.to_string()).collect())
        .or_else(|| Some(vec![]))
        .filter(|_| use_clippy);

    if use_clippy && !config.cli_unstable().unstable_options {
        return Err(failure::format_err!(
            "`cargo fix --clippy` is unstable, pass `-Z unstable-options` to enable it"
        )
        .into());
    }

    if let CompileFilter::Default { .. } = opts.filter {
        opts.filter = CompileFilter::Only {
            all_targets: true,
            lib: LibRule::Default,
            bins: FilterRule::All,
            examples: FilterRule::All,
            benches: FilterRule::All,
            tests: FilterRule::All,
        }
    }

    ops::fix(
        &ws,
        &mut ops::FixOptions {
            edition: args.is_present("edition"),
            prepare_for: args.value_of("prepare-for"),
            idioms: args.is_present("idioms"),
            compile_opts: opts,
            allow_dirty: args.is_present("allow-dirty"),
            allow_no_vcs: args.is_present("allow-no-vcs"),
            allow_staged: args.is_present("allow-staged"),
            broken_code: args.is_present("broken-code"),
            clippy_args,
        },
    )?;
    Ok(())
}
<|endoftext|>