<commit_before>use decoder::{Decoder, MAX_COMPONENTS};
use error::{Error, Result, UnsupportedFeature};
use huffman::{fill_default_mjpeg_tables, HuffmanDecoder, HuffmanTable};
use marker::Marker;
use parser::Predictor;
use parser::{
    parse_app, parse_com, parse_dht, parse_dqt, parse_dri, parse_sof, parse_sos,
    AdobeColorTransform, AppData, CodingProcess, Component, Dimensions, EntropyCoding, FrameInfo,
    IccChunk, ScanInfo,
};
use std::io::Read;

impl<R: Read> Decoder<R> {
    /// decode_scan_lossless
    pub fn decode_scan_lossless(
        &mut self,
        frame: &FrameInfo,
        scan: &ScanInfo,
    ) -> Result<(Option<Marker>, Option<Vec<Vec<u16>>>)> {
        assert!(scan.component_indices.len() <= MAX_COMPONENTS);
        let mut results = vec![Vec::new(); MAX_COMPONENTS];

        let components: Vec<Component> = scan
            .component_indices
            .iter()
            .map(|&i| frame.components[i].clone())
            .collect();

        // Verify that all required huffman tables has been set.
        if scan
            .dc_table_indices
            .iter()
            .any(|&i| self.dc_huffman_tables[i].is_none())
        {
            return Err(Error::Format(
                "scan makes use of unset dc huffman table".to_owned(),
            ));
        }

        let mut huffman = HuffmanDecoder::new();
        let reader = &mut self.reader;
        let mut ra = 0;
        let mut rb = 0;
        let mut rc = 0;
        for mcu_y in 0..frame.image_size.height as usize {
            for mcu_x in 0..frame.image_size.width as usize {
                for (i, component) in components.iter().enumerate() {
                    let dc_table = self.dc_huffman_tables[scan.dc_table_indices[i]]
                        .as_ref()
                        .unwrap();
                    let value = huffman.decode(reader, dc_table)?;
                    let diff = match value {
                        0 => 0,
                        1..=15 => huffman.receive_extend(reader, value)?,
                        // 16 => 32768,
                        _ => {
                            // Section F.1.2.1.1
                            // Table F.1
                            return Err(Error::Format(
                                "invalid DC difference magnitude category".to_owned(),
                            ));
                        }
                    };
                    if mcu_y > 0 {
                        rb = results[i][(mcu_y - 1) * frame.image_size.width as usize + mcu_x];
                        if mcu_x > 0 {
                            rc = results[i]
                                [(mcu_y - 1) * frame.image_size.width as usize + (mcu_x - 1)];
                        }
                    }
                    let prediction = reverse_predict(
                        diff,
                        ra,
                        rb,
                        rc,
                        scan.predictor_selection,
                        scan.point_transform,
                        frame.precision,
                        mcu_x,
                        mcu_y,
                        false,
                    );
                    results[i].push(prediction << scan.point_transform);
                    ra = prediction;
                }
            }
        }

        let mut marker = huffman.take_marker(&mut self.reader)?;
        while let Some(Marker::RST(_)) = marker {
            marker = self.read_marker().ok();
        }

        println!("image size : {:?}", frame.image_size);
        println!("results size : {:?}", results[0].len());
        println!("ouput size : {:?}", frame.output_size);
        println!("point transform : {:?}", scan.point_transform);
        println!("predictor : {:?}", scan.predictor_selection);
        Ok((marker, Some(results)))
    }
}

/// H.1.2.1
fn reverse_predict(
    diff: i16,
    ra: u16,
    rb: u16,
    rc: u16,
    predictor: Predictor,
    point_transform: u8,
    input_precision: u8,
    ix: usize,
    iy: usize,
    restart: bool,
) -> u16 {
    let prediction = if (ix == 0 && iy == 0) || restart {
        // start of first line or restart
        0 //1 << (input_precision - point_transform - 1)
    } else if iy == 0 {
        // rest of first line
        ra
    } else if ix == 0 {
        // start of other line
        rb
    } else {
        // use predictor Table H.1
        match predictor {
            Predictor::NoPrediction => 0,
            Predictor::Ra => ra,
            Predictor::Rb => rb,
            Predictor::Rc => rc,
            Predictor::RaRbRc1 => ra + rb - rc,
            Predictor::RaRbRc2 => ra + (rb - rc) >> 1,
            Predictor::RaRbRc3 => ra + (rc - rb) >> 1,
            Predictor::RaRb => (ra + rb) / 2,
        }
    };
    diff.wrapping_add(prediction as i16) as u16
}
<commit_msg>tests passing<commit_after>use decoder::{Decoder, MAX_COMPONENTS};
use error::{Error, Result, UnsupportedFeature};
use huffman::{fill_default_mjpeg_tables, HuffmanDecoder, HuffmanTable};
use marker::Marker;
use parser::Predictor;
use parser::{
    parse_app, parse_com, parse_dht, parse_dqt, parse_dri, parse_sof, parse_sos,
    AdobeColorTransform, AppData, CodingProcess, Component, Dimensions, EntropyCoding, FrameInfo,
    IccChunk, ScanInfo,
};
use std::io::Read;

impl<R: Read> Decoder<R> {
    /// decode_scan_lossless
    pub fn decode_scan_lossless(
        &mut self,
        frame: &FrameInfo,
        scan: &ScanInfo,
    ) -> Result<(Option<Marker>, Option<Vec<Vec<u16>>>)> {
        assert!(scan.component_indices.len() <= MAX_COMPONENTS);
        let mut results = vec![Vec::new(); MAX_COMPONENTS];

        let components: Vec<Component> = scan
            .component_indices
            .iter()
            .map(|&i| frame.components[i].clone())
            .collect();

        // Verify that all required huffman tables has been set.
        if scan
            .dc_table_indices
            .iter()
            .any(|&i| self.dc_huffman_tables[i].is_none())
        {
            return Err(Error::Format(
                "scan makes use of unset dc huffman table".to_owned(),
            ));
        }

        let mut huffman = HuffmanDecoder::new();
        let reader = &mut self.reader;
        let mut ra = 0;
        let mut rb = 0;
        let mut rc = 0;
        for mcu_y in 0..frame.image_size.height as usize {
            for mcu_x in 0..frame.image_size.width as usize {
                for (i, component) in components.iter().enumerate() {
                    let dc_table = self.dc_huffman_tables[scan.dc_table_indices[i]]
                        .as_ref()
                        .unwrap();
                    let value = huffman.decode(reader, dc_table)?;
                    let diff = match value {
                        0 => 0,
                        1..=15 => huffman.receive_extend(reader, value)?,
                        16 => -32768,
                        _ => {
                            // Section F.1.2.1.1
                            // Table F.1
                            return Err(Error::Format(
                                "invalid DC difference magnitude category".to_owned(),
                            ));
                        }
                    };
                    if mcu_y > 0 {
                        rb = results[i][(mcu_y - 1) * frame.image_size.width as usize + mcu_x];
                        if mcu_x > 0 {
                            rc = results[i]
                                [(mcu_y - 1) * frame.image_size.width as usize + (mcu_x - 1)];
                        }
                    }
                    let prediction = reverse_predict(
                        diff,
                        ra,
                        rb,
                        rc,
                        scan.predictor_selection,
                        scan.point_transform,
                        frame.precision,
                        mcu_x,
                        mcu_y,
                        false,
                    );
                    results[i].push(prediction << scan.point_transform);
                    ra = prediction;
                }
            }
        }

        let mut marker = huffman.take_marker(&mut self.reader)?;
        while let Some(Marker::RST(_)) = marker {
            marker = self.read_marker().ok();
        }

        println!("image size : {:?}", frame.image_size);
        println!("results size : {:?}", results[0].len());
        println!("ouput size : {:?}", frame.output_size);
        println!("point transform : {:?}", scan.point_transform);
        println!("predictor : {:?}", scan.predictor_selection);
        Ok((marker, Some(results)))
    }
}

/// H.1.2.1
fn reverse_predict(
    diff: i16,
    ra: u16,
    rb: u16,
    rc: u16,
    predictor: Predictor,
    point_transform: u8,
    input_precision: u8,
    ix: usize,
    iy: usize,
    restart: bool,
) -> u16 {
    let prediction = if ix == 0 && iy == 0 {
        // start of first line
        1 << (input_precision - point_transform - 1)
    } else if restart {
        1 << (input_precision - point_transform - 1)
    } else if iy == 0 {
        // rest of first line
        ra
    } else if ix == 0 {
        // start of other line
        rb
    } else {
        // use predictor Table H.1
        match predictor {
            Predictor::NoPrediction => 0,
            Predictor::Ra => ra,
            Predictor::Rb => rb,
            Predictor::Rc => rc,
            Predictor::RaRbRc1 => ra + rb - rc,
            Predictor::RaRbRc2 => ra + (rb - rc) >> 1,
            Predictor::RaRbRc3 => ra + (rc - rb) >> 1,
            Predictor::RaRb => (ra + rb) / 2,
        }
    };
    diff.wrapping_add(prediction as i16) as u16
}
<|endoftext|>


<commit_before>use terrain::gfx_macros::{TileMapData};
use data::{load_map_file, get_map_tile};
use game::constants::{MAP_FILE_PATH, TILEMAP_BUF_LENGTH, TILES_PCS_W, TILES_PCS_H};

#[derive(Debug)]
pub struct Terrain {
  pub tiles: Vec<TileMapData>
}

fn calc_index(xpos: usize, ypos: usize) -> usize {
  (ypos * TILES_PCS_W) + xpos
}

fn populate_tilemap(mut tiles: Vec<TileMapData>) -> Vec<TileMapData> {
  let map = load_map_file(MAP_FILE_PATH);
  for ypos in 0..TILES_PCS_H {
    for xpos in 0..TILES_PCS_W {
      let map_val = get_map_tile(&map, 0, xpos as usize, ypos as usize);
      let tex_x = map_val % (TILES_PCS_W as u32);
      let tex_y = (map_val - tex_x) / (TILES_PCS_W as u32);
      let idx = calc_index(xpos, ypos);
      tiles[idx] = TileMapData::new([(tex_x-1) as f32, tex_y as f32, 0.0, 0.0]);
    }
  }
  tiles
}

pub fn generate() -> Terrain {
  let mut charmap_data = Vec::with_capacity(TILEMAP_BUF_LENGTH);

  for _ in 0..TILEMAP_BUF_LENGTH {
    charmap_data.push(TileMapData::new_empty());
  }

  Terrain {
    tiles: populate_tilemap(charmap_data)
  }
}
<commit_msg>Fix tilemapping function<commit_after>use terrain::gfx_macros::{TileMapData};
use data::{load_map_file, get_map_tile};
use game::constants::{MAP_FILE_PATH, TILEMAP_BUF_LENGTH, TILES_PCS_W, TILES_PCS_H};

#[derive(Debug)]
pub struct Terrain {
  pub tiles: Vec<TileMapData>
}

fn calc_index(xpos: usize, ypos: usize) -> usize {
  (ypos * TILES_PCS_W) + xpos
}

fn populate_tilemap(mut tiles: Vec<TileMapData>) -> Vec<TileMapData> {
  let map = load_map_file(MAP_FILE_PATH);
  for ypos in 0..TILES_PCS_H {
    for xpos in 0..TILES_PCS_W {
      let map_val = get_map_tile(&map, 0, xpos as usize, ypos as usize);
      let tex_x = map_val % 32;
      let tex_y = (map_val - tex_x) / 32;
      let idx = calc_index(xpos, ypos);
      tiles[idx] = TileMapData::new([(tex_x-1) as f32, tex_y as f32, 0.0, 0.0]);
    }
  }
  tiles
}

