<commit_before>use serde::ser::{Serialize, Serializer};

use types::primitive::*;

#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize)]
pub struct ReplyKeyboardMarkup {
    pub keyboard: Vec<Vec<KeyboardButton>>,
    pub resize_keyboard: bool,
    pub one_time_keyboard: bool,
    pub selective: bool
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize)]
pub struct KeyboardButton {
    pub text: String,
    pub request_contact: bool,
    pub request_location: bool,
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize)]
pub struct ReplyKeyboardRemove {
    pub remove_keyboard: True,
    pub selective: bool,
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize)]
pub struct InlineKeyboardMarkup {
    pub inline_keyboard: Vec<Vec<InlineKeyboardButton>>
}

#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct InlineKeyboardButton {
    pub text: String,
    pub kind: InlineKeyboardButtonKind
}

impl Serialize for InlineKeyboardButton {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        use self::InlineKeyboardButtonKind::*;

        let mut raw = InlineKeyboardButtonRaw {
            text: &self.text,
            url: None,
            callback_data: None,
            switch_inline_query: None,
            switch_inline_query_current_chat: None,
//            callback_game: None,
        };

        match self.kind {
            Url(ref data) => raw.url = Some(data),
            CallbackData(ref data) => raw.callback_data = Some(data),
            SwitchInlineQuery(ref data) => raw.switch_inline_query = Some(data),
            SwitchInlineQueryCurrentChat(ref data) => raw.switch_inline_query_current_chat = Some(data),
//            CallbackGame(ref data) => raw.callback_game = Some(data),
        }

        Serialize::serialize(&raw, serializer)
    }
}

#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum InlineKeyboardButtonKind {
    Url(String), // TODO(knsd): Url?
    CallbackData(String),  //TODO(knsd) Validate size?
    SwitchInlineQuery(String),
    SwitchInlineQueryCurrentChat(String),
//    CallbackGame(CallbackGame),
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize)]
struct InlineKeyboardButtonRaw<'a> {
    text: &'a str,
    url: Option<&'a str>, // TODO(knsd): Url?
    callback_data: Option<&'a str>, //TODO(knsd) Validate size?
    switch_inline_query: Option<&'a str>,
    switch_inline_query_current_chat: Option<&'a str>,
//    callback_game: Option<CallbackGame>,
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize)]
pub struct ForceReply {
    pub force_reply: True,
    pub selective: Option<bool>,
}
<commit_msg>feat: skip serialization of optional fields in reply markup structs<commit_after>use std::ops::Not;

use serde::ser::{Serialize, Serializer};

use types::primitive::*;

#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize)]
pub struct ReplyKeyboardMarkup {
    pub keyboard: Vec<Vec<KeyboardButton>>,
    #[serde(skip_serializing_if = "Not::not")]
    pub resize_keyboard: bool,
    #[serde(skip_serializing_if = "Not::not")]
    pub one_time_keyboard: bool,
    #[serde(skip_serializing_if = "Not::not")]
    pub selective: bool
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize)]
pub struct KeyboardButton {
    pub text: String,
    #[serde(skip_serializing_if = "Not::not")]
    pub request_contact: bool,
    #[serde(skip_serializing_if = "Not::not")]
    pub request_location: bool,
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize)]
pub struct ReplyKeyboardRemove {
    pub remove_keyboard: True,
    #[serde(skip_serializing_if = "Not::not")]
    pub selective: bool,
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize)]
pub struct InlineKeyboardMarkup {
    pub inline_keyboard: Vec<Vec<InlineKeyboardButton>>
}

#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct InlineKeyboardButton {
    pub text: String,
    pub kind: InlineKeyboardButtonKind
}

impl Serialize for InlineKeyboardButton {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        use self::InlineKeyboardButtonKind::*;

        let mut raw = InlineKeyboardButtonRaw {
            text: &self.text,
            url: None,
            callback_data: None,
            switch_inline_query: None,
            switch_inline_query_current_chat: None,
//            callback_game: None,
        };

        match self.kind {
            Url(ref data) => raw.url = Some(data),
            CallbackData(ref data) => raw.callback_data = Some(data),
            SwitchInlineQuery(ref data) => raw.switch_inline_query = Some(data),
            SwitchInlineQueryCurrentChat(ref data) => raw.switch_inline_query_current_chat = Some(data),
//            CallbackGame(ref data) => raw.callback_game = Some(data),
        }

        Serialize::serialize(&raw, serializer)
    }
}

#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum InlineKeyboardButtonKind {
    Url(String), // TODO(knsd): Url?
    CallbackData(String),  //TODO(knsd) Validate size?
    SwitchInlineQuery(String),
    SwitchInlineQueryCurrentChat(String),
//    CallbackGame(CallbackGame),
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize)]
struct InlineKeyboardButtonRaw<'a> {
    text: &'a str,
    #[serde(skip_serializing_if = "Option::is_none")]
    url: Option<&'a str>, // TODO(knsd): Url?
    #[serde(skip_serializing_if = "Option::is_none")]
    callback_data: Option<&'a str>, //TODO(knsd) Validate size?
    #[serde(skip_serializing_if = "Option::is_none")]
    switch_inline_query: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    switch_inline_query_current_chat: Option<&'a str>,
//    callback_game: Option<CallbackGame>,
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize)]
pub struct ForceReply {
    pub force_reply: True,
    #[serde(skip_serializing_if = "Not::not")]
    pub selective: bool,
}
<|endoftext|>


<commit_before>use test;

use super::nbody::NBodyBenchmark;

// Because benchmarks run iteratively, use smaller constants by default:
const BENCH_BODIES: usize = 1000;

const BENCH_TICKS: usize = 10;

fn nbody_bench<TICK>(b: &mut test::Bencher, mut tick: TICK)
where
    TICK: FnMut(&mut NBodyBenchmark),
{
    let mut rng = ::seeded_rng();
    let mut benchmark = NBodyBenchmark::new(BENCH_BODIES, &mut rng);
    b.iter(|| {
        for _ in 0..BENCH_TICKS {
            tick(&mut benchmark);
        }
    });
}

#[bench]
fn nbody_seq(b: &mut ::test::Bencher) {
    nbody_bench(b, |n| {
        n.tick_seq();
    });
}

#[bench]
fn nbody_par(b: &mut ::test::Bencher) {
    nbody_bench(b, |n| {
        n.tick_par();
    });
}

#[bench]
fn nbody_par_bridge(b: &mut ::test::Bencher) {
    nbody_bench(b, |n| {
        n.tick_par_bridge();
    });
}

#[bench]
fn nbody_parreduce(b: &mut ::test::Bencher) {
    nbody_bench(b, |n| {
        n.tick_par_reduce();
    });
}
<commit_msg>rename `nbody_par` to `nbody_par_iter` so it has a consistent name<commit_after>use test;

use super::nbody::NBodyBenchmark;

// Because benchmarks run iteratively, use smaller constants by default:
const BENCH_BODIES: usize = 1000;

const BENCH_TICKS: usize = 10;

fn nbody_bench<TICK>(b: &mut test::Bencher, mut tick: TICK)
where
    TICK: FnMut(&mut NBodyBenchmark),
{
    let mut rng = ::seeded_rng();
    let mut benchmark = NBodyBenchmark::new(BENCH_BODIES, &mut rng);
    b.iter(|| {
        for _ in 0..BENCH_TICKS {
            tick(&mut benchmark);
        }
    });
}

#[bench]
fn nbody_seq(b: &mut ::test::Bencher) {
    nbody_bench(b, |n| {
        n.tick_seq();
    });
}

#[bench]
fn nbody_par_iter(b: &mut ::test::Bencher) {
    nbody_bench(b, |n| {
        n.tick_par();
    });
}

#[bench]
fn nbody_par_bridge(b: &mut ::test::Bencher) {
    nbody_bench(b, |n| {
        n.tick_par_bridge();
    });
}

#[bench]
fn nbody_parreduce(b: &mut ::test::Bencher) {
    nbody_bench(b, |n| {
        n.tick_par_reduce();
    });
}
<|endoftext|>


<commit_before>//! QuotientFilter implementation.
use std::collections::hash_map::DefaultHasher;
use std::hash::{BuildHasher, BuildHasherDefault, Hash, Hasher};

use filters::Filter;

/// Error that signals that the QuotientFilter is full.
#[derive(Debug)]
pub struct QuotientFilterFull;

/// TODO
/// Run: List of fingerprints with same quotient.
/// Cluster: set of runs
///
/// https://en.wikipedia.org/wiki/Quotient_filter
/// http://static.usenix.org/events/hotstorage11/tech/final_files/Bender.pdf
/// https://www.vldb.org/pvldb/vol5/p1627_michaelabender_vldb2012.pdf
#[derive(Debug)]
pub struct QuotientFilter<B = BuildHasherDefault<DefaultHasher>>
where
    B: BuildHasher + Clone + Eq,
{
    is_occupied: Vec<bool>,     // TODO: shrink
    is_continuation: Vec<bool>, // TODO: shrink
    is_shifted: Vec<bool>,      // TODO: shrink
    remainders: Vec<u64>,       // TODO: shrink
    bits_quotient: usize,
    bits_remainder: usize,
    buildhasher: B,
    n_elements: usize,
}

impl QuotientFilter {
    /// TODO
    pub fn with_params(bits_quotient: usize, bits_remainder: usize) -> Self {
        let buildhasher = BuildHasherDefault::<DefaultHasher>::default();
        QuotientFilter::with_params_and_hash(bits_quotient, bits_remainder, buildhasher)
    }
}

impl<B> QuotientFilter<B>
where
    B: BuildHasher + Clone + Eq,
{
    /// TODO
    pub fn with_params_and_hash(
        bits_quotient: usize,
        bits_remainder: usize,
        buildhasher: B,
    ) -> Self {
        assert!(
            bits_remainder > 0,
            "bits_remainder ({}) be larger than 0",
            bits_remainder,
        );
        assert!(
            bits_quotient > 0,
            "bits_quotient ({}) be larger than 0",
            bits_quotient,
        );
        assert!(
            bits_remainder + bits_quotient <= 64,
            "bits_remainder ({}) + bits_quotient ({}) must be smaller or equal than 64",
            bits_remainder,
            bits_quotient,
        );

        let len = 1 << bits_quotient;
        Self {
            is_occupied: vec![false; len],
            is_continuation: vec![false; len],
            is_shifted: vec![false; len],
            remainders: vec![0; len],
            bits_quotient,
            bits_remainder,
            buildhasher,
            n_elements: 0,
        }
    }

    fn calc_quotient_remainder<T>(&self, obj: &T) -> (usize, u64)
    where
        T: Hash,
    {
        let mut hasher = self.buildhasher.build_hasher();
        obj.hash(&mut hasher);
        let fingerprint = hasher.finish();
        let bits_trash = 64 - self.bits_remainder - self.bits_quotient;
        let trash = if bits_trash > 0 {
            (fingerprint >> (64 - bits_trash)) << (64 - bits_trash)
        } else {
            0
        };
        let fingerprint_clean = fingerprint - trash;
        let quotient = fingerprint_clean >> self.bits_remainder;
        let remainder = fingerprint_clean - (quotient << self.bits_remainder);
        (quotient as usize, remainder)
    }

    fn decr(&self, pos: &mut usize) {
        *pos = if *pos == 0 {
            self.is_occupied.len() - 1
        } else {
            *pos - 1
        };
    }

    fn incr(&self, pos: &mut usize) {
        *pos = if *pos == self.is_occupied.len() - 1 {
            0
        } else {
            *pos + 1
        }
    }

    fn scan(&self, quotient: usize, remainder: u64, on_insert: bool) -> (bool, usize, bool, usize) {
        let run_exists = self.is_occupied[quotient];
        if (!run_exists) && (!on_insert) {
            // fast-path for query, since we don't need to find the correct position for the
            // insertion process
            return (run_exists, quotient, run_exists, quotient);
        }

        // walk back to find the beginning of the cluster
        let mut b = quotient;
        while self.is_shifted[b] {
            self.decr(&mut b);
        }

        // walk forward to find the actual start of the run
        let mut s = b;
        while b != quotient {
            // invariant: `s` poins to first slot of bucket `b`

            // skip all elements in the current run
            loop {
                self.incr(&mut s);
                if !self.is_continuation[s] {
                    break;
                }
            }

            // find the next occupied bucket
            loop {
                self.incr(&mut b);
                if self.is_occupied[b] || ((b == quotient) && on_insert) {
                    break;
                }
            }
        }
        // `s` now points to the first remainder in bucket at `quotient`

        // search of remainder within the run
        let start_of_run = s;
        if run_exists {
            loop {
                if self.remainders[s] == remainder {
                    return (run_exists, s, run_exists, start_of_run);
                }
                if self.remainders[s] > remainder {
                    // remainders are sorted within run
                    break;
                }
                self.incr(&mut s);
                if !self.is_continuation[s] {
                    break;
                }
            }
        }
        (false, s, run_exists, start_of_run)
    }
}

