<commit_before>extern crate rsoundio;
extern crate rb;

use rb::{RB, SpscRb, RbProducer, RbConsumer};
use std::f32::consts::PI as PI32;
use std::thread;
use std::time::Duration;

fn main() {
    let rb = SpscRb::new(4096);
    let (producer, consumer) = (rb.producer(), rb.consumer());
    // create an audio context
    let mut sio = rsoundio::SoundIo::new();
    sio.set_name("rsoundio-example").unwrap();
    // connect to the default audio backend
    sio.connect().unwrap();
    println!("Connected to backend: {}", sio.current_backend().unwrap());
    sio.flush_events();
    // get default output device
    let dev = sio.default_output_device().unwrap();
    assert!(dev.probe_error().is_none());
    println!("Using output device: {}", dev);
    // create output stream
    let mut out = dev.create_outstream().unwrap();
    assert!(out.set_name("sine").is_ok());
    out.set_format(rsoundio::SioFormat::Float32LE).unwrap();
    println!("Output format: {}", out.format().unwrap());

    thread::spawn(move || {
        const LEN: usize = 512;
        let mut pos = 0;
        loop {
            let f = 440f32;
            let w = 2.0 * f * PI32 / 48_000.0;
            let cycle =  (48_000f32 / f) as usize;

            let samples: Vec<f32> = (0..LEN)
                                    .map(|i| (w * (i+pos) as f32).sin())
                                    .collect();
            producer.write_blocking(&samples).unwrap();
            pos = (pos + LEN) % cycle;
        }
    });

    // register callbacks
    out.register_write_callback(|out: rsoundio::OutStream,
                                 min_frame_count: u32,
                                 max_frame_count: u32| {
        let mut data = vec![0.0f32; 2048];
        consumer.read_blocking(&mut data);
        let frames = vec![data.clone(), data.clone()];
        out.write_stream_f32(min_frame_count, &frames).unwrap();
    });
    out.register_underflow_callback(|out: rsoundio::OutStream| {
        println!("Underflow in {} occured!", out.name().unwrap())
    });
    out.register_error_callback(|out: rsoundio::OutStream, err: rsoundio::SioError| {
        println!("{} error: {}", out.name().unwrap(), err)
    });

    // open output stream
    out.open().unwrap();
    let sr = out.sample_rate();
    println!("Sample rate: {}", sr);

    let layout = out.layout();
    println!("Output channel layout: {}", layout);
    // start audio output (now the `write_callback` will be called periodically)
    out.start().unwrap();
    thread::sleep(Duration::new(3, 0));
    println!("Pause for 1s");
    out.pause();
    thread::sleep(Duration::new(1, 0));
    println!("Unpausing");
    out.unpause();
    thread::sleep(Duration::new(3, 0));
}
<commit_msg>Read at most `max_frame_count` frames<commit_after>extern crate rsoundio;
extern crate rb;

use rb::{RB, SpscRb, RbProducer, RbConsumer};
use std::f32::consts::PI as PI32;
use std::thread;
use std::time::Duration;

fn main() {
    let rb = SpscRb::new(4096);
    let (producer, consumer) = (rb.producer(), rb.consumer());
    // create an audio context
    let mut sio = rsoundio::SoundIo::new();
    sio.set_name("rsoundio-example").unwrap();
    // connect to the default audio backend
    sio.connect().unwrap();
    let backend = sio.current_backend().unwrap();
    println!("Connected to backend: {}", backend);
    sio.flush_events();
    // get default output device
    let dev = sio.default_output_device().unwrap();
    assert!(dev.probe_error().is_none());
    println!("Using output device: {}", dev);
    // create output stream
    let mut out = dev.create_outstream().unwrap();
    assert!(out.set_name("sine").is_ok());
    out.set_format(rsoundio::SioFormat::Float32LE).unwrap();
    println!("Output format: {}", out.format().unwrap());

    thread::spawn(move || {
        const LEN: usize = 512;
        let mut pos = 0;
        loop {
            let f = 440f32;
            let w = 2.0 * f * PI32 / 48_000.0;
            let cycle =  (48_000f32 / f) as usize;

            let samples: Vec<f32> = (0..LEN)
                                    .map(|i| (w * (i+pos) as f32).sin())
                                    .collect();
            producer.write_blocking(&samples).unwrap();
            pos = (pos + LEN) % cycle;
        }
    });

    // register callbacks
    out.register_write_callback(|out: rsoundio::OutStream,
                                 min_frame_count: u32,
                                 max_frame_count: u32| {
        const BUF_SIZE: usize = 2048;
        let mut data = vec![0.0f32; BUF_SIZE];
        let len = if backend != rsoundio::SioBackend::PulseAudio {
            ::std::cmp::min(BUF_SIZE, max_frame_count as usize)
        } else {
            BUF_SIZE
        };
        consumer.read_blocking(&mut data[..len]);
        let frames = vec![data[..len].iter().cloned().collect(),
                          data[..len].iter().cloned().collect()];
        out.write_stream_f32(min_frame_count, &frames).unwrap();
    });
    out.register_underflow_callback(|out: rsoundio::OutStream| {
        println!("Underflow in {} occured!", out.name().unwrap())
    });
    out.register_error_callback(|out: rsoundio::OutStream, err: rsoundio::SioError| {
        println!("{} error: {}", out.name().unwrap(), err)
    });

    // open output stream
    out.open().unwrap();
    let sr = out.sample_rate();
    println!("Sample rate: {}", sr);

    let layout = out.layout();
    println!("Output channel layout: {}", layout);
    // start audio output (now the `write_callback` will be called periodically)
    out.start().unwrap();
    thread::sleep(Duration::new(3, 0));
    println!("Pause for 1s");
    out.pause();
    thread::sleep(Duration::new(1, 0));
    println!("Unpausing");
    out.unpause();
    thread::sleep(Duration::new(3, 0));
}
<|endoftext|>


<commit_before>//! Tidy checks source code in this repository.
//!
//! This program runs all of the various tidy checks for style, cleanliness,
//! etc. This is run by default on `make check` and as part of the auto
//! builders.

#![deny(warnings)]

use tidy::*;

use std::env;
use std::path::PathBuf;
use std::process;

fn main() {
    let path: PathBuf = env::args_os().nth(1).expect("need path to src").into();
    let cargo: PathBuf = env::args_os().nth(2).expect("need path to cargo").into();

    let args: Vec<String> = env::args().skip(1).collect();

    let mut bad = false;
    let verbose = args.iter().any(|s| *s == "--verbose");
    bins::check(&path, &mut bad);
    style::check(&path, &mut bad);
    debug_artifacts::check(&path, &mut bad);
    errors::check(&path, &mut bad);
    cargo::check(&path, &mut bad);
    edition::check(&path, &mut bad);
    let collected = features::check(&path, &mut bad, verbose);
    pal::check(&path, &mut bad);
    unstable_book::check(&path, collected, &mut bad);
    unit_tests::check(&path, &mut bad);
    if !args.iter().any(|s| *s == "--no-vendor") {
        deps::check(&path, &mut bad);
    }
    deps::check_whitelist(&path, &cargo, &mut bad);
    extdeps::check(&path, &mut bad);
    ui_tests::check(&path, &mut bad);
    error_codes_check::check(&path, &mut bad);

    if bad {
        eprintln!("some tidy checks failed");
        process::exit(1);
    }
}
<commit_msg>[tidy] update documentation from `make check` to `x.py test`<commit_after>//! Tidy checks source code in this repository.
//!
//! This program runs all of the various tidy checks for style, cleanliness,
//! etc. This is run by default on `./x.py test` and as part of the auto
//! builders. The tidy checks can be executed with `./x.py test src/tools/tidy`.

#![deny(warnings)]

use tidy::*;

use std::env;
use std::path::PathBuf;
use std::process;