pub fn generate() -> Terrain {
  let mut charmap_data = Vec::with_capacity(TILEMAP_BUF_LENGTH);

  for _ in 0..TILEMAP_BUF_LENGTH {
    charmap_data.push(TileMapData::new_empty());
  }

  Terrain {
    tiles: populate_tilemap(charmap_data)
  }
}
<|endoftext|>


<commit_before>#![crate_id(name="kill", vers="0.0.1", author="Maciej Dziardziel")]
#![feature(macro_rules)]
#![feature(phase)]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Maciej Dziardziel <fiedzia@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE file
 * that was distributed with this source code.
 */

extern crate getopts;
extern crate collections;
extern crate serialize;

#[phase(syntax, link)] extern crate log;

use std::os;
use std::from_str::from_str;
use std::io::process::Process;

use getopts::{
    getopts,
    optopt,
    optflag,
    optflagopt,
    usage,
};

use signals::{
    ALL_SIGNALS,
    DEFAULT_SIGNAL,
};

mod signals;

#[path = "../common/util.rs"]
mod util;

static NAME: &'static str = "kill";
static VERSION:  &'static str = "0.0.1";

static EXIT_OK:  i32 = 0;
static EXIT_ERR: i32 = 1;

pub enum Mode {
    Kill,
    Table,
    List,
    Help,
    Version,
}

fn main() {
    let args = os::args();

    let opts = ~[
        optflag("h", "help", "display this help and exit"),
        optflag("V", "version", "output version information and exit"),
        optopt("s", "signal", "specify the <signal> to be sent", "SIGNAL"),
        optflagopt("l", "list", "list all signal names, or convert one to a name", "LIST"),
        optflag("L", "table", "list all signal names in a nice table"),
    ];

    let usage = usage("[options] <pid> [...]", opts);

    let matches = match getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(e) => {
            let msg = format!("{}\n{}", e.to_err_msg(),  get_help_text(NAME, usage));
            show_error!(EXIT_ERR, "{}", msg);
            return
        },
    };

    let mode = if matches.opt_present("version") {
        Version
    } else if matches.opt_present("help") {
        Help
    } else if matches.opt_present("table") {
        Table
    } else if matches.opt_present("list") {
        List
    } else {
        Kill
    };

    match mode {
        Kill    => kill(matches.opt_str("signal").unwrap_or(~"9"), matches.free),
        Table   => table(),
        List    => list(matches.opt_str("list")),
        Help    => help(NAME, usage),
        Version => version(),
    }
}

fn version() {
    println!("{} {}", NAME, VERSION);
}

fn table() {

    let mut name_width = 0;
    /* Compute the maximum width of a signal name. */
    for s in ALL_SIGNALS.iter() {
        if s.name.len() > name_width {
            name_width = s.name.len()
        }
    }

    for (idx, signal) in ALL_SIGNALS.iter().enumerate() {
        print!("{0: >#2} {1: <#8}", idx+1, signal.name);
        //TODO: obtain max signal width here

        if (idx+1) % 7 == 0 {
            println!("");
        }
    }
}

fn print_signal(signal_name_or_value: ~str) {
    for signal in ALL_SIGNALS.iter() {
        if signal.name == signal_name_or_value  || ("SIG" + signal.name) == signal_name_or_value {
            println!("{}", signal.value)
            exit!(EXIT_OK)
        } else if signal_name_or_value == signal.value.to_str() {
            println!("{}", signal.name);
            exit!(EXIT_OK)
        }
    }
    crash!(EXIT_ERR, "unknown signal name {}", signal_name_or_value)
}

fn print_signals() {
    let mut pos = 0;
    for (idx, signal) in ALL_SIGNALS.iter().enumerate() {
        pos += signal.name.len();
        print!("{}", signal.name);
        if idx > 0 && pos > 73 {
            println!("");
            pos = 0;
        } else {
            pos += 1;
            print!(" ");
        }
    }
}

fn list(arg: Option<~str>) {
    match arg {
      Some(x) => print_signal(x),
      None => print_signals(),
    };
}

fn get_help_text(progname: &str, usage: &str) -> ~str {
    let msg = format!("Usage: \n {0} {1}", progname, usage);
    msg
}

fn help(progname: &str, usage: &str) {
    println!("{}", get_help_text(progname, usage));
}

fn signal_by_name_or_value(signal_name_or_value:~str) -> Option<uint> {
    if signal_name_or_value == ~"0"{
        return Some(0);
    }
    for signal in ALL_SIGNALS.iter() {
        let long_name = "SIG" + signal.name;
        if signal.name == signal_name_or_value  || (signal_name_or_value == signal.value.to_str()) || (long_name == signal_name_or_value) {
            return Some(signal.value);
        }
    }
    return None;
}

fn kill(signalname: ~str, pids: std::vec::Vec<~str>) {
    let optional_signal_value = signal_by_name_or_value(signalname.clone());
    let mut signal_value:uint = DEFAULT_SIGNAL;
    match optional_signal_value {
        Some(x) => signal_value = x,
        None => {
            crash!(EXIT_ERR, "unknown signal name {}", signalname)
        }
    }
    for pid in pids.iter() {
        match from_str::<i32>(*pid) {
            Some(x) => {
                let result = Process::kill(x, signal_value as int);
                match result {
                  Ok(_) => (),
                  Err(_) => ()
                };
            },
            None => {
                crash!(EXIT_ERR, "failed to parse argument {}", signalname)
            },
        };
    }
}
<commit_msg>pass params directly to show_error macro<commit_after>#![crate_id(name="kill", vers="0.0.1", author="Maciej Dziardziel")]
#![feature(macro_rules)]
#![feature(phase)]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Maciej Dziardziel <fiedzia@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE file
 * that was distributed with this source code.
 */

extern crate getopts;
extern crate collections;
extern crate serialize;

#[phase(syntax, link)] extern crate log;

use std::os;
use std::from_str::from_str;
use std::io::process::Process;

use getopts::{
    getopts,
    optopt,
    optflag,
    optflagopt,
    usage,
};

use signals::{
    ALL_SIGNALS,
    DEFAULT_SIGNAL,
};

mod signals;

#[path = "../common/util.rs"]
mod util;

static NAME: &'static str = "kill";
static VERSION:  &'static str = "0.0.1";

static EXIT_OK:  i32 = 0;
static EXIT_ERR: i32 = 1;

pub enum Mode {
    Kill,
    Table,
    List,
    Help,
    Version,
}

fn main() {
    let args = os::args();

    let opts = ~[
        optflag("h", "help", "display this help and exit"),
        optflag("V", "version", "output version information and exit"),
        optopt("s", "signal", "specify the <signal> to be sent", "SIGNAL"),
        optflagopt("l", "list", "list all signal names, or convert one to a name", "LIST"),
        optflag("L", "table", "list all signal names in a nice table"),
    ];

    let usage = usage("[options] <pid> [...]", opts);

    let matches = match getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(e) => {
            show_error!(EXIT_ERR, "{}\n{}", e.to_err_msg(),  get_help_text(NAME, usage));
            return
        },
    };

    let mode = if matches.opt_present("version") {
        Version
    } else if matches.opt_present("help") {
        Help
    } else if matches.opt_present("table") {
        Table
    } else if matches.opt_present("list") {
        List
    } else {
        Kill
    };

    match mode {
        Kill    => kill(matches.opt_str("signal").unwrap_or(~"9"), matches.free),
        Table   => table(),
        List    => list(matches.opt_str("list")),
        Help    => help(NAME, usage),
        Version => version(),
    }
}

fn version() {
    println!("{} {}", NAME, VERSION);
}

fn table() {

    let mut name_width = 0;
    /* Compute the maximum width of a signal name. */
    for s in ALL_SIGNALS.iter() {
        if s.name.len() > name_width {
            name_width = s.name.len()
        }
    }

    for (idx, signal) in ALL_SIGNALS.iter().enumerate() {
        print!("{0: >#2} {1: <#8}", idx+1, signal.name);
        //TODO: obtain max signal width here

        if (idx+1) % 7 == 0 {
            println!("");
        }
    }
}

fn print_signal(signal_name_or_value: ~str) {
    for signal in ALL_SIGNALS.iter() {
        if signal.name == signal_name_or_value  || ("SIG" + signal.name) == signal_name_or_value {
            println!("{}", signal.value)
            exit!(EXIT_OK)
        } else if signal_name_or_value == signal.value.to_str() {
            println!("{}", signal.name);
            exit!(EXIT_OK)
        }
    }
    crash!(EXIT_ERR, "unknown signal name {}", signal_name_or_value)
}

fn print_signals() {
    let mut pos = 0;
    for (idx, signal) in ALL_SIGNALS.iter().enumerate() {
        pos += signal.name.len();
        print!("{}", signal.name);
        if idx > 0 && pos > 73 {
            println!("");
            pos = 0;
        } else {
            pos += 1;
            print!(" ");
        }
    }
}

fn list(arg: Option<~str>) {
    match arg {
      Some(x) => print_signal(x),
      None => print_signals(),
    };
}

fn get_help_text(progname: &str, usage: &str) -> ~str {
    let msg = format!("Usage: \n {0} {1}", progname, usage);
    msg
}

fn help(progname: &str, usage: &str) {
    println!("{}", get_help_text(progname, usage));
}

fn signal_by_name_or_value(signal_name_or_value:~str) -> Option<uint> {
    if signal_name_or_value == ~"0"{
        return Some(0);
    }
    for signal in ALL_SIGNALS.iter() {
        let long_name = "SIG" + signal.name;
        if signal.name == signal_name_or_value  || (signal_name_or_value == signal.value.to_str()) || (long_name == signal_name_or_value) {
            return Some(signal.value);
        }
    }
    return None;
}

fn kill(signalname: ~str, pids: std::vec::Vec<~str>) {
    let optional_signal_value = signal_by_name_or_value(signalname.clone());
    let mut signal_value:uint = DEFAULT_SIGNAL;
    match optional_signal_value {
        Some(x) => signal_value = x,
        None => {
            crash!(EXIT_ERR, "unknown signal name {}", signalname)
        }
    }
    for pid in pids.iter() {
        match from_str::<i32>(*pid) {
            Some(x) => {
                let result = Process::kill(x, signal_value as int);
                match result {
                  Ok(_) => (),
                  Err(_) => ()
                };
            },
            None => {
                crash!(EXIT_ERR, "failed to parse argument {}", signalname)
            },
        };
    }
}
<|endoftext|>


<commit_before>// library
extern crate my_extern_lib;

// modules
mod simple_functions {
    pub fn print_hello_world() {
        println!("Hello, World! (from the simple_functions module)");
     }

    // nested modules
    pub mod simple_math {
        pub fn multiple_two_integers(a: i32, b: i32) -> i32 {
            a * b
        }
    }
}

use simple_functions::simple_math::multiple_two_integers;

fn print_some_msg() {
    println!("Modules: printing from the outer function");
}

mod sample_module {

    pub fn call_sample_module() {
        use second_module::print_some_msg as print_second;
        use self::second_module::print_some_msg as print_second_sample;
        use super::print_some_msg as print_outside;
        print_outside();
        print_second();
        print_some_msg();
        print_second_sample();
    }

    mod second_module {

        pub fn print_some_msg() {
            println!("Modules: printing from the second module inside the sample module");
        }

    }

    fn print_some_msg() {
        println!("Modules: printing from the inside of the sample module");
    }

}

mod second_module {
    pub fn print_some_msg() {
        println!("Modules: printing from the second module");
    }
}

mod modules;