impl<B> Filter for QuotientFilter<B>
where
    B: BuildHasher + Clone + Eq,
{
    type InsertErr = QuotientFilterFull;

    fn clear(&mut self) {
        unimplemented!()
    }

    fn insert<T>(&mut self, t: &T) -> Result<(), Self::InsertErr>
    where
        T: Hash,
    {
        let (quotient, remainder) = self.calc_quotient_remainder(t);
        let (present, mut position, run_exists, start_of_run) =
            self.scan(quotient, remainder, true);

        // early exit if the element is already present
        if present {
            return Ok(());
        }
        // we need to insert the element into the filter

        // error out if there is no space left
        if self.n_elements == self.is_occupied.len() {
            return Err(QuotientFilterFull);
        }

        // set up swap chain
        let mut current_is_continuation =
            self.is_continuation[position] || (run_exists && (position == start_of_run));
        let mut current_remainder = self.remainders[position];
        let mut current_used = self.is_occupied[position] || self.is_shifted[position];

        // set current state
        self.remainders[position] = remainder;
        if position != start_of_run {
            // might be an append operation, ensure is_continuation and is_shifted are set
            self.is_continuation[position] = true;
        }
        if position != quotient {
            // not at canonical slot
            self.is_shifted[position] = true;
        }

        // run swap chain until nothing to do
        let start = position;
        while current_used {
            self.incr(&mut position);
            let next_is_continuation = self.is_continuation[position];
            let next_remainder = self.remainders[position];
            let next_used = self.is_occupied[position] || self.is_shifted[position];

            self.is_shifted[position] = true;
            self.is_continuation[position] = current_is_continuation;
            self.remainders[position] = current_remainder;

            current_is_continuation = next_is_continuation;
            current_remainder = next_remainder;
            current_used = next_used;

            if position == start {
                panic!("infinite loop detected");
            }
        }

        // mark canonical slot as occupied
        self.is_occupied[quotient] = true;

        // done
        self.n_elements += 1;
        Ok(())
    }

    fn is_empty(&self) -> bool {
        self.n_elements == 0
    }

    fn len(&self) -> usize {
        self.n_elements
    }

    fn query<T>(&self, obj: &T) -> bool
    where
        T: Hash,
    {
        let (quotient, remainder) = self.calc_quotient_remainder(obj);
        let (present, _position, _run_exists, _start_of_run) =
            self.scan(quotient, remainder, false);
        present
    }
}

#[cfg(test)]
mod tests {
    use super::QuotientFilter;
    use filters::Filter;

    #[test]
    fn new() {
        let qf = QuotientFilter::with_params(3, 16);
        assert!(qf.is_empty());
        assert_eq!(qf.len(), 0);
        assert!(!qf.query(&13));
    }

    #[test]
    fn insert() {
        let mut qf = QuotientFilter::with_params(3, 16);
        qf.insert(&13).unwrap();
        assert!(!qf.is_empty());
        assert_eq!(qf.len(), 1);
        assert!(qf.query(&13));
        assert!(!qf.query(&42));
    }

    #[test]
    fn double_insert() {
        let mut qf = QuotientFilter::with_params(3, 16);
        qf.insert(&13).unwrap();
        qf.insert(&13).unwrap();
        assert!(!qf.is_empty());
        assert_eq!(qf.len(), 1);
        assert!(qf.query(&13));
        assert!(!qf.query(&42));
    }

    #[test]
    fn full() {
        let mut qf = QuotientFilter::with_params(3, 16);
        for i in 0..8 {
            qf.insert(&i).unwrap();
            for j in 0..i {
                assert!(qf.query(&j), "Cannot find {} after inserting {}", j, i);
            }
        }
        assert!(qf.insert(&1000).is_err());
    }
}
<commit_msg>quotientfilter: extend docs, tests and getters<commit_after>//! QuotientFilter implementation.
use std::collections::hash_map::DefaultHasher;
use std::hash::{BuildHasher, BuildHasherDefault, Hash, Hasher};

use filters::Filter;

/// Error that signals that the QuotientFilter is full.
#[derive(Debug)]
pub struct QuotientFilterFull;

/// TODO
/// Run: List of fingerprints with same quotient.
/// Cluster: set of runs
///
/// https://en.wikipedia.org/wiki/Quotient_filter
/// http://static.usenix.org/events/hotstorage11/tech/final_files/Bender.pdf
/// https://www.vldb.org/pvldb/vol5/p1627_michaelabender_vldb2012.pdf
#[derive(Debug)]
pub struct QuotientFilter<B = BuildHasherDefault<DefaultHasher>>
where
    B: BuildHasher + Clone + Eq,
{
    is_occupied: Vec<bool>,     // TODO: shrink
    is_continuation: Vec<bool>, // TODO: shrink
    is_shifted: Vec<bool>,      // TODO: shrink
    remainders: Vec<u64>,       // TODO: shrink
    bits_quotient: usize,
    bits_remainder: usize,
    buildhasher: B,
    n_elements: usize,
}

impl QuotientFilter {
    /// Create new quotient filter with:
    ///
    /// - `bits_quotient`: number of bits used for a quotient, aka `2^bits_quotient` slots will be
    ///   allocated
    /// - `bits_remainder`: number of bits used for the remainder, so every slot will require
    ///   `bits_remainder + 3` bits of storage
    ///
    /// and a default hasher.
    pub fn with_params(bits_quotient: usize, bits_remainder: usize) -> Self {
        let buildhasher = BuildHasherDefault::<DefaultHasher>::default();
        QuotientFilter::with_params_and_hash(bits_quotient, bits_remainder, buildhasher)
    }
}

impl<B> QuotientFilter<B>
where
    B: BuildHasher + Clone + Eq,
{
    /// Create new quotient filter with:
    ///
    /// - `bits_quotient`: number of bits used for a quotient, aka `2^bits_quotient` slots will be
    ///   allocated
    /// - `bits_remainder`: number of bits used for the remainder, so every slot will require
    ///   `bits_remainder + 3` bits of storage
    /// - `buildhasher`: hash implementation
    pub fn with_params_and_hash(
        bits_quotient: usize,
        bits_remainder: usize,
        buildhasher: B,
    ) -> Self {
        assert!(
            bits_remainder > 0,
            "bits_remainder ({}) must be greater than 0",
            bits_remainder,
        );
        assert!(
            bits_quotient > 0,
            "bits_quotient ({}) must be greater than 0",
            bits_quotient,
        );
        assert!(
            bits_remainder + bits_quotient <= 64,
            "bits_remainder ({}) + bits_quotient ({}) must be smaller or equal than 64",
            bits_remainder,
            bits_quotient,
        );

        let len = 1 << bits_quotient;
        Self {
            is_occupied: vec![false; len],
            is_continuation: vec![false; len],
            is_shifted: vec![false; len],
            remainders: vec![0; len],
            bits_quotient,
            bits_remainder,
            buildhasher,
            n_elements: 0,
        }
    }

    /// Number of bits used for addressing slots.
    pub fn bits_quotient(&self) -> usize {
        self.bits_quotient
    }

    /// Number of bits stored as fingeprint information.
    pub fn bits_remainder(&self) -> usize {
        self.bits_remainder
    }

    fn calc_quotient_remainder<T>(&self, obj: &T) -> (usize, u64)
    where
        T: Hash,
    {
        let mut hasher = self.buildhasher.build_hasher();
        obj.hash(&mut hasher);
        let fingerprint = hasher.finish();
        let bits_trash = 64 - self.bits_remainder - self.bits_quotient;
        let trash = if bits_trash > 0 {
            (fingerprint >> (64 - bits_trash)) << (64 - bits_trash)
        } else {
            0
        };
        let fingerprint_clean = fingerprint - trash;
        let quotient = fingerprint_clean >> self.bits_remainder;
        let remainder = fingerprint_clean - (quotient << self.bits_remainder);
        (quotient as usize, remainder)
    }

    fn decr(&self, pos: &mut usize) {
        *pos = if *pos == 0 {
            self.is_occupied.len() - 1
        } else {
            *pos - 1
        };
    }

    fn incr(&self, pos: &mut usize) {
        *pos = if *pos == self.is_occupied.len() - 1 {
            0
        } else {
            *pos + 1
        }
    }

    fn scan(&self, quotient: usize, remainder: u64, on_insert: bool) -> (bool, usize, bool, usize) {
        let run_exists = self.is_occupied[quotient];
        if (!run_exists) && (!on_insert) {
            // fast-path for query, since we don't need to find the correct position for the
            // insertion process
            return (run_exists, quotient, run_exists, quotient);
        }

        // walk back to find the beginning of the cluster
        let mut b = quotient;
        while self.is_shifted[b] {
            self.decr(&mut b);
        }

        // walk forward to find the actual start of the run
        let mut s = b;
        while b != quotient {
            // invariant: `s` poins to first slot of bucket `b`

            // skip all elements in the current run
            loop {
                self.incr(&mut s);
                if !self.is_continuation[s] {
                    break;
                }
            }

            // find the next occupied bucket
            loop {
                self.incr(&mut b);
                if self.is_occupied[b] || ((b == quotient) && on_insert) {
                    break;
                }
            }
        }
        // `s` now points to the first remainder in bucket at `quotient`

        // search of remainder within the run
        let start_of_run = s;
        if run_exists {
            loop {
                if self.remainders[s] == remainder {
                    return (run_exists, s, run_exists, start_of_run);
                }
                if self.remainders[s] > remainder {
                    // remainders are sorted within run
                    break;
                }
                self.incr(&mut s);
                if !self.is_continuation[s] {
                    break;
                }
            }
        }
        (false, s, run_exists, start_of_run)
    }
}

impl<B> Filter for QuotientFilter<B>
where
    B: BuildHasher + Clone + Eq,
{
    type InsertErr = QuotientFilterFull;

    fn clear(&mut self) {
        unimplemented!()
    }

    fn insert<T>(&mut self, t: &T) -> Result<(), Self::InsertErr>
    where
        T: Hash,
    {
        let (quotient, remainder) = self.calc_quotient_remainder(t);
        let (present, mut position, run_exists, start_of_run) =
            self.scan(quotient, remainder, true);

        // early exit if the element is already present
        if present {
            return Ok(());
        }
        // we need to insert the element into the filter

        // error out if there is no space left
        if self.n_elements == self.is_occupied.len() {
            return Err(QuotientFilterFull);
        }

        // set up swap chain
        let mut current_is_continuation =
            self.is_continuation[position] || (run_exists && (position == start_of_run));
        let mut current_remainder = self.remainders[position];
        let mut current_used = self.is_occupied[position] || self.is_shifted[position];

        // set current state
        self.remainders[position] = remainder;
        if position != start_of_run {
            // might be an append operation, ensure is_continuation and is_shifted are set
            self.is_continuation[position] = true;
        }
        if position != quotient {
            // not at canonical slot
            self.is_shifted[position] = true;
        }

        // run swap chain until nothing to do
        let start = position;
        while current_used {
            self.incr(&mut position);
            let next_is_continuation = self.is_continuation[position];
            let next_remainder = self.remainders[position];
            let next_used = self.is_occupied[position] || self.is_shifted[position];

            self.is_shifted[position] = true;
            self.is_continuation[position] = current_is_continuation;
            self.remainders[position] = current_remainder;

            current_is_continuation = next_is_continuation;
            current_remainder = next_remainder;
            current_used = next_used;

            if position == start {
                panic!("infinite loop detected");
            }
        }

        // mark canonical slot as occupied
        self.is_occupied[quotient] = true;

        // done
        self.n_elements += 1;
        Ok(())
    }

    fn is_empty(&self) -> bool {
        self.n_elements == 0
    }

    fn len(&self) -> usize {
        self.n_elements
    }

    fn query<T>(&self, obj: &T) -> bool
    where
        T: Hash,
    {
        let (quotient, remainder) = self.calc_quotient_remainder(obj);
        let (present, _position, _run_exists, _start_of_run) =
            self.scan(quotient, remainder, false);
        present
    }
}