fn main() {
    let path: PathBuf = env::args_os().nth(1).expect("need path to src").into();
    let cargo: PathBuf = env::args_os().nth(2).expect("need path to cargo").into();

    let args: Vec<String> = env::args().skip(1).collect();

    let mut bad = false;
    let verbose = args.iter().any(|s| *s == "--verbose");
    bins::check(&path, &mut bad);
    style::check(&path, &mut bad);
    debug_artifacts::check(&path, &mut bad);
    errors::check(&path, &mut bad);
    cargo::check(&path, &mut bad);
    edition::check(&path, &mut bad);
    let collected = features::check(&path, &mut bad, verbose);
    pal::check(&path, &mut bad);
    unstable_book::check(&path, collected, &mut bad);
    unit_tests::check(&path, &mut bad);
    if !args.iter().any(|s| *s == "--no-vendor") {
        deps::check(&path, &mut bad);
    }
    deps::check_whitelist(&path, &cargo, &mut bad);
    extdeps::check(&path, &mut bad);
    ui_tests::check(&path, &mut bad);
    error_codes_check::check(&path, &mut bad);

    if bad {
        eprintln!("some tidy checks failed");
        process::exit(1);
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2017-2018, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

use std::cmp;
use FrameInvariants;
use FrameState;
use partition::*;
use context::BlockOffset;
use plane::*;
use context::BLOCK_TO_PLANE_SHIFT;

pub fn motion_estimation(fi: &FrameInvariants, fs: &mut FrameState, bsize: BlockSize,
                         bo: &BlockOffset, ref_frame: usize) -> MotionVector {

  match fi.rec_buffer.frames[fi.ref_frames[ref_frame - LAST_FRAME]] {
    Some(ref rec) => {
      let po = PlaneOffset { x: bo.x << BLOCK_TO_PLANE_SHIFT, y: bo.y << BLOCK_TO_PLANE_SHIFT };
      let range = 16 as usize;
      let blk_w = bsize.width();
      let blk_h = bsize.height();
      let x_lo = cmp::max(0, po.x as isize - range as isize) as usize;
      let x_hi = cmp::min(fs.input.planes[0].cfg.width - blk_w, po.x + range);
      let y_lo = cmp::max(0, po.y as isize - range as isize) as usize;
      let y_hi = cmp::min(fs.input.planes[0].cfg.height - blk_h, po.y + range);

      let mut lowest_sad = 128*128*4096 as u32;
      let mut best_mv = MotionVector { row: 0, col: 0 };

      for y in (y_lo..y_hi).step_by(1) {
        for x in (x_lo..x_hi).step_by(1) {
          let mut sad = 0 as u32;
          let mut plane_org = fs.input.planes[0].slice(&po);
          let mut plane_ref = rec.frame.planes[0].slice(&PlaneOffset { x: x, y: y });

          for _r in 0..blk_h {
            {
              let slice_org = plane_org.as_slice_w_width(blk_w);
              let slice_ref = plane_ref.as_slice_w_width(blk_w);
              sad += slice_org.iter().zip(slice_ref).map(|(&a, &b)| (a as i32 - b as i32).abs() as u32).sum::<u32>();
            }
            plane_org.y += 1;
            plane_ref.y += 1;
          }

          if sad < lowest_sad {
            lowest_sad = sad;
            best_mv = MotionVector { row: 8*(y as i16 - po.y as i16), col: 8*(x as i16 - po.x as i16) }
          }

        }
      }

      let mode = PredictionMode::NEWMV;
      let mut tmp_plane = Plane::new(blk_w, blk_h, 0, 0);

      let mut steps = vec![4, 2];
      if fi.allow_high_precision_mv {
        steps.push(1);
      }

      for step in steps {
        let center_mv_h = best_mv;
        for i in 0..3 {
          for j in 0..3 {
            // Skip the center point that was already tested
            if i == 1 && j == 1 { continue; }

            let cand_mv = MotionVector { row: center_mv_h.row + step*(i as i16 - 1),
            col: center_mv_h.col + step*(j as i16 - 1) };

            {
              let tmp_slice = &mut tmp_plane.mut_slice(&PlaneOffset { x:0, y:0 });

              mode.predict_inter(fi, 0, &po, tmp_slice, blk_w, blk_h, ref_frame, &cand_mv, 8);
            }

            let mut sad = 0 as u32;
            let mut plane_org = fs.input.planes[0].slice(&po);
            let mut plane_ref = tmp_plane.slice(&PlaneOffset { x:0, y:0 });

            for _r in 0..blk_h {
              {
                let slice_org = plane_org.as_slice_w_width(blk_w);
                let slice_ref = plane_ref.as_slice_w_width(blk_w);
                sad += slice_org.iter().zip(slice_ref).map(|(&a, &b)| (a as i32 - b as i32).abs() as u32).sum::<u32>();
              }
              plane_org.y += 1;
              plane_ref.y += 1;
            }

            if sad < lowest_sad {
              lowest_sad = sad;
              best_mv = cand_mv;
            }
          }
        }
      }

      best_mv
    },

    None => MotionVector { row: 0, col : 0 }
  }
}
<commit_msg>Refactor: move SAD computation into a separate function (#517)<commit_after>// Copyright (c) 2017-2018, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

use std::cmp;
use FrameInvariants;
use FrameState;
use partition::*;
use context::BlockOffset;
use plane::*;
use context::BLOCK_TO_PLANE_SHIFT;

#[inline(always)]
pub fn get_sad(plane_org: &mut PlaneSlice, plane_ref: &mut PlaneSlice, blk_h: usize, blk_w: usize) -> u32 {
  let mut sum = 0 as u32;

  for _r in 0..blk_h {
    {
      let slice_org = plane_org.as_slice_w_width(blk_w);
      let slice_ref = plane_ref.as_slice_w_width(blk_w);
      sum += slice_org.iter().zip(slice_ref).map(|(&a, &b)| (a as i32 - b as i32).abs() as u32).sum::<u32>();
    }
    plane_org.y += 1;
    plane_ref.y += 1;
  }

  sum
}

pub fn motion_estimation(fi: &FrameInvariants, fs: &mut FrameState, bsize: BlockSize,
                         bo: &BlockOffset, ref_frame: usize) -> MotionVector {

  match fi.rec_buffer.frames[fi.ref_frames[ref_frame - LAST_FRAME]] {
    Some(ref rec) => {
      let po = PlaneOffset { x: bo.x << BLOCK_TO_PLANE_SHIFT, y: bo.y << BLOCK_TO_PLANE_SHIFT };
      let range = 16 as usize;
      let blk_w = bsize.width();
      let blk_h = bsize.height();
      let x_lo = cmp::max(0, po.x as isize - range as isize) as usize;
      let x_hi = cmp::min(fs.input.planes[0].cfg.width - blk_w, po.x + range);
      let y_lo = cmp::max(0, po.y as isize - range as isize) as usize;
      let y_hi = cmp::min(fs.input.planes[0].cfg.height - blk_h, po.y + range);

      let mut lowest_sad = 128*128*4096 as u32;
      let mut best_mv = MotionVector { row: 0, col: 0 };

      for y in (y_lo..y_hi).step_by(1) {
        for x in (x_lo..x_hi).step_by(1) {
          let mut plane_org = fs.input.planes[0].slice(&po);
          let mut plane_ref = rec.frame.planes[0].slice(&PlaneOffset { x: x, y: y });

          let sad = get_sad(&mut plane_org, &mut plane_ref, blk_h, blk_w);

          if sad < lowest_sad {
            lowest_sad = sad;
            best_mv = MotionVector { row: 8*(y as i16 - po.y as i16), col: 8*(x as i16 - po.x as i16) }
          }

        }
      }

      let mode = PredictionMode::NEWMV;
      let mut tmp_plane = Plane::new(blk_w, blk_h, 0, 0);

      let mut steps = vec![4, 2];
      if fi.allow_high_precision_mv {
        steps.push(1);
      }

      for step in steps {
        let center_mv_h = best_mv;
        for i in 0..3 {
          for j in 0..3 {
            // Skip the center point that was already tested
            if i == 1 && j == 1 { continue; }

            let cand_mv = MotionVector { row: center_mv_h.row + step*(i as i16 - 1),
            col: center_mv_h.col + step*(j as i16 - 1) };

            {
              let tmp_slice = &mut tmp_plane.mut_slice(&PlaneOffset { x:0, y:0 });

              mode.predict_inter(fi, 0, &po, tmp_slice, blk_w, blk_h, ref_frame, &cand_mv, 8);
            }

            let mut plane_org = fs.input.planes[0].slice(&po);
            let mut plane_ref = tmp_plane.slice(&PlaneOffset { x:0, y:0 });

            let sad = get_sad(&mut plane_org, &mut plane_ref, blk_h, blk_w);

            if sad < lowest_sad {
              lowest_sad = sad;
              best_mv = cand_mv;
            }
          }
        }
      }

      best_mv
    },

    None => MotionVector { row: 0, col : 0 }
  }
}
<|endoftext|>


<commit_before>import rustc::syntax::ast;

export fn_attrs, arg_attrs;
export parse_fn;

type fn_attrs = {
    brief: option<str>,
    desc: option<str>,
    args: [arg_attrs],
    return: option<str>
};

type arg_attrs = {
    name: str,
    desc: str
};

fn parse_fn(
    attrs: [ast::attribute]
) -> fn_attrs {

    for attr in attrs {
        alt attr.node.value.node {
          ast::meta_name_value(
              "doc", {node: ast::lit_str(value), span: _}) {
            ret {
                brief: none,
                desc: some(value),
                args: [],
                return: none
            };
          }
          ast::meta_list("doc", docs) {
            ret parse_fn_(docs);
          }
          _ { }
        }
    }

    {
        brief: none,
        desc: none,
        args: [],
        return: none
    }
}

fn parse_fn_(
    items: [@ast::meta_item]
) -> fn_attrs {
    let brief = none;
    let desc = none;
    let return = none;
    let argdocs = [];
    let argdocsfound = none;
    for item: @ast::meta_item in items {
        alt item.node {
            ast::meta_name_value("brief", {node: ast::lit_str(value),
                                           span: _}) {
                brief = some(value);
            }
            ast::meta_name_value("desc", {node: ast::lit_str(value),
                                              span: _}) {
                desc = some(value);
            }
            ast::meta_name_value("return", {node: ast::lit_str(value),
                                            span: _}) {
                return = some(value);
            }
            ast::meta_list("args", args) {
                argdocsfound = some(args);
            }
            _ { }
        }
    }

    alt argdocsfound {
        none. { }
        some(ds) {
            for d: @ast::meta_item in ds {
                alt d.node {
                  ast::meta_name_value(key, {node: ast::lit_str(value),
                                             span: _}) {
                    argdocs += [{
                        name: key,
                        desc: value
                    }];
                  }
                }
            }
        }
    }

    {
        brief: brief,
        desc: desc,
        args: argdocs,
        return: return
    }
}

#[cfg(test)]
mod tests {

    fn parse_attributes(source: str) -> [ast::attribute] {
        import rustc::driver::diagnostic;
        import rustc::syntax::codemap;
        import rustc::syntax::parse::parser;

        let cm = codemap::new_codemap();
        let parse_sess = @{
            cm: cm,
            mutable next_id: 0,
            diagnostic: diagnostic::mk_handler(cm, none)
        };
        let parser = parser::new_parser_from_source_str(
            parse_sess, [], "-", source);

        parser::parse_outer_attributes(parser)
    }

    #[test]
    fn parse_fn_should_handle_undocumented_functions() {
        let source = "";
        let attrs = parse_attributes(source);
        let attrs = parse_fn(attrs);
        assert attrs.brief == none;
        assert attrs.desc == none;
        assert attrs.return == none;
        assert vec::len(attrs.args) == 0u;
    }

    #[tes]
    fn parse_fn_should_parse_simple_doc_attributes() {
        let source = "#[doc = \"basic\"]";
        let attrs = parse_attributes(source);
        let attrs = parse_fn(attrs);
        assert attrs.brief == some("basic");
    }

    #[test]
    fn parse_fn_should_parse_the_brief_description() {
        let source = "#[doc(brief = \"short\")]";
        let attrs = parse_attributes(source);
        let attrs = parse_fn(attrs);
        assert attrs.brief == some("short");
    }

    #[test]
    fn parse_fn_should_parse_the_long_description() {
        let source = "#[doc(desc = \"description\")]";
        let attrs = parse_attributes(source);
        let attrs = parse_fn(attrs);
        assert attrs.desc == some("description");
    }

    #[test]
    fn parse_fn_should_parse_the_return_value_description() {
        let source = "#[doc(return = \"return value\")]";
        let attrs = parse_attributes(source);
        let attrs = parse_fn(attrs);
        assert attrs.return == some("return value");
    }

    #[test]
    fn parse_fn_should_parse_the_argument_descriptions() {
        let source = "#[doc(args(a = \"arg a\", b = \"arg b\"))]";
        let attrs = parse_attributes(source);
        let attrs = parse_fn(attrs);
        assert attrs.args[0] == {name: "a", desc: "arg a"};
        assert attrs.args[1] == {name: "b", desc: "arg b"};
    }
}<commit_msg>rustdoc: Use attr API in attr_parser<commit_after>import rustc::syntax::ast;
import rustc::front::attr;

export fn_attrs, arg_attrs;
export parse_fn;

type fn_attrs = {
    brief: option<str>,
    desc: option<str>,
    args: [arg_attrs],
    return: option<str>
};

type arg_attrs = {
    name: str,
    desc: str
};

fn doc_meta(
    attrs: [ast::attribute]
) -> option<@ast::meta_item> {
    let doc_attrs = attr::find_attrs_by_name(attrs, "doc");
    let doc_metas = attr::attr_metas(doc_attrs);
    if vec::is_not_empty(doc_metas) {
        if vec::len(doc_metas) != 1u {
            #warn("ignoring %u doc attributes", vec::len(doc_metas) - 1u);
        }
        some(doc_metas[0])
    } else {
        none
    }
}

fn parse_fn(
    attrs: [ast::attribute]
) -> fn_attrs {

    let no_attrs = {
        brief: none,
        desc: none,
        args: [],
        return: none
    };

    ret alt doc_meta(attrs) {
      some(meta) {
        alt attr::get_meta_item_value_str(meta) {
          some(desc) {
            {
                brief: none,
                desc: some(desc),
                args: [],
                return: none
            }
          }
          none. {
            alt attr::get_meta_item_list(meta) {
              some(list) {
                parse_fn_(list)
              }
              none. {
                no_attrs
              }
            }
          }
        }
      }
      none. {
        no_attrs
      }
    };
}

fn meta_item_from_list(
    items: [@ast::meta_item],
    name: str
) -> option<@ast::meta_item> {
    let items = attr::find_meta_items_by_name(items, name);
    vec::last(items)
}

fn meta_item_value_from_list(
    items: [@ast::meta_item],
    name: str
) -> option<str> {
    alt meta_item_from_list(items, name) {
      some(item) {
        alt attr::get_meta_item_value_str(item) {
          some(value) { some(value) }
          none. { none }
        }
      }
      none. { none }
    }
}

fn meta_item_list_from_list(
    items: [@ast::meta_item],
    name: str
) -> option<[@ast::meta_item]> {
    alt meta_item_from_list(items, name) {
      some(item) {
        attr::get_meta_item_list(item)
      }
      none. { none }
    }
}

fn name_value_str_pair(
    item: @ast::meta_item
) -> option<(str, str)> {
    alt attr::get_meta_item_value_str(item) {
      some(value) {
        let name = attr::get_meta_item_name(item);
        some((name, value))
      }
      none. { none }
    }
}

fn fst<T, U>(+pair: (T, U)) -> T {
    let (t, _) = pair;
    ret t;
}

fn snd<T, U>(+pair: (T, U)) -> U {
    let (_, u) = pair;
    ret u;
}

fn parse_fn_(
    items: [@ast::meta_item]
) -> fn_attrs {
    let brief = meta_item_value_from_list(items, "brief");
    let desc = meta_item_value_from_list(items, "desc");
    let return = meta_item_value_from_list(items, "return");

    let args = alt meta_item_list_from_list(items, "args") {
      some(items) {
        vec::filter_map(items) {|item|
            option::map(name_value_str_pair(item)) { |pair|
                {
                    name: fst(pair),
                    desc: snd(pair)
                }
            }
        }
      }
      none. { [] }
    };

    {
        brief: brief,
        desc: desc,
        args: args,
        return: return
    }
}

#[cfg(test)]
mod tests {

    fn parse_attributes(source: str) -> [ast::attribute] {
        import rustc::syntax::parse::parser;
        // FIXME: Uncommenting this results in rustc bugs
        //import rustc::syntax::codemap;
        import rustc::driver::diagnostic;

        let cm = rustc::syntax::codemap::new_codemap();
        let parse_sess = @{
            cm: cm,
            mutable next_id: 0,
            diagnostic: diagnostic::mk_handler(cm, none)
        };
        let parser = parser::new_parser_from_source_str(
            parse_sess, [], "-", source);

        parser::parse_outer_attributes(parser)
    }

    #[test]
    fn parse_fn_should_handle_undocumented_functions() {
        let source = "";
        let attrs = parse_attributes(source);
        let attrs = parse_fn(attrs);
        assert attrs.brief == none;
        assert attrs.desc == none;
        assert attrs.return == none;
        assert vec::len(attrs.args) == 0u;
    }

    #[test]
    fn parse_fn_should_parse_simple_doc_attributes() {
        let source = "#[doc = \"basic\"]";
        let attrs = parse_attributes(source);
        let attrs = parse_fn(attrs);
        assert attrs.desc == some("basic");
    }

    #[test]
    fn parse_fn_should_parse_the_brief_description() {
        let source = "#[doc(brief = \"short\")]";
        let attrs = parse_attributes(source);
        let attrs = parse_fn(attrs);
        assert attrs.brief == some("short");
    }

    #[test]
    fn parse_fn_should_parse_the_long_description() {
        let source = "#[doc(desc = \"description\")]";
        let attrs = parse_attributes(source);
        let attrs = parse_fn(attrs);
        assert attrs.desc == some("description");
    }

    #[test]
    fn parse_fn_should_parse_the_return_value_description() {
        let source = "#[doc(return = \"return value\")]";
        let attrs = parse_attributes(source);
        let attrs = parse_fn(attrs);
        assert attrs.return == some("return value");
    }

    #[test]
    fn parse_fn_should_parse_the_argument_descriptions() {
        let source = "#[doc(args(a = \"arg a\", b = \"arg b\"))]";
        let attrs = parse_attributes(source);
        let attrs = parse_fn(attrs);
        assert attrs.args[0] == {name: "a", desc: "arg a"};
        assert attrs.args[1] == {name: "b", desc: "arg b"};
    }
}<|endoftext|>


<commit_before>//! Implements persistence for `BooleanIndex`.
//! e.g. writing the index to a bytestream; reading the index from a bytestream.
//! The API-Entrypoints are defined in the trait `index::PersistentIndex`

use index::{PersistentIndex, ByteEncodable, ByteDecodable};
use index::boolean_index::BooleanIndex;
use index::boolean_index::posting::Posting;

use std::mem::transmute;
use std::io::{Read, Write};
use std::collections::BTreeMap;
use std;

const CHUNKSIZE: usize = 1_000_000;

impl ByteEncodable for String {
    fn encode(&self) -> Vec<u8> {
        let mut result = Vec::with_capacity(self.len());
        result.extend_from_slice(self.as_bytes());
        result
    }
}

impl ByteDecodable for String {
    fn decode(bytes: Vec<u8>) -> Result<Self, String> {
        String::from_utf8(bytes).map_err(|e| format!("{:?}", e))
    }
}

impl ByteEncodable for usize {
    fn encode(&self) -> Vec<u8> {
        let mut result = Vec::with_capacity(8);
        result.extend_from_slice(unsafe { &transmute::<_, [u8; 8]>(*self as u64) });
        result
    }
}

impl ByteDecodable for usize {
    fn decode(bytes: Vec<u8>) -> Result<Self, String> {
        Ok(read_u64(bytes.as_slice()) as usize)
    }
}

impl<TTerm: Ord + ByteDecodable + ByteEncodable> BooleanIndex<TTerm> {
    /// Writes all the terms with postings of the index to specified target
    /// Layout:
    /// [u8; 4] -> Number of bytes term + postings need encoded
    /// [u8] -> term + postings
    fn write_terms<TTarget: Write>(&self, target: &mut TTarget) -> std::io::Result<usize> {
        // Write blocks of 1MB to target
        let mut bytes = Vec::with_capacity(2 * CHUNKSIZE);
        for term in &self.index {
            let term_bytes = encode_term(&term);
            let term_bytes_len: [u8; 4] =
                unsafe { transmute::<_, [u8; 4]>(term_bytes.len() as u32) };

            bytes.extend_from_slice(&term_bytes_len);
            bytes.extend_from_slice(term_bytes.as_slice());
            if bytes.len() > CHUNKSIZE {
                if let Err(e) = target.write(bytes.as_slice()) {
                    return Err(e);
                } else {
                    bytes.clear();
                }
            }
        }
        target.write(bytes.as_slice())
    }

    fn read_terms<TSource: Read>(source: &mut TSource)
                                 -> Result<BTreeMap<TTerm, Vec<Posting>>, String> {
        let mut bytes = Vec::new();
        if let Err(e) = source.read_to_end(&mut bytes) {
            return Err(format!("{:?}", e));
        }

        let mut ptr = 0;
        let mut result = BTreeMap::new();
        while ptr < bytes.len() {
            let entry_size = read_u32(&bytes[ptr..ptr + 4]) as usize;
            ptr += 4;
            match decode_term(&bytes[ptr..ptr + entry_size]) {
                Ok(term_posting) => {
                    result.insert(term_posting.0, term_posting.1);
                    ptr += entry_size;
                }
                Err(e) => return Err(e),
            }
        }
        Ok(result)
    }
}

fn decode_term<TTerm: ByteDecodable>(f: &[u8]) -> Result<(TTerm, Vec<Posting>), String> {
    let term_len: u8 = f[0] + 1;
    let term_bytes_vec = Vec::from(&f[1..(term_len) as usize]);
    match TTerm::decode(term_bytes_vec) {
        Ok(term) => {
            let mut ptr = term_len as usize;
            let mut postings = Vec::with_capacity(100);
            while ptr < f.len() {
                // 8bytes doc_id
                let doc_id = read_u64(&f[ptr..ptr + 8]);
                ptr += 8;
                let positions_len = read_u32(&f[ptr..ptr + 4]);
                ptr += 4;
                let positions = unsafe {
                    std::slice::from_raw_parts(f[ptr..].as_ptr() as *const u32,
                                               positions_len as usize)
                };
                ptr += positions_len as usize * 4 as usize;
                let mut positions_vec = Vec::with_capacity(positions_len as usize);
                positions_vec.extend_from_slice(positions);
                postings.push((doc_id, positions_vec));
            }
            Ok((term, postings))
        }
        Err(e) => Err(e),
    }
}

// Represents a term-entry in the inverted index as a vector of bytes
// Layout:
// [u8; 1] length of term in bytes
// [u8] term0
// [u8; 8] doc_id
// [u8; 4] #positions
// [u8] u32 encoded positions
fn encode_term<TTerm: ByteEncodable>(term: &(&TTerm, &Vec<Posting>)) -> Vec<u8> {
    let mut bytes: Vec<u8> = Vec::with_capacity(10);
    let term_bytes = term.0.encode();
    let term_len: u8 = term_bytes.len() as u8;
    bytes.push(term_len);
    bytes.extend_from_slice(term_bytes.as_slice());
    for posting in term.1.iter() {
        let doc_id_bytes = unsafe { transmute::<_, [u8; 8]>(posting.0) };
        let positions_len_bytes: [u8; 4] =
            unsafe { transmute::<_, [u8; 4]>(posting.1.len() as u32) };
        let position_bytes = unsafe {
            std::slice::from_raw_parts(posting.1.as_ptr() as *const u8, posting.1.len() * 4)
        };
        bytes.extend_from_slice(&doc_id_bytes);
        bytes.extend_from_slice(&positions_len_bytes);
        bytes.extend_from_slice(position_bytes);
    }
    bytes
}

impl<TTerm: ByteDecodable + ByteEncodable + Ord> PersistentIndex for BooleanIndex<TTerm> {
    fn write_to<TTarget: Write>(&self, target: &mut TTarget) -> std::io::Result<usize> {
        self.write_terms(target)
    }

    fn read_from<TSource: Read>(source: &mut TSource) -> Result<Self, String> {
        Self::read_terms(source).map(|btree| {
            BooleanIndex {
                document_count: 0,
                index: btree,
            }
        })
    }
}

fn read_u32(barry: &[u8]) -> u32 {
    let mut array = [0u8; 4];
    for (&x, p) in barry.iter().zip(array.iter_mut()) {
        *p = x;
    }
    unsafe { transmute::<_, u32>(array) }
}

fn read_u64(barry: &[u8]) -> u64 {
    let mut array = [0u8; 8];
    for (&x, p) in barry.iter().zip(array.iter_mut()) {
        *p = x;
    }
    unsafe { transmute::<_, u64>(array) }
}

fn vbyte_encode(mut number: usize) -> Vec<u8>{
    let mut result = Vec::new();
    loop {
        result.insert(0, (number % 128) as u8);
        if number < 128 {
            break;
        } else {
            number /= 128;
        }
    }
    let len = result.len();
    result[len - 1] += 128;
    result
}

macro_rules! unwrap_or_return_none{
    ($operand:expr) => {
        if let Some(x) = $operand {
            x
        } else {
            return None;
        }
    }
}

struct VByteDecoder<T: Iterator<Item=u8>> {
    bytes: T
}

impl<T: Iterator<Item=u8>> VByteDecoder<T> {
    fn new(bytes: T) -> Self {
        VByteDecoder{
            bytes: bytes
        }
    }
}

impl<T: Iterator<Item=u8>> Iterator for VByteDecoder<T>{
    type Item = usize;
    fn next(&mut self) -> Option<Self::Item> {

        let mut result: usize = 0;
        loop {
            result *= 128;
            let val = unwrap_or_return_none!(self.bytes.next());
            result += val as usize;
            if val >= 128 {
                result -= 128;
                break;
            }
        }
        Some(result)
    }
}

#[test]
fn test_vbyte_encode() {
    assert_eq!(vbyte_encode(0), vec![0x80]);
    assert_eq!(vbyte_encode(5), vec![0x85]);
    assert_eq!(vbyte_encode(127), vec![0xFF]);
    assert_eq!(vbyte_encode(128), vec![0x01, 0x80]);
    assert_eq!(vbyte_encode(130), vec![0x01, 0x82]);
    assert_eq!(vbyte_encode(255), vec![0x01, 0xFF]);
    assert_eq!(vbyte_encode(20_000), vec![0x01, 0x1C, 0xA0]);
    assert_eq!(vbyte_encode(0xFFFF), vec![0x03, 0x7F, 0xFF]);
}

#[test]
fn test_vbyte_decode() {
    assert_eq!(VByteDecoder::new(vec![0x80].into_iter()).collect::<Vec<_>>(), vec![0]);
    assert_eq!(VByteDecoder::new(vec![0x85].into_iter()).collect::<Vec<_>>(), vec![5]);
    assert_eq!(VByteDecoder::new(vec![0xFF].into_iter()).collect::<Vec<_>>(), vec![127]);
    assert_eq!(VByteDecoder::new(vec![0x80, 0x81].into_iter()).collect::<Vec<_>>(), vec![0, 1]);
    assert_eq!(VByteDecoder::new(vec![0x03, 0x7F, 0xFF, 0x01, 0x82, 0x85].into_iter()).collect::<Vec<_>>(), vec![0xFFFF, 130, 5]);
    assert_eq!(VByteDecoder::new(vec![0x80].into_iter()).collect::<Vec<_>>(), vec![0]);
}

#[cfg(test)]
mod tests {
    use index::boolean_index::BooleanIndex;
    use index::boolean_index::tests::prepare_index;
    use index::{Index, PersistentIndex};
    use std::io::Cursor;

    #[test]
    fn basic() {
        let index = prepare_index();
        let mut bytes: Vec<u8> = vec![];
        index.write_to(&mut bytes).unwrap();
        let mut buff = Cursor::new(bytes.clone());
        let mut bytes_2: Vec<u8> = vec![];
        BooleanIndex::<usize>::read_from(&mut buff).unwrap().write_to(&mut bytes_2).unwrap();
        assert_eq!(bytes, bytes_2);
    }

    #[test]
    fn length() {
        let index = prepare_index();
        let mut bytes: Vec<u8> = vec![];
        index.write_to(&mut bytes).unwrap();
        let mut buff = Cursor::new(bytes.clone());
        let mut bytes_2: Vec<u8> = vec![];
        let mut read_index = BooleanIndex::<usize>::read_from(&mut buff).unwrap();
        read_index.index_document(1..24);
        read_index.write_to(&mut bytes_2).unwrap();
        assert!(bytes.len() < bytes_2.len());
    }
}
<commit_msg>Turned on basic compression<commit_after>//! Implements persistence for `BooleanIndex`.
//! e.g. writing the index to a bytestream; reading the index from a bytestream.
//! The API-Entrypoints are defined in the trait `index::PersistentIndex`

use index::{PersistentIndex, ByteEncodable, ByteDecodable};
use index::boolean_index::BooleanIndex;
use index::boolean_index::posting::Posting;

use std::mem::transmute;
use std::io::{Read, Write};
use std::collections::BTreeMap;
use std;

const CHUNKSIZE: usize = 1_000_000;

impl ByteEncodable for String {
    fn encode(&self) -> Vec<u8> {
        let mut result = Vec::with_capacity(self.len());
        result.extend_from_slice(self.as_bytes());
        result
    }
}

impl ByteDecodable for String {
    fn decode(bytes: Vec<u8>) -> Result<Self, String> {
        String::from_utf8(bytes).map_err(|e| format!("{:?}", e))
    }
}

impl ByteEncodable for usize {
    fn encode(&self) -> Vec<u8> {
        let mut result = Vec::with_capacity(8);
        result.extend_from_slice(unsafe { &transmute::<_, [u8; 8]>(*self as u64) });
        result
    }
}

impl ByteDecodable for usize {
    fn decode(bytes: Vec<u8>) -> Result<Self, String> {
        Ok(read_u64(bytes.as_slice()) as usize)
    }
}

impl<TTerm: Ord + ByteDecodable + ByteEncodable> BooleanIndex<TTerm> {
    /// Writes all the terms with postings of the index to specified target
    /// Layout:
    /// [u8; 4] -> Number of bytes term + postings need encoded
    /// [u8] -> term + postings
    fn write_terms<TTarget: Write>(&self, target: &mut TTarget) -> std::io::Result<usize> {
        // Write blocks of 1MB to target
        let mut bytes = Vec::with_capacity(2 * CHUNKSIZE);
        for term in &self.index {
            let term_bytes = vbyte_encode_term(&term);
            let term_bytes_len: [u8; 4] =
                unsafe { transmute::<_, [u8; 4]>(term_bytes.len() as u32) };

            bytes.extend_from_slice(&term_bytes_len);
            bytes.extend_from_slice(term_bytes.as_slice());
            if bytes.len() > CHUNKSIZE {
                if let Err(e) = target.write(bytes.as_slice()) {
                    return Err(e);
                } else {
                    bytes.clear();
                }
            }
        }
        target.write(bytes.as_slice())
    }

    fn read_terms<TSource: Read>(source: &mut TSource)
                                 -> Result<BTreeMap<TTerm, Vec<Posting>>, String> {
        let mut bytes = Vec::new();
        if let Err(e) = source.read_to_end(&mut bytes) {
            return Err(format!("{:?}", e));
        }

        let mut ptr = 0;
        let mut result = BTreeMap::new();
        while ptr < bytes.len() {
            let entry_size = read_u32(&bytes[ptr..ptr + 4]) as usize;
            ptr += 4;
            match vbyte_decode_term(&bytes[ptr..ptr + entry_size]) {
                Ok(term_posting) => {
                    result.insert(term_posting.0, term_posting.1);
                    ptr += entry_size;
                }
                Err(e) => return Err(e),
            }
        }
        Ok(result)
    }
}

fn decode_term<TTerm: ByteDecodable>(f: &[u8]) -> Result<(TTerm, Vec<Posting>), String> {
    let term_len: u8 = f[0] + 1;
    let term_bytes_vec = Vec::from(&f[1..(term_len) as usize]);
    match TTerm::decode(term_bytes_vec) {
        Ok(term) => {
            let mut ptr = term_len as usize;
            let mut postings = Vec::with_capacity(100);
            while ptr < f.len() {
                // 8bytes doc_id
                let doc_id = read_u64(&f[ptr..ptr + 8]);
                ptr += 8;
                let positions_len = read_u32(&f[ptr..ptr + 4]);
                ptr += 4;
                let positions = unsafe {
                    std::slice::from_raw_parts(f[ptr..].as_ptr() as *const u32,
                                               positions_len as usize)
                };
                ptr += positions_len as usize * 4 as usize;
                let mut positions_vec = Vec::with_capacity(positions_len as usize);
                positions_vec.extend_from_slice(positions);
                postings.push((doc_id, positions_vec));
            }
            Ok((term, postings))
        }
        Err(e) => Err(e),
    }
}

fn vbyte_decode_term<TTerm: ByteDecodable>(f: &[u8]) -> Result<(TTerm, Vec<Posting>), String> {
    let term_len: u8 = f[0] + 1;
    let term_bytes_vec = Vec::from(&f[1..(term_len) as usize]);
    match TTerm::decode(term_bytes_vec) {
        Ok(term) => {
            let mut postings = Vec::new();
            let mut decoder = VByteDecoder::new((&f[term_len as usize..]).iter().map(|x| *x));
            while let Some(doc_id) = decoder.next() {
                let positions_len = decoder.next().unwrap();
                let mut positions = Vec::with_capacity(positions_len as usize);
                for _ in 0..positions_len {
                    positions.push(decoder.next().unwrap() as u32);
                }
                postings.push((doc_id as u64, positions));

            }
            Ok((term, postings))
        }
        Err(e) => Err(e),
    }

}

// Represents a term-entry in the inverted index as a vector of bytes
// Layout:
// [u8; 1] length of term in bytes
// [u8] term
// Loop over postings
// |  [u8; 8] doc_id
// |  [u8; 4] #positions
// |  [u8] u32 encoded positions
fn encode_term<TTerm: ByteEncodable>(term: &(&TTerm, &Vec<Posting>)) -> Vec<u8> {
    let mut bytes: Vec<u8> = Vec::new();
    let term_bytes = term.0.encode();
    let term_len: u8 = term_bytes.len() as u8;
    bytes.push(term_len);
    bytes.extend_from_slice(term_bytes.as_slice());
    for posting in term.1.iter() {
        let doc_id_bytes = unsafe { transmute::<_, [u8; 8]>(posting.0) };
        let positions_len_bytes: [u8; 4] =
            unsafe { transmute::<_, [u8; 4]>(posting.1.len() as u32) };
        let position_bytes = unsafe {
            std::slice::from_raw_parts(posting.1.as_ptr() as *const u8, posting.1.len() * 4)
        };
        bytes.extend_from_slice(&doc_id_bytes);
        bytes.extend_from_slice(&positions_len_bytes);
        bytes.extend_from_slice(position_bytes);
    }
    bytes
}

// Represents a term-entry in the inverted index as a vector of bytes
// Layout:
// [u8; 1] length of term in bytes
// [u8] term
// For every posting:
// [u8] stream of vbyte encoded numbers: doc_id, #positions, [positions]
fn vbyte_encode_term<TTerm: ByteEncodable>(term: &(&TTerm, &Vec<Posting>)) -> Vec<u8> {
    let mut bytes: Vec<u8> = Vec::new();
    let term_bytes = term.0.encode();
    let term_len: u8 = term_bytes.len() as u8;
    bytes.push(term_len);
    bytes.extend_from_slice(term_bytes.as_slice());
    for posting in term.1.iter() {
        bytes.append(&mut vbyte_encode(posting.0 as usize));
        bytes.append(&mut vbyte_encode(posting.1.len() as usize));
        for position in posting.1.iter() {
            bytes.append(&mut vbyte_encode(*position as usize));
        }
    }
    bytes
}

impl<TTerm: ByteDecodable + ByteEncodable + Ord> PersistentIndex for BooleanIndex<TTerm> {
    fn write_to<TTarget: Write>(&self, target: &mut TTarget) -> std::io::Result<usize> {
        self.write_terms(target)
    }

    fn read_from<TSource: Read>(source: &mut TSource) -> Result<Self, String> {
        Self::read_terms(source).map(|btree| {
            BooleanIndex {
                document_count: 0,
                index: btree,
            }
        })
    }
}

fn read_u32(barry: &[u8]) -> u32 {
    let mut array = [0u8; 4];
    for (&x, p) in barry.iter().zip(array.iter_mut()) {
        *p = x;
    }
    unsafe { transmute::<_, u32>(array) }
}

fn read_u64(barry: &[u8]) -> u64 {
    let mut array = [0u8; 8];
    for (&x, p) in barry.iter().zip(array.iter_mut()) {
        *p = x;
    }
    unsafe { transmute::<_, u64>(array) }
}

fn vbyte_encode(mut number: usize) -> Vec<u8> {
    let mut result = Vec::new();
    loop {
        result.insert(0, (number % 128) as u8);
        if number < 128 {
            break;
        } else {
            number /= 128;
        }
    }
    let len = result.len();
    result[len - 1] += 128;
    result
}

macro_rules! unwrap_or_return_none{
    ($operand:expr) => {
        if let Some(x) = $operand {
            x
        } else {
            return None;
        }
    }
}

struct VByteDecoder<T: Iterator<Item = u8>> {
    bytes: T,
}

impl<T: Iterator<Item = u8>> VByteDecoder<T> {
    fn new(bytes: T) -> Self {
        VByteDecoder { bytes: bytes }
    }
}

impl<T: Iterator<Item = u8>> Iterator for VByteDecoder<T> {
    type Item = usize;
    fn next(&mut self) -> Option<Self::Item> {

        let mut result: usize = 0;
        loop {
            result *= 128;
            let val = unwrap_or_return_none!(self.bytes.next());
            result += val as usize;
            if val >= 128 {
                result -= 128;
                break;
            }
        }
        Some(result)
    }
}

#[test]
fn test_vbyte_encode() {
    assert_eq!(vbyte_encode(0), vec![0x80]);
    assert_eq!(vbyte_encode(5), vec![0x85]);
    assert_eq!(vbyte_encode(127), vec![0xFF]);
    assert_eq!(vbyte_encode(128), vec![0x01, 0x80]);
    assert_eq!(vbyte_encode(130), vec![0x01, 0x82]);
    assert_eq!(vbyte_encode(255), vec![0x01, 0xFF]);
    assert_eq!(vbyte_encode(20_000), vec![0x01, 0x1C, 0xA0]);
    assert_eq!(vbyte_encode(0xFFFF), vec![0x03, 0x7F, 0xFF]);
}

#[test]
fn test_vbyte_decode() {
    assert_eq!(VByteDecoder::new(vec![0x80].into_iter()).collect::<Vec<_>>(),
               vec![0]);
    assert_eq!(VByteDecoder::new(vec![0x85].into_iter()).collect::<Vec<_>>(),
               vec![5]);
    assert_eq!(VByteDecoder::new(vec![0xFF].into_iter()).collect::<Vec<_>>(),
               vec![127]);
    assert_eq!(VByteDecoder::new(vec![0x80, 0x81].into_iter()).collect::<Vec<_>>(),
               vec![0, 1]);
    assert_eq!(VByteDecoder::new(vec![0x03, 0x7F, 0xFF, 0x01, 0x82, 0x85].into_iter())
                   .collect::<Vec<_>>(),
               vec![0xFFFF, 130, 5]);
    assert_eq!(VByteDecoder::new(vec![0x80].into_iter()).collect::<Vec<_>>(),
               vec![0]);
}

#[cfg(test)]
mod tests {
    use index::boolean_index::BooleanIndex;
    use index::boolean_index::tests::prepare_index;
    use index::{Index, PersistentIndex};
    use std::io::Cursor;

    #[test]
    fn basic() {
        let index = prepare_index();
        let mut bytes: Vec<u8> = vec![];
        index.write_to(&mut bytes).unwrap();
        let mut buff = Cursor::new(bytes.clone());
        let mut bytes_2: Vec<u8> = vec![];
        BooleanIndex::<usize>::read_from(&mut buff).unwrap().write_to(&mut bytes_2).unwrap();
        assert_eq!(bytes, bytes_2);
    }

    #[test]
    fn length() {
        let index = prepare_index();
        let mut bytes: Vec<u8> = vec![];
        index.write_to(&mut bytes).unwrap();
        let mut buff = Cursor::new(bytes.clone());
        let mut bytes_2: Vec<u8> = vec![];
        let mut read_index = BooleanIndex::<usize>::read_from(&mut buff).unwrap();
        read_index.index_document(1..24);
        read_index.write_to(&mut bytes_2).unwrap();
        assert!(bytes.len() < bytes_2.len());
    }
}
<|endoftext|>


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

//! This module offers functions to interact with taskwarrior. This will expect the `task` binary
//! in your path. This will always call task and never interact with your `.task` directory itself.
//! (This is in accordance with the taskwarrior api guide lines.)

use error::{Result, ResultExt, ErrorKind as EK};
use task::Task;
use std::process::{Command, Stdio};
use std::io::Write;
use import::import;
use serde_json;

/// This will give you all tasks which match the given query in the taskwarrior query syntax.
/// This is not sanitized. Never get the query string from an untrusted user.
pub fn query(query: &str) -> Result<Vec<Task>> {
    let mut cmd = Command::new("task");
    for filter in query.split_whitespace() {
        cmd.arg(filter);
    }
    let mut export = cmd.arg("export").stdout(Stdio::piped()).spawn().chain_err(
        || {
            EK::TaskCmdError
        },
    )?;
    export.wait().chain_err(|| EK::TaskCmdError)?;
    import(export.stdout.chain_err(|| EK::TaskCmdError)?)
}

/// This will save the given tasks to taskwarrior. Call with `Some(task)` if you just have one
/// task.
pub fn save<T>(tasks: T) -> Result<()>
where
    T: IntoIterator<Item = Task>,
{
    let tasks: Vec<Task> = tasks.into_iter().collect();
    let input_buffer = serde_json::to_string(&tasks).chain_err(
        || EK::SerializeError,
    )?;
    let mut import = Command::new("task")
        .arg("import")
        .stdin(Stdio::piped())
        .spawn()
        .chain_err(|| EK::TaskCmdError)?;
    import
        .stdin
        .as_mut()
        .chain_err(|| EK::TaskCmdError)?
        .write_all(input_buffer.as_bytes())
        .chain_err(|| EK::TaskCmdError)?;
    import.wait().chain_err(|| EK::TaskCmdError)?;
    Ok(())
}
<commit_msg>Make tw module more flexible<commit_after>//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

//! This module offers functions to interact with taskwarrior. This will expect the `task` binary
//! in your path. This will always call task and never interact with your `.task` directory itself.
//! (This is in accordance with the taskwarrior api guide lines.)

use error::{Result, ResultExt, ErrorKind as EK};
use task::Task;
use std::process::{Command, Stdio, Child};
use std::io::Write;
use std::iter::once;
use import::import;
use serde_json;

/// This will give you all tasks which match the given query in the taskwarrior query syntax.
/// This is not sanitized. Never get the query string from an untrusted user.
pub fn query(query: &str) -> Result<Vec<Task>> {
    let mut cmd = add_query_to_cmd(query, Command::new("task"));
    cmd.stdout(Stdio::piped());
    run_query_cmd(cmd)
}

/// This will take a Command, and append the given query string splited at whitespace followed by
/// the "export" command to the arguments of the Command.
pub fn add_query_to_cmd(query: &str, mut cmd: Command) -> Command {
    for x in query.split_whitespace().chain(once("export")) {
        cmd.arg(x);
    }
    cmd
}

/// This executes the given Command and trys to convert the Result into a Vec<Task>.
pub fn run_query_cmd(mut cmd: Command) -> Result<Vec<Task>> {
    let mut export = cmd.spawn().chain_err(|| EK::TaskCmdError)?;
    export.wait().chain_err(|| EK::TaskCmdError)?;
    import(export.stdout.chain_err(|| EK::TaskCmdError)?)
}

/// This function runs the given Command, pipes the tasks as JSON to it and returns a handle to the child process.
pub fn save_to_cmd<'a>(tasks: Vec<&'a Task>, mut cmd: Command) -> Result<Child> {
    let input_buffer = serde_json::to_string(&tasks).chain_err(
        || EK::SerializeError,
    )?;
    let mut import = cmd.spawn().chain_err(|| EK::TaskCmdError)?;
    import
        .stdin
        .as_mut()
        .chain_err(|| EK::TaskCmdError)?
        .write_all(input_buffer.as_bytes())
        .chain_err(|| EK::TaskCmdError)?;
    Ok(import)
}

/// This will save the given tasks to taskwarrior. Call with `Some(&task)` if you just have one
/// task.
/// This will block until the save was successful.
pub fn save<'a, T>(tasks: T) -> Result<()>
where
    T: IntoIterator<Item = &'a Task>,
{
    save_async(tasks)?.wait().chain_err(|| EK::TaskCmdError)?;
    Ok(())
}

/// This function returns the handle to a child process which saves the given tasks.
pub fn save_async<'a, T>(tasks: T) -> Result<Child>
where
    T: IntoIterator<Item = &'a Task>,
{
    let mut cmd = Command::new("task");
    cmd.arg("import").stdin(Stdio::piped());
    save_to_cmd(tasks.into_iter().collect(), cmd)
}
<|endoftext|>


<commit_before>//! This module handles the expected information a crate should have
//! and manages the serialising and deserialising of this information
//! to and from structs. The serlializing is only utilised in
//! integration tests.
use std::collections::HashMap;

use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
use semver;

use models::krate::MAX_NAME_LENGTH;

use models::Keyword as CrateKeyword;
use models::DependencyKind;
use models::Crate;

#[derive(Deserialize, Serialize, Debug)]
pub struct NewCrate {
    pub name: CrateName,
    pub vers: CrateVersion,
    pub deps: Vec<CrateDependency>,
    pub features: HashMap<FeatureName, Vec<Feature>>,
    pub authors: Vec<String>,
    pub description: Option<String>,
    pub homepage: Option<String>,
    pub documentation: Option<String>,
    pub readme: Option<String>,
    pub readme_file: Option<String>,
    pub keywords: Option<KeywordList>,
    pub categories: Option<CategoryList>,
    pub license: Option<String>,
    pub license_file: Option<String>,
    pub repository: Option<String>,
    pub badges: Option<HashMap<String, HashMap<String, String>>>,
    #[serde(default)]
    pub links: Option<String>,
}

#[derive(PartialEq, Eq, Hash, Serialize, Debug, Deref)]
pub struct CrateName(pub String);
#[derive(Debug, Deref)]
pub struct CrateVersion(pub semver::Version);
#[derive(Debug, Deref)]
pub struct CrateVersionReq(pub semver::VersionReq);
#[derive(Serialize, Debug, Deref)]
pub struct KeywordList(pub Vec<Keyword>);
#[derive(Serialize, Debug, Deref)]
pub struct Keyword(pub String);
#[derive(Serialize, Debug, Deref)]
pub struct CategoryList(pub Vec<Category>);
#[derive(Serialize, Deserialize, Debug, Deref)]
pub struct Category(pub String);
#[derive(Serialize, Debug, Deref)]
pub struct Feature(pub String);
#[derive(PartialEq, Eq, Hash, Serialize, Debug, Deref)]
pub struct FeatureName(pub String);

#[derive(Serialize, Deserialize, Debug)]
pub struct CrateDependency {
    pub optional: bool,
    pub default_features: bool,
    pub name: CrateName,
    pub features: Vec<Feature>,
    pub version_req: CrateVersionReq,
    pub target: Option<String>,
    pub kind: Option<DependencyKind>,
}

impl<'de> Deserialize<'de> for CrateName {
    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<CrateName, D::Error> {
        let s = String::deserialize(d)?;
        if !Crate::valid_name(&s) {
            let value = de::Unexpected::Str(&s);
            let expected = format!(
                "a valid crate name to start with a letter, contain only letters, \
                 numbers, hyphens, or underscores and have at most {} characters",
                MAX_NAME_LENGTH
            );
            Err(de::Error::invalid_value(value, &expected.as_ref()))
        } else {
            Ok(CrateName(s))
        }
    }
}

impl<T: ?Sized> PartialEq<T> for CrateName
where
    String: PartialEq<T>,
{
    fn eq(&self, rhs: &T) -> bool {
        self.0 == *rhs
    }
}

impl<'de> Deserialize<'de> for Keyword {
    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Keyword, D::Error> {
        let s = String::deserialize(d)?;
        if !CrateKeyword::valid_name(&s) {
            let value = de::Unexpected::Str(&s);
            let expected = "a valid keyword specifier";
            Err(de::Error::invalid_value(value, &expected))
        } else {
            Ok(Keyword(s))
        }
    }
}

impl<'de> Deserialize<'de> for FeatureName {
    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
        let s = String::deserialize(d)?;
        if !Crate::valid_feature_name(&s) {
            let value = de::Unexpected::Str(&s);
            let expected = "a valid feature name containing only letters, \
                            numbers, hyphens, or underscores";
            Err(de::Error::invalid_value(value, &expected))
        } else {
            Ok(FeatureName(s))
        }
    }
}

impl<'de> Deserialize<'de> for Feature {
    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Feature, D::Error> {
        let s = String::deserialize(d)?;
        if !Crate::valid_feature_name(&s) {
            let value = de::Unexpected::Str(&s);
            let expected = "a valid feature name";
            Err(de::Error::invalid_value(value, &expected))
        } else {
            Ok(Feature(s))
        }
    }
}

impl<'de> Deserialize<'de> for CrateVersion {
    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<CrateVersion, D::Error> {
        let s = String::deserialize(d)?;
        match semver::Version::parse(&s) {
            Ok(v) => Ok(CrateVersion(v)),
            Err(..) => {
                let value = de::Unexpected::Str(&s);
                let expected = "a valid semver";
                Err(de::Error::invalid_value(value, &expected))
            }
        }
    }
}

impl<'de> Deserialize<'de> for CrateVersionReq {
    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<CrateVersionReq, D::Error> {
        let s = String::deserialize(d)?;
        match semver::VersionReq::parse(&s) {
            Ok(v) => Ok(CrateVersionReq(v)),
            Err(..) => {
                let value = de::Unexpected::Str(&s);
                let expected = "a valid version req";
                Err(de::Error::invalid_value(value, &expected))
            }
        }
    }
}

impl<T: ?Sized> PartialEq<T> for CrateVersionReq
where
    semver::VersionReq: PartialEq<T>,
{
    fn eq(&self, rhs: &T) -> bool {
        self.0 == *rhs
    }
}

impl<'de> Deserialize<'de> for KeywordList {
    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<KeywordList, D::Error> {
        let inner = <Vec<Keyword> as Deserialize<'de>>::deserialize(d)?;
        if inner.len() > 5 {
            let expected = "at most 5 keywords per crate";
            return Err(de::Error::invalid_length(inner.len(), &expected));
        }
        for val in &inner {
            if val.len() > 20 {
                let expected = "a keyword with less than 20 characters";
                return Err(de::Error::invalid_length(val.len(), &expected));
            }
        }
        Ok(KeywordList(inner))
    }
}

impl<'de> Deserialize<'de> for CategoryList {
    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<CategoryList, D::Error> {
        let inner = <Vec<Category> as Deserialize<'de>>::deserialize(d)?;
        if inner.len() > 5 {
            let expected = "at most 5 categories per crate";
            Err(de::Error::invalid_length(inner.len(), &expected))
        } else {
            Ok(CategoryList(inner))
        }
    }
}

impl Serialize for CrateVersion {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(&(**self).to_string())
    }
}