fn main() {

    // formatted output
    println!("Hello, Rust!");
    println!("Integer number = {}", 23);
    println!("Float number = {}", 1.012);
    println!("Repeat printing: {0}, {1}, {1}, {3}, {2}", 2, 1, 44, 9);
    println!("Named arguments: {name}, {age}, {occupation}", age="24", name="Ann", occupation="Designer");
    println!("{:08b} XOR {:08b} = {:08b}", 3i8, 32i8, 3i8 ^ 34i8);
    println!("Floating point number {:?}", 2.910210);
    println!("Hex: {:08X}, {:08x}", 131342112, 131342112);
    // TODO find out why this doesn't work:
    //println!("{0:08X}, {0:08x}", 7661);

    // variables
    let integer = 3i32;
    let floating_point = 2.1137;

    let mut u_integer = 3u32;
    //integer += 1; error: an immutable variable
    u_integer += 1;

    println!("{}, {}, {}", integer, floating_point, u_integer);
    // TODO find out why snake case instead of camel case

    // shadowing
    let first_var = 4;
    {
        let first_var = 51;
        println!("first_var = {}", first_var);
    }
    println!("first_var = {}", first_var);

    // unitialized variables
    let uninit_var;
    //println!("uninit_var = {}", uninit_var); error: use of an init variable
    uninit_var = 231.2;
    println!("already initialized uninit_var = {}", uninit_var);

    // type casting
    let a_integer = 0x40_u8;
    let a_char = a_integer as char;
    println!("char cast from integer {}: {}", a_integer, a_char);

    let a_float = 8.45511;
    println!("integer cast from float {}: {}", a_float, a_float as i32);

    println!("Binary represntation of {}: {:08b}", -1_i8, -1_i8);
    println!("Binary represntation of {}: {:08b}", -2_i8, -2_i8);

    // aliases
    type FloatingPoint32 = f32;
    let a_float_2 : FloatingPoint32 = 3 as f32;
    println!("Type alias: {}, size of var {}", a_float_2, std::mem::size_of_val(&a_float_2));

    // expressions
    let expr = {
        let x = 4.09;
        let y = 1.28;
        println!("x = {}, y = {}", x, y);
        x / y
    };
    println!("expr = {}", expr);

    // if-statement (every if-statement is an expression too, which is really a cool thing)
    let speed = 10;
    let mass = 890;
    let consumption =
        if speed < 0 {
            -1.0
        }
        else if speed == 0 {
            0.8
        }
        else if speed > 0 && speed < 10 {
            18.52
        }
        else if speed >= 10 && speed < 30 {
            let x = mass / speed;
            (x as f32) * 0.05
        }
        else {
            11.71
        };
        println!("Speed = {}, consumption = {}", speed, consumption);

        // loop
        let mut count = 0u32;
        loop {
            println!("loop iteration #{}", count);
            count += 1;
            if count > 9 {
            break;
            }
        }

        count = 0;
        while count < 10 {
            println!("while loop iteration #{}", count);
            count += 1;
        }

        for n in 0u32..10 {
            println!("for loop iteration #{}", n);
        }

        // matching
        let age = 19;
        match age {
            1  => println!("Seems like 1"),
            5  => println!("It's 5"),
            18 => println!("Exactly 18!"),
            _  => println!("I couldn't guess :("),
        }

        match age {
            a if a > 1 && a <= 9  => println!("The age is in range [1,9]"),
            a if a > 9 && a <= 19 => println!("The age is in range [10, 19]"),
            _                     => println!("Nothing, I don't know what range the age is in :("),
        }

        // the previous match is equivalent to the following:
        match age {
            a @ 1...9   => println!("The age is {} and in range [1,9]", a),
            a @ 10...19 => println!("The age is {} and in range [10, 19]", a),
            a           => println!("Nothing, I don't know what range the age {} is in :(", a),
        }

        // if let
        let a_some = Some(0.0008);
        if let Some(i) = a_some {
            println!("a_some is not None, {}", i);
            println!("result {}",  9.0 / i);
        }
        else {
            println!("None");
        }

        // while let
        let mut a_optional = Some(10);

        while let Some(i) = a_optional {
            if i == 20 {
                println!("while let: i equals 20, leave");
                a_optional = None;
            }
            else {
                a_optional = Some(i + 1);
            }
        }

        // functions, finally!
        let first_integer: i32 = -20;
        let second_integer: i32 = 8;
        let result_of_addition = add_two_integers(first_integer, second_integer);
        println!("{} + {} = {}", first_integer, second_integer, result_of_addition);

        simple_functions::print_hello_world();
        let mul_result = simple_functions::simple_math::multiple_two_integers(3, 15);
        println!("Modules: multiplication result = {}", mul_result);

        // this doesn't work.. why?
        println!("Modules: multiplication result 2 = {}", multiple_two_integers(-1, 8));

        // "super" and "self"
        sample_module::call_sample_module();

        // file hierarchy
        {
            let a : i32 = 4;
            let b : i32 = 15;
            println!("modules::math {} + {} = {}", a, b, modules::math::add_two_int(a, b));
        }

        // call external library
        my_extern_lib::run(5);

        // tuples
        let pair = ("key", 4);
        println!("tuple value: ({}, {})", pair.0, pair.1);
        println!("tuple value: {:?}", pair);

        // structs
        let bmw: Car = Car {color: "Blue".to_string(), weight: 940};
        println!("BMW: {} - {}", bmw.color, bmw.weight);

        // tuple structs
        let color_1: RgbColor = RgbColor(123, 33, 81);
        println!("RGB color: {}, {}, {}", color_1.0, color_1.1, color_1.2);

        // unit structs
        let _nil = Nil;

        // a struct with a constructor and getter
        let rabbit = my_extern_lib::Animal::new(2, 4, "The King");
        println!("Rabbit: {}, {}, {}", rabbit.age, rabbit.weight, rabbit.get_secret_info());

        // generics
        {
            struct ThreeValues<T, U, V> {
                first: T,
                second: U,
                third: V,
            }

            let three_values = ThreeValues { first: 4, second: 2.01, third: "hello" };
            println!("Generic data structure: {}, {}, {}", three_values.first, three_values.second, three_values.third);

            // generic function
            fn swap<U, V>(first_value: U, second_value: V) -> (V, U) {
                (second_value, first_value)
            }

            let random_tuple = swap(4, 2);
            println!("Use unused variables: {} {}", random_tuple.0, random_tuple.1);

        }

        // box (heap allocation)
        {

            let toyota: Car = Car {color: "Green".to_string(), weight: 1040,};
            let porche: Box<Car> = Box::new(Car {color: "Black".to_string(), weight: 876, });

            println!("Toyota's size on stack is {}", std::mem::size_of_val(&toyota));
            println!("Boxed porche's size on stack is {}", std::mem::size_of_val(&porche));

            let unboxed_porche: Car = *porche;
            println!("Unboxed porche's size on stack is {}", std::mem::size_of_val(&unboxed_porche));

        }

}

// a C-like struct
struct Car {
    color: String,
    weight: u32,
}

// a tuple struct s
struct RgbColor(i8, i8, i8);

// a unit struct
struct Nil;

fn add_two_integers(a: i32, b: i32) -> i32 {
    a + b
}
<commit_msg>Progress: ownership, mutability<commit_after>// library
extern crate my_extern_lib;

// modules
mod simple_functions {
    pub fn print_hello_world() {
        println!("Hello, World! (from the simple_functions module)");
     }

    // nested modules
    pub mod simple_math {
        pub fn multiple_two_integers(a: i32, b: i32) -> i32 {
            a * b
        }
    }
}

use simple_functions::simple_math::multiple_two_integers;

fn print_some_msg() {
    println!("Modules: printing from the outer function");
}

mod sample_module {

    pub fn call_sample_module() {
        use second_module::print_some_msg as print_second;
        use self::second_module::print_some_msg as print_second_sample;
        use super::print_some_msg as print_outside;
        print_outside();
        print_second();
        print_some_msg();
        print_second_sample();
    }

    mod second_module {

        pub fn print_some_msg() {
            println!("Modules: printing from the second module inside the sample module");
        }

    }

    fn print_some_msg() {
        println!("Modules: printing from the inside of the sample module");
    }

}

mod second_module {
    pub fn print_some_msg() {
        println!("Modules: printing from the second module");
    }
}

mod modules;

