<commit_before>use socket::Socket;

pub enum TriggerSource {
    EXT_PE,
    EXT_NE,
    INT,
    GATED,
}

impl ::std::fmt::Display for TriggerSource {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        let display = match self {
            &TriggerSource::EXT_PE => "EXT_PE",
            &TriggerSource::EXT_NE => "EXT_NE",
            &TriggerSource::INT => "INT",
            &TriggerSource::GATED => "GATED",
        };

        write!(f, "{}", display)
    }
}

#[derive(Clone)]
pub enum Form {
    SINE,
    SQUARE,
    TRIANGLE,
    SAWU,
    SAWD,
    PWM,
    ARBITRARY,
}

impl ::std::fmt::Display for Form {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        let display = match self {
            &Form::SINE => "SINE",
            &Form::SQUARE => "SQUARE",
            &Form::TRIANGLE => "TRIANGLE",
            &Form::SAWU => "SAWU",
            &Form::SAWD => "SAWD",
            &Form::PWM => "PWM",
            &Form::ARBITRARY => "ARBITRARY",
        };

        write!(f, "{}", display)
    }
}

pub enum Source {
    OUT1,
    OUT2,
}

impl ::std::fmt::Display for Source {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        let display = match self {
            &Source::OUT1 => "SOUR1",
            &Source::OUT2 => "SOUR2",
        };

        write!(f, "{}", display)
    }
}

// @TODO impl std::slice::SliceIndex<generator::State> instead
impl ::std::convert::Into<usize> for Source {
    fn into(self) -> usize {
        match self {
            Source::OUT1 => 0,
            Source::OUT2 => 1,
        }
    }
}

struct State {
    started: bool,
    form: Form,
    amplitude: f32,
    frequency: u32,
    dcyc: u32,
}

impl State {
    pub fn new() -> Self {
        State {
            started: false,
            form: Form::SINE,
            amplitude: 1.0,
            frequency: 1000,
            dcyc: 50,
        }
    }
}

pub struct Generator {
    socket: Socket,
    states: [State; 2],
}

impl Generator {
    pub fn new(socket: Socket) -> Self {
        Generator {
            socket: socket,
            states: [
                State::new(),
                State::new(),
            ],
        }
    }

    /**
     * Enable fast analog outputs.
     */
    pub fn start(&mut self, source: Source) {
        self.set_state(&source, "ON");
        self.states[source as usize].started = true;
    }

    /**
     * Disable fast analog outputs.
     */
    pub fn stop(&mut self, source: Source) {
        self.set_state(&source, "OFF");
        self.states[source as usize].started = false;
    }

    fn set_state(&mut self, source: &Source, state: &str) {
        let output = match *source {
            Source::OUT1 => "OUTPUT1",
            Source::OUT2 => "OUTPUT2",
        };

        self.socket.send(format!("{}:STATE {}", output, state));
    }

    pub fn is_started(&self, source: Source) -> bool {
        self.states[source as usize].started
    }

    /**
     * Set frequency of fast analog outputs.
     */
    pub fn set_frequency(&mut self, source: Source, frequency: u32) {
        self.socket.send(format!("{}:FREQ:FIX {}", source, frequency));
        self.states[source as usize].frequency = frequency;
    }

    pub fn get_frequency(&self, source: Source) -> u32 {
        self.states[source as usize].frequency
    }

    /**
     * Set waveform of fast analog outputs.
     */
    pub fn set_form(&mut self, source: Source, form: Form) {
        self.socket.send(format!("{}:FUNC {}", source, form));
        self.states[source as usize].form = form;
    }

    pub fn get_form(&self, source: Source) -> Form {
        self.states[source as usize].form.clone()
    }

    /**
     * Set amplitude voltage of fast analog outputs.
     *
     * Amplitude + offset value must be less than maximum output range ± 1V
     */
    pub fn set_amplitude(&mut self, source: Source, amplitude: f32) {
        self.socket.send(format!("{}:VOLT {}", source, amplitude));
        self.states[source as usize].amplitude = amplitude;
    }

    pub fn get_amplitude(&self, source: Source) -> f32 {
        self.states[source as usize].amplitude
    }

    /**
     * Set offset voltage of fast analog outputs.
     *
     * Amplitude + offset value must be less than maximum output range ± 1V
     */
    pub fn set_offset(&mut self, source: Source, offset: f32) {
        self.socket.send(format!("{}:VOLT:OFFS {}", source, offset));
    }

    /**
     * Set phase of fast analog outputs.
     */
    pub fn set_phase(&mut self, source: Source, phase: i32) {
        self.socket.send(format!("{}:PHAS {}", source, phase));
    }

    /**
     * Set duty cycle of PWM waveform.
     */
    pub fn set_dcyc(&mut self, source: Source, dcyc: u32) {
        self.socket.send(format!("{}:DCYC {}", source, dcyc));
        self.states[source as usize].dcyc = dcyc;
    }

    pub fn get_dcyc(&self, source: Source) -> u32 {
        self.states[source as usize].dcyc
    }

    /**
     * Import data for arbitrary waveform generation.
     */
    pub fn arbitrary_waveform(&mut self, source: Source, data: Vec<f32>) {
        let mut data = data.iter()
            .fold(String::new(), |acc, e| {
                format!("{}{},", acc, e)
            });
        data.pop();

        self.socket.send(format!("{}:TRAC:DATA:DATA {}", source, data));
    }

    /**
     * Set trigger source for selected signal.
     */
    pub fn set_trigger_source(&mut self, source: Source, trigger: TriggerSource) {
        self.socket.send(format!("{}:TRIG:SOUR {}", source, trigger));
    }

    /**
     * Triggers selected source immediately.
     */
    pub fn trigger(&mut self, source: Source) {
        self.socket.send(format!("{}:TRIG:IMM", source));
    }

    /**
     * Triggers both sources immediately.
     */
    pub fn trigger_all(&mut self) {
        self.socket.send("TRIG:IMM");
    }

    /**
     * Reset generator to default settings.
     */
    pub fn reset(&mut self) {
        self.socket.send("GEN:RST");
    }
}

#[cfg(test)]
mod test {
    macro_rules! generator_assert {
        ($f:ident, $e:expr) => {
            let (rx, mut generator) = create_generator();

            generator.$f();
            assert_eq!($e, rx.recv().unwrap());
        }
    }