#[cfg(test)]
mod tests {
    use super::QuotientFilter;
    use filters::Filter;

    #[test]
    #[should_panic(expected = "bits_quotient (0) must be greater than 0")]
    fn new_bits_quotient_0() {
        QuotientFilter::with_params(0, 16);
    }

    #[test]
    #[should_panic(expected = "bits_remainder (0) must be greater than 0")]
    fn new_bits_remainder_0() {
        QuotientFilter::with_params(3, 0);
    }

    #[test]
    #[should_panic(
        expected = "bits_remainder (5) + bits_quotient (60) must be smaller or equal than 64"
    )]
    fn new_too_many_bits() {
        QuotientFilter::with_params(60, 5);
    }

    #[test]
    fn new() {
        let qf = QuotientFilter::with_params(3, 16);
        assert!(qf.is_empty());
        assert_eq!(qf.len(), 0);
        assert!(!qf.query(&13));
        assert_eq!(qf.bits_quotient(), 3);
        assert_eq!(qf.bits_remainder(), 16);
    }

    #[test]
    fn insert() {
        let mut qf = QuotientFilter::with_params(3, 16);
        qf.insert(&13).unwrap();
        assert!(!qf.is_empty());
        assert_eq!(qf.len(), 1);
        assert!(qf.query(&13));
        assert!(!qf.query(&42));
    }

    #[test]
    fn double_insert() {
        let mut qf = QuotientFilter::with_params(3, 16);
        qf.insert(&13).unwrap();
        qf.insert(&13).unwrap();
        assert!(!qf.is_empty());
        assert_eq!(qf.len(), 1);
        assert!(qf.query(&13));
        assert!(!qf.query(&42));
    }

    #[test]
    fn full() {
        let mut qf = QuotientFilter::with_params(3, 16);
        for i in 0..8 {
            qf.insert(&i).unwrap();
            for j in 0..i {
                assert!(qf.query(&j), "Cannot find {} after inserting {}", j, i);
            }
        }
        assert!(qf.insert(&1000).is_err());
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
use libc::{
    c_char,
    c_int,
};

use types::{
    CLPK_complex,
    CLPK_doublecomplex,
    CLPK_doublereal,
    CLPK_integer,
    CLPK_real,
};

#[link(name = "lapack")]
extern "C" {
    pub fn ssygv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, a: *mut CLPK_real, lda: *const CLPK_integer,
            b: *mut CLPK_real, ldb: *const CLPK_integer, w: CLPK_real,
            work: CLPK_real, lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;
    pub fn dsygv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, a: *mut CLPK_doublereal, lda: *const CLPK_integer,
            b: *mut CLPK_doublereal, ldb: *const CLPK_integer, w: CLPK_doublereal,
            work: CLPK_doublereal, lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;

    pub fn chegv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, a: *mut CLPK_complex, lda: *const CLPK_integer,
            b: *mut CLPK_complex, ldb: *const CLPK_integer, w: CLPK_real,
            work: CLPK_complex, lwork: CLPK_integer, rwork: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn zhegv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, a: *mut CLPK_doublecomplex, lda: *const CLPK_integer,
            b: *mut CLPK_doublecomplex, ldb: *const CLPK_integer,
            w: CLPK_doublereal, work: CLPK_doublecomplex,
            lwork: CLPK_integer, rwork: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;

    pub fn sspgv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, ap: CLPK_real, bp: CLPK_real,
            w: CLPK_real, z: CLPK_real, ldz: CLPK_integer,
            work: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn dspgv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, ap: CLPK_doublereal, bp: CLPK_doublereal,
            w: CLPK_doublereal, z: CLPK_doublereal, ldz: CLPK_integer,
            work: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;
}
<commit_msg>Add Hpgv trait<commit_after>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
use libc::{
    c_char,
    c_int,
};

use types::{
    CLPK_complex,
    CLPK_doublecomplex,
    CLPK_doublereal,
    CLPK_integer,
    CLPK_real,
};

#[link(name = "lapack")]
extern "C" {
    pub fn ssygv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, a: *mut CLPK_real, lda: *const CLPK_integer,
            b: *mut CLPK_real, ldb: *const CLPK_integer, w: CLPK_real,
            work: CLPK_real, lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;
    pub fn dsygv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, a: *mut CLPK_doublereal, lda: *const CLPK_integer,
            b: *mut CLPK_doublereal, ldb: *const CLPK_integer, w: CLPK_doublereal,
            work: CLPK_doublereal, lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;

    pub fn chegv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, a: *mut CLPK_complex, lda: *const CLPK_integer,
            b: *mut CLPK_complex, ldb: *const CLPK_integer, w: CLPK_real,
            work: CLPK_complex, lwork: CLPK_integer, rwork: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn zhegv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, a: *mut CLPK_doublecomplex, lda: *const CLPK_integer,
            b: *mut CLPK_doublecomplex, ldb: *const CLPK_integer,
            w: CLPK_doublereal, work: CLPK_doublecomplex,
            lwork: CLPK_integer, rwork: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;

    pub fn sspgv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, ap: CLPK_real, bp: CLPK_real,
            w: CLPK_real, z: CLPK_real, ldz: CLPK_integer,
            work: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn dspgv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, ap: CLPK_doublereal, bp: CLPK_doublereal,
            w: CLPK_doublereal, z: CLPK_doublereal, ldz: CLPK_integer,
            work: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;

    pub fn chpgv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, ap: CLPK_complex, bp: CLPK_complex,
            w: CLPK_real, z: CLPK_complex, ldz: CLPK_integer,
            work: CLPK_complex, rwork: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn zhpgv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, ap: CLPK_doublecomplex,
            bp: CLPK_doublecomplex, w: CLPK_doublereal,
            z: CLPK_doublecomplex, ldz: CLPK_integer,
            work: CLPK_doublecomplex, rwork: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;
}
<|endoftext|>


<commit_before>use data_url;
use gio_sys;
use glib_sys;
use libc;

use gio::{
    BufferedInputStream,
    BufferedInputStreamExt,
    Cancellable,
    ConverterInputStream,
    File as GFile,
    FileExt,
    InputStream,
    MemoryInputStream,
    ZlibCompressorFormat,
    ZlibDecompressor,
};
use glib::translate::*;
use glib::Bytes as GBytes;
use glib::Cast;
use std::ptr;

use error::{set_gerror, LoadingError, RsvgError};
use handle::BinaryData;
use util::utf8_cstr;

fn decode_data_uri(uri: &str) -> Result<BinaryData, LoadingError> {
    let data_url = data_url::DataUrl::process(uri).map_err(|_| LoadingError::BadDataUrl)?;

    let mime_type = data_url.mime_type().to_string();

    let (bytes, fragment_id) = data_url
        .decode_to_vec()
        .map_err(|_| LoadingError::BadDataUrl)?;

    // See issue #377 - per the data: URL spec
    // (https://fetch.spec.whatwg.org/#data-urls), those URLs cannot
    // have fragment identifiers.  So, just return an error if we find
    // one.  This probably indicates mis-quoted SVG data inside the
    // data: URL.
    if fragment_id.is_some() {
        return Err(LoadingError::BadDataUrl);
    }

    Ok(BinaryData {
        data: bytes,
        content_type: Some(mime_type),
    })
}

fn binary_data_to_glib(
    binary_data: &BinaryData,
    out_mime_type: *mut *mut libc::c_char,
    out_size: *mut usize,
) -> *mut libc::c_char {
    unsafe {
        if !out_mime_type.is_null() {
            *out_mime_type = binary_data.content_type.to_glib_full();
        }

        *out_size = binary_data.data.len();

        ToGlibContainerFromSlice::to_glib_full_from_slice(&binary_data.data) as *mut libc::c_char
    }
}

#[no_mangle]
pub fn rsvg_decode_data_uri(
    uri: *const libc::c_char,
    out_mime_type: *mut *mut libc::c_char,
    out_size: *mut usize,
    error: *mut *mut glib_sys::GError,
) -> *mut libc::c_char {
    unsafe {
        assert!(!out_size.is_null());

        let uri = utf8_cstr(uri);

        match decode_data_uri(uri) {
            Ok(binary_data) => {
                if !error.is_null() {
                    *error = ptr::null_mut();
                }

                binary_data_to_glib(&binary_data, out_mime_type, out_size)
            }

            Err(_) => {
                if !out_mime_type.is_null() {
                    *out_mime_type = ptr::null_mut();
                }

                *out_size = 0;

                set_gerror(error, 0, "could not decode data: URL");

                ptr::null_mut()
            }
        }
    }
}

// Header of a gzip data stream
const GZ_MAGIC_0: u8 = 0x1f;
const GZ_MAGIC_1: u8 = 0x8b;

fn get_input_stream_for_loading(
    stream: InputStream,
    cancellable: Option<Cancellable>,
) -> Result<InputStream, glib::Error> {
    // detect gzipped streams (svgz)

    let buffered = BufferedInputStream::new(&stream);
    let num_read = buffered.fill(2, cancellable.as_ref())?;
    if num_read < 2 {
        // FIXME: this string was localized in the original; localize it
        return Err(glib::Error::new(RsvgError, "Input file is too short"));
    }

    let buf = buffered.peek_buffer();
    assert!(buf.len() >= 2);
    if buf[0] == GZ_MAGIC_0 && buf[1] == GZ_MAGIC_1 {
        let decomp = ZlibDecompressor::new(ZlibCompressorFormat::Gzip);
        let converter = ConverterInputStream::new(&buffered, &decomp);
        Ok(converter.upcast::<InputStream>())
    } else {
        Ok(buffered.upcast::<InputStream>())
    }
}

#[no_mangle]
pub unsafe fn rsvg_get_input_stream_for_loading(
    stream: *mut gio_sys::GInputStream,
    cancellable: *mut gio_sys::GCancellable,
    error: *mut *mut glib_sys::GError,
) -> *mut gio_sys::GInputStream {
    let stream = from_glib_borrow(stream);
    let cancellable = from_glib_borrow(cancellable);

    match get_input_stream_for_loading(stream, cancellable) {
        Ok(stream) => stream.to_glib_full(),

        Err(e) => {
            if !error.is_null() {
                *error = e.to_glib_full() as *mut _;
            }

            ptr::null_mut()
        }
    }
}

/// Returns an input stream.  The uri can be a data: URL or a plain URI
fn acquire_stream(
    uri: &str,
    cancellable: Option<Cancellable>,
) -> Result<InputStream, LoadingError> {
    if uri.starts_with("data:") {
        let BinaryData { data, .. } = decode_data_uri(uri)?;

        let stream = MemoryInputStream::new_from_bytes(&GBytes::from_owned(data));
        Ok(stream.upcast::<InputStream>())
    } else {
        let file = GFile::new_for_uri(uri);
        let stream = file.read(cancellable.as_ref())?;

        Ok(stream.upcast::<InputStream>())
    }
}

#[no_mangle]
pub unsafe fn rsvg_io_acquire_stream(
    uri: *const libc::c_char,
    cancellable: *mut gio_sys::GCancellable,
    error: *mut *mut glib_sys::GError,
) -> *mut gio_sys::GInputStream {
    assert!(!uri.is_null());

    let uri: String = from_glib_none(uri);
    let cancellable = from_glib_borrow(cancellable);

    match acquire_stream(&uri, cancellable) {
        Ok(stream) => stream.to_glib_full(),

        Err(_e) => {
            set_gerror(error, 0, "Could not acquire stream");

            ptr::null_mut()
        }
    }
}

fn acquire_data(uri: &str, cancellable: Option<Cancellable>) -> Result<BinaryData, LoadingError> {
    if uri.starts_with("data:") {
        Ok(decode_data_uri(uri)?)
    } else {
        let file = GFile::new_for_uri(uri);
        let (contents, _etag) = file.load_contents(cancellable.as_ref())?;

        let (content_type, _uncertain) = gio::content_type_guess(uri, &contents);
        let mime_type = gio::content_type_get_mime_type(&content_type);

        Ok(BinaryData {
            data: contents,
            content_type: mime_type,
        })
    }
}

#[no_mangle]
pub unsafe fn rsvg_io_acquire_data(
    uri: *const libc::c_char,
    out_mime_type: *mut *mut libc::c_char,
    out_size: *mut usize,
    cancellable: *mut gio_sys::GCancellable,
    error: *mut *mut glib_sys::GError,
) -> *mut libc::c_char {
    assert!(!uri.is_null());

    let uri: String = from_glib_none(uri);
    let cancellable = from_glib_borrow(cancellable);

    match acquire_data(&uri, cancellable) {
        Ok(binary_data) => {
            if !error.is_null() {
                *error = ptr::null_mut();
            }

            binary_data_to_glib(&binary_data, out_mime_type, out_size)
        }

        Err(_e) => {
            set_gerror(error, 0, "Could not acquire data");
            ptr::null_mut()
        }
    }
}
<commit_msg>(#383): bring glib and gio into the namespace.<commit_after>use data_url;
use gio_sys;
use glib_sys;
use libc;

use gio::{
    self,
    BufferedInputStream,
    BufferedInputStreamExt,
    Cancellable,
    ConverterInputStream,
    File as GFile,
    FileExt,
    InputStream,
    MemoryInputStream,
    ZlibCompressorFormat,
    ZlibDecompressor,
};
use glib::{self, translate::*, Bytes as GBytes, Cast};
use std::ptr;

use error::{set_gerror, LoadingError, RsvgError};
use handle::BinaryData;
use util::utf8_cstr;

fn decode_data_uri(uri: &str) -> Result<BinaryData, LoadingError> {
    let data_url = data_url::DataUrl::process(uri).map_err(|_| LoadingError::BadDataUrl)?;

    let mime_type = data_url.mime_type().to_string();

    let (bytes, fragment_id) = data_url
        .decode_to_vec()
        .map_err(|_| LoadingError::BadDataUrl)?;

    // See issue #377 - per the data: URL spec
    // (https://fetch.spec.whatwg.org/#data-urls), those URLs cannot
    // have fragment identifiers.  So, just return an error if we find
    // one.  This probably indicates mis-quoted SVG data inside the
    // data: URL.
    if fragment_id.is_some() {
        return Err(LoadingError::BadDataUrl);
    }

    Ok(BinaryData {
        data: bytes,
        content_type: Some(mime_type),
    })
}

fn binary_data_to_glib(
    binary_data: &BinaryData,
    out_mime_type: *mut *mut libc::c_char,
    out_size: *mut usize,
) -> *mut libc::c_char {
    unsafe {
        if !out_mime_type.is_null() {
            *out_mime_type = binary_data.content_type.to_glib_full();
        }

        *out_size = binary_data.data.len();

        ToGlibContainerFromSlice::to_glib_full_from_slice(&binary_data.data) as *mut libc::c_char
    }
}

#[no_mangle]
pub fn rsvg_decode_data_uri(
    uri: *const libc::c_char,
    out_mime_type: *mut *mut libc::c_char,
    out_size: *mut usize,
    error: *mut *mut glib_sys::GError,
) -> *mut libc::c_char {
    unsafe {
        assert!(!out_size.is_null());

        let uri = utf8_cstr(uri);

        match decode_data_uri(uri) {
            Ok(binary_data) => {
                if !error.is_null() {
                    *error = ptr::null_mut();
                }

                binary_data_to_glib(&binary_data, out_mime_type, out_size)
            }

            Err(_) => {
                if !out_mime_type.is_null() {
                    *out_mime_type = ptr::null_mut();
                }

                *out_size = 0;

                set_gerror(error, 0, "could not decode data: URL");

                ptr::null_mut()
            }
        }
    }
}

// Header of a gzip data stream
const GZ_MAGIC_0: u8 = 0x1f;
const GZ_MAGIC_1: u8 = 0x8b;

fn get_input_stream_for_loading(
    stream: InputStream,
    cancellable: Option<Cancellable>,
) -> Result<InputStream, glib::Error> {
    // detect gzipped streams (svgz)

    let buffered = BufferedInputStream::new(&stream);
    let num_read = buffered.fill(2, cancellable.as_ref())?;
    if num_read < 2 {
        // FIXME: this string was localized in the original; localize it
        return Err(glib::Error::new(RsvgError, "Input file is too short"));
    }

    let buf = buffered.peek_buffer();
    assert!(buf.len() >= 2);
    if buf[0] == GZ_MAGIC_0 && buf[1] == GZ_MAGIC_1 {
        let decomp = ZlibDecompressor::new(ZlibCompressorFormat::Gzip);
        let converter = ConverterInputStream::new(&buffered, &decomp);
        Ok(converter.upcast::<InputStream>())
    } else {
        Ok(buffered.upcast::<InputStream>())
    }
}

#[no_mangle]
pub unsafe fn rsvg_get_input_stream_for_loading(
    stream: *mut gio_sys::GInputStream,
    cancellable: *mut gio_sys::GCancellable,
    error: *mut *mut glib_sys::GError,
) -> *mut gio_sys::GInputStream {
    let stream = from_glib_borrow(stream);
    let cancellable = from_glib_borrow(cancellable);

    match get_input_stream_for_loading(stream, cancellable) {
        Ok(stream) => stream.to_glib_full(),

        Err(e) => {
            if !error.is_null() {
                *error = e.to_glib_full() as *mut _;
            }

            ptr::null_mut()
        }
    }
}

/// Returns an input stream.  The uri can be a data: URL or a plain URI
fn acquire_stream(
    uri: &str,
    cancellable: Option<Cancellable>,
) -> Result<InputStream, LoadingError> {
    if uri.starts_with("data:") {
        let BinaryData { data, .. } = decode_data_uri(uri)?;

        let stream = MemoryInputStream::new_from_bytes(&GBytes::from_owned(data));
        Ok(stream.upcast::<InputStream>())
    } else {
        let file = GFile::new_for_uri(uri);
        let stream = file.read(cancellable.as_ref())?;

        Ok(stream.upcast::<InputStream>())
    }
}

#[no_mangle]
pub unsafe fn rsvg_io_acquire_stream(
    uri: *const libc::c_char,
    cancellable: *mut gio_sys::GCancellable,
    error: *mut *mut glib_sys::GError,
) -> *mut gio_sys::GInputStream {
    assert!(!uri.is_null());

    let uri: String = from_glib_none(uri);
    let cancellable = from_glib_borrow(cancellable);

    match acquire_stream(&uri, cancellable) {
        Ok(stream) => stream.to_glib_full(),

        Err(_e) => {
            set_gerror(error, 0, "Could not acquire stream");

            ptr::null_mut()
        }
    }
}

fn acquire_data(uri: &str, cancellable: Option<Cancellable>) -> Result<BinaryData, LoadingError> {
    if uri.starts_with("data:") {
        Ok(decode_data_uri(uri)?)
    } else {
        let file = GFile::new_for_uri(uri);
        let (contents, _etag) = file.load_contents(cancellable.as_ref())?;

        let (content_type, _uncertain) = gio::content_type_guess(uri, &contents);
        let mime_type = gio::content_type_get_mime_type(&content_type);

        Ok(BinaryData {
            data: contents,
            content_type: mime_type,
        })
    }
}

#[no_mangle]
pub unsafe fn rsvg_io_acquire_data(
    uri: *const libc::c_char,
    out_mime_type: *mut *mut libc::c_char,
    out_size: *mut usize,
    cancellable: *mut gio_sys::GCancellable,
    error: *mut *mut glib_sys::GError,
) -> *mut libc::c_char {
    assert!(!uri.is_null());

    let uri: String = from_glib_none(uri);
    let cancellable = from_glib_borrow(cancellable);

    match acquire_data(&uri, cancellable) {
        Ok(binary_data) => {
            if !error.is_null() {
                *error = ptr::null_mut();
            }

            binary_data_to_glib(&binary_data, out_mime_type, out_size)
        }

        Err(_e) => {
            set_gerror(error, 0, "Could not acquire data");
            ptr::null_mut()
        }
    }
}
<|endoftext|>


<commit_before>extern crate gcc;

use std::fs::File;
use std::path::Path;
use std::io::Write;
use std::process::Command;
use std::env;

fn main() {
    if cfg!(target_os = "linux") || cfg!(target_os = "macos") || cfg!(target_os = "windows") {
        env::set_var("CC", "gcc");
        env::set_var("AS", "gcc -c");
        if cfg!(target_os = "linux") {
            env::set_var("AR", "ar");
        }
    } else if cfg!(target_os = "freebsd") || cfg!(target_os = "openbsd") {
        env::set_var("CC", "cc");
        env::set_var("AS", "cc -c");
        env::set_var("AR", "ar");
    }

    let sse3 = if cfg!(target_os = "windows") {
        cfg!(feature = "sse")
    } else {
        let output = if cfg!(target_os = "freebsd") || cfg!(target_os = "openbsd") {
            // /usr/bin/grep -o SSSE3 /var/run/dmesg.boot | /usr/bin/head -1
            Command::new("/usr/bin/grep")
                .arg("-o")
                .arg("SSE3")
                .arg("/var/run/dmesg.boot")
                .arg("|")
                .arg("/usr/bin/head")
                .arg("-1")
                .output()
                .unwrap()
        } else if cfg!(target_os = "macos") {
            // /usr/sbin/sysctl machdep.cpu.features | grep -m 1 -ow SSSE3
            Command::new("/usr/sbin/sysctl")
                .arg("machdep.cpu.features")
                .arg("|")
                .arg("grep")
                .arg("-m")
                .arg("1")
                .arg("-ow")
                .arg("SSE3")
                .output()
                .unwrap()
        } else {
            // /bin/grep -m 1 -o ssse3 /proc/cpuinfo
            Command::new("/bin/grep")
                .arg("-m")
                .arg("1")
                .arg("-o")
                .arg("sse3")
                .arg("/proc/cpuinfo")
                .output()
                .unwrap()
        };
        let output = std::str::from_utf8(&output.stdout[..]).unwrap().trim();

        if cfg!(target_os = "freebsd") || cfg!(target_os = "openbsd") || cfg!(target_os = "macos") {
            output == "SSSE3"
        } else {
            output == "sse3"
        }
    };

    let mut cflags = "-g -Wall -Wextra -Wno-unused-parameter".to_owned();
    if !cfg!(feature = "no-sse") && sse3 {
        cflags = cflags + " -mssse3";
    }
    if cfg!(feature = "no-sse") && cfg!(target_os = "macos") {
        cflags = cflags + " -march=x86-64";
    }
    cflags = cflags + " -O2";

    env::set_var("CFLAGS", cflags);

    let mut config = gcc::Config::new();
    config.file("src/c/src/bitstring.c")
          .file("src/c/src/encparams.c")
          .file("src/c/src/hash.c")
          .file("src/c/src/idxgen.c")
          .file("src/c/src/key.c")
          .file("src/c/src/mgf.c")
          .file("src/c/src/ntru.c")
          .file("src/c/src/poly.c")
          .file("src/c/src/rand.c")
          .file("src/c/src/arith.c")
          .file("src/c/src/sha1.c")
          .file("src/c/src/sha2.c")
          .file("src/c/src/nist_ctr_drbg.c")
          .file("src/c/src/rijndael.c")
          .file("src/c/src/rijndael-alg-fst.c");

    if sse3 &&
       (cfg!(target_pointer_width = "64") || cfg!(target_os = "macos") ||
        cfg!(target_os = "windows")) {
        let out = if cfg!(target_os = "windows") {
            Command::new("c:\\mingw\\msys\\1.0\\bin\\perl")
                .arg("src/c/src/sha1-mb-x86_64.pl")
                .arg("elf")
                .output()
                .unwrap()
        } else {
            Command::new("/usr/bin/perl")
                .arg("src/c/src/sha1-mb-x86_64.pl")
                .arg("elf")
                .output()
                .unwrap()
        };
        let out = std::str::from_utf8(&out.stdout[..]).unwrap().trim();

        let p = Path::new("src/c/src/sha1-mb-x86_64.s");
        let mut f = File::create(&p).unwrap();
        f.write(out.as_bytes()).unwrap();

        if cfg!(target_os = "linux") || cfg!(target_os = "macos") {
            Command::new("gcc")
                .arg("-c")
                .arg("src/c/src/sha1-mb-x86_64.s")
                .arg("-o")
                .arg("src/c/src/sha1-mb-x86_64.o")
                .output()
                .unwrap();
        } else if cfg!(target_os = "freebsd") || cfg!(target_os = "openbsd") {
            Command::new("cc")
                .arg("-c")
                .arg("src/c/src/sha1-mb-x86_64.s")
                .arg("-o")
                .arg("src/c/src/sha1-mb-x86_64.o")
                .output()
                .unwrap();
        }

        let out = if cfg!(target_os = "windows") {
            Command::new("c:\\mingw\\msys\\1.0\\bin\\perl")
                .arg("src/c/src/sha256-mb-x86_64.pl")
                .arg("elf")
                .output()
                .unwrap()
        } else {
            Command::new("/usr/bin/perl")
                .arg("src/c/src/sha256-mb-x86_64.pl")
                .arg("elf")
                .output()
                .unwrap()
        };
        let out = std::str::from_utf8(&out.stdout[..]).unwrap().trim();

        let p = Path::new("src/c/src/sha256-mb-x86_64.s");
        let mut f = File::create(&p).unwrap();
        f.write(out.as_bytes()).unwrap();

        if cfg!(target_os = "linux") || cfg!(target_os = "macos") {
            Command::new("gcc")
                .arg("-c")
                .arg("src/c/src/sha256-mb-x86_64.s")
                .arg("-o")
                .arg("src/c/src/sha256-mb-x86_64.o")
                .output()
                .unwrap();
        } else if cfg!(target_os = "freebsd") || cfg!(target_os = "openbsd") {
            Command::new("cc")
                .arg("-c")
                .arg("src/c/src/sha256-mb-x86_64.s")
                .arg("-o")
                .arg("src/c/src/sha256-mb-x86_64.o")
                .output()
                .unwrap();
        }

        config.object("src/c/src/sha1-mb-x86_64.o").object("src/c/src/sha256-mb-x86_64.o");
    }

    config.include("src/c/src").compile("libntru.a");

    if !cfg!(feature = "no-sse") && sse3 {
        println!("cargo:rustc-cfg=SSE3")
    }
}
<commit_msg>Another typo found<commit_after>extern crate gcc;

use std::fs::File;
use std::path::Path;
use std::io::Write;
use std::process::Command;
use std::env;

fn main() {
    if cfg!(target_os = "linux") || cfg!(target_os = "macos") || cfg!(target_os = "windows") {
        env::set_var("CC", "gcc");
        env::set_var("AS", "gcc -c");
        if cfg!(target_os = "linux") {
            env::set_var("AR", "ar");
        }
    } else if cfg!(target_os = "freebsd") || cfg!(target_os = "openbsd") {
        env::set_var("CC", "cc");
        env::set_var("AS", "cc -c");
        env::set_var("AR", "ar");
    }

    let sse3 = if cfg!(target_os = "windows") {
        cfg!(feature = "sse")
    } else {
        let output = if cfg!(target_os = "freebsd") || cfg!(target_os = "openbsd") {
            // /usr/bin/grep -o SSSE3 /var/run/dmesg.boot | /usr/bin/head -1
            Command::new("/usr/bin/grep")
                .arg("-o")
                .arg("SSE3")
                .arg("/var/run/dmesg.boot")
                .arg("|")
                .arg("/usr/bin/head")
                .arg("-1")
                .output()
                .unwrap()
        } else if cfg!(target_os = "macos") {
            // /usr/sbin/sysctl machdep.cpu.features | grep -m 1 -ow SSSE3
            Command::new("/usr/sbin/sysctl")
                .arg("machdep.cpu.features")
                .arg("|")
                .arg("grep")
                .arg("-m")
                .arg("1")
                .arg("-ow")
                .arg("SSSE3")
                .output()
                .unwrap()
        } else {
            // /bin/grep -m 1 -o ssse3 /proc/cpuinfo
            Command::new("/bin/grep")
                .arg("-m")
                .arg("1")
                .arg("-o")
                .arg("sse3")
                .arg("/proc/cpuinfo")
                .output()
                .unwrap()
        };
        let output = std::str::from_utf8(&output.stdout[..]).unwrap().trim();

        if cfg!(target_os = "freebsd") || cfg!(target_os = "openbsd") || cfg!(target_os = "macos") {
            output == "SSSE3"
        } else {
            output == "sse3"
        }
    };

    let mut cflags = "-g -Wall -Wextra -Wno-unused-parameter".to_owned();
    if !cfg!(feature = "no-sse") && sse3 {
        cflags = cflags + " -mssse3";
    }
    if cfg!(feature = "no-sse") && cfg!(target_os = "macos") {
        cflags = cflags + " -march=x86-64";
    }
    cflags = cflags + " -O2";

    env::set_var("CFLAGS", cflags);

    let mut config = gcc::Config::new();
    config.file("src/c/src/bitstring.c")
          .file("src/c/src/encparams.c")
          .file("src/c/src/hash.c")
          .file("src/c/src/idxgen.c")
          .file("src/c/src/key.c")
          .file("src/c/src/mgf.c")
          .file("src/c/src/ntru.c")
          .file("src/c/src/poly.c")
          .file("src/c/src/rand.c")
          .file("src/c/src/arith.c")
          .file("src/c/src/sha1.c")
          .file("src/c/src/sha2.c")
          .file("src/c/src/nist_ctr_drbg.c")
          .file("src/c/src/rijndael.c")
          .file("src/c/src/rijndael-alg-fst.c");

    if sse3 &&
       (cfg!(target_pointer_width = "64") || cfg!(target_os = "macos") ||
        cfg!(target_os = "windows")) {
        let out = if cfg!(target_os = "windows") {
            Command::new("c:\\mingw\\msys\\1.0\\bin\\perl")
                .arg("src/c/src/sha1-mb-x86_64.pl")
                .arg("elf")
                .output()
                .unwrap()
        } else {
            Command::new("/usr/bin/perl")
                .arg("src/c/src/sha1-mb-x86_64.pl")
                .arg("elf")
                .output()
                .unwrap()
        };
        let out = std::str::from_utf8(&out.stdout[..]).unwrap().trim();

        let p = Path::new("src/c/src/sha1-mb-x86_64.s");
        let mut f = File::create(&p).unwrap();
        f.write(out.as_bytes()).unwrap();

        if cfg!(target_os = "linux") || cfg!(target_os = "macos") {
            Command::new("gcc")
                .arg("-c")
                .arg("src/c/src/sha1-mb-x86_64.s")
                .arg("-o")
                .arg("src/c/src/sha1-mb-x86_64.o")
                .output()
                .unwrap();
        } else if cfg!(target_os = "freebsd") || cfg!(target_os = "openbsd") {
            Command::new("cc")
                .arg("-c")
                .arg("src/c/src/sha1-mb-x86_64.s")
                .arg("-o")
                .arg("src/c/src/sha1-mb-x86_64.o")
                .output()
                .unwrap();
        }

        let out = if cfg!(target_os = "windows") {
            Command::new("c:\\mingw\\msys\\1.0\\bin\\perl")
                .arg("src/c/src/sha256-mb-x86_64.pl")
                .arg("elf")
                .output()
                .unwrap()
        } else {
            Command::new("/usr/bin/perl")
                .arg("src/c/src/sha256-mb-x86_64.pl")
                .arg("elf")
                .output()
                .unwrap()
        };
        let out = std::str::from_utf8(&out.stdout[..]).unwrap().trim();

        let p = Path::new("src/c/src/sha256-mb-x86_64.s");
        let mut f = File::create(&p).unwrap();
        f.write(out.as_bytes()).unwrap();

        if cfg!(target_os = "linux") || cfg!(target_os = "macos") {
            Command::new("gcc")
                .arg("-c")
                .arg("src/c/src/sha256-mb-x86_64.s")
                .arg("-o")
                .arg("src/c/src/sha256-mb-x86_64.o")
                .output()
                .unwrap();
        } else if cfg!(target_os = "freebsd") || cfg!(target_os = "openbsd") {
            Command::new("cc")
                .arg("-c")
                .arg("src/c/src/sha256-mb-x86_64.s")
                .arg("-o")
                .arg("src/c/src/sha256-mb-x86_64.o")
                .output()
                .unwrap();
        }

        config.object("src/c/src/sha1-mb-x86_64.o").object("src/c/src/sha256-mb-x86_64.o");
    }

    config.include("src/c/src").compile("libntru.a");

    if !cfg!(feature = "no-sse") && sse3 {
        println!("cargo:rustc-cfg=SSE3")
    }
}
<|endoftext|>


<commit_before>// build.rs

use std::env;
use std::path::Path;
#[macro_use]
extern crate error_chain;

#[cfg(windows)]
mod execs {
    use std::process::Command;

    pub fn cmd(program: &str) -> Command {
        let mut cmd = Command::new("cmd");
        cmd.args(&["/c", program]);
        cmd
    }
}
#[cfg(not(windows))]
mod execs {
    use std::process::Command;

    pub fn cmd(program: &str) -> Command {
        Command::new(program)
    }
}

error_chain!{
 foreign_links {
        Io(std::io::Error);
    }
}

fn program_exists(program: &str) -> Result<()> {
    execs::cmd(program).arg("-v")
                       .output()
                       .chain_err(|| format!("Please install '{}'!", program))?;
    Ok(())
}

fn npm_package_exists(package: &str) -> Result<()> {
    let status = execs::cmd("npm").args(&["list", "-g"])
                                  .arg(package)
                                  .output();

    match status {
        Ok(ref out) if out.status.success() => Ok(()),
        _ => {
            bail!("Missing npm package '{0}' install with: 'npm -g install {0}'",
                  package)
        }
    }
}

pub enum Resource<'a> {
    Program(&'a str),
    Package(&'a str),
}
use Resource::{Package, Program};

impl<'a> Resource<'a> {
    pub fn exists(&self) -> Result<()> {
        match *self {
            Program(name) => program_exists(name),
            Package(name) => npm_package_exists(name),
        }
    }
}

fn run() -> Result<()> {
    if let Ok(_) = env::var("CARGO_FEATURE_REGENERATE_CSS") {
        // Check dependencies
        Program("npm").exists()?;
        Program("node").exists().or(Program("nodejs").exists())?;
        Package("nib").exists()?;
        Package("stylus").exists()?;

        // Compile stylus stylesheet to css
        let manifest_dir = env::var("CARGO_MANIFEST_DIR")
            .chain_err(|| "Please run the script with: 'cargo build'!")?;
        let theme_dir = Path::new(&manifest_dir).join("src/theme/");
        let stylus_dir = theme_dir.join("stylus/book.styl");

        if !execs::cmd("stylus").arg(stylus_dir)
                                .arg("--out")
                                .arg(theme_dir)
                                .arg("--use")
                                .arg("nib")
                                .status()?
                                .success()
        {
            bail!("Stylus encoutered an error");
        }
    }
    Ok(())
}

quick_main!(run);
<commit_msg>Fix typo<commit_after>// build.rs

use std::env;
use std::path::Path;
#[macro_use]
extern crate error_chain;

#[cfg(windows)]
mod execs {
    use std::process::Command;

    pub fn cmd(program: &str) -> Command {
        let mut cmd = Command::new("cmd");
        cmd.args(&["/c", program]);
        cmd
    }
}
#[cfg(not(windows))]
mod execs {
    use std::process::Command;

    pub fn cmd(program: &str) -> Command {
        Command::new(program)
    }
}

error_chain!{
 foreign_links {
        Io(std::io::Error);
    }
}

fn program_exists(program: &str) -> Result<()> {
    execs::cmd(program).arg("-v")
                       .output()
                       .chain_err(|| format!("Please install '{}'!", program))?;
    Ok(())
}

fn npm_package_exists(package: &str) -> Result<()> {
    let status = execs::cmd("npm").args(&["list", "-g"])
                                  .arg(package)
                                  .output();

    match status {
        Ok(ref out) if out.status.success() => Ok(()),
        _ => {
            bail!("Missing npm package '{0}' install with: 'npm -g install {0}'",
                  package)
        }
    }
}

pub enum Resource<'a> {
    Program(&'a str),
    Package(&'a str),
}
use Resource::{Package, Program};

impl<'a> Resource<'a> {
    pub fn exists(&self) -> Result<()> {
        match *self {
            Program(name) => program_exists(name),
            Package(name) => npm_package_exists(name),
        }
    }
}

fn run() -> Result<()> {
    if let Ok(_) = env::var("CARGO_FEATURE_REGENERATE_CSS") {
        // Check dependencies
        Program("npm").exists()?;
        Program("node").exists().or(Program("nodejs").exists())?;
        Package("nib").exists()?;
        Package("stylus").exists()?;

        // Compile stylus stylesheet to css
        let manifest_dir = env::var("CARGO_MANIFEST_DIR")
            .chain_err(|| "Please run the script with: 'cargo build'!")?;
        let theme_dir = Path::new(&manifest_dir).join("src/theme/");
        let stylus_dir = theme_dir.join("stylus/book.styl");

        if !execs::cmd("stylus").arg(stylus_dir)
                                .arg("--out")
                                .arg(theme_dir)
                                .arg("--use")
                                .arg("nib")
                                .status()?
                                .success()
        {
            bail!("Stylus encountered an error");
        }
    }
    Ok(())
}

quick_main!(run);
<|endoftext|>


<commit_before>fn main() {
    let ac = autocfg::new();

    // Check for a minimum version for a few features
    if ac.probe_rustc_version(1, 31) {
        println!("cargo:rustc-cfg=allow_clippy");
    }
    if ac.probe_rustc_version(1, 36) {
        println!("cargo:rustc-cfg=maybe_uninit");
    }
    if ac.probe_rustc_version(1, 40) {
        println!("cargo:rustc-cfg=doctests");
    }
}
<commit_msg>Fixed build for 1.19<commit_after>extern crate autocfg;

fn main() {
    let ac = autocfg::new();

    // Check for a minimum version for a few features
    if ac.probe_rustc_version(1, 31) {
        println!("cargo:rustc-cfg=allow_clippy");
    }
    if ac.probe_rustc_version(1, 36) {
        println!("cargo:rustc-cfg=maybe_uninit");
    }
    if ac.probe_rustc_version(1, 40) {
        println!("cargo:rustc-cfg=doctests");
    }
}
<|endoftext|>


<commit_before>use skeptic;
use std::path::PathBuf;

fn main() {
    let mut mdbook_files = skeptic::markdown_files_of_directory("docs/guides/");

    let other_files: Vec<PathBuf> = vec!["README.md".into()];
    mdbook_files.extend(other_files);
    skeptic::generate_doc_tests(&mdbook_files);
}
<commit_msg>Removes redundant import from build.rs<commit_after>use std::path::PathBuf;

fn main() {
    let mut mdbook_files = skeptic::markdown_files_of_directory("docs/guides/");

    let other_files: Vec<PathBuf> = vec!["README.md".into()];
    mdbook_files.extend(other_files);
    skeptic::generate_doc_tests(&mdbook_files);
}
<|endoftext|>


<commit_before>//! Provides a simple SAH split based BVH2 that stores types implementing the Boundable trait

use std::sync::Arc;

use geometry::Boundable;
use linalg::Ray;

pub struct BVH<T> {
    // Maximum amount of geometry we're willing to put in a leaf
    max_geom: usize,
    objects: Arc<Vec<T>>,
}

impl<T: Boundable> BVH<T> {
    pub fn new(max_geom: usize, objects: Arc<Vec<T>>) -> BVH<T> {
        BVH { max_geom: max_geom, objects: objects }
    }
    /// Traverse the BVH and call the function passed on the objects in the leaf nodes
    /// of the BVH, returning the value returned by the function after traversal
    /// completes.
    /// TODO: I've tried to base this interface on that of `Iterator::map` however they don't seem
    /// to take `f` as a mutable parameter?
    pub fn intersect<'a, F, R>(&'a self, ray: &mut Ray, f: F) -> Option<R>
            where F: Fn(&mut Ray, &'a T) -> Option<R> {
        let mut result = None;
		for o in &*self.objects {
			result = f(ray, o).or(result);
		}
        result
    }
}

<commit_msg>Trying to workout how to handle storing the ordered geometry info<commit_after>//! Provides a simple SAH split based BVH2 that stores types implementing the Boundable trait

use std::sync::Arc;

use geometry::Boundable;
use linalg::Ray;

pub struct BVH<T> {
    /// Maximum amount of geometry we're willing to put in a leaf
    max_geom: usize,
    /// Reference to the vec containing the unordered objects in the BVH
    objects: Arc<Vec<T>>,
    /// Should this be a vec of references? or of indices?
    /// doing ordered_geom: Vec<&T> seems to be a lifetime annotation nightmare
}

impl<T: Boundable> BVH<T> {
    pub fn new(max_geom: usize, objects: Arc<Vec<T>>) -> BVH<T> {
        BVH { max_geom: max_geom, objects: objects }
    }
    /// Traverse the BVH and call the function passed on the objects in the leaf nodes
    /// of the BVH, returning the value returned by the function after traversal
    /// completes.
    /// TODO: I've tried to base this interface on that of `Iterator::map` however they don't seem
    /// to take `f` as a mutable parameter?
    pub fn intersect<'a, F, R>(&'a self, ray: &mut Ray, f: F) -> Option<R>
            where F: Fn(&mut Ray, &'a T) -> Option<R> {
        let mut result = None;
		for o in &*self.objects {
			result = f(ray, o).or(result);
		}
        result
    }
}

<|endoftext|>


<commit_before>/*!
 * Compiled representation of a grammar. Simplified, normalized
 * version of `parse_tree`. The normalization passes produce this
 * representation incrementally.
 */

use intern::InternedString;
use grammar::parse_tree::Span;
use std::collections::HashMap;
use std::fmt::{Display, Formatter, Error};
use util::Sep;

#[derive(Clone, Debug)]
pub struct Grammar {
    pub action_fn_defns: Vec<ActionFnDefn>,
    pub productions: Vec<Production>,
    pub conversions: HashMap<InternedString, InternedString>,
    pub types: Types,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Production {
    pub span: Span,
    pub nonterminal: InternedString,
    pub symbols: Vec<Symbol>,
    pub action_fn: ActionFn,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Symbol {
    Nonterminal(InternedString),
    Terminal(InternedString),
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ActionFnDefn {
    pub arg_patterns: Vec<InternedString>,
    pub arg_types: Vec<TypeRepr>,
    pub ret_type: TypeRepr,
    pub code: String,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum TypeRepr {
    Tuple(Vec<TypeRepr>),
    Nominal { path: Vec<InternedString>, types: Vec<TypeRepr> },
    Lifetime(InternedString),
}

#[derive(Clone, Debug)]
pub struct Types {
    terminal_type: TypeRepr,
    nonterminal_types: HashMap<InternedString, TypeRepr>
}

impl Types {
    pub fn new(terminal_type: TypeRepr) -> Types {
        Types { terminal_type: terminal_type,
                nonterminal_types: HashMap::new() }
    }

    pub fn add_type(&mut self, nt_id: InternedString, ty: TypeRepr) {
        assert!(self.nonterminal_types.insert(nt_id, ty).is_none());
    }

    pub fn terminal_type(&self) -> &TypeRepr {
        &self.terminal_type
    }

    pub fn lookup_nonterminal_type(&self, nt_id: InternedString) -> Option<&TypeRepr> {
        self.nonterminal_types.get(&nt_id)
    }

    pub fn nonterminal_type(&self, nt_id: InternedString) -> &TypeRepr {
        &self.nonterminal_types[&nt_id]
    }
}

impl Display for TypeRepr {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        match *self {
            TypeRepr::Tuple(ref types) =>
                write!(fmt, "({})", Sep(", ", types)),
            TypeRepr::Nominal { ref path, ref types } if types.len() == 0 =>
                write!(fmt, "{}", Sep("::", path)),
            TypeRepr::Nominal { ref path, ref types } =>
                write!(fmt, "{}<{}>", Sep("::", path), Sep(", ", types)),
            TypeRepr::Lifetime(id) =>
                write!(fmt, "{}", id),
        }
    }
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct ActionFn(u32);

impl ActionFn {
    pub fn new(x: usize) -> ActionFn {
        ActionFn(x as u32)
    }

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

impl Symbol {
    pub fn ty<'ty>(&self, t: &'ty Types) -> &'ty TypeRepr {
        match *self {
            Symbol::Nonterminal(id) => t.terminal_type(),
            Symbol::Terminal(id) => t.nonterminal_type(id),
        }
    }
}
<commit_msg>Improve the Debug/Display impls<commit_after>/*!
 * Compiled representation of a grammar. Simplified, normalized
 * version of `parse_tree`. The normalization passes produce this
 * representation incrementally.
 */

use intern::InternedString;
use grammar::parse_tree::Span;
use std::collections::HashMap;
use std::fmt::{Debug, Display, Formatter, Error};
use util::Sep;

#[derive(Clone, Debug)]
pub struct Grammar {
    pub action_fn_defns: Vec<ActionFnDefn>,
    pub productions: Vec<Production>,
    pub conversions: HashMap<InternedString, InternedString>,
    pub types: Types,
}

#[derive(Clone, PartialEq, Eq)]
pub struct Production {
    pub span: Span,
    pub nonterminal: InternedString,
    pub symbols: Vec<Symbol>,
    pub action_fn: ActionFn,
}

#[derive(Clone, PartialEq, Eq)]
pub enum Symbol {
    Nonterminal(InternedString),
    Terminal(InternedString),
}

#[derive(Clone, PartialEq, Eq)]
pub struct ActionFnDefn {
    pub arg_patterns: Vec<InternedString>,
    pub arg_types: Vec<TypeRepr>,
    pub ret_type: TypeRepr,
    pub code: String,
}

#[derive(Clone, PartialEq, Eq)]
pub enum TypeRepr {
    Tuple(Vec<TypeRepr>),
    Nominal { path: Vec<InternedString>, types: Vec<TypeRepr> },
    Lifetime(InternedString),
}

#[derive(Clone, Debug)]
pub struct Types {
    terminal_type: TypeRepr,
    nonterminal_types: HashMap<InternedString, TypeRepr>
}

impl Types {
    pub fn new(terminal_type: TypeRepr) -> Types {
        Types { terminal_type: terminal_type,
                nonterminal_types: HashMap::new() }
    }

    pub fn add_type(&mut self, nt_id: InternedString, ty: TypeRepr) {
        assert!(self.nonterminal_types.insert(nt_id, ty).is_none());
    }

    pub fn terminal_type(&self) -> &TypeRepr {
        &self.terminal_type
    }

    pub fn lookup_nonterminal_type(&self, nt_id: InternedString) -> Option<&TypeRepr> {
        self.nonterminal_types.get(&nt_id)
    }

    pub fn nonterminal_type(&self, nt_id: InternedString) -> &TypeRepr {
        &self.nonterminal_types[&nt_id]
    }
}

impl Display for TypeRepr {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        match *self {
            TypeRepr::Tuple(ref types) =>
                write!(fmt, "({})", Sep(", ", types)),
            TypeRepr::Nominal { ref path, ref types } if types.len() == 0 =>
                write!(fmt, "{}", Sep("::", path)),
            TypeRepr::Nominal { ref path, ref types } =>
                write!(fmt, "{}<{}>", Sep("::", path), Sep(", ", types)),
            TypeRepr::Lifetime(id) =>
                write!(fmt, "{}", id),
        }
    }
}

impl Debug for TypeRepr {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        Display::fmt(self, fmt)
    }
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct ActionFn(u32);

impl ActionFn {
    pub fn new(x: usize) -> ActionFn {
        ActionFn(x as u32)
    }

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

impl Symbol {
    pub fn ty<'ty>(&self, t: &'ty Types) -> &'ty TypeRepr {
        match *self {
            Symbol::Nonterminal(id) => t.terminal_type(),
            Symbol::Terminal(id) => t.nonterminal_type(id),
        }
    }
}

impl Display for Symbol {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        match *self {
            Symbol::Nonterminal(id) => write!(fmt, "{}", id),
            Symbol::Terminal(id) => write!(fmt, "\"{}\"", id),
        }
    }
}

impl Debug for Symbol {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        Display::fmt(self, fmt)
    }
}

impl Debug for Production {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        write!(fmt,
               "{} = {} => {:?};",
               self.nonterminal, Sep(", ", &self.symbols), self.action_fn)
    }
}