impl Serialize for CrateVersionReq {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(&(**self).to_string())
    }
}

use diesel::pg::Pg;
use diesel::serialize::{self, Output, ToSql};
use diesel::sql_types::Text;
use std::io::Write;

impl ToSql<Text, Pg> for Feature {
    fn to_sql<W: Write>(&self, out: &mut Output<W, Pg>) -> serialize::Result {
        ToSql::<Text, Pg>::to_sql(&**self, out)
    }
}
<commit_msg>use the correct validator for feature<commit_after>//! This module handles the expected information a crate should have
//! and manages the serialising and deserialising of this information
//! to and from structs. The serlializing is only utilised in
//! integration tests.
use std::collections::HashMap;

use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
use semver;

use models::krate::MAX_NAME_LENGTH;

use models::Keyword as CrateKeyword;
use models::DependencyKind;
use models::Crate;

#[derive(Deserialize, Serialize, Debug)]
pub struct NewCrate {
    pub name: CrateName,
    pub vers: CrateVersion,
    pub deps: Vec<CrateDependency>,
    pub features: HashMap<FeatureName, Vec<Feature>>,
    pub authors: Vec<String>,
    pub description: Option<String>,
    pub homepage: Option<String>,
    pub documentation: Option<String>,
    pub readme: Option<String>,
    pub readme_file: Option<String>,
    pub keywords: Option<KeywordList>,
    pub categories: Option<CategoryList>,
    pub license: Option<String>,
    pub license_file: Option<String>,
    pub repository: Option<String>,
    pub badges: Option<HashMap<String, HashMap<String, String>>>,
    #[serde(default)]
    pub links: Option<String>,
}