    #[test]
    fn test_start() {
        let (rx, mut generator) = create_generator();

        generator.start(::generator::Source::OUT2);
        assert_eq!("OUTPUT2:STATE ON\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_stop() {
        let (rx, mut generator) = create_generator();

        generator.stop(::generator::Source::OUT2);
        assert_eq!("OUTPUT2:STATE OFF\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_is_started() {
        let (_, mut generator) = create_generator();

        assert_eq!(generator.is_started(::generator::Source::OUT1), false);
        generator.start(::generator::Source::OUT1);
        assert_eq!(generator.is_started(::generator::Source::OUT1), true);
        generator.stop(::generator::Source::OUT1);
        assert_eq!(generator.is_started(::generator::Source::OUT1), false);
    }

    #[test]
    fn test_set_frequency() {
        let (rx, mut generator) = create_generator();

        generator.set_frequency(::generator::Source::OUT1, 500);
        assert_eq!("SOUR1:FREQ:FIX 500\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_get_frequency() {
        let (_, generator) = create_generator();

        assert_eq!(generator.get_frequency(::generator::Source::OUT1), 1000);
    }

    #[test]
    fn test_form() {
        let (rx, mut generator) = create_generator();

        generator.set_form(::generator::Source::OUT1, ::generator::Form::SINE);
        assert_eq!("SOUR1:FUNC SINE\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_amplitude() {
        let (rx, mut generator) = create_generator();

        generator.set_amplitude(::generator::Source::OUT1, -0.9);
        assert_eq!("SOUR1:VOLT -0.9\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_set_offset() {
        let (rx, mut generator) = create_generator();

        generator.set_offset(::generator::Source::OUT1, -1.0);
        assert_eq!("SOUR1:VOLT:OFFS -1\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_set_phase() {
        let (rx, mut generator) = create_generator();

        generator.set_phase(::generator::Source::OUT1, -360);
        assert_eq!("SOUR1:PHAS -360\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_dcyc() {
        let (rx, mut generator) = create_generator();

        generator.set_dcyc(::generator::Source::OUT1, 100);
        assert_eq!("SOUR1:DCYC 100\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_arbitrary_waveform() {
        let (rx, mut generator) = create_generator();

        generator.arbitrary_waveform(::generator::Source::OUT1, vec![1.0, 0.5, 0.2]);
        assert_eq!("SOUR1:TRAC:DATA:DATA 1,0.5,0.2\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_set_trigger_source() {
        let (rx, mut generator) = create_generator();

        generator.set_trigger_source(::generator::Source::OUT1, ::generator::TriggerSource::EXT_PE);
        assert_eq!("SOUR1:TRIG:SOUR EXT_PE\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_trigger() {
        let (rx, mut generator) = create_generator();

        generator.trigger(::generator::Source::OUT1);
        assert_eq!("SOUR1:TRIG:IMM\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_trigger_all() {
        generator_assert!(trigger_all, "TRIG:IMM\r\n");
    }

    #[test]
    fn test_reset() {
        generator_assert!(reset, "GEN:RST\r\n");
    }

    fn create_generator() -> (::std::sync::mpsc::Receiver<String>, ::generator::Generator) {
        let (addr, rx) = ::test::launch_server();
        let socket = ::socket::Socket::new(addr);

        (rx, ::generator::Generator::new(socket))
    }
}
<commit_msg>Rename generator methods<commit_after>use socket::Socket;

pub enum TriggerSource {
    EXT_PE,
    EXT_NE,
    INT,
    GATED,
}

impl ::std::fmt::Display for TriggerSource {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        let display = match self {
            &TriggerSource::EXT_PE => "EXT_PE",
            &TriggerSource::EXT_NE => "EXT_NE",
            &TriggerSource::INT => "INT",
            &TriggerSource::GATED => "GATED",
        };

        write!(f, "{}", display)
    }
}

#[derive(Clone)]
pub enum Form {
    SINE,
    SQUARE,
    TRIANGLE,
    SAWU,
    SAWD,
    PWM,
    ARBITRARY,
}

impl ::std::fmt::Display for Form {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        let display = match self {
            &Form::SINE => "SINE",
            &Form::SQUARE => "SQUARE",
            &Form::TRIANGLE => "TRIANGLE",
            &Form::SAWU => "SAWU",
            &Form::SAWD => "SAWD",
            &Form::PWM => "PWM",
            &Form::ARBITRARY => "ARBITRARY",
        };

        write!(f, "{}", display)
    }
}

pub enum Source {
    OUT1,
    OUT2,
}

impl ::std::fmt::Display for Source {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        let display = match self {
            &Source::OUT1 => "SOUR1",
            &Source::OUT2 => "SOUR2",
        };

        write!(f, "{}", display)
    }
}

// @TODO impl std::slice::SliceIndex<generator::State> instead
impl ::std::convert::Into<usize> for Source {
    fn into(self) -> usize {
        match self {
            Source::OUT1 => 0,
            Source::OUT2 => 1,
        }
    }
}

struct State {
    started: bool,
    form: Form,
    amplitude: f32,
    frequency: u32,
    dcyc: u32,
}

impl State {
    pub fn new() -> Self {
        State {
            started: false,
            form: Form::SINE,
            amplitude: 1.0,
            frequency: 1000,
            dcyc: 50,
        }
    }
}

pub struct Generator {
    socket: Socket,
    states: [State; 2],
}

impl Generator {
    pub fn new(socket: Socket) -> Self {
        Generator {
            socket: socket,
            states: [
                State::new(),
                State::new(),
            ],
        }
    }

    /**
     * Enable fast analog outputs.
     */
    pub fn start(&mut self, source: Source) {
        self.set_state(&source, "ON");
        self.states[source as usize].started = true;
    }

    /**
     * Disable fast analog outputs.
     */
    pub fn stop(&mut self, source: Source) {
        self.set_state(&source, "OFF");
        self.states[source as usize].started = false;
    }

    fn set_state(&mut self, source: &Source, state: &str) {
        let output = match *source {
            Source::OUT1 => "OUTPUT1",
            Source::OUT2 => "OUTPUT2",
        };

        self.socket.send(format!("{}:STATE {}", output, state));
    }

    pub fn is_started(&self, source: Source) -> bool {
        self.states[source as usize].started
    }

    /**
     * Set frequency of fast analog outputs.
     */
    pub fn set_frequency(&mut self, source: Source, frequency: u32) {
        self.socket.send(format!("{}:FREQ:FIX {}", source, frequency));
        self.states[source as usize].frequency = frequency;
    }

    pub fn get_frequency(&self, source: Source) -> u32 {
        self.states[source as usize].frequency
    }

    /**
     * Set waveform of fast analog outputs.
     */
    pub fn set_form(&mut self, source: Source, form: Form) {
        self.socket.send(format!("{}:FUNC {}", source, form));
        self.states[source as usize].form = form;
    }

    pub fn get_form(&self, source: Source) -> Form {
        self.states[source as usize].form.clone()
    }

    /**
     * Set amplitude voltage of fast analog outputs.
     *
     * Amplitude + offset value must be less than maximum output range ± 1V
     */
    pub fn set_amplitude(&mut self, source: Source, amplitude: f32) {
        self.socket.send(format!("{}:VOLT {}", source, amplitude));
        self.states[source as usize].amplitude = amplitude;
    }

    pub fn get_amplitude(&self, source: Source) -> f32 {
        self.states[source as usize].amplitude
    }

    /**
     * Set offset voltage of fast analog outputs.
     *
     * Amplitude + offset value must be less than maximum output range ± 1V
     */
    pub fn set_offset(&mut self, source: Source, offset: f32) {
        self.socket.send(format!("{}:VOLT:OFFS {}", source, offset));
    }

    /**
     * Set phase of fast analog outputs.
     */
    pub fn set_phase(&mut self, source: Source, phase: i32) {
        self.socket.send(format!("{}:PHAS {}", source, phase));
    }

    /**
     * Set duty cycle of PWM waveform.
     */
    pub fn set_duty_cicle(&mut self, source: Source, dcyc: u32) {
        self.socket.send(format!("{}:DCYC {}", source, dcyc));
        self.states[source as usize].dcyc = dcyc;
    }

    pub fn get_duty_cicle(&self, source: Source) -> u32 {
        self.states[source as usize].dcyc
    }

    /**
     * Import data for arbitrary waveform generation.
     */
    pub fn arbitrary_waveform(&mut self, source: Source, data: Vec<f32>) {
        let mut data = data.iter()
            .fold(String::new(), |acc, e| {
                format!("{}{},", acc, e)
            });
        data.pop();

        self.socket.send(format!("{}:TRAC:DATA:DATA {}", source, data));
    }

    /**
     * Set trigger source for selected signal.
     */
    pub fn set_trigger_source(&mut self, source: Source, trigger: TriggerSource) {
        self.socket.send(format!("{}:TRIG:SOUR {}", source, trigger));
    }

    /**
     * Triggers selected source immediately.
     */
    pub fn trigger(&mut self, source: Source) {
        self.socket.send(format!("{}:TRIG:IMM", source));
    }

    /**
     * Triggers both sources immediately.
     */
    pub fn trigger_all(&mut self) {
        self.socket.send("TRIG:IMM");
    }

    /**
     * Reset generator to default settings.
     */
    pub fn reset(&mut self) {
        self.socket.send("GEN:RST");
    }
}

#[cfg(test)]
mod test {
    macro_rules! generator_assert {
        ($f:ident, $e:expr) => {
            let (rx, mut generator) = create_generator();

            generator.$f();
            assert_eq!($e, rx.recv().unwrap());
        }
    }

    #[test]
    fn test_start() {
        let (rx, mut generator) = create_generator();

        generator.start(::generator::Source::OUT2);
        assert_eq!("OUTPUT2:STATE ON\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_stop() {
        let (rx, mut generator) = create_generator();

        generator.stop(::generator::Source::OUT2);
        assert_eq!("OUTPUT2:STATE OFF\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_is_started() {
        let (_, mut generator) = create_generator();

        assert_eq!(generator.is_started(::generator::Source::OUT1), false);
        generator.start(::generator::Source::OUT1);
        assert_eq!(generator.is_started(::generator::Source::OUT1), true);
        generator.stop(::generator::Source::OUT1);
        assert_eq!(generator.is_started(::generator::Source::OUT1), false);
    }

    #[test]
    fn test_set_frequency() {
        let (rx, mut generator) = create_generator();

        generator.set_frequency(::generator::Source::OUT1, 500);
        assert_eq!("SOUR1:FREQ:FIX 500\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_get_frequency() {
        let (_, generator) = create_generator();

        assert_eq!(generator.get_frequency(::generator::Source::OUT1), 1000);
    }

    #[test]
    fn test_set_form() {
        let (rx, mut generator) = create_generator();

        generator.set_form(::generator::Source::OUT1, ::generator::Form::SINE);
        assert_eq!("SOUR1:FUNC SINE\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_amplitude() {
        let (rx, mut generator) = create_generator();

        generator.set_amplitude(::generator::Source::OUT1, -0.9);
        assert_eq!("SOUR1:VOLT -0.9\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_set_offset() {
        let (rx, mut generator) = create_generator();

        generator.set_offset(::generator::Source::OUT1, -1.0);
        assert_eq!("SOUR1:VOLT:OFFS -1\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_set_phase() {
        let (rx, mut generator) = create_generator();

        generator.set_phase(::generator::Source::OUT1, -360);
        assert_eq!("SOUR1:PHAS -360\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_set_duty_cicle() {
        let (rx, mut generator) = create_generator();

        generator.set_duty_cicle(::generator::Source::OUT1, 100);
        assert_eq!("SOUR1:DCYC 100\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_arbitrary_waveform() {
        let (rx, mut generator) = create_generator();

        generator.arbitrary_waveform(::generator::Source::OUT1, vec![1.0, 0.5, 0.2]);
        assert_eq!("SOUR1:TRAC:DATA:DATA 1,0.5,0.2\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_set_trigger_source() {
        let (rx, mut generator) = create_generator();

        generator.set_trigger_source(::generator::Source::OUT1, ::generator::TriggerSource::EXT_PE);
        assert_eq!("SOUR1:TRIG:SOUR EXT_PE\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_trigger() {
        let (rx, mut generator) = create_generator();

        generator.trigger(::generator::Source::OUT1);
        assert_eq!("SOUR1:TRIG:IMM\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_trigger_all() {
        generator_assert!(trigger_all, "TRIG:IMM\r\n");
    }

    #[test]
    fn test_reset() {
        generator_assert!(reset, "GEN:RST\r\n");
    }

    fn create_generator() -> (::std::sync::mpsc::Receiver<String>, ::generator::Generator) {
        let (addr, rx) = ::test::launch_server();
        let socket = ::socket::Socket::new(addr);

        (rx, ::generator::Generator::new(socket))
    }
}
<|endoftext|>


<commit_before>// (C)opyleft 2013 Frank Denis

/*!
 * Bindings for the GeoIP library
 */
#![desc = "Bindings for the GeoIP library."]
#![license = "BSD"]
#![crate_id = "geoip#0.1"]
#![crate_type = "rlib"]

#![warn(non_camel_case_types,
        non_uppercase_statics,
        unnecessary_qualification,
        managed_heap_memory)]

extern crate libc;

use libc::{c_void, c_char, c_int, c_ulong};
use std::c_str::CString;
use std::fmt;
use std::io::net::ip::{IpAddr,Ipv4Addr,Ipv6Addr};

type GeoIP_ = *c_void;
type In6Addr = [u8, ..16];

struct GeoIPLookup {
    netmask: c_int
}

impl GeoIPLookup {
    fn new() -> GeoIPLookup {
        GeoIPLookup {
            netmask: 0
        }
    }
}

#[link(name = "GeoIP")]
extern {
    fn GeoIP_open(dbtype: *c_char, flags: c_int) -> GeoIP_;
    fn GeoIP_delete(db: GeoIP_);
    fn GeoIP_name_by_ipnum_gl(db: GeoIP_, ipnum: c_ulong, gl: &GeoIPLookup) -> *c_char;
    fn GeoIP_name_by_ipnum_v6_gl(db: GeoIP_, ipnum: In6Addr, gl: &GeoIPLookup) -> *c_char;
}

pub enum Options {
    Standard = 0,
    MemoryCache = 1,
    CheckCache = 2,
    IndexCache = 4,
    MmapCache = 8
}

pub enum DBType {
    CountryEdition = 1,
    RegionEditionRev0 = 7,
    CityEditionRev0 = 6,
    ORGEdition = 5,
    ISPEdition = 4,
    CityEditionRev1 = 2,
    RegionEditionRev1 = 3,
    ProxyEdition = 8,
    ASNUMEdition = 9,
    NetSpeedEdition = 10,
    DomainEdition = 11,
    CountryEditionV6 = 12,
    LocationAEdition = 13,
    AccuracyRadiusEdition = 14,
    LargeCountryEdition = 17,
    LargeCountryEditionV6 = 18,
    ASNumEditionV6 = 21,
    ISPEditionV6 = 22,
    ORGEditionV6 = 23,
    DomainEditionV6 = 24,
    LoctionAEditionV6 = 25,
    RegistrarEdition = 26,
    RegistrarEditionV6 = 27,
    UserTypeEdition = 28,
    UserTypeEditionV6 = 29,
    CityEditionRev1V6 = 30,
    CityEditionRev0V6 = 31,
    NetSpeedEditionRev1 = 32,
    NetSpeedEditionRev1V6 = 33,
    CountryConfEdition = 34,
    CityConfEdition = 35,
    RegionConfEdition = 36,
    PostalConfEdition = 37,
    AccuracyRadiusEditionV6 = 38
}

pub struct GeoIP {
    db: GeoIP_
}

pub struct ASInfo {
    pub asn: uint,
    pub name: ~str,
    pub netmask: uint
}

impl fmt::Show for ASInfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}\t{}", self.asn, self.name)
    }
}

impl GeoIP {
    pub fn open(path: &Path, options: Options) -> Result<GeoIP, ~str> {
        let file = match path.as_str() {
            None => return Err(format!("Invalid path {}", path.display())),
            Some(file) => file
        };
        let db = unsafe {
            GeoIP_open(file.to_c_str().unwrap(), options as c_int)
        };
        match db.is_null() {
            true => Err(format!("Can't open {}", file)),
            false => Ok(GeoIP {
                    db: db
                })
        }
    }

    pub fn as_info_by_ip(&self, ip: IpAddr) -> Option<ASInfo> {
        let gl = GeoIPLookup::new();
        let cres = match ip {
            Ipv4Addr(a, b, c, d) => {
                let ipnum: c_ulong =
                    (a as c_ulong << 24) | (b as c_ulong << 16) |
                    (c as c_ulong << 8)  | (d as c_ulong);
                unsafe {
                    GeoIP_name_by_ipnum_gl(self.db, ipnum, &gl)
                }
            },
            Ipv6Addr(a, b, c, d, e, f, g, h) => {
                let in6_addr: In6Addr = [(a >> 8) as u8, a as u8,
                                         (b >> 8) as u8, b as u8,
                                         (c >> 8) as u8, c as u8,
                                         (d >> 8) as u8, d as u8,
                                         (e >> 8) as u8, e as u8,
                                         (f >> 8) as u8, f as u8,
                                         (g >> 8) as u8, g as u8,
                                         (h >> 8) as u8, h as u8];
                unsafe {
                    GeoIP_name_by_ipnum_v6_gl(self.db, in6_addr, &gl)
                }
            }
        };
        if cres.is_null() {
            return None;
        }
        let description_cstr = unsafe { CString::new(cres, true) };
        let description = match description_cstr.as_str() {
            None => return None,
            Some(description) => description
        };
        let mut di = description.splitn(' ', 1);
        let asn = match di.next() {
            None => return None,
            Some(asn) => {
                if ! asn.starts_with("AS") {
                    return None
                } else {
                    from_str::<uint>(asn.slice_from(2)).unwrap()
                }
            }
        };
        let name = di.next().unwrap_or("(none)");
        let asinfo = ASInfo {
            asn: asn,
            name: name.to_owned(),
            netmask: gl.netmask as uint
        };
        Some(asinfo)
    }
}

impl Drop for GeoIP {
    fn drop(&mut self) {
        unsafe {
            GeoIP_delete(self.db);
        }
    }
}

#[test]
fn geoip_test_basic() {
    let geoip = match GeoIP::open(&from_str("/opt/geoip/GeoIPASNum.dat").unwrap(), MemoryCache) {
        Err(err) => fail!(err),
        Ok(geoip) => geoip
    };
    let ip = from_str("91.203.184.192").unwrap();
    let res = geoip.as_info_by_ip(ip).unwrap();
    assert!(res.asn == 41064);
    assert!(res.name.contains("Telefun"));
    assert!(res.netmask == 22);
}
<commit_msg>~str is gone<commit_after>// (C)opyleft 2013 Frank Denis

/*!
 * Bindings for the GeoIP library
 */
#![desc = "Bindings for the GeoIP library."]
#![license = "BSD"]
#![crate_id = "geoip#0.1"]
#![crate_type = "rlib"]

#![warn(non_camel_case_types,
        non_uppercase_statics,
        unnecessary_qualification,
        managed_heap_memory)]

extern crate libc;

use libc::{c_void, c_char, c_int, c_ulong};
use std::c_str::CString;
use std::fmt;
use std::io::net::ip::{IpAddr,Ipv4Addr,Ipv6Addr};

type GeoIP_ = *c_void;
type In6Addr = [u8, ..16];

struct GeoIPLookup {
    netmask: c_int
}

impl GeoIPLookup {
    fn new() -> GeoIPLookup {
        GeoIPLookup {
            netmask: 0
        }
    }
}

#[link(name = "GeoIP")]
extern {
    fn GeoIP_open(dbtype: *c_char, flags: c_int) -> GeoIP_;
    fn GeoIP_delete(db: GeoIP_);
    fn GeoIP_name_by_ipnum_gl(db: GeoIP_, ipnum: c_ulong, gl: &GeoIPLookup) -> *c_char;
    fn GeoIP_name_by_ipnum_v6_gl(db: GeoIP_, ipnum: In6Addr, gl: &GeoIPLookup) -> *c_char;
}

pub enum Options {
    Standard = 0,
    MemoryCache = 1,
    CheckCache = 2,
    IndexCache = 4,
    MmapCache = 8
}

pub enum DBType {
    CountryEdition = 1,
    RegionEditionRev0 = 7,
    CityEditionRev0 = 6,
    ORGEdition = 5,
    ISPEdition = 4,
    CityEditionRev1 = 2,
    RegionEditionRev1 = 3,
    ProxyEdition = 8,
    ASNUMEdition = 9,
    NetSpeedEdition = 10,
    DomainEdition = 11,
    CountryEditionV6 = 12,
    LocationAEdition = 13,
    AccuracyRadiusEdition = 14,
    LargeCountryEdition = 17,
    LargeCountryEditionV6 = 18,
    ASNumEditionV6 = 21,
    ISPEditionV6 = 22,
    ORGEditionV6 = 23,
    DomainEditionV6 = 24,
    LoctionAEditionV6 = 25,
    RegistrarEdition = 26,
    RegistrarEditionV6 = 27,
    UserTypeEdition = 28,
    UserTypeEditionV6 = 29,
    CityEditionRev1V6 = 30,
    CityEditionRev0V6 = 31,
    NetSpeedEditionRev1 = 32,
    NetSpeedEditionRev1V6 = 33,
    CountryConfEdition = 34,
    CityConfEdition = 35,
    RegionConfEdition = 36,
    PostalConfEdition = 37,
    AccuracyRadiusEditionV6 = 38
}

pub struct GeoIP {
    db: GeoIP_
}

pub struct ASInfo {
    pub asn: uint,
    pub name: StrBuf,
    pub netmask: uint
}

impl fmt::Show for ASInfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}\t{}", self.asn, self.name)
    }
}

impl GeoIP {
    pub fn open(path: &Path, options: Options) -> Result<GeoIP, StrBuf> {
        let file = match path.as_str() {
            None => return Err(format!("Invalid path {}", path.display())),
            Some(file) => file
        };
        let db = unsafe {
            GeoIP_open(file.to_c_str().unwrap(), options as c_int)
        };
        match db.is_null() {
            true => Err(format!("Can't open {}", file)),
            false => Ok(GeoIP {
                    db: db
                })
        }
    }

    pub fn as_info_by_ip(&self, ip: IpAddr) -> Option<ASInfo> {
        let gl = GeoIPLookup::new();
        let cres = match ip {
            Ipv4Addr(a, b, c, d) => {
                let ipnum: c_ulong =
                    (a as c_ulong << 24) | (b as c_ulong << 16) |
                    (c as c_ulong << 8)  | (d as c_ulong);
                unsafe {
                    GeoIP_name_by_ipnum_gl(self.db, ipnum, &gl)
                }
            },
            Ipv6Addr(a, b, c, d, e, f, g, h) => {
                let in6_addr: In6Addr = [(a >> 8) as u8, a as u8,
                                         (b >> 8) as u8, b as u8,
                                         (c >> 8) as u8, c as u8,
                                         (d >> 8) as u8, d as u8,
                                         (e >> 8) as u8, e as u8,
                                         (f >> 8) as u8, f as u8,
                                         (g >> 8) as u8, g as u8,
                                         (h >> 8) as u8, h as u8];
                unsafe {
                    GeoIP_name_by_ipnum_v6_gl(self.db, in6_addr, &gl)
                }
            }
        };
        if cres.is_null() {
            return None;
        }
        let description_cstr = unsafe { CString::new(cres, true) };
        let description = match description_cstr.as_str() {
            None => return None,
            Some(description) => description
        };
        let mut di = description.splitn(' ', 1);
        let asn = match di.next() {
            None => return None,
            Some(asn) => {
                if ! asn.starts_with("AS") {
                    return None
                } else {
                    from_str::<uint>(asn.slice_from(2)).unwrap()
                }
            }
        };
        let name = di.next().unwrap_or("(none)");
        let asinfo = ASInfo {
            asn: asn,
            name: name.to_owned(),
            netmask: gl.netmask as uint
        };
        Some(asinfo)
    }
}

impl Drop for GeoIP {
    fn drop(&mut self) {
        unsafe {
            GeoIP_delete(self.db);
        }
    }
}

#[test]
fn geoip_test_basic() {
    let geoip = match GeoIP::open(&from_str("/opt/geoip/GeoIPASNum.dat").unwrap(), MemoryCache) {
        Err(err) => fail!(err),
        Ok(geoip) => geoip
    };
    let ip = from_str("91.203.184.192").unwrap();
    let res = geoip.as_info_by_ip(ip).unwrap();
    assert!(res.asn == 41064);
    assert!(res.name.as_slice().contains("Telefun"));
    assert!(res.netmask == 22);
}
<|endoftext|>


<commit_before>use std::fs::{ File, OpenOptions };
use std::io::{ BufRead, BufReader, Write };
use std::path::Path;

fn parse_list(path: &Path) -> Result<Vec<(String, u32)>, String> {
    let list = match File::open(path) {
        Ok(x) => x,
        Err(why) => return Err(format!("{}", why))
    };
    let list = BufReader::new(list);

    let mut parsed_packages = Vec::new();
    for line in list.lines() {
        let line = line.unwrap_or("".to_string());
        let split: Vec<&str> = line.trim().split('=').collect();
        let package_name = String::from(split[0]);
        let package_version = split[1].parse::<u32>().unwrap_or(0); // For this reason, version of packages MUST NOT BE 0

        if !package_name.is_empty() || package_version != 0 {
            parsed_packages.push((package_name, package_version));
        }
    }

    if parsed_packages.len() > 0 {
        return Ok(parsed_packages)
    } else {
        return Err(String::from("No package found."))
    }
}

pub fn get_version(name: &str, path: &Path) -> Option<u32> {
    //TODO:
    //  Gets the version of the package
    let list = match parse_list(path) {
        Ok(x) => x,
        Err(why) => return None
    };

    for package in list {
        if package.0 == name {
            return Some(package.1)
        }
    }

    return None
}

pub fn update_version(name: &str, version: u32, path: &Path) -> Result<bool, String>{
    let mut list = match parse_list(path) {
        Ok(x) => x,
        Err(why) => return Err(format!("{}", why))
    };

    list.retain(|ref x| x.0 == name);

    if list.len() == 0 {
        let mut file = match OpenOptions::new()
                    .append(true)
                    .write(true)
                    .create(true)
                    .open("installed_packages") {
            Ok(x) => x,
            Err(why) => return Err(format!("{}", why))
        };

        writeln!(file, "{}={}\n", name, version);
        return Ok(true);
    } else if list.len() == 1 {
        if list[0].1 == version {
            return Ok(false)
        } else {
            let mut updated_list = String::new();
            {
                let file = match File::open("installed_packages") {
                    Ok(x) => x,
                    Err(why) => return Err(format!("{}", why))
                };

                let file = BufReader::new(file);
                for line in file.lines() {
                    let current_line = line.unwrap();
                    if current_line.contains(name) {
                        updated_list += name;
                        updated_list += "=";
                        updated_list += &(version.to_string());
                        updated_list += "\n";
                    } else {
                        updated_list += current_line.trim();
                    }
                }
            }

            {
                let mut file = match File::open("installed_packages") {
                    Ok(x) => x,
                    Err(why) => return Err(format!("{}", why))
                };

                file.write_all(updated_list.as_bytes());
            }
            return Ok(true);
        }
    } else {
        return Err("There are two or more packages with the same name, this shouldn't happen!".to_string());
    }
}
<commit_msg>Remove unused variable<commit_after>use std::fs::{ File, OpenOptions };
use std::io::{ BufRead, BufReader, Write };
use std::path::Path;

fn parse_list(path: &Path) -> Result<Vec<(String, u32)>, String> {
    let list = match File::open(path) {
        Ok(x) => x,
        Err(why) => return Err(format!("{}", why))
    };
    let list = BufReader::new(list);

    let mut parsed_packages = Vec::new();
    for line in list.lines() {
        let line = line.unwrap_or("".to_string());
        let split: Vec<&str> = line.trim().split('=').collect();
        let package_name = String::from(split[0]);
        let package_version = split[1].parse::<u32>().unwrap_or(0); // For this reason, version of packages MUST NOT BE 0

        if !package_name.is_empty() || package_version != 0 {
            parsed_packages.push((package_name, package_version));
        }
    }

    if parsed_packages.len() > 0 {
        return Ok(parsed_packages)
    } else {
        return Err(String::from("No package found."))
    }
}

pub fn get_version(name: &str, path: &Path) -> Option<u32> {
    //TODO:
    //  Gets the version of the package
    let list = match parse_list(path) {
        Ok(x) => x,
        Err(_) => return None
    };

    for package in list {
        if package.0 == name {
            return Some(package.1)
        }
    }

    return None
}

pub fn update_version(name: &str, version: u32, path: &Path) -> Result<bool, String>{
    let mut list = match parse_list(path) {
        Ok(x) => x,
        Err(why) => return Err(format!("{}", why))
    };

    list.retain(|ref x| x.0 == name);

    if list.len() == 0 {
        let mut file = match OpenOptions::new()
                    .append(true)
                    .write(true)
                    .create(true)
                    .open("installed_packages") {
            Ok(x) => x,
            Err(why) => return Err(format!("{}", why))
        };

        writeln!(file, "{}={}\n", name, version);
        return Ok(true);
    } else if list.len() == 1 {
        if list[0].1 == version {
            return Ok(false)
        } else {
            let mut updated_list = String::new();
            {
                let file = match File::open("installed_packages") {
                    Ok(x) => x,
                    Err(why) => return Err(format!("{}", why))
                };

                let file = BufReader::new(file);
                for line in file.lines() {
                    let current_line = line.unwrap();
                    if current_line.contains(name) {
                        updated_list += name;
                        updated_list += "=";
                        updated_list += &(version.to_string());
                        updated_list += "\n";
                    } else {
                        updated_list += current_line.trim();
                    }
                }
            }

            {
                let mut file = match File::open("installed_packages") {
                    Ok(x) => x,
                    Err(why) => return Err(format!("{}", why))
                };

                file.write_all(updated_list.as_bytes());
            }
            return Ok(true);
        }
    } else {
        return Err("There are two or more packages with the same name, this shouldn't happen!".to_string());
    }
}
<|endoftext|>


<commit_before>extern crate serde;
extern crate serde_json;
extern crate time;
extern crate uuid;
extern crate http_event_store as es;

mod support;
use support::*;

use es::event::Event;
use es::client::Client;
use es::expected_version::ExpectedVersion;
use es::error::HesError::*;
use es::error::UserErrorKind::*;

#[test]
fn it_appends_events_in_right_order() {
    let events: Vec<Event> = vec![
        TaskCreated { name: format!("Created {:?}", time::get_time()), event_id: uuid::Uuid::parse_str("baca1a30-b6f1-470b-b68e-f79338020327").unwrap() }.into(),
        TaskRenamed { name: format!("Renamed {:?}", time::get_time()), event_id: uuid::Uuid::parse_str("cbad187b-2fd0-4ad2-b78b-80d83f1ff303").unwrap() }.into()
    ];

    let client = Client::default();
    let stream_name = test_stream_name();
    client.append_to_stream(&stream_name, ExpectedVersion::NotExist, events).unwrap();
    let stream = client.read_stream_events_forward(&stream_name, 0, 2, true).unwrap();

    assert_eq!("task-renamed", stream.entries[0].event_type);
    assert_eq!("task-created", stream.entries[1].event_type);
    assert_eq!("cbad187b-2fd0-4ad2-b78b-80d83f1ff303", stream.entries[0].event_id);
    assert_eq!("baca1a30-b6f1-470b-b68e-f79338020327", stream.entries[1].event_id);
}

#[test]
fn it_requires_expected_version_to_be_correct() {
    let client = Client::default();
    let stream_name = test_stream_name();

    let mut version = ExpectedVersion::NotExist;
    client.append_to_stream(&stream_name, version, vec![task_created_event().into()]).unwrap();
    assert_eq!(1, client.read_stream_events_forward(&stream_name, 0, 3, true).unwrap().entries.len());

    version = ExpectedVersion::Number(0);
    client.append_to_stream(&stream_name, version, vec![task_renamed_event().into()]).unwrap();
    assert_eq!(2, client.read_stream_events_forward(&stream_name, 0, 3, true).unwrap().entries.len());

    version = ExpectedVersion::Number(1);
    client.append_to_stream(&stream_name, version, vec![task_renamed_event().into()]).unwrap();
    assert_eq!(3, client.read_stream_events_forward(&stream_name, 0, 3, true).unwrap().entries.len());

    println!("{:?}", client.read_stream_events_forward(&stream_name, 0, 3, true).unwrap().entries)
}

#[test]
fn it_returns_event_number_mismatch_error_if_expected_version_is_wrong() {
    let client = Client::default();
    let stream_name = test_stream_name();

    let version = ExpectedVersion::Number(1);
    let result = client.append_to_stream(&stream_name, version, vec![task_created_event().into()]);

    match result {
        Err(e) => match e {
            UserError(client_error) => {
                match client_error {
                    EventNumberMismatch(_) => assert!(true),
                    _ => assert!(false)
                }
            },
            _ => assert!(false)
        },
        _ => assert!(false)
    }
}

#[test]
fn it_returns_bad_request_error_if_event_data_is_malformed()  {
    let client = Client::default();
    let stream_name = test_stream_name();

    let malformed_event = es::event::Event {
        event_id: uuid::Uuid::new_v4(),
        event_type: "task-created".to_string(),
        data: Some("?-/*".to_string())
    };
    let result = client.append_to_stream(&stream_name, ExpectedVersion::NotExist, vec![malformed_event]);

    match result {
        Err(e) => match e {
            UserError(client_error) => {
                match client_error {
                    BadRequest(_) => assert!(true),
                    _ => assert!(false)
                }
            },
            _ => assert!(false)
        },
        _ => assert!(false)
    }
}

fn test_stream_name() -> String {
    format!("task-{}", uuid::Uuid::new_v4().simple())
}

fn task_created_event() -> TaskCreated {
    TaskCreated { name: format!("Created {:?}", time::get_time()), event_id: uuid::Uuid::new_v4() }
}
fn task_renamed_event() -> TaskRenamed {
    TaskRenamed { name: format!("Renamed {:?}", time::get_time()), event_id: uuid::Uuid::new_v4() }
}
<commit_msg>Refactor tests<commit_after>extern crate serde;
extern crate serde_json;
extern crate time;
extern crate uuid;
extern crate http_event_store as hes;

mod support;
use support::*;

use hes::event::Event;
use hes::client::Client;
use hes::expected_version::ExpectedVersion;
use hes::error::HesError::*;
use hes::error::UserErrorKind::*;
use hes::types::Result as HesResult;

macro_rules! assert_user_error {
    ($kind:pat, $actual_error:expr) => ({
        assert!(
            match $actual_error {
                hes::error::HesError::UserError(k) => {
                      match k {
                          $kind => true,
                          _ => false
                      }
                },
                _ => false
        })

    })
}

#[test]
fn it_appends_events_in_right_order() {
    let events: Vec<Event> = vec![
        TaskCreated { name: format!("Created {:?}", time::get_time()), event_id: uuid::Uuid::parse_str("baca1a30-b6f1-470b-b68e-f79338020327").unwrap() }.into(),
        TaskRenamed { name: format!("Renamed {:?}", time::get_time()), event_id: uuid::Uuid::parse_str("cbad187b-2fd0-4ad2-b78b-80d83f1ff303").unwrap() }.into()
    ];

    let client = Client::default();
    let stream_name = test_stream_name();
    client.append_to_stream(&stream_name, ExpectedVersion::NotExist, events).unwrap();
    let stream = client.read_stream_events_forward(&stream_name, 0, 2, true).unwrap();

    assert_eq!("task-renamed", stream.entries[0].event_type);
    assert_eq!("task-created", stream.entries[1].event_type);
    assert_eq!("cbad187b-2fd0-4ad2-b78b-80d83f1ff303", stream.entries[0].event_id);
    assert_eq!("baca1a30-b6f1-470b-b68e-f79338020327", stream.entries[1].event_id);
}

#[test]
fn it_requires_expected_version_to_be_correct() {
    let client = Client::default();
    let stream_name = test_stream_name();

    let mut version = ExpectedVersion::NotExist;
    client.append_to_stream(&stream_name, version, vec![task_created_event().into()]).unwrap();
    assert_eq!(1, client.read_stream_events_forward(&stream_name, 0, 3, true).unwrap().entries.len());

    version = ExpectedVersion::Number(0);
    client.append_to_stream(&stream_name, version, vec![task_renamed_event().into()]).unwrap();
    assert_eq!(2, client.read_stream_events_forward(&stream_name, 0, 3, true).unwrap().entries.len());

    version = ExpectedVersion::Number(1);
    client.append_to_stream(&stream_name, version, vec![task_renamed_event().into()]).unwrap();
    assert_eq!(3, client.read_stream_events_forward(&stream_name, 0, 3, true).unwrap().entries.len());

    println!("{:?}", client.read_stream_events_forward(&stream_name, 0, 3, true).unwrap().entries)
}

#[test]
fn it_returns_event_number_mismatch_error_if_expected_version_is_wrong() {
    let client = Client::default();
    let stream_name = test_stream_name();

    let version = ExpectedVersion::Number(1);
    let result = client.append_to_stream(&stream_name, version, vec![task_created_event().into()]);

    assert_user_error!(EventNumberMismatch(..), result.unwrap_err());
}

#[test]
fn it_returns_bad_request_error_if_event_data_is_malformed() {
    let client = Client::default();
    let stream_name = test_stream_name();

    let malformed_event = hes::event::Event {
        event_id: uuid::Uuid::new_v4(),
        event_type: "task-created".to_string(),
        data: Some("?-/*".to_string())
    };
    let result = client.append_to_stream(&stream_name, ExpectedVersion::NotExist, vec![malformed_event]);

    assert_user_error!(BadRequest(..), result.unwrap_err());
}

fn test_stream_name() -> String {
    format!("task-{}", uuid::Uuid::new_v4().simple())
}

fn task_created_event() -> TaskCreated {
    TaskCreated { name: format!("Created {:?}", time::get_time()), event_id: uuid::Uuid::new_v4() }
}
fn task_renamed_event() -> TaskRenamed {
    TaskRenamed { name: format!("Renamed {:?}", time::get_time()), event_id: uuid::Uuid::new_v4() }
}
<|endoftext|>


<commit_before>use super::{fieldnorm_to_id, id_to_fieldnorm};
use crate::common::CompositeFile;
use crate::directory::FileSlice;
use crate::directory::OwnedBytes;
use crate::schema::Field;
use crate::space_usage::PerFieldSpaceUsage;
use crate::DocId;
use std::sync::Arc;

/// Reader for the fieldnorm (for each document, the number of tokens indexed in the
/// field) of all indexed fields in the index.
///
/// Each fieldnorm is approximately compressed over one byte. We refer to this byte as
/// `fieldnorm_id`.
/// The mapping from `fieldnorm` to `fieldnorm_id` is given by monotonic.
#[derive(Clone)]
pub struct FieldNormReaders {
    data: Arc<CompositeFile>,
}

impl FieldNormReaders {
    /// Creates a field norm reader.
    pub fn open(file: FileSlice) -> crate::Result<FieldNormReaders> {
        let data = CompositeFile::open(&file)?;
        Ok(FieldNormReaders {
            data: Arc::new(data),
        })
    }

    /// Returns the FieldNormReader for a specific field.
    pub fn get_field(&self, field: Field) -> crate::Result<Option<FieldNormReader>> {
        if let Some(file) = self.data.open_read(field) {
            let fieldnorm_reader = FieldNormReader::open(file)?;
            Ok(Some(fieldnorm_reader))
        } else {
            Ok(None)
        }
    }

    /// Return a break down of the space usage per field.
    pub fn space_usage(&self) -> PerFieldSpaceUsage {
        self.data.space_usage()
    }
}

/// Reads the fieldnorm associated to a document.
/// The fieldnorm represents the length associated to
/// a given Field of a given document.
///
/// This metric is important to compute the score of a
/// document : a document having a query word in one its short fields
/// (e.g. title)  is likely to be more relevant than in one of its longer field
/// (e.g. body).
///
/// tantivy encodes `fieldnorm` on one byte with some precision loss,
/// using the same scheme as Lucene. Each value is place on a log-scale
/// that takes values from `0` to `255`.
///
/// A value on this scale is identified by a `fieldnorm_id`.
/// Apart from compression, this scale also makes it possible to
/// precompute computationally expensive functions of the fieldnorm
/// in a very short array.
#[derive(Clone)]
pub struct FieldNormReader {
    data: OwnedBytes,
}

impl FieldNormReader {
    /// Creates a `FieldNormReader` with a constant fieldnorm.
    pub fn constant(num_docs: u32, fieldnorm: u32) -> FieldNormReader {
        let fieldnorm_id = fieldnorm_to_id(fieldnorm);
        let field_norms_data = OwnedBytes::new(vec![fieldnorm_id; num_docs as usize]);
        FieldNormReader::new(field_norms_data)
    }

    /// Opens a field norm reader given its file.
    pub fn open(fieldnorm_file: FileSlice) -> crate::Result<Self> {
        let data = fieldnorm_file.read_bytes()?;
        Ok(FieldNormReader::new(data))
    }

    fn new(data: OwnedBytes) -> Self {
        FieldNormReader { data }
    }

    /// Returns the number of documents in this segment.
    pub fn num_docs(&self) -> u32 {
        self.data.len() as u32
    }

    /// Returns the `fieldnorm` associated to a doc id.
    /// The fieldnorm is a value approximating the number
    /// of tokens in a given field of the `doc_id`.
    ///
    /// It is imprecise, and always lower than the actual
    /// number of tokens.
    ///
    /// The fieldnorm is effectively decoded from the
    /// `fieldnorm_id` by doing a simple table lookup.
    pub fn fieldnorm(&self, doc_id: DocId) -> u32 {
        let fieldnorm_id = self.fieldnorm_id(doc_id);
        id_to_fieldnorm(fieldnorm_id)
    }

    /// Returns the `fieldnorm_id` associated to a document.
    #[inline(always)]
    pub fn fieldnorm_id(&self, doc_id: DocId) -> u8 {
        self.data.as_slice()[doc_id as usize]
    }

    /// Converts a `fieldnorm_id` into a fieldnorm.
    #[inline(always)]
    pub fn id_to_fieldnorm(id: u8) -> u32 {
        id_to_fieldnorm(id)
    }

    /// Converts a `fieldnorm` into a `fieldnorm_id`.
    /// (This function is not injective).
    #[inline(always)]
    pub fn fieldnorm_to_id(fieldnorm: u32) -> u8 {
        fieldnorm_to_id(fieldnorm)
    }

    #[cfg(test)]
    pub fn for_test(field_norms: &[u32]) -> FieldNormReader {
        let field_norms_id = field_norms
            .iter()
            .cloned()
            .map(FieldNormReader::fieldnorm_to_id)
            .collect::<Vec<u8>>();
        let field_norms_data = OwnedBytes::new(field_norms_id);
        FieldNormReader {
            data: field_norms_data,
        }
    }
}

#[cfg(test)]
mod tests {
    use crate::fieldnorm::FieldNormReader;

    #[test]
    fn test_from_fieldnorms_array() {
        let fieldnorms = &[1, 2, 3, 4, 1_000_000];
        let fieldnorm_reader = FieldNormReader::for_test(fieldnorms);
        assert_eq!(fieldnorm_reader.num_docs(), 5);
        assert_eq!(fieldnorm_reader.fieldnorm(0), 1);
        assert_eq!(fieldnorm_reader.fieldnorm(1), 2);
        assert_eq!(fieldnorm_reader.fieldnorm(2), 3);
        assert_eq!(fieldnorm_reader.fieldnorm(3), 4);
        assert_eq!(fieldnorm_reader.fieldnorm(4), 983_064);
    }
}
<commit_msg>Fix perf regression in the benchmark for the Count collector.<commit_after>use super::{fieldnorm_to_id, id_to_fieldnorm};
use crate::common::CompositeFile;
use crate::directory::FileSlice;
use crate::directory::OwnedBytes;
use crate::schema::Field;
use crate::space_usage::PerFieldSpaceUsage;
use crate::DocId;
use std::sync::Arc;

/// Reader for the fieldnorm (for each document, the number of tokens indexed in the
/// field) of all indexed fields in the index.
///
/// Each fieldnorm is approximately compressed over one byte. We refer to this byte as
/// `fieldnorm_id`.
/// The mapping from `fieldnorm` to `fieldnorm_id` is given by monotonic.
#[derive(Clone)]
pub struct FieldNormReaders {
    data: Arc<CompositeFile>,
}

impl FieldNormReaders {
    /// Creates a field norm reader.
    pub fn open(file: FileSlice) -> crate::Result<FieldNormReaders> {
        let data = CompositeFile::open(&file)?;
        Ok(FieldNormReaders {
            data: Arc::new(data),
        })
    }

    /// Returns the FieldNormReader for a specific field.
    pub fn get_field(&self, field: Field) -> crate::Result<Option<FieldNormReader>> {
        if let Some(file) = self.data.open_read(field) {
            let fieldnorm_reader = FieldNormReader::open(file)?;
            Ok(Some(fieldnorm_reader))
        } else {
            Ok(None)
        }
    }

    /// Return a break down of the space usage per field.
    pub fn space_usage(&self) -> PerFieldSpaceUsage {
        self.data.space_usage()
    }
}

/// Reads the fieldnorm associated to a document.
/// The fieldnorm represents the length associated to
/// a given Field of a given document.
///
/// This metric is important to compute the score of a
/// document : a document having a query word in one its short fields
/// (e.g. title)  is likely to be more relevant than in one of its longer field
/// (e.g. body).
///
/// tantivy encodes `fieldnorm` on one byte with some precision loss,
/// using the same scheme as Lucene. Each value is place on a log-scale
/// that takes values from `0` to `255`.
///
/// A value on this scale is identified by a `fieldnorm_id`.
/// Apart from compression, this scale also makes it possible to
/// precompute computationally expensive functions of the fieldnorm
/// in a very short array.
#[derive(Clone)]
pub struct FieldNormReader(ReaderImplEnum);

impl From<ReaderImplEnum> for FieldNormReader {
    fn from(reader_enum: ReaderImplEnum) -> FieldNormReader {
        FieldNormReader(reader_enum)
    }
}

#[derive(Clone)]
enum ReaderImplEnum {
    FromData(OwnedBytes),
    Const {
        num_docs: u32,
        fieldnorm_id: u8,
        fieldnorm: u32,
    },
}

impl FieldNormReader {
    /// Creates a `FieldNormReader` with a constant fieldnorm.
    ///
    /// The fieldnorm will be subjected to compression as if it was coming
    /// from an array-backed fieldnorm reader.
    pub fn constant(num_docs: u32, fieldnorm: u32) -> FieldNormReader {
        let fieldnorm_id = fieldnorm_to_id(fieldnorm);
        let fieldnorm = id_to_fieldnorm(fieldnorm_id);
        ReaderImplEnum::Const {
            num_docs,
            fieldnorm_id,
            fieldnorm,
        }
        .into()
    }

    /// Opens a field norm reader given its file.
    pub fn open(fieldnorm_file: FileSlice) -> crate::Result<Self> {
        let data = fieldnorm_file.read_bytes()?;
        Ok(FieldNormReader::new(data))
    }

    fn new(data: OwnedBytes) -> Self {
        ReaderImplEnum::FromData(data).into()
    }

    /// Returns the number of documents in this segment.
    pub fn num_docs(&self) -> u32 {
        match &self.0 {
            ReaderImplEnum::FromData(data) => data.len() as u32,
            ReaderImplEnum::Const { num_docs, .. } => *num_docs,
        }
    }

    /// Returns the `fieldnorm` associated to a doc id.
    /// The fieldnorm is a value approximating the number
    /// of tokens in a given field of the `doc_id`.
    ///
    /// It is imprecise, and always lower than the actual
    /// number of tokens.
    ///
    /// The fieldnorm is effectively decoded from the
    /// `fieldnorm_id` by doing a simple table lookup.
    pub fn fieldnorm(&self, doc_id: DocId) -> u32 {
        match &self.0 {
            ReaderImplEnum::FromData(data) => {
                let fieldnorm_id = data.as_slice()[doc_id as usize];
                id_to_fieldnorm(fieldnorm_id)
            }
            ReaderImplEnum::Const { fieldnorm, .. } => *fieldnorm,
        }
    }

    /// Returns the `fieldnorm_id` associated to a document.
    #[inline(always)]
    pub fn fieldnorm_id(&self, doc_id: DocId) -> u8 {
        match &self.0 {
            ReaderImplEnum::FromData(data) => {
                let fieldnorm_id = data.as_slice()[doc_id as usize];
                fieldnorm_id
            }
            ReaderImplEnum::Const { fieldnorm_id, .. } => *fieldnorm_id,
        }
    }

    /// Converts a `fieldnorm_id` into a fieldnorm.
    #[inline(always)]
    pub fn id_to_fieldnorm(id: u8) -> u32 {
        id_to_fieldnorm(id)
    }

    /// Converts a `fieldnorm` into a `fieldnorm_id`.
    /// (This function is not injective).
    #[inline(always)]
    pub fn fieldnorm_to_id(fieldnorm: u32) -> u8 {
        fieldnorm_to_id(fieldnorm)
    }

    #[cfg(test)]
    pub fn for_test(field_norms: &[u32]) -> FieldNormReader {
        let field_norms_id = field_norms
            .iter()
            .cloned()
            .map(FieldNormReader::fieldnorm_to_id)
            .collect::<Vec<u8>>();
        let field_norms_data = OwnedBytes::new(field_norms_id);
        FieldNormReader::new(field_norms_data)
    }
}

#[cfg(test)]
mod tests {
    use crate::fieldnorm::FieldNormReader;

    #[test]
    fn test_from_fieldnorms_array() {
        let fieldnorms = &[1, 2, 3, 4, 1_000_000];
        let fieldnorm_reader = FieldNormReader::for_test(fieldnorms);
        assert_eq!(fieldnorm_reader.num_docs(), 5);
        assert_eq!(fieldnorm_reader.fieldnorm(0), 1);
        assert_eq!(fieldnorm_reader.fieldnorm(1), 2);
        assert_eq!(fieldnorm_reader.fieldnorm(2), 3);
        assert_eq!(fieldnorm_reader.fieldnorm(3), 4);
        assert_eq!(fieldnorm_reader.fieldnorm(4), 983_064);
    }

    #[test]
    fn test_const_fieldnorm_reader_small_fieldnorm_id() {
        let fieldnorm_reader = FieldNormReader::constant(1_000_000u32, 10u32);
        assert_eq!(fieldnorm_reader.num_docs(), 1_000_000u32);
        assert_eq!(fieldnorm_reader.fieldnorm(0u32), 10u32);
        assert_eq!(fieldnorm_reader.fieldnorm_id(0u32), 10u8);
    }

    #[test]
    fn test_const_fieldnorm_reader_large_fieldnorm_id() {
        let fieldnorm_reader = FieldNormReader::constant(1_000_000u32, 300u32);
        assert_eq!(fieldnorm_reader.num_docs(), 1_000_000u32);
        assert_eq!(fieldnorm_reader.fieldnorm(0u32), 280u32);
        assert_eq!(fieldnorm_reader.fieldnorm_id(0u32), 72u8);
    }
}
<|endoftext|>


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

//! A simple test for testing many permutations of allowedness of
//! impl Trait
use std::fmt::Debug;

// Allowed
fn in_parameters(_: impl Debug) { panic!() }

// Allowed
fn in_return() -> impl Debug { panic!() }

// Allowed
fn in_adt_in_parameters(_: Vec<impl Debug>) { panic!() }

// Allowed
fn in_adt_in_return() -> Vec<impl Debug> { panic!() }

// Disallowed
fn in_fn_parameter_in_parameters(_: fn(impl Debug)) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
fn in_fn_return_in_parameters(_: fn() -> impl Debug) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
fn in_fn_parameter_in_return() -> fn(impl Debug) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
fn in_fn_return_in_return() -> fn() -> impl Debug { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
fn in_dyn_Fn_parameter_in_parameters(_: &dyn Fn(impl Debug)) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
fn in_dyn_Fn_return_in_parameters(_: &dyn Fn() -> impl Debug) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
fn in_dyn_Fn_return_in_return() -> &'static dyn Fn() -> impl Debug { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
//~^^ ERROR nested `impl Trait` is not allowed

// Disallowed
fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
//~^^ ERROR nested `impl Trait` is not allowed

// Disallowed
fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
fn in_Fn_parameter_in_generics<F: Fn(impl Debug)> (_: F) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
fn in_Fn_return_in_generics<F: Fn() -> impl Debug> (_: F) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Allowed
fn in_impl_Trait_in_parameters(_: impl Iterator<Item = impl Iterator>) { panic!() }

// Allowed
fn in_impl_Trait_in_return() -> impl IntoIterator<Item = impl IntoIterator> {
    vec![vec![0; 10], vec![12; 7], vec![8; 3]]
}

// Disallowed
struct InBraceStructField { x: impl Debug }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
struct InAdtInBraceStructField { x: Vec<impl Debug> }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
struct InTupleStructField(impl Debug);
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
enum InEnum {
    InBraceVariant { x: impl Debug },
    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
    InTupleVariant(impl Debug),
    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}

// Allowed
trait InTraitDefnParameters {
    fn in_parameters(_: impl Debug);
}

// Disallowed
trait InTraitDefnReturn {
    fn in_return() -> impl Debug;
    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}

// Allowed and disallowed in trait impls
trait DummyTrait {
    type Out;
    fn in_trait_impl_parameter(impl Debug);
    fn in_trait_impl_return() -> Self::Out;
}
impl DummyTrait for () {
    type Out = impl Debug;
    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

    fn in_trait_impl_parameter(_: impl Debug) { }
    // Allowed

    fn in_trait_impl_return() -> impl Debug { () }
    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}

// Allowed
struct DummyType;
impl DummyType {
    fn in_inherent_impl_parameters(_: impl Debug) { }
    fn in_inherent_impl_return() -> impl Debug { () }
}

// Disallowed
extern "C" {
    fn in_foreign_parameters(_: impl Debug);
    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

    fn in_foreign_return() -> impl Debug;
    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}

// Allowed
extern "C" fn in_extern_fn_parameters(_: impl Debug) {
}

// Allowed
extern "C" fn in_extern_fn_return() -> impl Debug {
    22
}

type InTypeAlias<R> = impl Debug;
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

type InReturnInTypeAlias<R> = fn() -> impl Debug;
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed in impl headers
impl PartialEq<impl Debug> for () {
    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}

// Disallowed in impl headers
impl PartialEq<()> for impl Debug {
    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}

// Disallowed in inherent impls
impl impl Debug {
    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}

// Disallowed in inherent impls
struct InInherentImplAdt<T> { t: T }
impl InInherentImplAdt<impl Debug> {
    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}

// Disallowed in where clauses
fn in_fn_where_clause()
    where impl Debug: Debug
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
{
}

// Disallowed in where clauses
fn in_adt_in_fn_where_clause()
    where Vec<impl Debug>: Debug
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
{
}

// Disallowed
fn in_trait_parameter_in_fn_where_clause<T>()
    where T: PartialEq<impl Debug>
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
{
}

// Disallowed
fn in_Fn_parameter_in_fn_where_clause<T>()
    where T: Fn(impl Debug)
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
{
}

// Disallowed
fn in_Fn_return_in_fn_where_clause<T>()
    where T: Fn() -> impl Debug
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
{
}

fn main() {
    let _in_local_variable: impl Fn() = || {};
    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
    let _in_return_in_local_variable = || -> impl Fn() { || {} };
    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}

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

//! A simple test for testing many permutations of allowedness of
//! impl Trait
use std::fmt::Debug;

// Allowed
fn in_parameters(_: impl Debug) { panic!() }

// Allowed
fn in_return() -> impl Debug { panic!() }

// Allowed
fn in_adt_in_parameters(_: Vec<impl Debug>) { panic!() }

// Allowed
fn in_adt_in_return() -> Vec<impl Debug> { panic!() }

// Disallowed
fn in_fn_parameter_in_parameters(_: fn(impl Debug)) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
fn in_fn_return_in_parameters(_: fn() -> impl Debug) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
fn in_fn_parameter_in_return() -> fn(impl Debug) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
fn in_fn_return_in_return() -> fn() -> impl Debug { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
fn in_dyn_Fn_parameter_in_parameters(_: &dyn Fn(impl Debug)) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
fn in_dyn_Fn_return_in_parameters(_: &dyn Fn() -> impl Debug) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
fn in_dyn_Fn_return_in_return() -> &'static dyn Fn() -> impl Debug { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
//~^^ ERROR nested `impl Trait` is not allowed

// Disallowed
fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
//~^^ ERROR nested `impl Trait` is not allowed

// Disallowed
fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
fn in_Fn_parameter_in_generics<F: Fn(impl Debug)> (_: F) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
fn in_Fn_return_in_generics<F: Fn() -> impl Debug> (_: F) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Allowed
fn in_impl_Trait_in_parameters(_: impl Iterator<Item = impl Iterator>) { panic!() }

// Allowed
fn in_impl_Trait_in_return() -> impl IntoIterator<Item = impl IntoIterator> {
    vec![vec![0; 10], vec![12; 7], vec![8; 3]]
}

// Disallowed
struct InBraceStructField { x: impl Debug }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
struct InAdtInBraceStructField { x: Vec<impl Debug> }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
struct InTupleStructField(impl Debug);
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
enum InEnum {
    InBraceVariant { x: impl Debug },
    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
    InTupleVariant(impl Debug),
    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}

// Allowed
trait InTraitDefnParameters {
    fn in_parameters(_: impl Debug);
}

// Disallowed
trait InTraitDefnReturn {
    fn in_return() -> impl Debug;
    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}

// Allowed and disallowed in trait impls
trait DummyTrait {
    type Out;
    fn in_trait_impl_parameter(_: impl Debug);
    fn in_trait_impl_return() -> Self::Out;
}
impl DummyTrait for () {
    type Out = impl Debug;
    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

    fn in_trait_impl_parameter(_: impl Debug) { }
    // Allowed

    fn in_trait_impl_return() -> impl Debug { () }
    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}

// Allowed
struct DummyType;
impl DummyType {
    fn in_inherent_impl_parameters(_: impl Debug) { }
    fn in_inherent_impl_return() -> impl Debug { () }
}

// Disallowed
extern "C" {
    fn in_foreign_parameters(_: impl Debug);
    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

    fn in_foreign_return() -> impl Debug;
    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}

// Allowed
extern "C" fn in_extern_fn_parameters(_: impl Debug) {
}

// Allowed
extern "C" fn in_extern_fn_return() -> impl Debug {
    22
}

type InTypeAlias<R> = impl Debug;
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

type InReturnInTypeAlias<R> = fn() -> impl Debug;
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed in impl headers
impl PartialEq<impl Debug> for () {
    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}

// Disallowed in impl headers
impl PartialEq<()> for impl Debug {
    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}

// Disallowed in inherent impls
impl impl Debug {
    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}

// Disallowed in inherent impls
struct InInherentImplAdt<T> { t: T }
impl InInherentImplAdt<impl Debug> {
    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}

// Disallowed in where clauses
fn in_fn_where_clause()
    where impl Debug: Debug
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
{
}

// Disallowed in where clauses
fn in_adt_in_fn_where_clause()
    where Vec<impl Debug>: Debug
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
{
}

// Disallowed
fn in_trait_parameter_in_fn_where_clause<T>()
    where T: PartialEq<impl Debug>
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
{
}

// Disallowed
fn in_Fn_parameter_in_fn_where_clause<T>()
    where T: Fn(impl Debug)
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
{
}

// Disallowed
fn in_Fn_return_in_fn_where_clause<T>()
    where T: Fn() -> impl Debug
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
{
}

fn main() {
    let _in_local_variable: impl Fn() = || {};
    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
    let _in_return_in_local_variable = || -> impl Fn() { || {} };
    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}

<|endoftext|>


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

//! Icosahedral sphere

use std::collections::HashMap;

use cgmath::{InnerSpace, Vector3};

use {Vertex, Triangle};
use generators::{IndexedPolygon, SharedVertex};

/// Icosahedral sphere with radius 1, centered at (0., 0., 0.)
#[derive(Clone, Debug)]
pub struct IcoSphere {
    i: usize,
    vertices: Vec<[f32; 3]>,
    faces: Vec<[usize; 3]>,
}

const T: f32 = 0.85065080835204;
const X: f32 = 0.5257311121191336;

// The vertices of a regular icosahedron can be visualised as lying at the corner points of 3
// orthogonal rectangles in 3D space.
// https://en.wikipedia.org/wiki/Regular_icosahedron#/media/File:Icosahedron-golden-rectangles.svg
// for a visualisation of this
const VERTICES: [[f32; 3]; 12] = [
    // corners of the rectangle in the XY plane
    [-X, T, 0.],
    [X, T, 0.],
    [-X, -T, 0.],
    [X, -T, 0.],

    // corners of the rectangle in the YZ plane
    [0., -X, T],
    [0., X, T],
    [0., -X, -T],
    [0., X, -T],

    // corners of the rectangle in the XZ plane
    [T, 0., -X],
    [T, 0., X],
    [-T, 0., -X],
    [-T, 0., X],
];

const FACES: [[usize; 3]; 20] = [
    // 5 faces around point 0
    [0, 11, 5],
    [0, 5, 1],
    [0, 1, 7],
    [0, 7, 10],
    [0, 10, 11],

    // 5 faces adjacent to the faces around point 0
    [1, 5, 9],
    [5, 11, 4],
    [11, 10, 2],
    [10, 7, 6],
    [7, 1, 8],

    // 5 faces around point 3
    [3, 9, 4],
    [3, 4, 2],
    [3, 2, 6],
    [3, 6, 8],
    [3, 8, 9],

    // 5 faces adjacent to the faces around point 3
    [4, 9, 5],
    [2, 4, 11],
    [6, 2, 10],
    [8, 6, 7],
    [9, 8, 1],
];

impl IcoSphere {

    /// Create a unit sphere with 20 faces and 12 vertices.
    pub fn new() -> Self {
        Self {
            i: 0,
            vertices: VERTICES.to_vec(),
            faces: FACES.to_vec(),
        }
    }

    /// Create a unit sphere with subdivision, resulting in 20 * 4^N faces, where N is the number of
    /// subdivisions.
    ///
    /// ## Parameters
    ///
    /// - `subdivides`: Number of subdivisions to perform.
    pub fn subdivide(subdivides: usize) -> Self {
        let mut vertices = VERTICES.to_vec();
        let mut faces = FACES.to_vec();

        for _ in 0..subdivides {
            let (v, f) = subdivide_impl(vertices, faces);
            vertices = v;
            faces = f;
        }

        Self {
            i: 0,
            vertices,
            faces,
        }
    }

    fn vert(&self, index: usize) -> Vertex {
        Vertex {
            pos: self.vertices[index],
            normal: self.vertices[index],
        }
    }
}

fn subdivide_impl(
    mut vertices: Vec<[f32; 3]>,
    faces: Vec<[usize; 3]>,
) -> (Vec<[f32; 3]>, Vec<[usize; 3]>) {
    let mut lookup = HashMap::<(usize, usize), usize>::default();
    let mut new_faces = Vec::<[usize; 3]>::default();
    for face in &faces {
        let mut mid: [usize; 3] = [0; 3];
        for i in 0..3 {
            let pair = (face[i], face[(i + 1) % 3]);
            // find new vertex on the edge
            mid[i] = match lookup.get(&pair) {
                Some(i) => *i,
                None => vertices.len(),
            };
            if mid[i] == vertices.len() {
                lookup.insert(pair, mid[i]);
                lookup.insert((pair.1, pair.0), mid[i]);
                let new = new_point(vertices[pair.0], vertices[pair.1]);
                vertices.push(new);
            }
        }
        new_faces.push([face[0], mid[0], mid[2]]);
        new_faces.push([face[1], mid[1], mid[0]]);
        new_faces.push([face[2], mid[2], mid[1]]);
        new_faces.push([mid[0], mid[1], mid[2]]);
    }
    (vertices, new_faces)
}

fn new_point(start: [f32; 3], end: [f32; 3]) -> [f32; 3] {
    Vector3::new(start[0] + end[0], start[1] + end[1], start[2] + end[2])
        .normalize()
        .into()
}

impl Iterator for IcoSphere {
    type Item = Triangle<Vertex>;

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.faces.len(), Some(self.faces.len()))
    }

    fn next(&mut self) -> Option<Self::Item> {
        if self.i == self.faces.len() {
            return None;
        }

        let face = self.faces[self.i];
        let x = self.vert(face[0]);
        let y = self.vert(face[1]);
        let z = self.vert(face[2]);
        self.i += 1;

        Some(Triangle::new(x, y, z))
    }
}

impl SharedVertex<Vertex> for IcoSphere {
    fn shared_vertex_count(&self) -> usize {
        self.vertices.len()
    }

    fn shared_vertex(&self, idx: usize) -> Vertex {
        self.vert(idx)
    }
}

impl IndexedPolygon<Triangle<usize>> for IcoSphere {
    fn indexed_polygon_count(&self) -> usize {
        self.faces.len()
    }

    fn indexed_polygon(&self, idx: usize) -> Triangle<usize> {
        Triangle::new(self.faces[idx][0], self.faces[idx][1], self.faces[idx][2])
    }
}
<commit_msg>Adding explanation of the hardcoded constants used for icosahedral sphere generation.<commit_after>//   Copyright GFX Developers 2014-2017
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.

//! Icosahedral sphere

use std::collections::HashMap;

use cgmath::{InnerSpace, Vector3};

use {Vertex, Triangle};
use generators::{IndexedPolygon, SharedVertex};

/// Icosahedral sphere with radius 1, centered at (0., 0., 0.)
#[derive(Clone, Debug)]
pub struct IcoSphere {
    i: usize,
    vertices: Vec<[f32; 3]>,
    faces: Vec<[usize; 3]>,
}

// The vertices of a regular icosahedron can be visualised as lying at the corner points of 3
// orthogonal rectangles in 3D space.
// https://en.wikipedia.org/wiki/Regular_icosahedron#/media/File:Icosahedron-golden-rectangles.svg
// for a visualisation of this.
// These rectangles are all the same size, and are golden rectangles, which means their sides have
// the golden ratio: 1 : (1 + sqrt(5)) / 2. If we take those values directly however, we will not
// get a unit sphere, therefore we need to normalize the vector (0, 1, (1 + sqrt(5)) / 2). This
// gives us the values below. These values are the half dimensions of the orthogonal rectangles
// from which we get the corner points that define a unit icosahedral sphere.
const T: f32 = 0.85065080835204;
const X: f32 = 0.5257311121191336;

const VERTICES: [[f32; 3]; 12] = [
    // corners of the rectangle in the XY plane
    [-X, T, 0.],
    [X, T, 0.],
    [-X, -T, 0.],
    [X, -T, 0.],

    // corners of the rectangle in the YZ plane
    [0., -X, T],
    [0., X, T],
    [0., -X, -T],
    [0., X, -T],

    // corners of the rectangle in the XZ plane
    [T, 0., -X],
    [T, 0., X],
    [-T, 0., -X],
    [-T, 0., X],
];

const FACES: [[usize; 3]; 20] = [
    // 5 faces around point 0
    [0, 11, 5],
    [0, 5, 1],
    [0, 1, 7],
    [0, 7, 10],
    [0, 10, 11],

    // 5 faces adjacent to the faces around point 0
    [1, 5, 9],
    [5, 11, 4],
    [11, 10, 2],
    [10, 7, 6],
    [7, 1, 8],

    // 5 faces around point 3
    [3, 9, 4],
    [3, 4, 2],
    [3, 2, 6],
    [3, 6, 8],
    [3, 8, 9],

    // 5 faces adjacent to the faces around point 3
    [4, 9, 5],
    [2, 4, 11],
    [6, 2, 10],
    [8, 6, 7],
    [9, 8, 1],
];

impl IcoSphere {

    /// Create a unit sphere with 20 faces and 12 vertices.
    pub fn new() -> Self {
        Self {
            i: 0,
            vertices: VERTICES.to_vec(),
            faces: FACES.to_vec(),
        }
    }

    /// Create a unit sphere with subdivision, resulting in 20 * 4^N faces, where N is the number of
    /// subdivisions.
    ///
    /// ## Parameters
    ///
    /// - `subdivides`: Number of subdivisions to perform.
    pub fn subdivide(subdivides: usize) -> Self {
        let mut vertices = VERTICES.to_vec();
        let mut faces = FACES.to_vec();

        for _ in 0..subdivides {
            let (v, f) = subdivide_impl(vertices, faces);
            vertices = v;
            faces = f;
        }

        Self {
            i: 0,
            vertices,
            faces,
        }
    }

    fn vert(&self, index: usize) -> Vertex {
        Vertex {
            pos: self.vertices[index],
            normal: self.vertices[index],
        }
    }
}

fn subdivide_impl(
    mut vertices: Vec<[f32; 3]>,
    faces: Vec<[usize; 3]>,
) -> (Vec<[f32; 3]>, Vec<[usize; 3]>) {
    let mut lookup = HashMap::<(usize, usize), usize>::default();
    let mut new_faces = Vec::<[usize; 3]>::default();
    for face in &faces {
        let mut mid: [usize; 3] = [0; 3];
        for i in 0..3 {
            let pair = (face[i], face[(i + 1) % 3]);
            // find new vertex on the edge
            mid[i] = match lookup.get(&pair) {
                Some(i) => *i,
                None => vertices.len(),
            };
            if mid[i] == vertices.len() {
                lookup.insert(pair, mid[i]);
                lookup.insert((pair.1, pair.0), mid[i]);
                let new = new_point(vertices[pair.0], vertices[pair.1]);
                vertices.push(new);
            }
        }
        new_faces.push([face[0], mid[0], mid[2]]);
        new_faces.push([face[1], mid[1], mid[0]]);
        new_faces.push([face[2], mid[2], mid[1]]);
        new_faces.push([mid[0], mid[1], mid[2]]);
    }
    (vertices, new_faces)
}

fn new_point(start: [f32; 3], end: [f32; 3]) -> [f32; 3] {
    Vector3::new(start[0] + end[0], start[1] + end[1], start[2] + end[2])
        .normalize()
        .into()
}

impl Iterator for IcoSphere {
    type Item = Triangle<Vertex>;

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.faces.len(), Some(self.faces.len()))
    }

    fn next(&mut self) -> Option<Self::Item> {
        if self.i == self.faces.len() {
            return None;
        }

        let face = self.faces[self.i];
        let x = self.vert(face[0]);
        let y = self.vert(face[1]);
        let z = self.vert(face[2]);
        self.i += 1;

        Some(Triangle::new(x, y, z))
    }
}

impl SharedVertex<Vertex> for IcoSphere {
    fn shared_vertex_count(&self) -> usize {
        self.vertices.len()
    }

    fn shared_vertex(&self, idx: usize) -> Vertex {
        self.vert(idx)
    }
}

impl IndexedPolygon<Triangle<usize>> for IcoSphere {
    fn indexed_polygon_count(&self) -> usize {
        self.faces.len()
    }

    fn indexed_polygon(&self, idx: usize) -> Triangle<usize> {
        Triangle::new(self.faces[idx][0], self.faces[idx][1], self.faces[idx][2])
    }
}
<|endoftext|>


<commit_before>use std::fmt::Debug;

use float_duration::FloatDuration;
use clock::GameTime;
use super::FrameRateSampler;

pub const DEFAULT_SLOW_THRESHOLD: f64 = 0.95;

pub trait FrameCount: Debug {
    fn target_frame_rate(&self) -> f64;
    fn target_time_per_frame(&self) -> FloatDuration;
    fn remaining_frame_time(&self, time: &GameTime) -> FloatDuration;
    fn tick(&mut self, time: &GameTime);
    fn average_frame_rate(&self) -> f64;
    fn is_running_slow(&self, time: &GameTime) -> bool;
}

#[derive(Debug, Clone)]
pub struct FrameCounter<S: FrameRateSampler> {
    target_frame_rate: f64,
    slow_threshold: f64,
    sampler: S,
}

impl<S: FrameRateSampler> FrameCounter<S> {
    pub fn new(target_frame_rate: f64, sampler: S) -> FrameCounter<S> {
        FrameCounter {
            target_frame_rate,
            slow_threshold: DEFAULT_SLOW_THRESHOLD,
            sampler,
        }
    }
    pub fn set_slow_threshold(&mut self, val: f64) -> &mut FrameCounter<S> {
        self.slow_threshold = val;
        self
    }
    pub fn slow_threshold(&self) -> f64 {
        self.slow_threshold
    }

    pub fn set_target_frame_rate(&mut self, val: f64) -> &mut FrameCounter<S> {
        self.target_frame_rate = val;
        self
    }
    pub fn is_saturated(&self) -> bool {
        self.sampler.is_saturated()
    }
    pub fn sampler(&self) -> &S {
        &self.sampler
    }
}

impl<S: FrameRateSampler> FrameCount for FrameCounter<S> {
    fn target_frame_rate(&self) -> f64 {
        self.target_frame_rate
    }
    fn target_time_per_frame(&self) -> FloatDuration {
        FloatDuration::seconds(1.0) / self.target_frame_rate
    }
    fn remaining_frame_time(&self, time: &GameTime) -> FloatDuration {
        self.target_time_per_frame() - time.elapsed_time_since_frame_start()
    }
    fn tick(&mut self, time: &GameTime) {
        self.sampler.tick(time);
    }
    fn average_frame_rate(&self) -> f64 {
        self.sampler.average_frame_rate()
    }
    fn is_running_slow(&self, time: &GameTime) -> bool {
        let ratio = self.target_time_per_frame().as_seconds() /
                    time.elapsed_wall_time().as_seconds();
        ratio <= self.slow_threshold
    }
}
<commit_msg>Documented `framerate.counter` module.<commit_after>//! Provides utilities for tracking frame rate.
use std::fmt::Debug;

use float_duration::FloatDuration;
use clock::GameTime;
use super::FrameRateSampler;

/// The default slow threshold for `FrameCounter`.
pub const DEFAULT_SLOW_THRESHOLD: f64 = 0.95;

/// A frame rate counter and tracker.
pub trait FrameCount: Debug {
    /// The target frame rate for the simulation.
    fn target_frame_rate(&self) -> f64;
    /// The target wall time for each frame.
    fn target_time_per_frame(&self) -> FloatDuration;
    /// The duration remaining to reach the optimal frame time.
    ///
    /// The duration can be negative if the current frame has
    /// executed longer than the optimal time.
    fn remaining_frame_time(&self, time: &GameTime) -> FloatDuration;
    /// Update the counter for a new frame.
    fn tick(&mut self, time: &GameTime);
    /// The average frame rate for the current frame.
    fn average_frame_rate(&self) -> f64;
    /// Return whether the simulation is running slowly.
    fn is_running_slow(&self, time: &GameTime) -> bool;
}

/// A basic frame rate counter.
#[derive(Debug, Clone)]
pub struct FrameCounter<S: FrameRateSampler> {
    target_frame_rate: f64,
    slow_threshold: f64,
    sampler: S,
}

impl<S: FrameRateSampler> FrameCounter<S> {
    /// Create a new `FrameCounter` with a target frame rate and sampler.
    pub fn new(target_frame_rate: f64, sampler: S) -> FrameCounter<S> {
        FrameCounter {
            target_frame_rate,
            slow_threshold: DEFAULT_SLOW_THRESHOLD,
            sampler,
        }
    }
    /// Set a new slow threshold.
    pub fn set_slow_threshold(&mut self, val: f64) -> &mut FrameCounter<S> {
        self.slow_threshold = val;
        self
    }
    /// Return the current slow threshold.
    ///
    /// If the current frame rate divided by the target frame rate
    /// is less than this value, then
    /// [`FrameCount::is_running_slowly`](./trait.FrameCount.html#tymethod.is_running_slowly)
    /// will return true.
    pub fn slow_threshold(&self) -> f64 {
        self.slow_threshold
    }

    /// Set the target frame rate.
    pub fn set_target_frame_rate(&mut self, val: f64) -> &mut FrameCounter<S> {
        self.target_frame_rate = val;
        self
    }
    /// Return true if the sampler is saturated.
    pub fn is_saturated(&self) -> bool {
        self.sampler.is_saturated()
    }
    /// Return a reference to the sampler object.
    pub fn sampler(&self) -> &S {
        &self.sampler
    }
}

impl<S: FrameRateSampler> FrameCount for FrameCounter<S> {
    fn target_frame_rate(&self) -> f64 {
        self.target_frame_rate
    }
    fn target_time_per_frame(&self) -> FloatDuration {
        FloatDuration::seconds(1.0) / self.target_frame_rate
    }
    fn remaining_frame_time(&self, time: &GameTime) -> FloatDuration {
        self.target_time_per_frame() - time.elapsed_time_since_frame_start()
    }
    fn tick(&mut self, time: &GameTime) {
        self.sampler.tick(time);
    }
    fn average_frame_rate(&self) -> f64 {
        self.sampler.average_frame_rate()
    }
    fn is_running_slow(&self, time: &GameTime) -> bool {
        let ratio = self.target_time_per_frame().as_seconds() /
                    time.elapsed_wall_time().as_seconds();
        ratio <= self.slow_threshold
    }
}
<|endoftext|>