impl Debug for ActionFnDefn {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        write!(fmt, "{}", self.to_fn_string("_"))
    }
}

impl ActionFnDefn {
    fn to_fn_string(&self, name: &str) -> String {
        let arg_strings: Vec<String> =
               self.arg_patterns
                   .iter()
                   .zip(self.arg_types.iter())
                   .map(|(p, t)| format!("{}: {}", p, t))
                   .collect();

        format!("fn {}({}) -> {} {{ {} }}",
                name, Sep(", ", &arg_strings), self.ret_type, self.code)
    }
}
<|endoftext|>


<commit_before>use communication::Data;
use communication::pact::Pipeline;
use construction::{Stream, GraphBuilder};
use construction::operators::unary::UnaryStreamExt;

pub trait InspectExt<D: Data> {
    fn inspect<F: FnMut(&D)+'static>(&self, func: F) -> Self;
}

// TODO : could use look() rather than take()
impl<G: GraphBuilder, D: Data> InspectExt<D> for Stream<G, D> {
    fn inspect<F: FnMut(&D)+'static>(&self, mut func: F) -> Stream<G, D> {
        self.unary_stream(Pipeline, "Inspect", move |input, output| {
            while let Some((time, data)) = input.pull() {
                for datum in data.iter() { func(datum); }
                output.session(time).give_message(data);
            }
        })
    }
}