#[derive(PartialEq, Eq, Hash, Serialize, Debug, Deref)]
pub struct CrateName(pub String);
#[derive(Debug, Deref)]
pub struct CrateVersion(pub semver::Version);
#[derive(Debug, Deref)]
pub struct CrateVersionReq(pub semver::VersionReq);
#[derive(Serialize, Debug, Deref)]
pub struct KeywordList(pub Vec<Keyword>);
#[derive(Serialize, Debug, Deref)]
pub struct Keyword(pub String);
#[derive(Serialize, Debug, Deref)]
pub struct CategoryList(pub Vec<Category>);
#[derive(Serialize, Deserialize, Debug, Deref)]
pub struct Category(pub String);
#[derive(Serialize, Debug, Deref)]
pub struct Feature(pub String);
#[derive(PartialEq, Eq, Hash, Serialize, Debug, Deref)]
pub struct FeatureName(pub String);

#[derive(Serialize, Deserialize, Debug)]
pub struct CrateDependency {
    pub optional: bool,
    pub default_features: bool,
    pub name: CrateName,
    pub features: Vec<Feature>,
    pub version_req: CrateVersionReq,
    pub target: Option<String>,
    pub kind: Option<DependencyKind>,
}

impl<'de> Deserialize<'de> for CrateName {
    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<CrateName, D::Error> {
        let s = String::deserialize(d)?;
        if !Crate::valid_name(&s) {
            let value = de::Unexpected::Str(&s);
            let expected = format!(
                "a valid crate name to start with a letter, contain only letters, \
                 numbers, hyphens, or underscores and have at most {} characters",
                MAX_NAME_LENGTH
            );
            Err(de::Error::invalid_value(value, &expected.as_ref()))
        } else {
            Ok(CrateName(s))
        }
    }
}