fn main() {

    // formatted output
    println!("Hello, Rust!");
    println!("Integer number = {}", 23);
    println!("Float number = {}", 1.012);
    println!("Repeat printing: {0}, {1}, {1}, {3}, {2}", 2, 1, 44, 9);
    println!("Named arguments: {name}, {age}, {occupation}", age="24", name="Ann", occupation="Designer");
    println!("{:08b} XOR {:08b} = {:08b}", 3i8, 32i8, 3i8 ^ 34i8);
    println!("Floating point number {:?}", 2.910210);
    println!("Hex: {:08X}, {:08x}", 131342112, 131342112);
    // TODO find out why this doesn't work:
    //println!("{0:08X}, {0:08x}", 7661);

    // variables
    let integer = 3i32;
    let floating_point = 2.1137;

    let mut u_integer = 3u32;
    //integer += 1; error: an immutable variable
    u_integer += 1;

    println!("{}, {}, {}", integer, floating_point, u_integer);
    // TODO find out why snake case instead of camel case

    // shadowing
    let first_var = 4;
    {
        let first_var = 51;
        println!("first_var = {}", first_var);
    }
    println!("first_var = {}", first_var);

    // unitialized variables
    let uninit_var;
    //println!("uninit_var = {}", uninit_var); error: use of an init variable
    uninit_var = 231.2;
    println!("already initialized uninit_var = {}", uninit_var);

    // type casting
    let a_integer = 0x40_u8;
    let a_char = a_integer as char;
    println!("char cast from integer {}: {}", a_integer, a_char);

    let a_float = 8.45511;
    println!("integer cast from float {}: {}", a_float, a_float as i32);

    println!("Binary represntation of {}: {:08b}", -1_i8, -1_i8);
    println!("Binary represntation of {}: {:08b}", -2_i8, -2_i8);

    // aliases
    type FloatingPoint32 = f32;
    let a_float_2 : FloatingPoint32 = 3 as f32;
    println!("Type alias: {}, size of var {}", a_float_2, std::mem::size_of_val(&a_float_2));

    // expressions
    let expr = {
        let x = 4.09;
        let y = 1.28;
        println!("x = {}, y = {}", x, y);
        x / y
    };
    println!("expr = {}", expr);

    // if-statement (every if-statement is an expression too, which is really a cool thing)
    let speed = 10;
    let mass = 890;
    let consumption =
        if speed < 0 {
            -1.0
        }
        else if speed == 0 {
            0.8
        }
        else if speed > 0 && speed < 10 {
            18.52
        }
        else if speed >= 10 && speed < 30 {
            let x = mass / speed;
            (x as f32) * 0.05
        }
        else {
            11.71
        };
        println!("Speed = {}, consumption = {}", speed, consumption);

        // loop
        let mut count = 0u32;
        loop {
            println!("loop iteration #{}", count);
            count += 1;
            if count > 9 {
            break;
            }
        }

        count = 0;
        while count < 10 {
            println!("while loop iteration #{}", count);
            count += 1;
        }

        for n in 0u32..10 {
            println!("for loop iteration #{}", n);
        }

        // matching
        let age = 19;
        match age {
            1  => println!("Seems like 1"),
            5  => println!("It's 5"),
            18 => println!("Exactly 18!"),
            _  => println!("I couldn't guess :("),
        }

        match age {
            a if a > 1 && a <= 9  => println!("The age is in range [1,9]"),
            a if a > 9 && a <= 19 => println!("The age is in range [10, 19]"),
            _                     => println!("Nothing, I don't know what range the age is in :("),
        }

        // the previous match is equivalent to the following:
        match age {
            a @ 1...9   => println!("The age is {} and in range [1,9]", a),
            a @ 10...19 => println!("The age is {} and in range [10, 19]", a),
            a           => println!("Nothing, I don't know what range the age {} is in :(", a),
        }

        // if let
        let a_some = Some(0.0008);
        if let Some(i) = a_some {
            println!("a_some is not None, {}", i);
            println!("result {}",  9.0 / i);
        }
        else {
            println!("None");
        }

        // while let
        let mut a_optional = Some(10);

        while let Some(i) = a_optional {
            if i == 20 {
                println!("while let: i equals 20, leave");
                a_optional = None;
            }
            else {
                a_optional = Some(i + 1);
            }
        }

        // functions, finally!
        let first_integer: i32 = -20;
        let second_integer: i32 = 8;
        let result_of_addition = add_two_integers(first_integer, second_integer);
        println!("{} + {} = {}", first_integer, second_integer, result_of_addition);

        simple_functions::print_hello_world();
        let mul_result = simple_functions::simple_math::multiple_two_integers(3, 15);
        println!("Modules: multiplication result = {}", mul_result);

        // this doesn't work.. why?
        println!("Modules: multiplication result 2 = {}", multiple_two_integers(-1, 8));

        // "super" and "self"
        sample_module::call_sample_module();

        // file hierarchy
        {
            let a : i32 = 4;
            let b : i32 = 15;
            println!("modules::math {} + {} = {}", a, b, modules::math::add_two_int(a, b));
        }

        // call external library
        my_extern_lib::run(5);

        // tuples
        let pair = ("key", 4);
        println!("tuple value: ({}, {})", pair.0, pair.1);
        println!("tuple value: {:?}", pair);

        // structs
        let bmw: Car = Car {color: "Blue".to_string(), weight: 940};
        println!("BMW: {} - {}", bmw.color, bmw.weight);

        // tuple structs
        let color_1: RgbColor = RgbColor(123, 33, 81);
        println!("RGB color: {}, {}, {}", color_1.0, color_1.1, color_1.2);

        // unit structs
        let _nil = Nil;

        // a struct with a constructor and getter
        let rabbit = my_extern_lib::Animal::new(2, 4, "The King");
        println!("Rabbit: {}, {}, {}", rabbit.age, rabbit.weight, rabbit.get_secret_info());

        // generics
        {
            struct ThreeValues<T, U, V> {
                first: T,
                second: U,
                third: V,
            }

            let three_values = ThreeValues { first: 4, second: 2.01, third: "hello" };
            println!("Generic data structure: {}, {}, {}", three_values.first, three_values.second, three_values.third);

            // generic function
            fn swap<U, V>(first_value: U, second_value: V) -> (V, U) {
                (second_value, first_value)
            }

            let random_tuple = swap(4, 2);
            println!("Use unused variables: {} {}", random_tuple.0, random_tuple.1);

        }

        // box (heap allocation)
        {

            let toyota: Car = Car {color: "Green".to_string(), weight: 1040,};
            let porche: Box<Car> = Box::new(Car {color: "Black".to_string(), weight: 876, });

            println!("Toyota's size on stack is {}", std::mem::size_of_val(&toyota));
            println!("Boxed porche's size on stack is {}", std::mem::size_of_val(&porche));

            let unboxed_porche: Car = *porche;
            println!("Unboxed porche's size on stack is {}", std::mem::size_of_val(&unboxed_porche));

            // ownership
            let bmw : Box<Car> = Box::new(Car {color: "Yellow".to_string(), weight: 1620});
            println!("Boxed BMW at {:p}: {}/{}", &bmw, bmw.color, bmw.weight);
            let moved_bmw: Box<Car> = bmw;
            println!("Moved BMW at {:p}: {}/{}", &moved_bmw, moved_bmw.color, moved_bmw.weight);
            // can't do the following, the ownership has been moved
            // println!("Boxed BMW at {:p}: {}/{}", &bmw, bmw.color, bmw.weight);

            // mutability
            let immutable_car = Box::new(Car {color: "Pink".to_string(), weight: 510});
            // can't do this
            // immutable_car.weight = 403;

            // but we can change mutability
            let mut mutable_car = immutable_car;
            mutable_car.weight = 401;

        }

}

// a C-like struct
struct Car {
    color: String,
    weight: u32,
}

// a tuple struct s
struct RgbColor(i8, i8, i8);

// a unit struct
struct Nil;

fn add_two_integers(a: i32, b: i32) -> i32 {
    a + b
}
<|endoftext|>


<commit_before>
use syntax::ast;
use syntax::ast::{MetaItemKind,NestedMetaItemKind};
use rustc::hir::def_id::DefId;
use rustc::hir::def;
use syntax::codemap::Span;
use rustc::lint::{self, LintContext, LintPass, LateLintPass, LintArray};
use rustc::ty::{self, TyCtxt};
use rustc::hir;

declare_lint!(NOT_TAGGED_SAFE, Warn, "Warn about use of non-tagged methods within tagged function");

#[derive(Default)]
pub struct Pass
{
    visit_stack: Vec<ast::NodeId>,
}

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array!(NOT_TAGGED_SAFE)
    }
}

impl<'a,'b> LateLintPass<'a,'b> for Pass {
    fn check_fn(&mut self, cx: &lint::LateContext, _kind: hir::intravisit::FnKind, _decl: &hir::FnDecl, body: &hir::Body, _: Span, id: ast::NodeId) {
        let attrs = cx.tcx.hir.attrs(id);

        // If this function is tagged with a particular safety, store
        {
            let mut lh = ::database::CACHE.write().unwrap();
            for tag_name in get_tags(attrs, "is_safe")
            {
                let tag = lh.get_tag_or_add(&tag_name.as_str());
                lh.mark(id, tag,  true);
            }
            for tag_name in get_tags(attrs, "not_safe")
            {
                let tag = lh.get_tag_or_add(&tag_name.as_str());
                lh.mark(id, tag,  false);
            }
        }

        // For each required safety, check
        for tag_name in get_tags(attrs, "req_safe")
        {
            let ty_tag = {
                let mut lh = ::database::CACHE.write().unwrap();
                let tag = lh.get_tag_or_add(&tag_name.as_str());
                //let tag = if let Some(v) = lh.get_tag_opt(&tag_name.as_str()) { v } else { error!("Tag {} unknown", ty_name);  continue; };
                lh.mark(id, tag,  true);
                tag
                };

            // Search body for calls to non safe methods
            let mut v = Visitor {
                    pass: self, cx: cx, tag: ty_tag,
                    cb: |span| {
                            cx.span_lint(NOT_TAGGED_SAFE, *span,
                                &format!("Calling {0}-unsafe method from a #[req_safe({0})] method", tag_name)[..]
                                );
                        },
                    };
            debug!("Method {:?} is marked safe '{}'", id, tag_name);
            hir::intravisit::walk_body(&mut v, body);
        }

        // TODO: For all known safeties (that aren't already set) populate.
        // - Requires knowing all safeties (which we don't, ... yet)
    }
}

impl Pass
{
    fn fill_cache_for(&mut self, tcx: &TyCtxt, node_id: ast::NodeId)
    {
        debug!("Filling cache for node {:?}", node_id);
        let attrs = tcx.hir.attrs(node_id);
        let mut lh = ::database::CACHE.write().unwrap();
        for tag_name in Iterator::chain( get_tags(attrs, "is_safe"), get_tags(attrs, "req_safe") )
        {
            debug!("#[is_safe/req_safe] {} - {}", tag_name, node_id);
            let tag = lh.get_tag_or_add(&tag_name.as_str());
            lh.mark(node_id, tag,  true);
        }
        for tag_name in get_tags(attrs, "not_safe")
        {
            debug!("#[not_safe] {} - {}", tag_name, node_id);
            let tag = lh.get_tag_or_add(&tag_name.as_str());
            lh.mark(node_id, tag,  false);
        }
    }

    /// Recursively check that the provided function is either safe or unsafe.
    // Used to avoid excessive annotating
    fn recurse_fcn_body(&mut self, cx: &lint::LateContext, node_id: ast::NodeId, tag: ::database::Tag) -> bool
    {
        // and apply a visitor to all
        match cx.tcx.hir.get(node_id)
        {
        hir::map::NodeItem(i) =>
            match i.node {
            hir::ItemFn(_, _, _, _, _, ref body) => {
                // Enumerate this function's code, recursively checking for a call to an unsafe method
                let mut is_safe = true;
                {
                    let mut v = Visitor {
                        pass: self, cx: cx, tag: tag,
                        cb: |_| { is_safe = false; }
                        };
                    hir::intravisit::walk_body(&mut v, cx.tcx.hir.body(*body));
                }
                is_safe
                },
            ref v @ _ => {
                error!("Node ID {} points to a non-function item {:?}", node_id, v);
                true
                },
            },
        hir::map::NodeImplItem(i) =>
            match i.node {
            hir::ImplItemKind::Method(_, ref body) => {

                let mut is_safe = true;
                {
                    let mut v = Visitor {
                        pass: self, cx: cx, tag: tag,
                        cb: |_| { is_safe = false; }
                        };
                    hir::intravisit::walk_body(&mut v, cx.tcx.hir.body(*body));
                }
                is_safe
                },
            _ => true,
            },
        //hir::map::NodeForeignItem(i) =>
        //    if Self::check_for_marker(tcx, i.id, "tag_safe", name) {
        //        true
        //    }
        //    else if Self::check_for_marker(tcx, i.id, "tag_unsafe", name) {
        //        false
        //    }
        //    else {
        //        unknown_assume
        //    },
        ref v @ _ => {
            error!("Node ID {} points to non-item {:?}", node_id, v);
            true
            }
        }
    }

    /// Locate a #[tag_safe(<name>)] attribute on the passed item
    pub fn method_is_safe(&mut self, cx: &lint::LateContext, id: DefId, tag: ::database::Tag) -> bool
    {
        if ! id.is_local()
        {
            // TODO: Get the entry from the crate cache
            if let Some(v) = ::database::CACHE.read().unwrap().get_extern(&cx.tcx,id.krate, id.index, tag) {
                debug!("{:?} - {} (extern cached)", id, v);
                v
            }
            else {
                debug!("{:?} - {} (extern assumed)", id, true);
                true
            }
        }
        else
        {
            let node_id = cx.tcx.hir.as_local_node_id(id).expect("Unable to locate node");
            let mut local_opt = ::database::CACHE.read().unwrap().get_local(node_id, tag);
            // NOTE: This only fires once (ideally)
            if local_opt.is_none() {
                self.fill_cache_for(&cx.tcx, node_id);
                local_opt = ::database::CACHE.read().unwrap().get_local(node_id, tag);
            }
            if let Some(v) = local_opt {
                debug!("{} - {} (cached)", node_id, v);
                v
            }
            else {
                // If this node is currently being checked, assume it's valid.
                // TODO: This can lead to a false positive being stored.
                if self.visit_stack.iter().position(|x| *x == node_id).is_some() {
                    warn!("Recursion, assuming true");
                    true
                }
                else {
                    self.visit_stack.push(node_id);
                    let rv = self.recurse_fcn_body(cx, node_id, tag);
                    self.visit_stack.pop();

                    debug!("{} - {} (recursed)", node_id, rv);
                    ::database::CACHE.write().unwrap().mark(node_id, tag,  rv);
                    rv
                }
            }
        }
    }
}

struct Visitor<'a, 'tcx: 'a, F: FnMut(&Span) + 'a>
{
    pass: &'a mut Pass,
	cx: &'a lint::LateContext<'a,'tcx>,
    tag: ::database::Tag,
    cb: F,
}