pub trait InspectBatchExt<G: GraphBuilder, D: Data> {
    fn inspect_batch<F: FnMut(&G::Timestamp, &[D])+'static>(&self, mut func: F) -> Self;
}

// TODO : could use look() rather than take()
impl<G: GraphBuilder, D: Data> InspectBatchExt<G, D> for Stream<G, D> {
    fn inspect_batch<F: FnMut(&G::Timestamp, &[D])+'static>(&self, mut func: F) -> Stream<G, D> {
        self.unary_stream(Pipeline, "Inspect", move |input, output| {
            while let Some((time, data)) = input.pull() {
                func(&time, &data[..]);
                output.session(time).give_message(data);
            }
        })
    }
}
<commit_msg>unified methods into one trait<commit_after>use communication::Data;
use communication::pact::Pipeline;
use construction::{Stream, GraphBuilder};
use construction::operators::unary::UnaryStreamExt;

pub trait InspectExt<D: Data> {
    fn inspect<F: FnMut(&D)+'static>(&self, func: F) -> Self;
    fn inspect_batch<F: FnMut(&G::Timestamp, &[D])+'static>(&self, mut func: F) -> Self;
}

impl<G: GraphBuilder, D: Data> InspectExt<D> for Stream<G, D> {
    fn inspect<F: FnMut(&D)+'static>(&self, mut func: F) -> Stream<G, D> {
        self.unary_stream(Pipeline, "Inspect", move |input, output| {
            while let Some((time, data)) = input.pull() {
                for datum in data.iter() { func(datum); }
                output.session(time).give_message(data);
            }
        })
    }

    fn inspect_batch<F: FnMut(&G::Timestamp, &[D])+'static>(&self, mut func: F) -> Stream<G, D> {
        self.unary_stream(Pipeline, "Inspect", move |input, output| {
            while let Some((time, data)) = input.pull() {
                func(&time, &data[..]);
                output.session(time).give_message(data);
            }
        })
    }
}
<|endoftext|>