impl<T: ?Sized> PartialEq<T> for CrateName
where
    String: PartialEq<T>,
{
    fn eq(&self, rhs: &T) -> bool {
        self.0 == *rhs
    }
}

impl<'de> Deserialize<'de> for Keyword {
    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Keyword, D::Error> {
        let s = String::deserialize(d)?;
        if !CrateKeyword::valid_name(&s) {
            let value = de::Unexpected::Str(&s);
            let expected = "a valid keyword specifier";
            Err(de::Error::invalid_value(value, &expected))
        } else {
            Ok(Keyword(s))
        }
    }
}

impl<'de> Deserialize<'de> for FeatureName {
    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
        let s = String::deserialize(d)?;
        if !Crate::valid_feature_name(&s) {
            let value = de::Unexpected::Str(&s);
            let expected = "a valid feature name containing only letters, \
                            numbers, hyphens, or underscores";
            Err(de::Error::invalid_value(value, &expected))
        } else {
            Ok(FeatureName(s))
        }
    }
}

impl<'de> Deserialize<'de> for Feature {
    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Feature, D::Error> {
        let s = String::deserialize(d)?;
        if !Crate::valid_feature(&s) {
            let value = de::Unexpected::Str(&s);
            let expected = "a valid feature name";
            Err(de::Error::invalid_value(value, &expected))
        } else {
            Ok(Feature(s))
        }
    }
}