impl<'a, 'tcx: 'a, F: FnMut(&Span)> hir::intravisit::Visitor<'a> for Visitor<'a, 'tcx, F>
{
	fn nested_visit_map<'this>(&'this mut self) -> hir::intravisit::NestedVisitorMap<'this, 'a> {
		hir::intravisit::NestedVisitorMap::None
	}

    // Locate function/method calls in a code block
    fn visit_expr(&mut self, ex: &'a hir::Expr) {
        debug!("visit node - {:?}", ex);
        match ex.node
        {
        // Call expressions - check that it's a path call
        hir::ExprCall(ref fcn, ..) =>
			match fcn.node
			{
			hir::ExprPath(ref qp, ..) =>
				match self.cx.tables.qpath_def(qp, fcn.id)
				{
				def::Def::Fn(did) | def::Def::Method(did) =>
					// Check for a safety tag
					if !self.pass.method_is_safe(self.cx, did, self.tag)
					{
						(self.cb)(&ex.span);
					}
					else {
						debug!("Safe call {:?}", ex);
					},
				_ => {
					info!("Call ExprPath with an unknown Def type");
					},
				},
			_ => {
				info!("Call without ExprPath");
				},
			},

        // Method call expressions - get the relevant method
        hir::ExprMethodCall(ref _id, ref _tys, ref _exprs) =>
			match self.cx.tables.method_map.get( &ty::MethodCall::expr(ex.id) )
			{
			Some(callee) => {
                let id = callee.def_id;

				// Check for a safety tag
				if !self.pass.method_is_safe(self.cx, id, self.tag) {
					(self.cb)(&ex.span);
				}
				},
			None => info!("ExprMethodCall with unknown callee"),
			},

        // Ignore any other type of node
        _ => {},
        }
        hir::intravisit::walk_expr(self, ex);
    }
}

fn get_tags<'a>(meta_items: &'a [ast::Attribute], attr_name: &'a str) -> impl Iterator<Item=::syntax::symbol::Symbol>+'a {
    meta_items.iter()
        .filter(move |attr| attr.name().map(move |n| n == attr_name).unwrap_or(false))
        .flat_map(|attr|
			if let Some(v) = attr.meta() {
				if let MetaItemKind::List(v) = v.node {
					v.into_iter()
				}
				else {
					panic!("");
				}
			}
			else {
				panic!("");
			}
            )
        .filter_map(|tag_meta|
            if let NestedMetaItemKind::MetaItem(ref ptr) = tag_meta.node {
                if let MetaItemKind::Word = ptr.node {
                    Some(ptr.name)
                }
                else {
                    warn!("");
                    None
                }
            }
            else {
                warn!("");
                None
            }
            )
}
<commit_msg>Nightly broke things<commit_after>
use syntax::ast;
use syntax::ast::{MetaItemKind,NestedMetaItemKind};
use rustc::hir::def_id::DefId;
use rustc::hir::def;
use syntax::codemap::Span;
use rustc::lint::{self, LintContext, LintPass, LateLintPass, LintArray};
use rustc::ty::{self, TyCtxt};
use rustc::hir;

declare_lint!(NOT_TAGGED_SAFE, Warn, "Warn about use of non-tagged methods within tagged function");

#[derive(Default)]
pub struct Pass
{
    visit_stack: Vec<ast::NodeId>,
}

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array!(NOT_TAGGED_SAFE)
    }
}

impl<'a,'b> LateLintPass<'a,'b> for Pass {
    fn check_fn(&mut self, cx: &lint::LateContext, _kind: hir::intravisit::FnKind, _decl: &hir::FnDecl, body: &hir::Body, _: Span, id: ast::NodeId) {
        let attrs = cx.tcx.hir.attrs(id);

        // If this function is tagged with a particular safety, store
        {
            let mut lh = ::database::CACHE.write().unwrap();
            for tag_name in get_tags(attrs, "is_safe")
            {
                let tag = lh.get_tag_or_add(&tag_name.as_str());
                lh.mark(id, tag,  true);
            }
            for tag_name in get_tags(attrs, "not_safe")
            {
                let tag = lh.get_tag_or_add(&tag_name.as_str());
                lh.mark(id, tag,  false);
            }
        }

        // For each required safety, check
        for tag_name in get_tags(attrs, "req_safe")
        {
            let ty_tag = {
                let mut lh = ::database::CACHE.write().unwrap();
                let tag = lh.get_tag_or_add(&tag_name.as_str());
                //let tag = if let Some(v) = lh.get_tag_opt(&tag_name.as_str()) { v } else { error!("Tag {} unknown", ty_name);  continue; };
                lh.mark(id, tag,  true);
                tag
                };

            // Search body for calls to non safe methods
            let mut v = Visitor {
                    pass: self, cx: cx, tag: ty_tag,
                    cb: |span| {
                            cx.span_lint(NOT_TAGGED_SAFE, *span,
                                &format!("Calling {0}-unsafe method from a #[req_safe({0})] method", tag_name)[..]
                                );
                        },
                    };
            debug!("Method {:?} is marked safe '{}'", id, tag_name);
            hir::intravisit::walk_body(&mut v, body);
        }

        // TODO: For all known safeties (that aren't already set) populate.
        // - Requires knowing all safeties (which we don't, ... yet)
    }
}

impl Pass
{
    fn fill_cache_for(&mut self, tcx: &TyCtxt, node_id: ast::NodeId)
    {
        debug!("Filling cache for node {:?}", node_id);
        let attrs = tcx.hir.attrs(node_id);
        let mut lh = ::database::CACHE.write().unwrap();
        for tag_name in Iterator::chain( get_tags(attrs, "is_safe"), get_tags(attrs, "req_safe") )
        {
            debug!("#[is_safe/req_safe] {} - {}", tag_name, node_id);
            let tag = lh.get_tag_or_add(&tag_name.as_str());
            lh.mark(node_id, tag,  true);
        }
        for tag_name in get_tags(attrs, "not_safe")
        {
            debug!("#[not_safe] {} - {}", tag_name, node_id);
            let tag = lh.get_tag_or_add(&tag_name.as_str());
            lh.mark(node_id, tag,  false);
        }
    }

    /// Recursively check that the provided function is either safe or unsafe.
    // Used to avoid excessive annotating
    fn recurse_fcn_body(&mut self, cx: &lint::LateContext, node_id: ast::NodeId, tag: ::database::Tag) -> bool
    {
        // and apply a visitor to all
        match cx.tcx.hir.get(node_id)
        {
        hir::map::NodeItem(i) =>
            match i.node {
            hir::ItemFn(_, _, _, _, _, ref body) => {
                // Enumerate this function's code, recursively checking for a call to an unsafe method
                let mut is_safe = true;
                {
                    let mut v = Visitor {
                        pass: self, cx: cx, tag: tag,
                        cb: |_| { is_safe = false; }
                        };
                    hir::intravisit::walk_body(&mut v, cx.tcx.hir.body(*body));
                }
                is_safe
                },
            ref v @ _ => {
                error!("Node ID {} points to a non-function item {:?}", node_id, v);
                true
                },
            },
        hir::map::NodeImplItem(i) =>
            match i.node {
            hir::ImplItemKind::Method(_, ref body) => {

                let mut is_safe = true;
                {
                    let mut v = Visitor {
                        pass: self, cx: cx, tag: tag,
                        cb: |_| { is_safe = false; }
                        };
                    hir::intravisit::walk_body(&mut v, cx.tcx.hir.body(*body));
                }
                is_safe
                },
            _ => true,
            },
        //hir::map::NodeForeignItem(i) =>
        //    if Self::check_for_marker(tcx, i.id, "tag_safe", name) {
        //        true
        //    }
        //    else if Self::check_for_marker(tcx, i.id, "tag_unsafe", name) {
        //        false
        //    }
        //    else {
        //        unknown_assume
        //    },
        ref v @ _ => {
            error!("Node ID {} points to non-item {:?}", node_id, v);
            true
            }
        }
    }

    /// Locate a #[tag_safe(<name>)] attribute on the passed item
    pub fn method_is_safe(&mut self, cx: &lint::LateContext, id: DefId, tag: ::database::Tag) -> bool
    {
        if ! id.is_local()
        {
            // TODO: Get the entry from the crate cache
            if let Some(v) = ::database::CACHE.read().unwrap().get_extern(&cx.tcx,id.krate, id.index, tag) {
                debug!("{:?} - {} (extern cached)", id, v);
                v
            }
            else {
                debug!("{:?} - {} (extern assumed)", id, true);
                true
            }
        }
        else
        {
            let node_id = cx.tcx.hir.as_local_node_id(id).expect("Unable to locate node");
            let mut local_opt = ::database::CACHE.read().unwrap().get_local(node_id, tag);
            // NOTE: This only fires once (ideally)
            if local_opt.is_none() {
                self.fill_cache_for(&cx.tcx, node_id);
                local_opt = ::database::CACHE.read().unwrap().get_local(node_id, tag);
            }
            if let Some(v) = local_opt {
                debug!("{} - {} (cached)", node_id, v);
                v
            }
            else {
                // If this node is currently being checked, assume it's valid.
                // TODO: This can lead to a false positive being stored.
                if self.visit_stack.iter().position(|x| *x == node_id).is_some() {
                    warn!("Recursion, assuming true");
                    true
                }
                else {
                    self.visit_stack.push(node_id);
                    let rv = self.recurse_fcn_body(cx, node_id, tag);
                    self.visit_stack.pop();

                    debug!("{} - {} (recursed)", node_id, rv);
                    ::database::CACHE.write().unwrap().mark(node_id, tag,  rv);
                    rv
                }
            }
        }
    }
}

struct Visitor<'a, 'tcx: 'a, F: FnMut(&Span) + 'a>
{
    pass: &'a mut Pass,
	cx: &'a lint::LateContext<'a,'tcx>,
    tag: ::database::Tag,
    cb: F,
}

impl<'a, 'tcx: 'a, F: FnMut(&Span)> hir::intravisit::Visitor<'a> for Visitor<'a, 'tcx, F>
{
	fn nested_visit_map<'this>(&'this mut self) -> hir::intravisit::NestedVisitorMap<'this, 'a> {
		hir::intravisit::NestedVisitorMap::None
	}

    // Locate function/method calls in a code block
    fn visit_expr(&mut self, ex: &'a hir::Expr) {
        debug!("visit node - {:?}", ex);
        match ex.node
        {
        // Call expressions - check that it's a path call
        hir::ExprCall(ref fcn, ..) =>
			match fcn.node
			{
			hir::ExprPath(ref qp, ..) =>
				match self.cx.tables.qpath_def(qp, fcn.id)
				{
				def::Def::Fn(did) | def::Def::Method(did) =>
					// Check for a safety tag
					if !self.pass.method_is_safe(self.cx, did, self.tag)
					{
						(self.cb)(&ex.span);
					}
					else {
						debug!("Safe call {:?}", ex);
					},
				_ => {
					info!("Call ExprPath with an unknown Def type");
					},
				},
			_ => {
				info!("Call without ExprPath");
				},
			},

        // Method call expressions - get the relevant method
        hir::ExprMethodCall(ref _id, ref _tys, ref _exprs) =>
			match self.cx.tables.type_dependent_defs.get(&ex.id)
			{
			Some(callee) => {
                let id = callee.def_id();

				// Check for a safety tag
				if !self.pass.method_is_safe(self.cx, id, self.tag) {
					(self.cb)(&ex.span);
				}
				},
			None => info!("ExprMethodCall with unknown callee"),
			},

        // Ignore any other type of node
        _ => {},
        }
        hir::intravisit::walk_expr(self, ex);
    }
}