<commit_before>// This file is part of rgtk.
//
// rgtk is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// rgtk is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with rgtk.  If not, see <http://www.gnu.org/licenses/>.

use pango::{ffi, Rectangle};
use libc::c_int;
use std::default::Default;

/// A structure specifying a transformation between user-space coordinates and device coordinates.
/// The transformation is given by:
///
/// x_device = x_user * matrix->xx + y_user * matrix->xy + matrix->x0;
/// y_device = x_user * matrix->yx + y_user * matrix->yy + matrix->y0;
pub type Matrix = ffi::PangoMatrix;

impl Matrix {
    pub fn new(xx: f64, xy: f64, yx: f64, yy: f64, x0: f64, y0: f64) -> Matrix {
        Matrix {
            xx: xx,
            xy: xy,
            yx: yx,
            yy: yy,
            x0: x0,
            y0: y0
        }
    }

    pub fn copy(&self) -> Matrix {
        Matrix {
            xx: self.xx,
            xy: self.xy,
            yx: self.yx,
            yy: self.yy,
            x0: self.x0,
            y0: self.y0
        }
    }

    pub fn translate(&mut self, t_x: f64, t_y: f64) {
        unsafe { ffi::pango_matrix_translate(self, t_x, t_y) }
    }

    pub fn scale(&mut self, scale_x: f64, scale_y: f64) {
        unsafe { ffi::pango_matrix_scale(self, scale_x, scale_y) }
    }