impl<'de> Deserialize<'de> for CrateVersion {
    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<CrateVersion, D::Error> {
        let s = String::deserialize(d)?;
        match semver::Version::parse(&s) {
            Ok(v) => Ok(CrateVersion(v)),
            Err(..) => {
                let value = de::Unexpected::Str(&s);
                let expected = "a valid semver";
                Err(de::Error::invalid_value(value, &expected))
            }
        }
    }
}

impl<'de> Deserialize<'de> for CrateVersionReq {
    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<CrateVersionReq, D::Error> {
        let s = String::deserialize(d)?;
        match semver::VersionReq::parse(&s) {
            Ok(v) => Ok(CrateVersionReq(v)),
            Err(..) => {
                let value = de::Unexpected::Str(&s);
                let expected = "a valid version req";
                Err(de::Error::invalid_value(value, &expected))
            }
        }
    }
}

impl<T: ?Sized> PartialEq<T> for CrateVersionReq
where
    semver::VersionReq: PartialEq<T>,
{
    fn eq(&self, rhs: &T) -> bool {
        self.0 == *rhs
    }
}

impl<'de> Deserialize<'de> for KeywordList {
    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<KeywordList, D::Error> {
        let inner = <Vec<Keyword> as Deserialize<'de>>::deserialize(d)?;
        if inner.len() > 5 {
            let expected = "at most 5 keywords per crate";
            return Err(de::Error::invalid_length(inner.len(), &expected));
        }
        for val in &inner {
            if val.len() > 20 {
                let expected = "a keyword with less than 20 characters";
                return Err(de::Error::invalid_length(val.len(), &expected));
            }
        }
        Ok(KeywordList(inner))
    }
}