fn get_tags<'a>(meta_items: &'a [ast::Attribute], attr_name: &'a str) -> impl Iterator<Item=::syntax::symbol::Symbol>+'a {
    meta_items.iter()
        .filter(move |attr| attr.name().map(move |n| n == attr_name).unwrap_or(false))
        .flat_map(|attr|
			if let Some(v) = attr.meta() {
				if let MetaItemKind::List(v) = v.node {
					v.into_iter()
				}
				else {
					panic!("");
				}
			}
			else {
				panic!("");
			}
            )
        .filter_map(|tag_meta|
            if let NestedMetaItemKind::MetaItem(ref ptr) = tag_meta.node {
                if let MetaItemKind::Word = ptr.node {
                    Some(ptr.name)
                }
                else {
                    warn!("");
                    None
                }
            }
            else {
                warn!("");
                None
            }
            )
}
<|endoftext|>


<commit_before>extern crate ocl;
#[allow(non_camel_case_types)]
#[allow(non_upper_case_globals)]
#[allow(non_snake_case)]
pub mod ffi;
use std::mem;
pub use ffi::clfftSetupData;

macro_rules! clfft_try {
    ( $result_expr: expr) => {
        let result = $result_expr;
        if result != ffi::clfftStatus::CLFFT_SUCCESS {
            let error_code: i32 = unsafe { mem::transmute(result) };
            return ocl::Error::err(format!("FOREIGN_CLFFT_ERROR {}\nSee http://clmathlibraries.github.io/clFFT/clFFT_8h.html#a74e303bed132064cfa22c1cce96d2bce for further information", error_code));
        }
    }
}

macro_rules! clfft_panic {
    ( $result_expr: expr) => {
        let result = $result_expr;
        if result != ffi::clfftStatus::CLFFT_SUCCESS {
            panic!("Unexpeced error in foreign library: {:?}", result);
        }
    }
}

/// Initialize the internal FFT resources such as FFT implementation caches kernels, programs, and buffers.
pub fn init_lib() -> ffi::clfftSetupData {
    let mut major: ocl::ffi::cl_uint = 0;
    let mut minor: ocl::ffi::cl_uint = 0;
    let mut patch: ocl::ffi::cl_uint = 0;
    clfft_panic!( unsafe { ffi::clfftGetVersion(&mut major, &mut minor, &mut patch) } );
    let data = ffi::clfftSetupData {
        major: major,
        minor: minor,
        patch: patch,
        debugFlags: 0,
    };

    clfft_panic!(unsafe { ffi::clfftSetup(&data) });
    data
}

/// Release all internal resources acquired during `init_lib`.
pub fn drop_lib() {
    unsafe { ffi::clfftTeardown() };
}

fn translate_to_fft_dim(dims: ocl::SpatialDims) -> ffi::clfftDim {
    match dims.dim_count() {
        1 => ffi::clfftDim::CLFFT_1D,
        2 => ffi::clfftDim::CLFFT_2D,
        3 => ffi::clfftDim::CLFFT_3D,
        n => panic!("Number of dimensions must be 1, 2 or 3, but it is {}", n)
    }
}

pub struct FftPlan {
    handle: ffi::clfftPlanHandle
}

impl FftPlan {
    /// Create a plan object initialized entirely with default values.
    ///
    /// A plan is a repository of state for calculating FFT's.  Allows the runtime to pre-calculate kernels, programs
    /// and buffers and associate them with buffers of specified dimensions.
    pub fn default<D: Into<ocl::SpatialDims>>(pro_que: &ocl::ProQue, dims: D)
        -> ocl::Result<FftPlan> {
        let context = unsafe { pro_que.context().core_as_ref().as_ptr() };
        let dims = dims.into();
        let dim = translate_to_fft_dim(dims);
        let lengths = try!(dims.to_lens());
        let mut plan: ffi::clfftPlanHandle = 0;
        clfft_try!( unsafe { ffi::clfftCreateDefaultPlan(&mut plan, context, dim, &lengths as *const usize) } );
        Ok(FftPlan {  handle: plan })
    }

    /// Returns the native clFFT plan handle.
    pub fn plan_handle(&self) -> ffi::clfftPlanHandle {
        self.handle
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use ocl::{ProQue};
    use ocl::builders::ProgramBuilder;

    #[test]
    pub fn fft_test() {
        init_lib();
        let prog_bldr = ProgramBuilder::new();
        let ocl_pq = ProQue::builder()
            .prog_bldr(prog_bldr)
            .build()
            .expect("Building ProQue");
        FftPlan::default(&ocl_pq, [1000]);
        drop_lib();
    }
}<commit_msg>More functions for plans<commit_after>extern crate ocl;
#[allow(non_camel_case_types)]
#[allow(non_upper_case_globals)]
#[allow(non_snake_case)]
pub mod ffi;
use std::mem;
pub use ffi::clfftSetupData;

macro_rules! clfft_try {
    ( $result_expr: expr) => {
        let result = $result_expr;
        if result != ffi::clfftStatus::CLFFT_SUCCESS {
            let error_code: i32 = unsafe { mem::transmute(result) };
            return ocl::Error::err(format!("FOREIGN_CLFFT_ERROR {}\nSee http://clmathlibraries.github.io/clFFT/clFFT_8h.html#a74e303bed132064cfa22c1cce96d2bce for further information", error_code));
        }
    }
}

macro_rules! clfft_panic {
    ( $result_expr: expr) => {
        let result = $result_expr;
        if result != ffi::clfftStatus::CLFFT_SUCCESS {
            panic!("Unexpeced error in foreign library: {:?}", result);
        }
    }
}

/// Initialize the internal FFT resources such as FFT implementation caches kernels, programs, and buffers.
pub fn init_lib() -> ffi::clfftSetupData {
    let mut major: ocl::ffi::cl_uint = 0;
    let mut minor: ocl::ffi::cl_uint = 0;
    let mut patch: ocl::ffi::cl_uint = 0;
    clfft_panic!( unsafe { ffi::clfftGetVersion(&mut major, &mut minor, &mut patch) } );
    let data = ffi::clfftSetupData {
        major: major,
        minor: minor,
        patch: patch,
        debugFlags: 0,
    };

    clfft_panic!(unsafe { ffi::clfftSetup(&data) });
    data
}

/// Release all internal resources acquired during `init_lib`.
pub fn drop_lib() {
    unsafe { ffi::clfftTeardown() };
}

fn translate_to_fft_dim(dims: ocl::SpatialDims) -> ffi::clfftDim {
    match dims.dim_count() {
        1 => ffi::clfftDim::CLFFT_1D,
        2 => ffi::clfftDim::CLFFT_2D,
        3 => ffi::clfftDim::CLFFT_3D,
        n => panic!("Number of dimensions must be 1, 2 or 3, but it is {}", n)
    }
}

pub struct FftPlan {
    handle: ffi::clfftPlanHandle
}

/// Specify the expected precision of each FFT.
pub enum Precision {
    Single,
    Double,
    SingleFast,
    DoubleFast
}

fn translate_precision(precision: Precision) -> ffi::clfftPrecision {
    match precision {
        Precision::Single => ffi::clfftPrecision::CLFFT_SINGLE,
        Precision::Double => ffi::clfftPrecision::CLFFT_DOUBLE,
        Precision::SingleFast => ffi::clfftPrecision::CLFFT_SINGLE_FAST,
        Precision::DoubleFast => ffi::clfftPrecision::CLFFT_DOUBLE_FAST
    }
}

fn translate_precision_back(precision: ffi::clfftPrecision) -> Precision {
    match precision {
        ffi::clfftPrecision::CLFFT_SINGLE => Precision::Single,
        ffi::clfftPrecision::CLFFT_DOUBLE => Precision::Double,
        ffi::clfftPrecision::CLFFT_SINGLE_FAST => Precision::SingleFast,
        ffi::clfftPrecision::CLFFT_DOUBLE_FAST => Precision::DoubleFast,
        ffi::clfftPrecision::ENDPRECISION => panic!("ENDPRECISION should never be returned")
    }
}

impl FftPlan {
    /// Create a plan object initialized entirely with default values.
    ///
    /// A plan is a repository of state for calculating FFT's.  Allows the runtime to pre-calculate kernels, programs
    /// and buffers and associate them with buffers of specified dimensions.
    pub fn default<D: Into<ocl::SpatialDims>>(pro_que: &ocl::ProQue, dims: D)
        -> ocl::Result<FftPlan> {
        let context = unsafe { pro_que.context().core_as_ref().as_ptr() };
        let dims = dims.into();
        let dim = translate_to_fft_dim(dims);
        let lengths = try!(dims.to_lens());
        let mut plan: ffi::clfftPlanHandle = 0;
        clfft_try!( unsafe { ffi::clfftCreateDefaultPlan(&mut plan, context, dim, &lengths as *const usize) } );
        Ok(FftPlan {  handle: plan })
    }

    /// Returns the native clFFT plan handle.
    pub fn plan_handle(&self) -> ffi::clfftPlanHandle {
        self.handle
    }

    /// Set the floating point precision of the FFT data
    pub fn set_precision(&mut self, precision: Precision) -> ocl::Result<()> {
        let precision = translate_precision(precision);
        clfft_try!(unsafe { ffi::clfftSetPlanPrecision(self.handle, precision) });
        Ok(())
    }