    pub fn rotate(&mut self, degrees: f64) {
        unsafe { ffi::pango_matrix_rotate(self, degrees) }
    }

    pub fn concat(&mut self, new_matrix: &Matrix) {
        unsafe { ffi::pango_matrix_concat(self, new_matrix) }
    }

    pub fn transform_point(&self, x: &mut f64, y: &mut f64) {
        unsafe { ffi::pango_matrix_transform_point(self, x, y) }
    }

    pub fn transform_distance(&self, dx: &mut f64, dy: &mut f64) {
        unsafe { ffi::pango_matrix_transform_distance(self, dx, dy) }
    }

    pub fn transform_rectangle(&self, rect: &mut Rectangle) {
        unsafe { ffi::pango_matrix_transform_rectangle(self, rect) }
    }

    pub fn transform_pixel_rectangle(&self, rect: &mut Rectangle) {
        unsafe { ffi::pango_matrix_transform_pixel_rectangle(self, rect) }
    }

    pub fn get_font_scale_factor(&mut self) -> f64 {
        unsafe { ffi::pango_matrix_get_font_scale_factor(self) }
    }
}

impl Default for Matrix {
    fn default() -> Matrix {
        Matrix {
            xx: 1.,
            xy: 0.,
            yx: 0.,
            yy: 1.,
            x0: 0.,
            y0: 0.
        }
    }
}<commit_msg>Remove a useless import<commit_after>// This file is part of rgtk.
//
// rgtk is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// rgtk is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with rgtk.  If not, see <http://www.gnu.org/licenses/>.

use pango::{ffi, Rectangle};
use std::default::Default;

/// A structure specifying a transformation between user-space coordinates and device coordinates.
/// The transformation is given by:
///
/// x_device = x_user * matrix->xx + y_user * matrix->xy + matrix->x0;
/// y_device = x_user * matrix->yx + y_user * matrix->yy + matrix->y0;
pub type Matrix = ffi::PangoMatrix;

impl Matrix {
    pub fn new(xx: f64, xy: f64, yx: f64, yy: f64, x0: f64, y0: f64) -> Matrix {
        Matrix {
            xx: xx,
            xy: xy,
            yx: yx,
            yy: yy,
            x0: x0,
            y0: y0
        }
    }

    pub fn copy(&self) -> Matrix {
        Matrix {
            xx: self.xx,
            xy: self.xy,
            yx: self.yx,
            yy: self.yy,
            x0: self.x0,
            y0: self.y0
        }
    }

    pub fn translate(&mut self, t_x: f64, t_y: f64) {
        unsafe { ffi::pango_matrix_translate(self, t_x, t_y) }
    }

    pub fn scale(&mut self, scale_x: f64, scale_y: f64) {
        unsafe { ffi::pango_matrix_scale(self, scale_x, scale_y) }
    }

    pub fn rotate(&mut self, degrees: f64) {
        unsafe { ffi::pango_matrix_rotate(self, degrees) }
    }

    pub fn concat(&mut self, new_matrix: &Matrix) {
        unsafe { ffi::pango_matrix_concat(self, new_matrix) }
    }

    pub fn transform_point(&self, x: &mut f64, y: &mut f64) {
        unsafe { ffi::pango_matrix_transform_point(self, x, y) }
    }

    pub fn transform_distance(&self, dx: &mut f64, dy: &mut f64) {
        unsafe { ffi::pango_matrix_transform_distance(self, dx, dy) }
    }

    pub fn transform_rectangle(&self, rect: &mut Rectangle) {
        unsafe { ffi::pango_matrix_transform_rectangle(self, rect) }
    }

    pub fn transform_pixel_rectangle(&self, rect: &mut Rectangle) {
        unsafe { ffi::pango_matrix_transform_pixel_rectangle(self, rect) }
    }

    pub fn get_font_scale_factor(&mut self) -> f64 {
        unsafe { ffi::pango_matrix_get_font_scale_factor(self) }
    }
}

impl Default for Matrix {
    fn default() -> Matrix {
        Matrix {
            xx: 1.,
            xy: 0.,
            yx: 0.,
            yy: 1.,
            x0: 0.,
            y0: 0.
        }
    }
}<|endoftext|>


<commit_before>//! Defines the DifferentialGeometry type which is used to pass information
//! about the hit piece of geometry back from the intersection to the shading

use linalg::{Point, Normal};
use geometry::{Geometry, Instance};

/// Stores information about a hit piece of geometry of some object in the scene
#[deriving(Copy)]
pub struct DifferentialGeometry<'a, 'b> {
    /// The hit point
    pub p: Point,
    /// The shading normal
    pub n: Normal,
    /// The geometry normal
    pub ng: Normal,
    /// The geometry that was hit
    pub geom: &'a (Geometry + 'a),
    /// The instance of geometry that was hit
    pub instance: Option<&'b Instance<'b>>,
}

impl<'a, 'b> DifferentialGeometry<'a, 'b> {
    /// Initialize the differential geometry with 0 values for all fields
    /// and None for the hit geometry
    pub fn new(p: &Point, n: &Normal, ng: &Normal, geom: &'a (Geometry + 'a),
               instance: Option<&'b Instance<'b>>) -> DifferentialGeometry<'a, 'b> {
        DifferentialGeometry { p: *p, n: *n, ng: *ng, geom: geom, instance: instance }
    }
}