impl<'de> Deserialize<'de> for CategoryList {
    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<CategoryList, D::Error> {
        let inner = <Vec<Category> as Deserialize<'de>>::deserialize(d)?;
        if inner.len() > 5 {
            let expected = "at most 5 categories per crate";
            Err(de::Error::invalid_length(inner.len(), &expected))
        } else {
            Ok(CategoryList(inner))
        }
    }
}

impl Serialize for CrateVersion {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(&(**self).to_string())
    }
}

impl Serialize for CrateVersionReq {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(&(**self).to_string())
    }
}

use diesel::pg::Pg;
use diesel::serialize::{self, Output, ToSql};
use diesel::sql_types::Text;
use std::io::Write;

impl ToSql<Text, Pg> for Feature {
    fn to_sql<W: Write>(&self, out: &mut Output<W, Pg>) -> serialize::Result {
        ToSql::<Text, Pg>::to_sql(&**self, out)
    }
}
<|endoftext|>


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

use PanicStrategy;
use target::TargetOptions;
use std::default::Default;

pub fn opts() -> TargetOptions {
    TargetOptions {
        pre_link_args: vec![
            // We want to be able to strip as much executable code as possible
            // from the linker command line, and this flag indicates to the
            // linker that it can avoid linking in dynamic libraries that don't
            // actually satisfy any symbols up to that point (as with many other
            // resolutions the linker does). This option only applies to all
            // following libraries so we're sure to pass it as one of the first
            // arguments.
            "-Wl,--as-needed".to_string(),

            // Always enable NX protection when it is available
            "-Wl,-z,noexecstack".to_string(),

            // Do not link libc
            "-nostdlib".to_string(),

            // Static link
            "-static".to_string()
        ],
        executables: true,
        relocation_model: "static".to_string(),
        disable_redzone: true,
        eliminate_frame_pointer: false,
        target_family: Some("redox".to_string()),
        linker_is_gnu: true,
        no_default_libraries: true,
        lib_allocation_crate: "alloc_system".to_string(),
        exe_allocation_crate: "alloc_system".to_string(),
        has_elf_tls: true,
        panic_strategy: PanicStrategy::Abort,
        .. Default::default()
    }
}
<commit_msg>In order to successfully build, go back to ralloc<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use PanicStrategy;
use target::TargetOptions;
use std::default::Default;

pub fn opts() -> TargetOptions {
    TargetOptions {
        pre_link_args: vec![
            // We want to be able to strip as much executable code as possible
            // from the linker command line, and this flag indicates to the
            // linker that it can avoid linking in dynamic libraries that don't
            // actually satisfy any symbols up to that point (as with many other
            // resolutions the linker does). This option only applies to all
            // following libraries so we're sure to pass it as one of the first
            // arguments.
            "-Wl,--as-needed".to_string(),

            // Always enable NX protection when it is available
            "-Wl,-z,noexecstack".to_string(),

            // Do not link libc
            "-nostdlib".to_string(),

            // Static link
            "-static".to_string()
        ],
        executables: true,
        relocation_model: "static".to_string(),
        disable_redzone: true,
        eliminate_frame_pointer: false,
        target_family: Some("redox".to_string()),
        linker_is_gnu: true,
        no_default_libraries: true,
        lib_allocation_crate: "ralloc".to_string(),
        exe_allocation_crate: "ralloc".to_string(),
        has_elf_tls: true,
        panic_strategy: PanicStrategy::Abort,
        .. Default::default()
    }
}
<|endoftext|>


<commit_before>use core::cmp::PartialEq;
use core::ops::{BitAnd, BitOr, Not};
use core::marker::PhantomData;

pub trait ReadWrite<T>
{
    fn read(&self) -> T;
    fn write(&self, value: T);
}

/// Generic PIO
#[derive(Copy, Clone)]
pub struct Pio<T> {
    port: u16,
    value: PhantomData<T>,
}

/// Read/Write for byte PIO
impl ReadWrite<u8> for Pio<u8> {
    /// Read
    fn read(&self) -> u8 {
        let value: u8;
        unsafe {
            asm!("in $0, $1" : "={al}"(value) : "{dx}"(self.port) : "memory" : "intel", "volatile");
        }
        return value;
    }

    /// Write
    fn write(&self, value: u8) {
        unsafe {
            asm!("out $1, $0" : : "{al}"(value), "{dx}"(self.port) : "memory" : "intel", "volatile");
        }
    }
}

/// Read/Write for word PIO
impl ReadWrite<u16> for Pio<u16> {
    /// Read
    fn read(&self) -> u16 {
        let value: u16;
        unsafe {
            asm!("in $0, $1" : "={ax}"(value) : "{dx}"(self.port) : "memory" : "intel", "volatile");
        }
        return value;
    }

    /// Write
    fn write(&self, value: u16) {
        unsafe {
            asm!("out $1, $0" : : "{ax}"(value), "{dx}"(self.port) : "memory" : "intel", "volatile");
        }
    }
}

/// Read/Write for doubleword PIO
impl ReadWrite<u32> for Pio<u32> {
    /// Read
    fn read(&self) -> u32 {
        let value: u32;
        unsafe {
            asm!("in $0, $1" : "={eax}"(value) : "{dx}"(self.port) : "memory" : "intel", "volatile");
        }
        return value;
    }

    /// Write
    fn write(&self, value: u32) {
        unsafe {
            asm!("out $1, $0" : : "{eax}"(value), "{dx}"(self.port) : "memory" : "intel", "volatile");
        }
    }
}

impl<T> Pio<T>
    where Pio<T>: ReadWrite<T>,
          T: BitAnd<Output = T> + BitOr<Output = T> + PartialEq<T> + Not<Output = T> + Copy
{
    /// Create a PIO from a given port
    pub fn new(port: u16) -> Self {
        return Pio::<T> {
            port: port,
            value: PhantomData,
        };
    }

    pub fn readf(&self, flags: T) -> bool {
        (self.read() & flags) as T == flags
    }

    pub fn writef(&mut self, flags: T, value: bool) {
        let tmp: T = match value {
            true => self.read() | flags,
            false => self.read() & !flags,
        };
        self.write(tmp);
    }
}

// TODO: Remove
pub unsafe fn inb(port: u16) -> u8 {
    Pio::<u8>::new(port).read()
}

// TODO: Remove
pub unsafe fn outb(port: u16, value: u8) {
    Pio::<u8>::new(port).write(value);
}

// TODO: Remove
pub unsafe fn inw(port: u16) -> u16 {
    Pio::<u16>::new(port).read()
}

// TODO: Remove
pub unsafe fn outw(port: u16, value: u16) {
    Pio::<u16>::new(port).write(value);
}

// TODO: Remove
pub unsafe fn ind(port: u16) -> u32 {
    Pio::<u32>::new(port).read()
}

// TODO: Remove
pub unsafe fn outd(port: u16, value: u32) {
    Pio::<u32>::new(port).write(value);
}
<commit_msg>pio: rust style cleanup<commit_after>use core::cmp::PartialEq;
use core::ops::{BitAnd, BitOr, Not};
use core::marker::PhantomData;

pub trait ReadWrite<T>
{
    fn read(&self) -> T;
    fn write(&self, value: T);
}

/// Generic PIO
#[derive(Copy, Clone)]
pub struct Pio<T> {
    port: u16,
    value: PhantomData<T>,
}

/// Read/Write for byte PIO
impl ReadWrite<u8> for Pio<u8> {
    /// Read
    fn read(&self) -> u8 {
        let value: u8;
        unsafe {
            asm!("in $0, $1" : "={al}"(value) : "{dx}"(self.port) : "memory" : "intel", "volatile");
        }
        value
    }

    /// Write
    fn write(&self, value: u8) {
        unsafe {
            asm!("out $1, $0" : : "{al}"(value), "{dx}"(self.port) : "memory" : "intel", "volatile");
        }
    }
}

/// Read/Write for word PIO
impl ReadWrite<u16> for Pio<u16> {
    /// Read
    fn read(&self) -> u16 {
        let value: u16;
        unsafe {
            asm!("in $0, $1" : "={ax}"(value) : "{dx}"(self.port) : "memory" : "intel", "volatile");
        }
        value
    }

    /// Write
    fn write(&self, value: u16) {
        unsafe {
            asm!("out $1, $0" : : "{ax}"(value), "{dx}"(self.port) : "memory" : "intel", "volatile");
        }
    }
}

/// Read/Write for doubleword PIO
impl ReadWrite<u32> for Pio<u32> {
    /// Read
    fn read(&self) -> u32 {
        let value: u32;
        unsafe {
            asm!("in $0, $1" : "={eax}"(value) : "{dx}"(self.port) : "memory" : "intel", "volatile");
        }
        value
    }

    /// Write
    fn write(&self, value: u32) {
        unsafe {
            asm!("out $1, $0" : : "{eax}"(value), "{dx}"(self.port) : "memory" : "intel", "volatile");
        }
    }
}

impl<T> Pio<T>
    where Pio<T>: ReadWrite<T>,
          T: BitAnd<Output = T> + BitOr<Output = T> + PartialEq<T> + Not<Output = T> + Copy
{
    /// Create a PIO from a given port
    pub fn new(port: u16) -> Self {
        Pio::<T> {
            port: port,
            value: PhantomData,
        }
    }

    pub fn readf(&self, flags: T) -> bool {
        (self.read() & flags) as T == flags
    }

    pub fn writef(&mut self, flags: T, value: bool) {
        let tmp: T = match value {
            true => self.read() | flags,
            false => self.read() & !flags,
        };
        self.write(tmp);
    }
}

// TODO: Remove
pub unsafe fn inb(port: u16) -> u8 {
    Pio::<u8>::new(port).read()
}

// TODO: Remove
pub unsafe fn outb(port: u16, value: u8) {
    Pio::<u8>::new(port).write(value);
}

// TODO: Remove
pub unsafe fn inw(port: u16) -> u16 {
    Pio::<u16>::new(port).read()
}

// TODO: Remove
pub unsafe fn outw(port: u16, value: u16) {
    Pio::<u16>::new(port).write(value);
}