    pub fn get_precision(&self) -> ocl::Result<Precision> {
        let mut precision = ffi::clfftPrecision::CLFFT_SINGLE;
        clfft_try!(unsafe { ffi::clfftGetPlanPrecision(self.handle, &mut precision) });
        Ok(translate_precision_back(precision))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use ocl::{ProQue};
    use ocl::builders::ProgramBuilder;

    #[test]
    pub fn fft_test() {
        init_lib();
        let prog_bldr = ProgramBuilder::new();
        let ocl_pq = ProQue::builder()
            .prog_bldr(prog_bldr)
            .build()
            .expect("Building ProQue");
        FftPlan::default(&ocl_pq, [1000]);
        drop_lib();
    }
}<|endoftext|>


<commit_before>#[derive(Clone, PartialEq, ::prost::Message)]
#[derive(Serialize, Deserialize)]
pub struct Election {
    #[prost(string, optional, tag="1")]
    pub member_id: ::std::option::Option<std::string::String>,
    #[prost(string, optional, tag="2")]
    pub service_group: ::std::option::Option<std::string::String>,
    #[prost(uint64, optional, tag="3")]
    pub term: ::std::option::Option<u64>,
    #[prost(uint64, optional, tag="4")]
    pub suitability: ::std::option::Option<u64>,
    #[prost(enumeration="election::Status", optional, tag="5")]
    pub status: ::std::option::Option<i32>,
    #[prost(string, repeated, tag="6")]
    pub votes: ::std::vec::Vec<std::string::String>,
}
pub mod election {
    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
    #[repr(i32)]
    #[derive(Serialize, Deserialize)]
    pub enum Status {
        Running = 1,
        NoQuorum = 2,
        Finished = 3,
    }
}
#[derive(Clone, PartialEq, ::prost::Message)]
#[derive(Serialize, Deserialize)]
pub struct Service {
    #[prost(string, optional, tag="1")]
    pub member_id: ::std::option::Option<std::string::String>,
    #[prost(string, optional, tag="2")]
    pub service_group: ::std::option::Option<std::string::String>,
    #[prost(uint64, optional, tag="3")]
    pub incarnation: ::std::option::Option<u64>,
    #[prost(bool, optional, tag="8")]
    pub initialized: ::std::option::Option<bool>,
    #[prost(string, optional, tag="9")]
    pub pkg: ::std::option::Option<std::string::String>,
    #[prost(bytes, optional, tag="10")]
    pub cfg: ::std::option::Option<std::vec::Vec<u8>>,
    #[prost(message, optional, tag="12")]
    pub sys: ::std::option::Option<SysInfo>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
#[derive(Serialize, Deserialize)]
pub struct ServiceConfig {
    #[prost(string, optional, tag="1")]
    pub service_group: ::std::option::Option<std::string::String>,
    #[prost(uint64, optional, tag="2")]
    pub incarnation: ::std::option::Option<u64>,
    #[prost(bool, optional, tag="3")]
    pub encrypted: ::std::option::Option<bool>,
    #[prost(bytes, optional, tag="4")]
    pub config: ::std::option::Option<std::vec::Vec<u8>>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
#[derive(Serialize, Deserialize)]
pub struct ServiceFile {
    #[prost(string, optional, tag="1")]
    pub service_group: ::std::option::Option<std::string::String>,
    #[prost(uint64, optional, tag="2")]
    pub incarnation: ::std::option::Option<u64>,
    #[prost(bool, optional, tag="3")]
    pub encrypted: ::std::option::Option<bool>,
    #[prost(string, optional, tag="4")]
    pub filename: ::std::option::Option<std::string::String>,
    #[prost(bytes, optional, tag="5")]
    pub body: ::std::option::Option<std::vec::Vec<u8>>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
#[derive(Serialize, Deserialize)]
pub struct SysInfo {
    #[prost(string, optional, tag="1", default="127.0.0.1")]
    pub ip: ::std::option::Option<std::string::String>,
    #[prost(string, optional, tag="2", default="localhost")]
    pub hostname: ::std::option::Option<std::string::String>,
    #[prost(string, optional, tag="3", default="127.0.0.1")]
    pub gossip_ip: ::std::option::Option<std::string::String>,
    #[prost(uint32, optional, tag="4")]
    pub gossip_port: ::std::option::Option<u32>,
    #[prost(string, optional, tag="5", default="127.0.0.1")]
    pub http_gateway_ip: ::std::option::Option<std::string::String>,
    #[prost(uint32, optional, tag="6")]
    pub http_gateway_port: ::std::option::Option<u32>,
    #[prost(string, optional, tag="7", default="127.0.0.1")]
    pub ctl_gateway_ip: ::std::option::Option<std::string::String>,
    #[prost(uint32, optional, tag="8", default="9632")]
    pub ctl_gateway_port: ::std::option::Option<u32>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
#[derive(Serialize, Deserialize)]
pub struct Departure {
    #[prost(string, optional, tag="1")]
    pub member_id: ::std::option::Option<std::string::String>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
#[derive(Serialize, Deserialize)]
pub struct Rumor {
    #[prost(enumeration="rumor::Type", required, tag="1")]
    pub r#type: i32,
    #[prost(string, repeated, tag="2")]
    pub tag: ::std::vec::Vec<std::string::String>,
    #[prost(string, optional, tag="3")]
    pub from_id: ::std::option::Option<std::string::String>,
    #[prost(oneof="rumor::Payload", tags="4, 5, 6, 7, 8, 9")]
    pub payload: ::std::option::Option<rumor::Payload>,
}
pub mod rumor {
    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
    #[repr(i32)]
    #[derive(Serialize, Deserialize)]
    pub enum Type {
        Member = 1,
        Service = 2,
        Election = 3,
        ServiceConfig = 4,
        ServiceFile = 5,
        Fake = 6,
        Fake2 = 7,
        ElectionUpdate = 8,
        Departure = 9,
    }
    #[derive(Clone, PartialEq, ::prost::Oneof)]
    #[derive(Serialize, Deserialize)]
    pub enum Payload {
        #[prost(message, tag="4")]
        Member(super::super::swim::Membership),
        #[prost(message, tag="5")]
        Service(super::Service),
        #[prost(message, tag="6")]
        ServiceConfig(super::ServiceConfig),
        #[prost(message, tag="7")]
        ServiceFile(super::ServiceFile),
        #[prost(message, tag="8")]
        Election(super::Election),
        #[prost(message, tag="9")]
        Departure(super::Departure),
    }
}
<commit_msg>Allow clippy::large_enum_variant in generated code<commit_after>#[derive(Clone, PartialEq, ::prost::Message)]
#[derive(Serialize, Deserialize)]
pub struct Election {
    #[prost(string, optional, tag="1")]
    pub member_id: ::std::option::Option<std::string::String>,
    #[prost(string, optional, tag="2")]
    pub service_group: ::std::option::Option<std::string::String>,
    #[prost(uint64, optional, tag="3")]
    pub term: ::std::option::Option<u64>,
    #[prost(uint64, optional, tag="4")]
    pub suitability: ::std::option::Option<u64>,
    #[prost(enumeration="election::Status", optional, tag="5")]
    pub status: ::std::option::Option<i32>,
    #[prost(string, repeated, tag="6")]
    pub votes: ::std::vec::Vec<std::string::String>,
}
pub mod election {
    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
    #[repr(i32)]
    #[derive(Serialize, Deserialize)]
    pub enum Status {
        Running = 1,
        NoQuorum = 2,
        Finished = 3,
    }
}
#[derive(Clone, PartialEq, ::prost::Message)]
#[derive(Serialize, Deserialize)]
pub struct Service {
    #[prost(string, optional, tag="1")]
    pub member_id: ::std::option::Option<std::string::String>,
    #[prost(string, optional, tag="2")]
    pub service_group: ::std::option::Option<std::string::String>,
    #[prost(uint64, optional, tag="3")]
    pub incarnation: ::std::option::Option<u64>,
    #[prost(bool, optional, tag="8")]
    pub initialized: ::std::option::Option<bool>,
    #[prost(string, optional, tag="9")]
    pub pkg: ::std::option::Option<std::string::String>,
    #[prost(bytes, optional, tag="10")]
    pub cfg: ::std::option::Option<std::vec::Vec<u8>>,
    #[prost(message, optional, tag="12")]
    pub sys: ::std::option::Option<SysInfo>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
#[derive(Serialize, Deserialize)]
pub struct ServiceConfig {
    #[prost(string, optional, tag="1")]
    pub service_group: ::std::option::Option<std::string::String>,
    #[prost(uint64, optional, tag="2")]
    pub incarnation: ::std::option::Option<u64>,
    #[prost(bool, optional, tag="3")]
    pub encrypted: ::std::option::Option<bool>,
    #[prost(bytes, optional, tag="4")]
    pub config: ::std::option::Option<std::vec::Vec<u8>>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
#[derive(Serialize, Deserialize)]
pub struct ServiceFile {
    #[prost(string, optional, tag="1")]
    pub service_group: ::std::option::Option<std::string::String>,
    #[prost(uint64, optional, tag="2")]
    pub incarnation: ::std::option::Option<u64>,
    #[prost(bool, optional, tag="3")]
    pub encrypted: ::std::option::Option<bool>,
    #[prost(string, optional, tag="4")]
    pub filename: ::std::option::Option<std::string::String>,
    #[prost(bytes, optional, tag="5")]
    pub body: ::std::option::Option<std::vec::Vec<u8>>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
#[derive(Serialize, Deserialize)]
pub struct SysInfo {
    #[prost(string, optional, tag="1", default="127.0.0.1")]
    pub ip: ::std::option::Option<std::string::String>,
    #[prost(string, optional, tag="2", default="localhost")]
    pub hostname: ::std::option::Option<std::string::String>,
    #[prost(string, optional, tag="3", default="127.0.0.1")]
    pub gossip_ip: ::std::option::Option<std::string::String>,
    #[prost(uint32, optional, tag="4")]
    pub gossip_port: ::std::option::Option<u32>,
    #[prost(string, optional, tag="5", default="127.0.0.1")]
    pub http_gateway_ip: ::std::option::Option<std::string::String>,
    #[prost(uint32, optional, tag="6")]
    pub http_gateway_port: ::std::option::Option<u32>,
    #[prost(string, optional, tag="7", default="127.0.0.1")]
    pub ctl_gateway_ip: ::std::option::Option<std::string::String>,
    #[prost(uint32, optional, tag="8", default="9632")]
    pub ctl_gateway_port: ::std::option::Option<u32>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
#[derive(Serialize, Deserialize)]
pub struct Departure {
    #[prost(string, optional, tag="1")]
    pub member_id: ::std::option::Option<std::string::String>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
#[derive(Serialize, Deserialize)]
pub struct Rumor {
    #[prost(enumeration="rumor::Type", required, tag="1")]
    pub r#type: i32,
    #[prost(string, repeated, tag="2")]
    pub tag: ::std::vec::Vec<std::string::String>,
    #[prost(string, optional, tag="3")]
    pub from_id: ::std::option::Option<std::string::String>,
    #[prost(oneof="rumor::Payload", tags="4, 5, 6, 7, 8, 9")]
    pub payload: ::std::option::Option<rumor::Payload>,
}
pub mod rumor {
    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
    #[repr(i32)]
    #[derive(Serialize, Deserialize)]
    pub enum Type {
        Member = 1,
        Service = 2,
        Election = 3,
        ServiceConfig = 4,
        ServiceFile = 5,
        Fake = 6,
        Fake2 = 7,
        ElectionUpdate = 8,
        Departure = 9,
    }
    #[derive(Clone, PartialEq, ::prost::Oneof)]
    #[allow(clippy::large_enum_variant)]
    #[derive(Serialize, Deserialize)]
    pub enum Payload {
        #[prost(message, tag="4")]
        Member(super::super::swim::Membership),
        #[prost(message, tag="5")]
        Service(super::Service),
        #[prost(message, tag="6")]
        ServiceConfig(super::ServiceConfig),
        #[prost(message, tag="7")]
        ServiceFile(super::ServiceFile),
        #[prost(message, tag="8")]
        Election(super::Election),
        #[prost(message, tag="9")]
        Departure(super::Departure),
    }
}
<|endoftext|>


<commit_before>//! Prepared statements cache for faster execution.

use std::cell::RefCell;
use std::collections::VecDeque;
use {Result, Connection, Statement};

/// Prepared statements cache.
#[derive(Debug)]
pub struct StatementCache<'conn> {
    conn: &'conn Connection,
    cache: VecDeque<Statement<'conn>>, // back = LRU
}

pub struct CachedStatement<'conn> {
    stmt: Option<Statement<'conn>>,
    cache: RefCell<StatementCache<'conn>>,
    pub cacheable: bool,
}

impl<'conn> Drop for CachedStatement<'conn> {
    #[allow(unused_must_use)]
    fn drop(&mut self) {
        if self.cacheable {
            self.cache.borrow_mut().release(self.stmt.take().unwrap());
        } else {
            self.stmt.take().unwrap().finalize();
        }
    }
}

impl<'conn> StatementCache<'conn> {
    /// Create a statement cache.
    pub fn new(conn: &'conn Connection, capacity: usize) -> StatementCache<'conn> {
        StatementCache {
            conn: conn,
            cache: VecDeque::with_capacity(capacity),
        }
    }

    /// Search the cache for a prepared-statement object that implements `sql`.
    // If no such prepared-statement can be found, allocate and prepare a new one.
    ///
    /// # Failure
    ///
    /// Will return `Err` if no cached statement can be found and the underlying SQLite prepare call fails.
    pub fn get(&mut self, sql: &str) -> Result<Statement<'conn>> {
        match self.cache.iter().rposition(|entry| entry.eq(sql)) {
            Some(index) => Ok(self.cache.swap_remove_front(index).unwrap()), // FIXME Not LRU compliant
            _ => self.conn.prepare(sql),
        }
    }

    /// If `discard` is true, then the statement is deleted immediately.
    /// Otherwise it is added to the LRU list and may be returned
    /// by a subsequent call to `get()`.
    ///
    /// # Failure
    ///
    /// Will return `Err` if `stmt` (or the already cached statement implementing the same SQL) statement is `discard`ed
    /// and the underlying SQLite finalize call fails.
    fn release(&mut self, mut stmt: Statement<'conn>) {
        if self.cache.capacity() == self.cache.len() { // is full
            self.cache.pop_back(); // LRU dropped
        }
        stmt.reset_if_needed();
        stmt.clear_bindings();
        self.cache.push_front(stmt)
    }

    /// Flush the prepared statement cache
    pub fn clear(&mut self) {
        self.cache.clear();
    }