<commit_msg>Use 'static lifetime bound to require that geom is a real struct<commit_after>//! Defines the DifferentialGeometry type which is used to pass information
//! about the hit piece of geometry back from the intersection to the shading

use linalg::{Point, Normal};
use geometry::{Geometry, Instance};

/// Stores information about a hit piece of geometry of some object in the scene
#[deriving(Copy)]
pub struct DifferentialGeometry<'a, 'b> {
    /// The hit point
    pub p: Point,
    /// The shading normal
    pub n: Normal,
    /// The geometry normal
    pub ng: Normal,
    /// The geometry that was hit
    pub geom: &'a (Geometry + 'static),
    /// The instance of geometry that was hit
    pub instance: Option<&'b Instance<'b>>,
}

impl<'a, 'b> DifferentialGeometry<'a, 'b> {
    /// Initialize the differential geometry with 0 values for all fields
    /// and None for the hit geometry
    pub fn new(p: &Point, n: &Normal, ng: &Normal, geom: &'a (Geometry + 'static),
               instance: Option<&'b Instance<'b>>) -> DifferentialGeometry<'a, 'b> {
        DifferentialGeometry { p: *p, n: *n, ng: *ng, geom: geom, instance: instance }
    }
}

<|endoftext|>


<commit_before>use crate::{EarlyContext, EarlyLintPass, LintContext};
use rustc_ast::ast;
use rustc_data_structures::fx::FxHashMap;
use rustc_span::symbol::SymbolStr;

declare_lint! {
    pub NON_ASCII_IDENTS,
    Allow,
    "detects non-ASCII identifiers"
}

declare_lint! {
    pub UNCOMMON_CODEPOINTS,
    Warn,
    "detects uncommon Unicode codepoints in identifiers"
}

// FIXME: Change this to warn.
declare_lint! {
    pub CONFUSABLE_IDENTS,
    Allow,
    "detects visually confusable pairs between identifiers"
}

declare_lint_pass!(NonAsciiIdents => [NON_ASCII_IDENTS, UNCOMMON_CODEPOINTS, CONFUSABLE_IDENTS]);

use std::hash::{Hash, Hasher};
use std::ops::Deref;

enum CowBoxSymStr {
    Interned(SymbolStr),
    Owned(Box<str>),
}

impl Deref for CowBoxSymStr {
    type Target = str;

    fn deref(&self) -> &str {
        match self {
            CowBoxSymStr::Interned(interned) => interned,
            CowBoxSymStr::Owned(ref owned) => owned,
        }
    }
}

impl Hash for CowBoxSymStr {
    #[inline]
    fn hash<H: Hasher>(&self, state: &mut H) {
        Hash::hash(&**self, state)
    }
}

impl PartialEq<CowBoxSymStr> for CowBoxSymStr {
    #[inline]
    fn eq(&self, other: &CowBoxSymStr) -> bool {
        PartialEq::eq(&**self, &**other)
    }
}

impl Eq for CowBoxSymStr {}

fn calc_skeleton(symbol_str: SymbolStr, buffer: &'_ mut String) -> CowBoxSymStr {
    use std::mem::swap;
    use unicode_security::confusable_detection::skeleton;
    buffer.clear();
    buffer.extend(skeleton(&symbol_str));
    if symbol_str == *buffer {
        CowBoxSymStr::Interned(symbol_str)
    } else {
        let mut owned = String::new();
        swap(buffer, &mut owned);
        CowBoxSymStr::Owned(owned.into_boxed_str())
    }
}

impl EarlyLintPass for NonAsciiIdents {
    fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &ast::Crate) {
        use rustc_session::lint::Level;
        if cx.builder.lint_level(CONFUSABLE_IDENTS).0 == Level::Allow {
            return;
        }
        let symbols = cx.sess.parse_sess.symbol_gallery.symbols.lock();
        let mut symbol_strs_and_spans = Vec::with_capacity(symbols.len());
        for (symbol, sp) in symbols.iter() {
            let symbol_str = symbol.as_str();
            symbol_strs_and_spans.push((symbol_str, *sp));
        }
        drop(symbols);
        symbol_strs_and_spans.sort_by_key(|x| x.0.clone());
        let mut skeleton_map =
            FxHashMap::with_capacity_and_hasher(symbol_strs_and_spans.len(), Default::default());
        let mut str_buf = String::new();
        for (symbol_str, sp) in symbol_strs_and_spans {
            let skeleton = calc_skeleton(symbol_str.clone(), &mut str_buf);
            skeleton_map
                .entry(skeleton)
                .and_modify(|(existing_symbolstr, existing_span)| {
                    cx.struct_span_lint(CONFUSABLE_IDENTS, sp, |lint| {
                        lint.build(&format!(
                            "identifier pair considered confusable between `{}` and `{}`",
                            existing_symbolstr, symbol_str
                        ))
                        .span_label(
                            *existing_span,
                            "this is where the previous identifier occurred",
                        )
                        .emit();
                    });
                })
                .or_insert((symbol_str, sp));
        }
    }
    fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: ast::Ident) {
        use unicode_security::GeneralSecurityProfile;
        let name_str = ident.name.as_str();
        if name_str.is_ascii() {
            return;
        }
        cx.struct_span_lint(NON_ASCII_IDENTS, ident.span, |lint| {
            lint.build("identifier contains non-ASCII characters").emit()
        });
        if !name_str.chars().all(GeneralSecurityProfile::identifier_allowed) {
            cx.struct_span_lint(UNCOMMON_CODEPOINTS, ident.span, |lint| {
                lint.build("identifier contains uncommon Unicode codepoints").emit()
            })
        }
    }
}
<commit_msg>Add a fast code path to optimize `confusable_idents` lint for ASCII code base.<commit_after>use crate::{EarlyContext, EarlyLintPass, LintContext};
use rustc_ast::ast;
use rustc_data_structures::fx::FxHashMap;
use rustc_span::symbol::SymbolStr;
use std::hash::{Hash, Hasher};
use std::ops::Deref;

declare_lint! {
    pub NON_ASCII_IDENTS,
    Allow,
    "detects non-ASCII identifiers"
}

declare_lint! {
    pub UNCOMMON_CODEPOINTS,
    Warn,
    "detects uncommon Unicode codepoints in identifiers"
}

// FIXME: Change this to warn.
declare_lint! {
    pub CONFUSABLE_IDENTS,
    Allow,
    "detects visually confusable pairs between identifiers"
}

declare_lint_pass!(NonAsciiIdents => [NON_ASCII_IDENTS, UNCOMMON_CODEPOINTS, CONFUSABLE_IDENTS]);

enum CowBoxSymStr {
    Interned(SymbolStr),
    Owned(Box<str>),
}

impl Deref for CowBoxSymStr {
    type Target = str;

    fn deref(&self) -> &str {
        match self {
            CowBoxSymStr::Interned(interned) => interned,
            CowBoxSymStr::Owned(ref owned) => owned,
        }
    }
}

impl Hash for CowBoxSymStr {
    #[inline]
    fn hash<H: Hasher>(&self, state: &mut H) {
        Hash::hash(&**self, state)
    }
}

impl PartialEq<CowBoxSymStr> for CowBoxSymStr {
    #[inline]
    fn eq(&self, other: &CowBoxSymStr) -> bool {
        PartialEq::eq(&**self, &**other)
    }
}

impl Eq for CowBoxSymStr {}

fn calc_skeleton(symbol_str: SymbolStr, buffer: &'_ mut String) -> CowBoxSymStr {
    use std::mem::swap;
    use unicode_security::confusable_detection::skeleton;
    buffer.clear();
    buffer.extend(skeleton(&symbol_str));
    if symbol_str == *buffer {
        CowBoxSymStr::Interned(symbol_str)
    } else {
        let mut owned = String::new();
        swap(buffer, &mut owned);
        CowBoxSymStr::Owned(owned.into_boxed_str())
    }
}

fn is_in_ascii_confusable_closure(c: char) -> bool {
    // FIXME: move this table to `unicode_security` crate.
    // data here corresponds to Unicode 13.
    const ASCII_CONFUSABLE_CLOSURE: &[(u64, u64)] = &[(0x00, 0x7f), (0xba, 0xba), (0x2080, 0x2080)];
    let c = c as u64;
    for &(range_start, range_end) in ASCII_CONFUSABLE_CLOSURE {
        if c >= range_start && c <= range_end {
            return true;
        }
    }
    false
}

fn is_in_ascii_confusable_closure_relevant_list(c: char) -> bool {
    // FIXME: move this table to `unicode_security` crate.
    // data here corresponds to Unicode 13.
    const ASCII_CONFUSABLE_CLOSURE_RELEVANT_LIST: &[u64] = &[
        0x22, 0x25, 0x27, 0x2f, 0x30, 0x31, 0x49, 0x4f, 0x60, 0x6c, 0x6d, 0x6e, 0x72, 0x7c, 0xba,
        0x2080,
    ];
    let c = c as u64;
    for &item in ASCII_CONFUSABLE_CLOSURE_RELEVANT_LIST {
        if c == item {
            return true;
        }
    }
    false
}

impl EarlyLintPass for NonAsciiIdents {
    fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &ast::Crate) {
        use rustc_session::lint::Level;
        if cx.builder.lint_level(CONFUSABLE_IDENTS).0 == Level::Allow {
            return;
        }
        let symbols = cx.sess.parse_sess.symbol_gallery.symbols.lock();
        let mut symbol_strs_and_spans = Vec::with_capacity(symbols.len());
        let mut in_fast_path = true;
        for (symbol, sp) in symbols.iter() {
            // fast path
            let symbol_str = symbol.as_str();
            if !symbol_str.chars().all(is_in_ascii_confusable_closure) {
                // fallback to slow path.
                symbol_strs_and_spans.clear();
                in_fast_path = false;
                break;
            }
            if symbol_str.chars().any(is_in_ascii_confusable_closure_relevant_list) {
                symbol_strs_and_spans.push((symbol_str, *sp));
            }
        }
        if !in_fast_path {
            // slow path
            for (symbol, sp) in symbols.iter() {
                let symbol_str = symbol.as_str();
                symbol_strs_and_spans.push((symbol_str, *sp));
            }
        }
        drop(symbols);
        symbol_strs_and_spans.sort_by_key(|x| x.0.clone());
        let mut skeleton_map =
            FxHashMap::with_capacity_and_hasher(symbol_strs_and_spans.len(), Default::default());
        let mut str_buf = String::new();
        for (symbol_str, sp) in symbol_strs_and_spans {
            let skeleton = calc_skeleton(symbol_str.clone(), &mut str_buf);
            skeleton_map
                .entry(skeleton)
                .and_modify(|(existing_symbolstr, existing_span)| {
                    cx.struct_span_lint(CONFUSABLE_IDENTS, sp, |lint| {
                        lint.build(&format!(
                            "identifier pair considered confusable between `{}` and `{}`",
                            existing_symbolstr, symbol_str
                        ))
                        .span_label(
                            *existing_span,
                            "this is where the previous identifier occurred",
                        )
                        .emit();
                    });
                })
                .or_insert((symbol_str, sp));
        }
    }
    fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: ast::Ident) {
        use unicode_security::GeneralSecurityProfile;
        let name_str = ident.name.as_str();
        if name_str.is_ascii() {
            return;
        }
        cx.struct_span_lint(NON_ASCII_IDENTS, ident.span, |lint| {
            lint.build("identifier contains non-ASCII characters").emit()
        });
        if !name_str.chars().all(GeneralSecurityProfile::identifier_allowed) {
            cx.struct_span_lint(UNCOMMON_CODEPOINTS, ident.span, |lint| {
                lint.build("identifier contains uncommon Unicode codepoints").emit()
            })
        }
    }
}
<|endoftext|>