// TODO: Remove
pub unsafe fn ind(port: u16) -> u32 {
    Pio::<u32>::new(port).read()
}

// TODO: Remove
pub unsafe fn outd(port: u16, value: u32) {
    Pio::<u32>::new(port).write(value);
}
<|endoftext|>


<commit_before>//! Array-based data structures using densely numbered entity references as mapping keys.
//!
//! This crate defines a number of data structures based on arrays. The arrays are not indexed by
//! `usize` as usual, but by *entity references* which are integers wrapped in new-types. This has
//! a couple advantages:
//!
//! - Improved type safety. The various map and set types accept a specific key type, so there is
//!   no confusion about the meaning of an array index, as there is with plain arrays.
//! - Smaller indexes. The normal `usize` index is often 64 bits which is way too large for most
//!   purposes. The entity reference types can be smaller, allowing for more compact data
//!   structures.
//!
//! The `EntityRef` trait should be implemented by types to be used as indexed. The `entity_impl!`
//! macro provides convenient defaults for types wrapping `u32` which is common.
//!
//! - [`PrimaryMap`](struct.PrimaryMap.html) is used to keep track of a vector of entities,
//!   assigning a unique entity reference to each.
//! - [`SecondaryMap`](struct.SecondaryMap.html) is used to associate secondary information to an entity.
//!   The map is implemented as a simple vector, so it does not keep track of which entities have
//!   been inserted. Instead, any unknown entities map to the default value.
//! - [`SparseMap`](struct.SparseMap.html) is used to associate secondary information to a small
//!   number of entities. It tracks accurately which entities have been inserted. This is a
//!   specialized data structure which can use a lot of memory, so read the documentation before
//!   using it.
//! - [`EntitySet`](struct.EntitySet.html) is used to represent a secondary set of entities.
//!   The set is implemented as a simple vector, so it does not keep track of which entities have
//!   been inserted into the primary map. Instead, any unknown entities are not in the set.
//! - [`EntityList`](struct.EntityList.html) is a compact representation of lists of entity
//!   references allocated from an associated memory pool. It has a much smaller footprint than
//!   `Vec`.

#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)]
#![warn(unused_import_braces)]
#![cfg_attr(feature = "std", deny(unstable_features))]
#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))]
#![cfg_attr(
    feature = "cargo-clippy",
    allow(new_without_default, new_without_default_derive)
)]
#![cfg_attr(
    feature = "cargo-clippy",
    warn(
        clippy::float_arithmetic,
        clippy::mut_mut,
        clippy::nonminimal_bool,
        clippy::option_map_unwrap_or,
        clippy::option_map_unwrap_or_else,
        clippy::print_stdout,
        clippy::unicode_not_nfc,
        clippy::use_self
    )
)]
// Turns on no_std and alloc features if std is not available.
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(not(feature = "std"), feature(alloc))]

/// This replaces `std` in builds with `core`.
#[cfg(not(feature = "std"))]
mod std {
    extern crate alloc;
    pub use self::alloc::{boxed, string, vec};
    pub use core::*;
}

// Re-export core so that the macros works with both std and no_std crates
#[doc(hidden)]
pub extern crate core as __core;

/// A type wrapping a small integer index should implement `EntityRef` so it can be used as the key
/// of an `SecondaryMap` or `SparseMap`.
pub trait EntityRef: Copy + Eq {
    /// Create a new entity reference from a small integer.
    /// This should crash if the requested index is not representable.
    fn new(usize) -> Self;

    /// Get the index that was used to create this entity reference.
    fn index(self) -> usize;
}

/// Macro which provides the common implementation of a 32-bit entity reference.
#[macro_export]
macro_rules! entity_impl {
    // Basic traits.
    ($entity:ident) => {
        impl $crate::EntityRef for $entity {
            fn new(index: usize) -> Self {
                debug_assert!(index < ($crate::__core::u32::MAX as usize));
                $entity(index as u32)
            }

            fn index(self) -> usize {
                self.0 as usize
            }
        }

        impl $crate::packed_option::ReservedValue for $entity {
            fn reserved_value() -> $entity {
                $entity($crate::__core::u32::MAX)
            }
        }

        impl $entity {
            /// Return the underlying index value as a `u32`.
            #[allow(dead_code)]
            pub fn as_u32(self) -> u32 {
                self.0
            }
        }
    };

    // Include basic `Display` impl using the given display prefix.
    // Display an `Ebb` reference as "ebb12".
    ($entity:ident, $display_prefix:expr) => {
        entity_impl!($entity);

        impl $crate::__core::fmt::Display for $entity {
            fn fmt(&self, f: &mut $crate::__core::fmt::Formatter) -> $crate::__core::fmt::Result {
                write!(f, concat!($display_prefix, "{}"), self.0)
            }
        }

        impl $crate::__core::fmt::Debug for $entity {
            fn fmt(&self, f: &mut $crate::__core::fmt::Formatter) -> $crate::__core::fmt::Result {
                (self as &$crate::__core::fmt::Display).fmt(f)
            }
        }
    };
}

pub mod packed_option;

mod boxed_slice;
mod iter;
mod keys;
mod list;
mod map;
mod primary;
mod set;
mod sparse;

pub use self::boxed_slice::BoxedSlice;
pub use self::iter::{Iter, IterMut};
pub use self::keys::Keys;
pub use self::list::{EntityList, ListPool};
pub use self::map::SecondaryMap;
pub use self::primary::PrimaryMap;
pub use self::set::EntitySet;
pub use self::sparse::{SparseMap, SparseMapValue, SparseSet};
<commit_msg>Add a from_u32 function to EntityRef.<commit_after>//! Array-based data structures using densely numbered entity references as mapping keys.
//!
//! This crate defines a number of data structures based on arrays. The arrays are not indexed by
//! `usize` as usual, but by *entity references* which are integers wrapped in new-types. This has
//! a couple advantages:
//!
//! - Improved type safety. The various map and set types accept a specific key type, so there is
//!   no confusion about the meaning of an array index, as there is with plain arrays.
//! - Smaller indexes. The normal `usize` index is often 64 bits which is way too large for most
//!   purposes. The entity reference types can be smaller, allowing for more compact data
//!   structures.
//!
//! The `EntityRef` trait should be implemented by types to be used as indexed. The `entity_impl!`
//! macro provides convenient defaults for types wrapping `u32` which is common.
//!
//! - [`PrimaryMap`](struct.PrimaryMap.html) is used to keep track of a vector of entities,
//!   assigning a unique entity reference to each.
//! - [`SecondaryMap`](struct.SecondaryMap.html) is used to associate secondary information to an entity.
//!   The map is implemented as a simple vector, so it does not keep track of which entities have
//!   been inserted. Instead, any unknown entities map to the default value.
//! - [`SparseMap`](struct.SparseMap.html) is used to associate secondary information to a small
//!   number of entities. It tracks accurately which entities have been inserted. This is a
//!   specialized data structure which can use a lot of memory, so read the documentation before
//!   using it.
//! - [`EntitySet`](struct.EntitySet.html) is used to represent a secondary set of entities.
//!   The set is implemented as a simple vector, so it does not keep track of which entities have
//!   been inserted into the primary map. Instead, any unknown entities are not in the set.
//! - [`EntityList`](struct.EntityList.html) is a compact representation of lists of entity
//!   references allocated from an associated memory pool. It has a much smaller footprint than
//!   `Vec`.

#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)]
#![warn(unused_import_braces)]
#![cfg_attr(feature = "std", deny(unstable_features))]
#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))]
#![cfg_attr(
    feature = "cargo-clippy",
    allow(new_without_default, new_without_default_derive)
)]
#![cfg_attr(
    feature = "cargo-clippy",
    warn(
        clippy::float_arithmetic,
        clippy::mut_mut,
        clippy::nonminimal_bool,
        clippy::option_map_unwrap_or,
        clippy::option_map_unwrap_or_else,
        clippy::print_stdout,
        clippy::unicode_not_nfc,
        clippy::use_self
    )
)]
// Turns on no_std and alloc features if std is not available.
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(not(feature = "std"), feature(alloc))]

/// This replaces `std` in builds with `core`.
#[cfg(not(feature = "std"))]
mod std {
    extern crate alloc;
    pub use self::alloc::{boxed, string, vec};
    pub use core::*;
}

// Re-export core so that the macros works with both std and no_std crates
#[doc(hidden)]
pub extern crate core as __core;

/// A type wrapping a small integer index should implement `EntityRef` so it can be used as the key
/// of an `SecondaryMap` or `SparseMap`.
pub trait EntityRef: Copy + Eq {
    /// Create a new entity reference from a small integer.
    /// This should crash if the requested index is not representable.
    fn new(usize) -> Self;

    /// Get the index that was used to create this entity reference.
    fn index(self) -> usize;
}

/// Macro which provides the common implementation of a 32-bit entity reference.
#[macro_export]
macro_rules! entity_impl {
    // Basic traits.
    ($entity:ident) => {
        impl $crate::EntityRef for $entity {
            fn new(index: usize) -> Self {
                debug_assert!(index < ($crate::__core::u32::MAX as usize));
                $entity(index as u32)
            }

            fn index(self) -> usize {
                self.0 as usize
            }
        }

        impl $crate::packed_option::ReservedValue for $entity {
            fn reserved_value() -> $entity {
                $entity($crate::__core::u32::MAX)
            }
        }

        impl $entity {
            /// Return the underlying index value as a `u32`.
            #[allow(dead_code)]
            pub fn from_u32(x: u32) -> Self {
                debug_assert!(x < $crate::__core::u32::MAX);
                $entity(x)
            }

            /// Return the underlying index value as a `u32`.
            #[allow(dead_code)]
            pub fn as_u32(self) -> u32 {
                self.0
            }
        }
    };

    // Include basic `Display` impl using the given display prefix.
    // Display an `Ebb` reference as "ebb12".
    ($entity:ident, $display_prefix:expr) => {
        entity_impl!($entity);

        impl $crate::__core::fmt::Display for $entity {
            fn fmt(&self, f: &mut $crate::__core::fmt::Formatter) -> $crate::__core::fmt::Result {
                write!(f, concat!($display_prefix, "{}"), self.0)
            }
        }

        impl $crate::__core::fmt::Debug for $entity {
            fn fmt(&self, f: &mut $crate::__core::fmt::Formatter) -> $crate::__core::fmt::Result {
                (self as &$crate::__core::fmt::Display).fmt(f)
            }
        }
    };
}

pub mod packed_option;

mod boxed_slice;
mod iter;
mod keys;
mod list;
mod map;
mod primary;
mod set;
mod sparse;

pub use self::boxed_slice::BoxedSlice;
pub use self::iter::{Iter, IterMut};
pub use self::keys::Keys;
pub use self::list::{EntityList, ListPool};
pub use self::map::SecondaryMap;
pub use self::primary::PrimaryMap;
pub use self::set::EntitySet;
pub use self::sparse::{SparseMap, SparseMapValue, SparseSet};
<|endoftext|>