    /// Return current cache size.
    pub fn len(&self) -> usize {
        self.cache.len()
    }

    /// Return maximum cache size.
    pub fn capacity(&self) -> usize {
        self.cache.capacity()
    }
}

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

    #[test]
    fn test_cache() {
        let db = Connection::open_in_memory().unwrap();
        let mut cache = StatementCache::new(&db, 15);
        assert_eq!(0, cache.len());
        assert_eq!(15, cache.capacity());

        let sql = "PRAGMA schema_version";
        let mut stmt = cache.get(sql).unwrap();
        assert_eq!(0, cache.len());
        assert_eq!(0,
                   stmt.query(&[]).unwrap().get_expected_row().unwrap().get::<i64>(0));

        // println!("NEW {:?}", stmt);
        cache.release(stmt);
        assert_eq!(1, cache.len());

        stmt = cache.get(sql).unwrap();
        assert_eq!(0, cache.len());
        assert_eq!(0,
                   stmt.query(&[]).unwrap().get_expected_row().unwrap().get::<i64>(0));

        // println!("CACHED {:?}", stmt);
        cache.release(stmt);
        assert_eq!(1, cache.len());

        cache.clear();
        assert_eq!(0, cache.len());
        assert_eq!(15, cache.capacity());
    }
}
<commit_msg>Fail to create a new CachedStatement.<commit_after>//! Prepared statements cache for faster execution.

use std::cell::RefCell;
use std::collections::VecDeque;
use std::ops::{Deref, DerefMut};
use {Result, Connection, Statement};

/// Prepared statements cache.
#[derive(Debug)]
pub struct StatementCache<'conn> {
    conn: &'conn Connection,
    cache: VecDeque<Statement<'conn>>, // back = LRU
}

pub struct CachedStatement<'conn> {
    stmt: Option<Statement<'conn>>,
    cache: RefCell<StatementCache<'conn>>,
    pub cacheable: bool,
}

impl<'conn> Deref for CachedStatement<'conn> {
    type Target = Statement<'conn>;

    fn deref(&self) -> &Statement<'conn> {
        self.stmt.as_ref().unwrap()
    }
}

impl<'conn> DerefMut for CachedStatement<'conn> {
    fn deref_mut(&mut self) -> &mut Statement<'conn> {
        self.stmt.as_mut().unwrap()
    }
}

impl<'conn> Drop for CachedStatement<'conn> {
    #[allow(unused_must_use)]
    fn drop(&mut self) {
        if self.cacheable {
            self.cache.borrow_mut().release(self.stmt.take().unwrap());
        } else {
            self.stmt.take().unwrap().finalize();
        }
    }
}

impl<'conn> CachedStatement<'conn> {
    fn new(stmt: Statement<'conn>,
           cache: RefCell<StatementCache<'conn>>)
           -> CachedStatement<'conn> {
        CachedStatement {
            stmt: Some(stmt),
            cache: cache,
            cacheable: true,
        }
    }
}

impl<'conn> StatementCache<'conn> {
    /// Create a statement cache.
    pub fn new(conn: &'conn Connection, capacity: usize) -> StatementCache<'conn> {
        StatementCache {
            conn: conn,
            cache: VecDeque::with_capacity(capacity),
        }
    }

    /// Search the cache for a prepared-statement object that implements `sql`.
    // If no such prepared-statement can be found, allocate and prepare a new one.
    ///
    /// # Failure
    ///
    /// Will return `Err` if no cached statement can be found and the underlying SQLite prepare call fails.
    pub fn get(&mut self, sql: &str) -> Result<CachedStatement<'conn>> {
        let stmt = match self.cache.iter().rposition(|entry| entry.eq(sql)) {
            Some(index) => Ok(self.cache.swap_remove_front(index).unwrap()), // FIXME Not LRU compliant
            _ => self.conn.prepare(sql),
        };
        stmt.map(|stmt| CachedStatement::new(stmt, RefCell::new(self)))
    }

    /// If `discard` is true, then the statement is deleted immediately.
    /// Otherwise it is added to the LRU list and may be returned
    /// by a subsequent call to `get()`.
    ///
    /// # Failure
    ///
    /// Will return `Err` if `stmt` (or the already cached statement implementing the same SQL) statement is `discard`ed
    /// and the underlying SQLite finalize call fails.
    fn release(&mut self, mut stmt: Statement<'conn>) {
        if self.cache.capacity() == self.cache.len() {
            // is full
            self.cache.pop_back(); // LRU dropped
        }
        stmt.reset_if_needed();
        stmt.clear_bindings();
        self.cache.push_front(stmt)
    }

    /// Flush the prepared statement cache
    pub fn clear(&mut self) {
        self.cache.clear();
    }

    /// Return current cache size.
    pub fn len(&self) -> usize {
        self.cache.len()
    }

    /// Return maximum cache size.
    pub fn capacity(&self) -> usize {
        self.cache.capacity()
    }
}

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

    #[test]
    fn test_cache() {
        let db = Connection::open_in_memory().unwrap();
        let mut cache = StatementCache::new(&db, 15);
        assert_eq!(0, cache.len());
        assert_eq!(15, cache.capacity());

        let sql = "PRAGMA schema_version";
        let mut stmt = cache.get(sql).unwrap();
        assert_eq!(0, cache.len());
        assert_eq!(0,
                   stmt.query(&[]).unwrap().get_expected_row().unwrap().get::<i64>(0));

        // println!("NEW {:?}", stmt);
        cache.release(stmt);
        assert_eq!(1, cache.len());

        stmt = cache.get(sql).unwrap();
        assert_eq!(0, cache.len());
        assert_eq!(0,
                   stmt.query(&[]).unwrap().get_expected_row().unwrap().get::<i64>(0));

        // println!("CACHED {:?}", stmt);
        cache.release(stmt);
        assert_eq!(1, cache.len());

        cache.clear();
        assert_eq!(0, cache.len());
        assert_eq!(15, cache.capacity());
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2017, 2018 Erik Nordstrøm <erik@nordstroem.no>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

use strum::IntoEnumIterator;
use arrayvec::ArrayVec;
use rand::Rng;

use std::ops::Deref;

#[derive(EnumIter, Display, Copy, Clone)]
pub enum Color
{
    #[strum(serialize="?")]
    Unknown,
    #[strum(serialize="♠")]
    Spades,
    #[strum(serialize="♥")]
    Hearts,
    #[strum(serialize="♦")]
    Diamonds,
    #[strum(serialize="♣")]
    Clubs
}

#[derive(EnumIter, Display, Copy, Clone)]
pub enum Rank
{
    #[strum(serialize="?")]
    Unknown,
    A,
    #[strum(serialize="2")]
    Two,
    #[strum(serialize="3")]
    Three,
    #[strum(serialize="4")]
    Four,
    #[strum(serialize="5")]
    Five,
    #[strum(serialize="6")]
    Six,
    #[strum(serialize="7")]
    Seven,
    #[strum(serialize="8")]
    Eight,
    #[strum(serialize="9")]
    Nine,
    #[strum(serialize="10")]
    Ten,
    J,
    Q,
    K
}

pub struct Card
{
    pub color:     Color,
    pub rank:      Rank,
    pub id:        i8,
    pub facing_up: bool
}

// TODO: Change to ArrayVec<[Card; 52]> after PR for that size has been merged.
type DeckArray = [Card; 56];
type Deck = ArrayVec<DeckArray>;

pub struct ShuffledDeck(Deck);

NewtypeFrom! { () pub struct ShuffledDeck(Deck); }

impl ShuffledDeck
{
    pub fn new () -> ShuffledDeck
    {
        /*
         * The cards in the shuffled deck appear in order of their IDs,
         * such that the card with ID n is at array position n.
         */

        let mut deck = Deck::new();

        let mut card_ids: Vec<i8> = (0..52).collect();
        rand::thread_rng().shuffle(&mut card_ids);

        let mut card_ids_iter = card_ids.iter_mut();

        for color in Color::iter().skip(1)
        {
            for rank in Rank::iter().skip(1)
            {
                deck.push(Card
                {
                    color:     color,
                    rank:      rank,
                    id:        *(card_ids_iter.next().unwrap()),
                    facing_up: false
                });
            }
        }

        deck.sort_unstable_by_key(|k| k.id);

        ShuffledDeck::from(deck)
    }

    pub fn push (&mut self, element: <DeckArray as arrayvec::Array>::Item)
    {
        Deck::push(&mut self.0, element)
    }
}

impl Deref for ShuffledDeck
{
    type Target = [<DeckArray as arrayvec::Array>::Item];

    #[inline]
    fn deref (&self) -> &[<DeckArray as arrayvec::Array>::Item]
    {
        Deck::deref(&self.0)
    }
}
<commit_msg>Old shuffle was deprecated in crate "rand" 0.6.0 that we updated to. Use SliceRandom::shuffle instead like they tell us to.<commit_after>/*
 * Copyright (c) 2017, 2018 Erik Nordstrøm <erik@nordstroem.no>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

use strum::IntoEnumIterator;
use arrayvec::ArrayVec;
use rand::seq::SliceRandom;

use std::ops::Deref;

#[derive(EnumIter, Display, Copy, Clone)]
pub enum Color
{
    #[strum(serialize="?")]
    Unknown,
    #[strum(serialize="♠")]
    Spades,
    #[strum(serialize="♥")]
    Hearts,
    #[strum(serialize="♦")]
    Diamonds,
    #[strum(serialize="♣")]
    Clubs
}

#[derive(EnumIter, Display, Copy, Clone)]
pub enum Rank
{
    #[strum(serialize="?")]
    Unknown,
    A,
    #[strum(serialize="2")]
    Two,
    #[strum(serialize="3")]
    Three,
    #[strum(serialize="4")]
    Four,
    #[strum(serialize="5")]
    Five,
    #[strum(serialize="6")]
    Six,
    #[strum(serialize="7")]
    Seven,
    #[strum(serialize="8")]
    Eight,
    #[strum(serialize="9")]
    Nine,
    #[strum(serialize="10")]
    Ten,
    J,
    Q,
    K
}

pub struct Card
{
    pub color:     Color,
    pub rank:      Rank,
    pub id:        i8,
    pub facing_up: bool
}

// TODO: Change to ArrayVec<[Card; 52]> after PR for that size has been merged.
type DeckArray = [Card; 56];
type Deck = ArrayVec<DeckArray>;

pub struct ShuffledDeck(Deck);

NewtypeFrom! { () pub struct ShuffledDeck(Deck); }

impl ShuffledDeck
{
    pub fn new () -> ShuffledDeck
    {
        /*
         * The cards in the shuffled deck appear in order of their IDs,
         * such that the card with ID n is at array position n.
         */

        let mut deck = Deck::new();

        let mut card_ids: Vec<i8> = (0..52).collect();
        card_ids.shuffle(&mut rand::thread_rng());

        let mut card_ids_iter = card_ids.iter_mut();

        for color in Color::iter().skip(1)
        {
            for rank in Rank::iter().skip(1)
            {
                deck.push(Card
                {
                    color:     color,
                    rank:      rank,
                    id:        *(card_ids_iter.next().unwrap()),
                    facing_up: false
                });
            }
        }

        deck.sort_unstable_by_key(|k| k.id);

        ShuffledDeck::from(deck)
    }

    pub fn push (&mut self, element: <DeckArray as arrayvec::Array>::Item)
    {
        Deck::push(&mut self.0, element)
    }
}

impl Deref for ShuffledDeck
{
    type Target = [<DeckArray as arrayvec::Array>::Item];

    #[inline]
    fn deref (&self) -> &[<DeckArray as arrayvec::Array>::Item]
    {
        Deck::deref(&self.0)
    }
}
<|endoftext|>