<commit_before>// TODO: deny missing docs
#![allow(missing_docs)]

use dns::{Response, Result as LookupResult, Error as LookupError, Source};

use itertools::Itertools;
use std::collections::HashMap;
use trust_dns::rr::{RData, Record};

#[derive(Debug)]
pub struct RecordCount<'a> {
    record: &'a Record,
    sources: Vec<Source>,
}

impl<'a> RecordCount<'a> {
    pub fn count(&self) -> usize {
        self.sources.len()
    }

    pub fn record(&self) -> &Record {
        self.record
    }

    pub fn sources(&self) -> &Vec<Source> {
        &self.sources
    }
}

#[derive(Debug)]
pub struct Summary<'a> {
    pub num_of_samples: usize,
    pub num_of_ok_samples: usize,
    pub num_of_err_samples: usize,
    pub min_num_of_records: usize,
    pub max_num_of_records: usize,
    pub record_counts: HashMap<String, RecordCount<'a>>,
    pub failures: Vec<&'a LookupError>,
    pub alerts: Vec<Alert>
}

impl<'a> Summary<'a> {
    pub fn from(responses: &'a [LookupResult<Response>]) -> Self {
        let num_of_samples = responses.len();

        let (responses, failures): (Vec<_>, Vec<_>) =
            responses.into_iter().partition(|x| x.is_ok());
        let successes: Vec<&Response> =
            responses.into_iter().map(|x| x.as_ref().unwrap()).collect();
        let failures: Vec<&LookupError> = failures
            .into_iter()
            .map(|x| x.as_ref().unwrap_err())
            .collect();

        let num_of_ok_samples = successes.len();
        let num_of_err_samples = failures.len();

        let (min_num_of_records, max_num_of_records) = successes
            .iter()
            .map(|x| x.answers.len())
            .fold((::std::usize::MAX, 0), |(mut min, mut max), x| {
                if min > x {
                    min = x
                };
                if max < x {
                    max = x
                };
                (min, max)
            });

        let mut record_counts = HashMap::new();
        for response in &successes {
            for record in &response.answers {
                let key = format!("{:?}-{:?}", record.rr_type(), record.rdata());
                let value = record_counts.entry(key).or_insert( RecordCount{ record, sources: Vec::new() } );
                value.sources.push(response.server.source);
            }
        }

        let alerts = alerts(successes.as_slice());

        Summary {
            num_of_samples,
            num_of_ok_samples,
            num_of_err_samples,
            min_num_of_records,
            max_num_of_records,
            record_counts,
            failures,
            alerts
        }
    }
}

#[derive(Debug)]
pub enum Alert {
    SoaSnDiverge(HashMap<u32, u32>),
}

// TODO: &[&T] is totally weird
fn alerts(responses: &[&Response]) -> Vec<Alert> {
    let mut alerts = Vec::new();
    if let Some(serials) = check_soa_serial_numbers(responses) {
        alerts.push(serials)
    }

    alerts
}

// TODO: &[&T] is totally weird
fn check_soa_serial_numbers(responses: &[&Response]) -> Option<Alert> {
    let mut serial_counts = HashMap::new();
    responses
        .iter()
        .map(|r| r.answers
            .iter()
            .map(|a| match *a.rdata() {
                RData::SOA(ref soa) => Some(soa.serial()),
                _ => None
            })
        )
        .flatten()
        .filter_map(|x| x)
        .for_each(|key| {
            let value = serial_counts.entry(key).or_insert(0);
            *value += 1;
        });

    if serial_counts.len() > 1 {
        Some(Alert::SoaSnDiverge(serial_counts))
    } else {
        None
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use dns::{ErrorKind as LookupErrorKind, Server, Source};
    use std::net::IpAddr;
    use std::str::FromStr;
    use trust_dns::rr::{domain, RecordType};
    use trust_dns::rr::rdata::SOA;

    #[test]
    fn simple_summary() {
        let records_1: Vec<Record> = vec![
            Record::with(
                domain::Name::from_str("www.example.com").unwrap(),
                RecordType::A,
                100
            ),
            Record::with(
                domain::Name::from_str("www.example.com").unwrap(),
                RecordType::MX,
                99
            ),
        ];
        let response_1 = Response {
            server: Server::udp_from(IpAddr::from([127, 0, 0, 1]), Source::Additional),
            answers: records_1,
        };
        let records_2: Vec<Record> = vec![
            Record::with(
                domain::Name::from_str("www.example.com").unwrap(),
                RecordType::A,
                98
            ),
        ];
        let response_2 = Response {
            server: Server::udp_from(IpAddr::from([127, 0, 0, 2]), Source::Additional),
            answers: records_2,
        };
        let responses: Vec<LookupResult<Response>> =
            vec![
                Ok(response_1),
                Ok(response_2),
                Err(
                    LookupErrorKind::QueryError(1, RecordType::AAAA, IpAddr::from([127, 0, 0, 3]))
                        .into()
                ),
            ];

        let summary = Summary::from(&responses);

        assert_eq!(summary.num_of_samples, 3);
        assert_eq!(summary.num_of_ok_samples, 2);
        assert_eq!(summary.num_of_err_samples, 1);
        assert_eq!(summary.min_num_of_records, 1);
        assert_eq!(summary.max_num_of_records, 2);
        assert_eq!(summary.record_counts.len(), 2);

        let mut record_counts: Vec<_> = summary
            .record_counts
            .values()
            .map(|ref rc| rc.count())
            .collect();
        record_counts.sort();
        assert_eq!(record_counts, vec![1, 2]);

        assert_eq!(summary.failures.len(), 1);
    }

    #[test]
    fn test_alert_for_diverging_soa_serials() {
        let records_1: Vec<Record> = vec![
            Record::from_rdata(
                domain::Name::from_str("www.example.com").unwrap(),
                99,
                RecordType::SOA,
                RData::SOA(
                    SOA::new(
                        domain::Name::from_str("sns.dns.icann.org.").unwrap(),
                        domain::Name::from_str("noc.dns.icann.org.").unwrap(),
                        100,
                        7200,
                        3600,
                        1209600,
                        3600
                    )
                )
            )
        ];
        let response_1 = Response {
            server: Server::udp_from(IpAddr::from([127, 0, 0, 1]), Source::Additional),
            answers: records_1,
        };
        let records_2: Vec<Record> = vec![
            Record::from_rdata(
                domain::Name::from_str("www.example.com").unwrap(),
                99,
                RecordType::SOA,
                RData::SOA(
                    SOA::new(
                        domain::Name::from_str("sns.dns.icann.org.").unwrap(),
                        domain::Name::from_str("noc.dns.icann.org.").unwrap(),
                        200,
                        7200,
                        3600,
                        1209600,
                        3600
                    )
                )
            )];
        let response_2 = Response {
            server: Server::udp_from(IpAddr::from([127, 0, 0, 2]), Source::Additional),
            answers: records_2,
        };
        let responses: Vec<Response> = vec![response_1, response_2, ];

        let alerts = alerts(&responses.iter().collect::<Vec<_>>());

        assert_eq!(alerts.len(), 1);
        let &Alert::SoaSnDiverge(ref soa_serials) = alerts.first().unwrap();
        let mut serials = soa_serials.keys().collect::<Vec<_>>();
        serials.sort();
        assert_eq!(serials, vec![&100, &200]);
        let mut counts = soa_serials.values().collect::<Vec<_>>();
        counts.sort();
        assert_eq!(counts, vec![&1, &1]);
    }
}
<commit_msg>Add link to forum discussion to TODO<commit_after>// TODO: deny missing docs
#![allow(missing_docs)]

use dns::{Response, Result as LookupResult, Error as LookupError, Source};

use itertools::Itertools;
use std::collections::HashMap;
use trust_dns::rr::{RData, Record};

#[derive(Debug)]
pub struct RecordCount<'a> {
    record: &'a Record,
    sources: Vec<Source>,
}

impl<'a> RecordCount<'a> {
    pub fn count(&self) -> usize {
        self.sources.len()
    }

    pub fn record(&self) -> &Record {
        self.record
    }

    pub fn sources(&self) -> &Vec<Source> {
        &self.sources
    }
}

#[derive(Debug)]
pub struct Summary<'a> {
    pub num_of_samples: usize,
    pub num_of_ok_samples: usize,
    pub num_of_err_samples: usize,
    pub min_num_of_records: usize,
    pub max_num_of_records: usize,
    pub record_counts: HashMap<String, RecordCount<'a>>,
    pub failures: Vec<&'a LookupError>,
    pub alerts: Vec<Alert>
}

impl<'a> Summary<'a> {
    pub fn from(responses: &'a [LookupResult<Response>]) -> Self {
        let num_of_samples = responses.len();

        let (responses, failures): (Vec<_>, Vec<_>) =
            responses.into_iter().partition(|x| x.is_ok());
        let successes: Vec<&Response> =
            responses.into_iter().map(|x| x.as_ref().unwrap()).collect();
        let failures: Vec<&LookupError> = failures
            .into_iter()
            .map(|x| x.as_ref().unwrap_err())
            .collect();

        let num_of_ok_samples = successes.len();
        let num_of_err_samples = failures.len();

        let (min_num_of_records, max_num_of_records) = successes
            .iter()
            .map(|x| x.answers.len())
            .fold((::std::usize::MAX, 0), |(mut min, mut max), x| {
                if min > x {
                    min = x
                };
                if max < x {
                    max = x
                };
                (min, max)
            });

        let mut record_counts = HashMap::new();
        for response in &successes {
            for record in &response.answers {
                let key = format!("{:?}-{:?}", record.rr_type(), record.rdata());
                let value = record_counts.entry(key).or_insert( RecordCount{ record, sources: Vec::new() } );
                value.sources.push(response.server.source);
            }
        }

        let alerts = alerts(successes.as_slice());

        Summary {
            num_of_samples,
            num_of_ok_samples,
            num_of_err_samples,
            min_num_of_records,
            max_num_of_records,
            record_counts,
            failures,
            alerts
        }
    }
}

#[derive(Debug)]
pub enum Alert {
    SoaSnDiverge(HashMap<u32, u32>),
}

// TODO: &[&T] is totally weird -- cf. https://users.rust-lang.org/t/solved-function-taking-slice-of-objects-as-well-as-slice-of-references-to-objects/13553/9
fn alerts(responses: &[&Response]) -> Vec<Alert> {
    let mut alerts = Vec::new();
    if let Some(serials) = check_soa_serial_numbers(responses) {
        alerts.push(serials)
    }

    alerts
}

// TODO: &[&T] is totally weird
fn check_soa_serial_numbers(responses: &[&Response]) -> Option<Alert> {
    let mut serial_counts = HashMap::new();
    responses
        .iter()
        .map(|r| r.answers
            .iter()
            .map(|a| match *a.rdata() {
                RData::SOA(ref soa) => Some(soa.serial()),
                _ => None
            })
        )
        .flatten()
        .filter_map(|x| x)
        .for_each(|key| {
            let value = serial_counts.entry(key).or_insert(0);
            *value += 1;
        });

    if serial_counts.len() > 1 {
        Some(Alert::SoaSnDiverge(serial_counts))
    } else {
        None
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use dns::{ErrorKind as LookupErrorKind, Server, Source};
    use std::net::IpAddr;
    use std::str::FromStr;
    use trust_dns::rr::{domain, RecordType};
    use trust_dns::rr::rdata::SOA;

    #[test]
    fn simple_summary() {
        let records_1: Vec<Record> = vec![
            Record::with(
                domain::Name::from_str("www.example.com").unwrap(),
                RecordType::A,
                100
            ),
            Record::with(
                domain::Name::from_str("www.example.com").unwrap(),
                RecordType::MX,
                99
            ),
        ];
        let response_1 = Response {
            server: Server::udp_from(IpAddr::from([127, 0, 0, 1]), Source::Additional),
            answers: records_1,
        };
        let records_2: Vec<Record> = vec![
            Record::with(
                domain::Name::from_str("www.example.com").unwrap(),
                RecordType::A,
                98
            ),
        ];
        let response_2 = Response {
            server: Server::udp_from(IpAddr::from([127, 0, 0, 2]), Source::Additional),
            answers: records_2,
        };
        let responses: Vec<LookupResult<Response>> =
            vec![
                Ok(response_1),
                Ok(response_2),
                Err(
                    LookupErrorKind::QueryError(1, RecordType::AAAA, IpAddr::from([127, 0, 0, 3]))
                        .into()
                ),
            ];

        let summary = Summary::from(&responses);

        assert_eq!(summary.num_of_samples, 3);
        assert_eq!(summary.num_of_ok_samples, 2);
        assert_eq!(summary.num_of_err_samples, 1);
        assert_eq!(summary.min_num_of_records, 1);
        assert_eq!(summary.max_num_of_records, 2);
        assert_eq!(summary.record_counts.len(), 2);

        let mut record_counts: Vec<_> = summary
            .record_counts
            .values()
            .map(|ref rc| rc.count())
            .collect();
        record_counts.sort();
        assert_eq!(record_counts, vec![1, 2]);

        assert_eq!(summary.failures.len(), 1);
    }

    #[test]
    fn test_alert_for_diverging_soa_serials() {
        let records_1: Vec<Record> = vec![
            Record::from_rdata(
                domain::Name::from_str("www.example.com").unwrap(),
                99,
                RecordType::SOA,
                RData::SOA(
                    SOA::new(
                        domain::Name::from_str("sns.dns.icann.org.").unwrap(),
                        domain::Name::from_str("noc.dns.icann.org.").unwrap(),
                        100,
                        7200,
                        3600,
                        1209600,
                        3600
                    )
                )
            )
        ];
        let response_1 = Response {
            server: Server::udp_from(IpAddr::from([127, 0, 0, 1]), Source::Additional),
            answers: records_1,
        };
        let records_2: Vec<Record> = vec![
            Record::from_rdata(
                domain::Name::from_str("www.example.com").unwrap(),
                99,
                RecordType::SOA,
                RData::SOA(
                    SOA::new(
                        domain::Name::from_str("sns.dns.icann.org.").unwrap(),
                        domain::Name::from_str("noc.dns.icann.org.").unwrap(),
                        200,
                        7200,
                        3600,
                        1209600,
                        3600
                    )
                )
            )];
        let response_2 = Response {
            server: Server::udp_from(IpAddr::from([127, 0, 0, 2]), Source::Additional),
            answers: records_2,
        };
        let responses: Vec<Response> = vec![response_1, response_2, ];

        let alerts = alerts(&responses.iter().collect::<Vec<_>>());

        assert_eq!(alerts.len(), 1);
        let &Alert::SoaSnDiverge(ref soa_serials) = alerts.first().unwrap();
        let mut serials = soa_serials.keys().collect::<Vec<_>>();
        serials.sort();
        assert_eq!(serials, vec![&100, &200]);
        let mut counts = soa_serials.values().collect::<Vec<_>>();
        counts.sort();
        assert_eq!(counts, vec![&1, &1]);
    }
}
<|endoftext|>


<commit_before>mod irc;

pub struct TmiStream {
    irc_stream: irc::IrcStream
}

impl TmiStream {
    // Err(1): establishing IRC stream failed
    pub fn establish(server: String, pass: String, nick: String, channel: String) -> Result<Self, u8> {
        match irc::IrcStream::establish(server, pass, nick, channel) {
            Ok(irc_stream) => Ok(TmiStream { irc_stream: irc_stream} ),
            Err(_) => Err(1)
        }
    }

    // Ok((sender, message))
    // Err(1): unable to identify sender
    // Err(2): unable to identify message payload
    // Err(3): unable to identify message payload
    // Err(4): unable to receive message
    pub fn receive(&self) -> Result<(String, String), u8> {
        match self.irc_stream.receive_privmsg() {
            Ok(msg) => {
                let nick = match msg.prefix {
                    Some(prefix) => prefix.servername_nick,
                    None => return Err(1)
                };
                let message = match msg.params {
                    Some(mut params) => {
                        if params.len() < 2 {
                            params.remove(1)
                        } else {
                            return Err(2)
                        }
                    },
                    None => return Err(3)
                };
                Ok((nick, message))
            },
            Err(_) => Err(4)
        }
    }
}
<commit_msg>Fix TMI module<commit_after>mod irc;

pub struct TmiStream {
    irc_stream: irc::IrcStream
}

impl TmiStream {
    // Err(1): establishing IRC stream failed
    pub fn establish(server: String, pass: String, nick: String, channel: String) -> Result<Self, u8> {
        match irc::IrcStream::establish(server, pass, nick, channel) {
            Ok(irc_stream) => Ok(TmiStream { irc_stream: irc_stream} ),
            Err(_) => Err(1)
        }
    }

    // Ok((sender, message))
    // Err(1): unable to identify sender
    // Err(2): unable to identify message payload
    // Err(3): unable to identify message payload
    // Err(4): unable to receive message
    pub fn receive(&self) -> Result<(String, String), u8> {
        match self.irc_stream.receive_privmsg() {
            Ok(msg) => {
                let nick = match msg.prefix {
                    Some(prefix) => prefix.servername_nick,
                    None => return Err(1)
                };
                let message = match msg.params {
                    Some(mut params) => {
                        if params.len() < 2 {
                            return Err(2)
                        } else {
                            params.remove(1)
                        }
                    },
                    None => return Err(3)
                };
                Ok((nick, message))
            },
            Err(_) => Err(4)
        }
    }
}
<|endoftext|>


<commit_before>use std::any::{Any, AnyMutRefExt, AnyRefExt};
use std::boxed::BoxAny;
use std::intrinsics::TypeId;
use std::collections::HashMap;

pub struct TypeMap {
    data: HashMap<TypeId, Box<Any + 'static>>
}

impl TypeMap {
    pub fn new() -> TypeMap {
        TypeMap { data: HashMap::new() }
    }

    pub fn find<T: 'static>(&self) -> Option<&T> {
        self.data.find(&TypeId::of::<T>()).and_then(|a| a.downcast_ref())
    }

    pub fn find_mut<T: 'static>(&mut self) -> Option<&mut T> {
        self.data.find_mut(&TypeId::of::<T>()).and_then(|a| a.downcast_mut())
    }

    pub fn insert<T: 'static>(&mut self, val: T) -> bool {
        self.data.insert(TypeId::of::<T>(), box val as Box<Any>)
    }

    pub fn remove<T: 'static>(&mut self) -> bool {
        self.data.remove(&TypeId::of::<T>())
    }

    pub fn contains<T: 'static>(&mut self) -> bool {
        self.data.contains_key(&TypeId::of::<T>())
    }

    pub fn pop<T: 'static>(&mut self) -> Option<T> {
        let data = match self.data.pop(&TypeId::of::<T>()) {
            Some(data) => data,
            None => return None,
        };
        Some(*data.downcast::<T>().unwrap())
    }
}

#[cfg(test)]
mod tests {
    use super::TypeMap;

    #[test]
    fn smoke() {
        let mut m = TypeMap::new();
        assert!(m.insert(1i));
        assert_eq!(*m.find::<int>().unwrap(), 1);
        assert_eq!(*m.find_mut::<int>().unwrap(), 1);
        assert!(!m.insert(2i));
        assert!(m.remove::<int>());
        assert!(!m.contains::<int>());
        assert!(m.insert(4i));
        assert_eq!(m.pop::<int>().unwrap(), 4);
    }
}

<commit_msg>Don't require mut self for contains<commit_after>use std::any::{Any, AnyMutRefExt, AnyRefExt};
use std::boxed::BoxAny;
use std::intrinsics::TypeId;
use std::collections::HashMap;

pub struct TypeMap {
    data: HashMap<TypeId, Box<Any + 'static>>
}

impl TypeMap {
    pub fn new() -> TypeMap {
        TypeMap { data: HashMap::new() }
    }

    pub fn find<T: 'static>(&self) -> Option<&T> {
        self.data.find(&TypeId::of::<T>()).and_then(|a| a.downcast_ref())
    }

    pub fn find_mut<T: 'static>(&mut self) -> Option<&mut T> {
        self.data.find_mut(&TypeId::of::<T>()).and_then(|a| a.downcast_mut())
    }

    pub fn insert<T: 'static>(&mut self, val: T) -> bool {
        self.data.insert(TypeId::of::<T>(), box val as Box<Any>)
    }

    pub fn remove<T: 'static>(&mut self) -> bool {
        self.data.remove(&TypeId::of::<T>())
    }

    pub fn contains<T: 'static>(&self) -> bool {
        self.data.contains_key(&TypeId::of::<T>())
    }

    pub fn pop<T: 'static>(&mut self) -> Option<T> {
        let data = match self.data.pop(&TypeId::of::<T>()) {
            Some(data) => data,
            None => return None,
        };
        Some(*data.downcast::<T>().unwrap())
    }
}

#[cfg(test)]
mod tests {
    use super::TypeMap;

    #[test]
    fn smoke() {
        let mut m = TypeMap::new();
        assert!(m.insert(1i));
        assert_eq!(*m.find::<int>().unwrap(), 1);
        assert_eq!(*m.find_mut::<int>().unwrap(), 1);
        assert!(!m.insert(2i));
        assert!(m.remove::<int>());
        assert!(!m.contains::<int>());
        assert!(m.insert(4i));
        assert_eq!(m.pop::<int>().unwrap(), 4);
    }
}

<|endoftext|>


<commit_before>
//! Various methods for computing with vectors.

use {
    Line,
    Matrix2d,
    Ray,
    Rectangle,
    Vec2d,
    Triangle
};
use modular_index::{previous};

/// Multiplies two matrices.
#[inline(always)]
pub fn multiply(
    &Matrix2d(m): &Matrix2d,
    &Matrix2d(b): &Matrix2d
) -> Matrix2d {
    Matrix2d(
        [m[0]*b[0]+m[1]*b[3]+m[2]*0.0,  m[0]*b[1]+m[1]*b[4]+m[2]*0.0,  m[0]*b[2]+m[1]*b[5]+m[2]*1.0,
         m[3]*b[0]+m[4]*b[3]+m[5]*0.0,  m[3]*b[1]+m[4]*b[4]+m[5]*0.0,  m[3]*b[2]+m[4]*b[5]+m[5]*1.0]
    )
}

/// Creates a translation matrix.
#[inline(always)]
pub fn translate(x: f64, y: f64) -> Matrix2d {
    Matrix2d(
        [1.0, 0.0, x,
         0.0, 1.0, y]
    )
}

/// Creates a rotation matrix.
#[inline(always)]
pub fn rotate_radians(angle: f64) -> Matrix2d {
    let c = angle.cos();
    let s = angle.sin();
    Matrix2d(
        [c, -s, 0.0,
         s,  c, 0.0]
    )
}

/// Orients x axis to look at point.
///
/// Leaves x axis unchanged if the point to look at is the origin.
#[inline(always)]
pub fn orient(x: f64, y: f64) -> Matrix2d {
    let len = x * x + y * y;
    if len == 0.0 {
         return Matrix2d(
            [1.0, 0.0, 0.0,
             0.0, 1.0, 0.0]
         );
    }

    let len = len.sqrt();
    let c = x / len;
    let s = y / len;
    Matrix2d(
        [c, -s, 0.0,
         s,  c, 0.0]
    )
}

/// Create a scale matrix.
#[inline(always)]
pub fn scale(sx: f64, sy: f64) -> Matrix2d {
    Matrix2d(
        [sx, 0.0, 0.0,
         0.0, sy, 0.0]
    )
}

/// Create a shear matrix.
#[inline(always)]
pub fn shear(sx: f64, sy: f64) -> Matrix2d {
    Matrix2d(
        [1.0, sx, 0.0,
         sy, 1.0, 0.0]
    )
}

/// Create an identity matrix.
#[inline(always)]
pub fn identity() -> Matrix2d {
    Matrix2d(
        [1.0, 0.0, 0.0,
         0.0, 1.0, 0.0]
    )
}

/// Compute the shortest vector from point to ray.
/// A ray stores starting point and directional vector.
#[inline(always)]
pub fn separation(
    Ray(ray): Ray,
    x: f64,
    y: f64) -> Vec2d {
    // Get the directional vector.
    let (dir_x, dir_y) = (ray[2], ray[3]);
    // Get displacement vector from point.
    let (dx, dy) = (ray[0] - x, ray[1] - y);
    // Compute the component of position in ray direction.
    let dot = dir_x * x + dir_y * y;
    // The directional vector multiplied with the dot gives us a parallel vector.
    // When we subtract this from the displacement we get a vector normal to the ray.
    // This is the shortest vector from the point to the ray.
    Vec2d([dx - dot * dir_x, dy - dot * dir_y])
}

/// Returns the least separation out of four.
/// Each seperation can be computed using `separation` function.
/// The separation returned can be used to solve collision of rectangles.
#[inline(always)]
pub fn least_separation_4(
    &Vec2d(sep1): &Vec2d,
    &Vec2d(sep2): &Vec2d,
    &Vec2d(sep3): &Vec2d,
    &Vec2d(sep4): &Vec2d
) -> Vec2d {
    let dot1 = sep1[0] * sep1[0] + sep1[1] * sep1[1];
    let dot2 = sep2[0] * sep2[0] + sep2[1] * sep2[1];
    let dot3 = sep3[0] * sep3[0] + sep3[1] * sep3[1];
    let dot4 = sep4[0] * sep4[0] + sep4[1] * sep4[1];
    // Search for the smallest dot product.
    Vec2d(
        if dot1 < dot2 {
            if dot3 < dot4 {
                if dot1 < dot3 { sep1 } else { sep3 }
            } else {
                if dot1 < dot4 { sep1 } else { sep4 }
            }
        } else {
            if dot3 < dot4 {
                if dot2 < dot3 { sep2 } else { sep3 }
            } else {
                if dot2 < dot4 { sep2 } else { sep4 }
            }
        }
    )
}

/// Shrinks a rectangle by a factor on all sides.
#[inline(always)]
pub fn margin_rectangle(
    &Rectangle(rect): &Rectangle,
    m: f64
) -> Rectangle {
    let w = rect[2] - 2.0 * m;
    let h = rect[3] - 2.0 * m;
    let (x, w) = if w < 0.0 { (rect[0] + 0.5 * rect[2], 0.0) } else { (rect[0] + m, w) };
    let (y, h) = if h < 0.0 { (rect[1] + 0.5 * rect[3], 0.0) } else { (rect[1] + m, h) };
    Rectangle([x, y, w, h])
}

/// Computes a relative rectangle using the rectangle as a tile.
#[inline(always)]
pub fn relative_rectangle(
    &Rectangle(rect): &Rectangle,
    x: f64,
    y: f64
) -> Rectangle {
    Rectangle([rect[0] + x * rect[2], rect[1] + y * rect[3], rect[2], rect[3]])
}

/// Computes modular offset safely for numbers.
#[inline(always)]
pub fn modular_offset<T: Add<T, T> + Rem<T, T>>(n: &T, i: &T, off: &T) -> T {
    (*i + (*off % *n + *n)) % *n
}

#[test]
fn test_modular_offset() {
    assert_eq!(modular_offset(&3.0_f64, &0.0_f64, &-1.0_f64), 2.0_f64);
    assert_eq!(modular_offset(&3.0_f64, &1.0_f64, &-1.0_f64), 0.0_f64);
    assert_eq!(modular_offset(&3.0_f64, &2.0_f64, &-1.0_f64), 1.0_f64);
    assert_eq!(modular_offset(&3.0_f64, &3.0_f64, &-1.0_f64), 2.0_f64);

    assert_eq!(modular_offset(&3.0_f64, &0.0_f64, &1.0_f64), 1.0_f64);
    assert_eq!(modular_offset(&3.0_f64, &1.0_f64, &1.0_f64), 2.0_f64);
    assert_eq!(modular_offset(&3.0_f64, &2.0_f64, &1.0_f64), 0.0_f64);
    assert_eq!(modular_offset(&3.0_f64, &3.0_f64, &1.0_f64), 1.0_f64);
}

/// Computes the area and centroid of a simple polygon.
///
/// A simple polygon is one that does not intersect itself.
/// Source: http://en.wikipedia.org/wiki/Polygon_area#Simple_polygons
pub fn area_centroid(polygon: &[f64]) -> (f64, Vec2d) {
    let n = polygon.len() / 2;
    let mut sum = 0.0_f64;
    let (mut cx, mut cy) = (0.0_f64, 0.0_f64);
    for i in range(0, n) {
        let (qx, qy) = (polygon[i * 2], polygon[i * 2 + 1]);
        let p_i = previous(n, i);
        let (px, py) = (polygon[p_i * 2], polygon[p_i * 2 + 1]);
        let cross = px * qy - qx * py;
        cx += (px + qx) * cross;
        cy += (py + qy) * cross;
        sum += cross;
    }

    let area = 0.5 * sum;
    // 'cx / (6.0 * area)' = 'cx / (3.0 * sum)'
    let centroid = Vec2d([cx / (3.0 * sum), cy / (3.0 * sum)]);
    (area, centroid)
}

/// Computes area of a simple polygon.
///
/// A simple polygon is one that does not intersect itself.
#[inline(always)]
pub fn area(polygon: &[f64]) -> f64 {
    let (res, _) = area_centroid(polygon);
    res
}

/// Computes centroid of a simple polygon.
///
/// A simple polygon is one that does not intersect itself.
#[inline(always)]
pub fn centroid(polygon: &[f64]) -> Vec2d {
    let (_, res) = area_centroid(polygon);
    res
}

/// Returns a number that tells which side it is relative to a line.
///
/// Computes the cross product of the vector that gives the line
/// with the vector between point and starting point of line.
/// One side of the line has opposite sign of the other.
#[inline(always)]
pub fn line_side(
    &Line(line): &Line,
    x: f64,
    y: f64
) -> f64 {
    let (ax, ay) = (line[0], line[1]);
    let (bx, by) = (line[2], line[3]);
    (bx - ax) * (y - ay) - (by - ay) * (x - ax)
}

/// Returns true if point is inside triangle.
///
/// This is done by computing a `side` number for each edge.
/// If the number is inside if it is on the same side for all edges.
/// Might break for very small triangles.
pub fn inside_triangle(
    &Triangle(triangle): &Triangle,
    x: f64,
    y: f64
) -> bool {
    let (ax, ay) = (triangle[0], triangle[1]);
    let (bx, by) = (triangle[2], triangle[3]);
    let (cx, cy) = (triangle[4], triangle[5]);

    let ab_side = line_side(&Line([ax, ay, bx, by]), x, y);
    let bc_side = line_side(&Line([bx, by, cx, cy]), x, y);
    let ca_side = line_side(&Line([cx, cy, ax, ay]), x, y);

    let ab_positive = ab_side.is_positive();
    let bc_positive = bc_side.is_positive();
    let ca_positive = ca_side.is_positive();

    ab_positive == bc_positive
    && bc_positive == ca_positive
}

/// Returns true if triangle is clockwise.
///
/// This is done by computing which side the third vertex is relative to
/// the line starting from the first vertex to second vertex.
pub fn triangle_face(
    &Triangle(triangle): &Triangle
) -> bool {
    let (ax, ay) = (triangle[0], triangle[1]);
    let (bx, by) = (triangle[2], triangle[3]);
    let (cx, cy) = (triangle[4], triangle[5]);

    let ab_side = line_side(&Line([ax, ay, bx, by]), cx, cy);

    ab_side.is_negative()
}

#[test]
fn test_triangle() {
    // Triangle counter clock-wise.
    let tri_1 = Triangle([0.0, 0.0, 1.0, 0.0, 1.0, 1.0]);
    // Triangle clock-wise.
    let tri_2 = Triangle([0.0, 0.0, 1.0, 1.0, 1.0, 0.0]);
    let (x, y) = (0.5, 0.25);
    assert_eq!(inside_triangle(&tri_1, x, y), true);
    assert_eq!(inside_triangle(&tri_2, x, y), true);
    assert_eq!(triangle_face(&tri_1), false);
    assert_eq!(triangle_face(&tri_2), true);
}
<commit_msg>Changed from `Ray` to `&Ray` for consistency<commit_after>
//! Various methods for computing with vectors.

use {
    Line,
    Matrix2d,
    Ray,
    Rectangle,
    Vec2d,
    Triangle
};
use modular_index::{previous};

/// Multiplies two matrices.
#[inline(always)]
pub fn multiply(
    &Matrix2d(m): &Matrix2d,
    &Matrix2d(b): &Matrix2d
) -> Matrix2d {
    Matrix2d(
        [m[0]*b[0]+m[1]*b[3]+m[2]*0.0,  m[0]*b[1]+m[1]*b[4]+m[2]*0.0,  m[0]*b[2]+m[1]*b[5]+m[2]*1.0,
         m[3]*b[0]+m[4]*b[3]+m[5]*0.0,  m[3]*b[1]+m[4]*b[4]+m[5]*0.0,  m[3]*b[2]+m[4]*b[5]+m[5]*1.0]
    )
}

/// Creates a translation matrix.
#[inline(always)]
pub fn translate(x: f64, y: f64) -> Matrix2d {
    Matrix2d(
        [1.0, 0.0, x,
         0.0, 1.0, y]
    )
}

/// Creates a rotation matrix.
#[inline(always)]
pub fn rotate_radians(angle: f64) -> Matrix2d {
    let c = angle.cos();
    let s = angle.sin();
    Matrix2d(
        [c, -s, 0.0,
         s,  c, 0.0]
    )
}

/// Orients x axis to look at point.
///
/// Leaves x axis unchanged if the point to look at is the origin.
#[inline(always)]
pub fn orient(x: f64, y: f64) -> Matrix2d {
    let len = x * x + y * y;
    if len == 0.0 {
         return Matrix2d(
            [1.0, 0.0, 0.0,
             0.0, 1.0, 0.0]
         );
    }

    let len = len.sqrt();
    let c = x / len;
    let s = y / len;
    Matrix2d(
        [c, -s, 0.0,
         s,  c, 0.0]
    )
}

/// Create a scale matrix.
#[inline(always)]
pub fn scale(sx: f64, sy: f64) -> Matrix2d {
    Matrix2d(
        [sx, 0.0, 0.0,
         0.0, sy, 0.0]
    )
}

/// Create a shear matrix.
#[inline(always)]
pub fn shear(sx: f64, sy: f64) -> Matrix2d {
    Matrix2d(
        [1.0, sx, 0.0,
         sy, 1.0, 0.0]
    )
}

/// Create an identity matrix.
#[inline(always)]
pub fn identity() -> Matrix2d {
    Matrix2d(
        [1.0, 0.0, 0.0,
         0.0, 1.0, 0.0]
    )
}

/// Compute the shortest vector from point to ray.
/// A ray stores starting point and directional vector.
#[inline(always)]
pub fn separation(
    &Ray(ray): &Ray,
    x: f64,
    y: f64) -> Vec2d {
    // Get the directional vector.
    let (dir_x, dir_y) = (ray[2], ray[3]);
    // Get displacement vector from point.
    let (dx, dy) = (ray[0] - x, ray[1] - y);
    // Compute the component of position in ray direction.
    let dot = dir_x * x + dir_y * y;
    // The directional vector multiplied with the dot gives us a parallel vector.
    // When we subtract this from the displacement we get a vector normal to the ray.
    // This is the shortest vector from the point to the ray.
    Vec2d([dx - dot * dir_x, dy - dot * dir_y])
}

/// Returns the least separation out of four.
/// Each seperation can be computed using `separation` function.
/// The separation returned can be used to solve collision of rectangles.
#[inline(always)]
pub fn least_separation_4(
    &Vec2d(sep1): &Vec2d,
    &Vec2d(sep2): &Vec2d,
    &Vec2d(sep3): &Vec2d,
    &Vec2d(sep4): &Vec2d
) -> Vec2d {
    let dot1 = sep1[0] * sep1[0] + sep1[1] * sep1[1];
    let dot2 = sep2[0] * sep2[0] + sep2[1] * sep2[1];
    let dot3 = sep3[0] * sep3[0] + sep3[1] * sep3[1];
    let dot4 = sep4[0] * sep4[0] + sep4[1] * sep4[1];
    // Search for the smallest dot product.
    Vec2d(
        if dot1 < dot2 {
            if dot3 < dot4 {
                if dot1 < dot3 { sep1 } else { sep3 }
            } else {
                if dot1 < dot4 { sep1 } else { sep4 }
            }
        } else {
            if dot3 < dot4 {
                if dot2 < dot3 { sep2 } else { sep3 }
            } else {
                if dot2 < dot4 { sep2 } else { sep4 }
            }
        }
    )
}

/// Shrinks a rectangle by a factor on all sides.
#[inline(always)]
pub fn margin_rectangle(
    &Rectangle(rect): &Rectangle,
    m: f64
) -> Rectangle {
    let w = rect[2] - 2.0 * m;
    let h = rect[3] - 2.0 * m;
    let (x, w) = if w < 0.0 { (rect[0] + 0.5 * rect[2], 0.0) } else { (rect[0] + m, w) };
    let (y, h) = if h < 0.0 { (rect[1] + 0.5 * rect[3], 0.0) } else { (rect[1] + m, h) };
    Rectangle([x, y, w, h])
}

/// Computes a relative rectangle using the rectangle as a tile.
#[inline(always)]
pub fn relative_rectangle(
    &Rectangle(rect): &Rectangle,
    x: f64,
    y: f64
) -> Rectangle {
    Rectangle([rect[0] + x * rect[2], rect[1] + y * rect[3], rect[2], rect[3]])
}

/// Computes modular offset safely for numbers.
#[inline(always)]
pub fn modular_offset<T: Add<T, T> + Rem<T, T>>(n: &T, i: &T, off: &T) -> T {
    (*i + (*off % *n + *n)) % *n
}

#[test]
fn test_modular_offset() {
    assert_eq!(modular_offset(&3.0_f64, &0.0_f64, &-1.0_f64), 2.0_f64);
    assert_eq!(modular_offset(&3.0_f64, &1.0_f64, &-1.0_f64), 0.0_f64);
    assert_eq!(modular_offset(&3.0_f64, &2.0_f64, &-1.0_f64), 1.0_f64);
    assert_eq!(modular_offset(&3.0_f64, &3.0_f64, &-1.0_f64), 2.0_f64);

    assert_eq!(modular_offset(&3.0_f64, &0.0_f64, &1.0_f64), 1.0_f64);
    assert_eq!(modular_offset(&3.0_f64, &1.0_f64, &1.0_f64), 2.0_f64);
    assert_eq!(modular_offset(&3.0_f64, &2.0_f64, &1.0_f64), 0.0_f64);
    assert_eq!(modular_offset(&3.0_f64, &3.0_f64, &1.0_f64), 1.0_f64);
}

/// Computes the area and centroid of a simple polygon.
///
/// A simple polygon is one that does not intersect itself.
/// Source: http://en.wikipedia.org/wiki/Polygon_area#Simple_polygons
pub fn area_centroid(polygon: &[f64]) -> (f64, Vec2d) {
    let n = polygon.len() / 2;
    let mut sum = 0.0_f64;
    let (mut cx, mut cy) = (0.0_f64, 0.0_f64);
    for i in range(0, n) {
        let (qx, qy) = (polygon[i * 2], polygon[i * 2 + 1]);
        let p_i = previous(n, i);
        let (px, py) = (polygon[p_i * 2], polygon[p_i * 2 + 1]);
        let cross = px * qy - qx * py;
        cx += (px + qx) * cross;
        cy += (py + qy) * cross;
        sum += cross;
    }

    let area = 0.5 * sum;
    // 'cx / (6.0 * area)' = 'cx / (3.0 * sum)'
    let centroid = Vec2d([cx / (3.0 * sum), cy / (3.0 * sum)]);
    (area, centroid)
}

/// Computes area of a simple polygon.
///
/// A simple polygon is one that does not intersect itself.
#[inline(always)]
pub fn area(polygon: &[f64]) -> f64 {
    let (res, _) = area_centroid(polygon);
    res
}

/// Computes centroid of a simple polygon.
///
/// A simple polygon is one that does not intersect itself.
#[inline(always)]
pub fn centroid(polygon: &[f64]) -> Vec2d {
    let (_, res) = area_centroid(polygon);
    res
}

/// Returns a number that tells which side it is relative to a line.
///
/// Computes the cross product of the vector that gives the line
/// with the vector between point and starting point of line.
/// One side of the line has opposite sign of the other.
#[inline(always)]
pub fn line_side(
    &Line(line): &Line,
    x: f64,
    y: f64
) -> f64 {
    let (ax, ay) = (line[0], line[1]);
    let (bx, by) = (line[2], line[3]);
    (bx - ax) * (y - ay) - (by - ay) * (x - ax)
}

/// Returns true if point is inside triangle.
///
/// This is done by computing a `side` number for each edge.
/// If the number is inside if it is on the same side for all edges.
/// Might break for very small triangles.
pub fn inside_triangle(
    &Triangle(triangle): &Triangle,
    x: f64,
    y: f64
) -> bool {
    let (ax, ay) = (triangle[0], triangle[1]);
    let (bx, by) = (triangle[2], triangle[3]);
    let (cx, cy) = (triangle[4], triangle[5]);

    let ab_side = line_side(&Line([ax, ay, bx, by]), x, y);
    let bc_side = line_side(&Line([bx, by, cx, cy]), x, y);
    let ca_side = line_side(&Line([cx, cy, ax, ay]), x, y);

    let ab_positive = ab_side.is_positive();
    let bc_positive = bc_side.is_positive();
    let ca_positive = ca_side.is_positive();

    ab_positive == bc_positive
    && bc_positive == ca_positive
}

/// Returns true if triangle is clockwise.
///
/// This is done by computing which side the third vertex is relative to
/// the line starting from the first vertex to second vertex.
pub fn triangle_face(
    &Triangle(triangle): &Triangle
) -> bool {
    let (ax, ay) = (triangle[0], triangle[1]);
    let (bx, by) = (triangle[2], triangle[3]);
    let (cx, cy) = (triangle[4], triangle[5]);

    let ab_side = line_side(&Line([ax, ay, bx, by]), cx, cy);

    ab_side.is_negative()
}

#[test]
fn test_triangle() {
    // Triangle counter clock-wise.
    let tri_1 = Triangle([0.0, 0.0, 1.0, 0.0, 1.0, 1.0]);
    // Triangle clock-wise.
    let tri_2 = Triangle([0.0, 0.0, 1.0, 1.0, 1.0, 0.0]);
    let (x, y) = (0.5, 0.25);
    assert_eq!(inside_triangle(&tri_1, x, y), true);
    assert_eq!(inside_triangle(&tri_2, x, y), true);
    assert_eq!(triangle_face(&tri_1), false);
    assert_eq!(triangle_face(&tri_2), true);
}
<|endoftext|>


<commit_before>// Filebuffer -- Fast and simple file reading
// Copyright 2016 Ruud van Asseldonk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// A copy of the License has been included in the root of the repository.

//! This mod contains the platform-specific implementations for Windows based on the winapi crate.

use std::fs;
use std::io;
use std::os;
use std::os::windows::io::AsRawHandle;
use std::ptr;

extern crate kernel32;
extern crate winapi;

pub struct PlatformData {
    // On Windows, the file must be kept open for the lifetime of the mapping.
    #[allow(dead_code)] // The field is not dead, the destructor is effectful.
    file: fs::File,
    mapping_handle: winapi::winnt::HANDLE,
}

impl Drop for PlatformData {
    fn drop (&mut self) {
        if self.mapping_handle != ptr::null_mut() {
            let success = unsafe { kernel32::CloseHandle(self.mapping_handle) };
            assert!(success != 0);
        }
    }
}

pub fn map_file(file: fs::File) -> io::Result<(*const u8, usize, PlatformData)> {
    let file_handle = file.as_raw_handle();
    let length = try!(file.metadata()).len();

    if length > usize::max_value() as u64 {
        return Err(io::Error::new(io::ErrorKind::Other, "file is larger than address space"));
    }

    let mut platform_data = PlatformData {
        file: file,
        mapping_handle: ptr::null_mut(),
    };

    // Don't try to map anything if the file is empty.
    if length == 0 {
        return Ok((ptr::null(), 0, platform_data));
    }

    // Memory-mapping a file on Windows is a two-step process: first we create a file mapping
    // object, and then we create a view of that mapping in the virtual address space.
    platform_data.mapping_handle = unsafe {
        kernel32::CreateFileMappingW(
            file_handle,
            ptr::null_mut(),              // Use default security policy.
            winapi::winnt::PAGE_READONLY, // The memory will be read-only.
            0, 0,                         // The mapping size is the size of the file.
            ptr::null_mut()               // The mapping does not have a name.
        )
    };

    if platform_data.mapping_handle == ptr::null_mut() {
        return Err(io::Error::last_os_error());
    }

    let result = unsafe {
        kernel32::MapViewOfFile(
            platform_data.mapping_handle,
            winapi::memoryapi::FILE_MAP_READ, // The memory mapping will be read-only.
            0, 0,                             // Start offset of the mapping is 0.
            length                            // Map the entire file.
        )
    };

    if result == ptr::null_mut() {
        Err(io::Error::last_os_error())
    } else {
        Ok((result as *const u8, length as usize, platform_data))
    }
}

pub fn unmap_file(buffer: *const u8, _length: usize) {
    let success = unsafe { kernel32::UnmapViewOfFile(buffer as *mut os::raw::c_void) };
    assert!(success != 0);
}

/// See also `unix::get_resident`.
pub fn get_resident(_buffer: *const u8, _length: usize, residency: &mut [bool]) {
    // As far as I am aware, Windows does not expose a way to query whether pages are resident.
    // There is no equivalent of `mincore()`. The closest thing is `VirtualQuery()`, but the
    // `state` value in the `MEMORY_BASIC_INFORMATION` struct that it fills does not indicate
    // whether the page is resident.

    // Lie and pretend everything is resident.
    for x in residency {
        *x = true;
    }
}

/// See also `unix::prefetch`.
pub fn prefetch(buffer: *const u8, length: usize) {
    let mut entry = winapi::memoryapi::WIN32_MEMORY_RANGE_ENTRY {
        VirtualAddress: buffer as *mut os::raw::c_void,
        NumberOfBytes: length as winapi::basetsd::SIZE_T,
    };

    unsafe {
        let current_process_handle = kernel32::GetCurrentProcess();
        kernel32::PrefetchVirtualMemory(
            current_process_handle, // Prefetch for the current process.
            1, &mut entry,          // An array of length 1 that contains `entry`.
            0                       // Reserved flag that must be 0.
        );
    }

    // The return value of `PrefetchVirtualMemory` is ignored. MSDN says the function may fail if
    // the system is under memory pressure. (It is not entirely clear whether "fail" means
    // "returns a nonzero value", but I assume it does.)
}

pub fn get_page_size() -> usize {
    // Fill the `SYSTEM_INFO` struct with zeroes. It will be filled by
    // `GetSystemInfo` later but Rust requires it to be initialized.
    let mut sysinfo = winapi::sysinfoapi::SYSTEM_INFO {
        wProcessorArchitecture: 0,
        wReserved: 0,
        dwPageSize: 0,
        lpMinimumApplicationAddress: ptr::null_mut(),
        lpMaximumApplicationAddress: ptr::null_mut(),
        dwActiveProcessorMask: 0,
        dwNumberOfProcessors: 0,
        dwProcessorType: 0,
        dwAllocationGranularity: 0,
        wProcessorLevel: 0,
        wProcessorRevision: 0
    };
    unsafe { kernel32::GetSystemInfo(&mut sysinfo); }
    sysinfo.dwPageSize as usize
}
<commit_msg>Use correct size type on 32-bit Windows<commit_after>// Filebuffer -- Fast and simple file reading
// Copyright 2016 Ruud van Asseldonk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// A copy of the License has been included in the root of the repository.

//! This mod contains the platform-specific implementations for Windows based on the winapi crate.

use std::fs;
use std::io;
use std::os;
use std::os::windows::io::AsRawHandle;
use std::ptr;

extern crate kernel32;
extern crate winapi;

pub struct PlatformData {
    // On Windows, the file must be kept open for the lifetime of the mapping.
    #[allow(dead_code)] // The field is not dead, the destructor is effectful.
    file: fs::File,
    mapping_handle: winapi::winnt::HANDLE,
}

impl Drop for PlatformData {
    fn drop (&mut self) {
        if self.mapping_handle != ptr::null_mut() {
            let success = unsafe { kernel32::CloseHandle(self.mapping_handle) };
            assert!(success != 0);
        }
    }
}

pub fn map_file(file: fs::File) -> io::Result<(*const u8, usize, PlatformData)> {
    let file_handle = file.as_raw_handle();
    let length = try!(file.metadata()).len();

    if length > usize::max_value() as u64 {
        return Err(io::Error::new(io::ErrorKind::Other, "file is larger than address space"));
    }

    let mut platform_data = PlatformData {
        file: file,
        mapping_handle: ptr::null_mut(),
    };

    // Don't try to map anything if the file is empty.
    if length == 0 {
        return Ok((ptr::null(), 0, platform_data));
    }

    // Memory-mapping a file on Windows is a two-step process: first we create a file mapping
    // object, and then we create a view of that mapping in the virtual address space.
    platform_data.mapping_handle = unsafe {
        kernel32::CreateFileMappingW(
            file_handle,
            ptr::null_mut(),              // Use default security policy.
            winapi::winnt::PAGE_READONLY, // The memory will be read-only.
            0, 0,                         // The mapping size is the size of the file.
            ptr::null_mut()               // The mapping does not have a name.
        )
    };

    if platform_data.mapping_handle == ptr::null_mut() {
        return Err(io::Error::last_os_error());
    }

    let result = unsafe {
        kernel32::MapViewOfFile(
            platform_data.mapping_handle,
            winapi::memoryapi::FILE_MAP_READ, // The memory mapping will be read-only.
            0, 0,                             // Start offset of the mapping is 0.
            length as winapi::basetsd::SIZE_T // Map the entire file.
        )
    };

    if result == ptr::null_mut() {
        Err(io::Error::last_os_error())
    } else {
        Ok((result as *const u8, length as usize, platform_data))
    }
}

pub fn unmap_file(buffer: *const u8, _length: usize) {
    let success = unsafe { kernel32::UnmapViewOfFile(buffer as *mut os::raw::c_void) };
    assert!(success != 0);
}

/// See also `unix::get_resident`.
pub fn get_resident(_buffer: *const u8, _length: usize, residency: &mut [bool]) {
    // As far as I am aware, Windows does not expose a way to query whether pages are resident.
    // There is no equivalent of `mincore()`. The closest thing is `VirtualQuery()`, but the
    // `state` value in the `MEMORY_BASIC_INFORMATION` struct that it fills does not indicate
    // whether the page is resident.

    // Lie and pretend everything is resident.
    for x in residency {
        *x = true;
    }
}

/// See also `unix::prefetch`.
pub fn prefetch(buffer: *const u8, length: usize) {
    let mut entry = winapi::memoryapi::WIN32_MEMORY_RANGE_ENTRY {
        VirtualAddress: buffer as *mut os::raw::c_void,
        NumberOfBytes: length as winapi::basetsd::SIZE_T,
    };

    unsafe {
        let current_process_handle = kernel32::GetCurrentProcess();
        kernel32::PrefetchVirtualMemory(
            current_process_handle, // Prefetch for the current process.
            1, &mut entry,          // An array of length 1 that contains `entry`.
            0                       // Reserved flag that must be 0.
        );
    }

    // The return value of `PrefetchVirtualMemory` is ignored. MSDN says the function may fail if
    // the system is under memory pressure. (It is not entirely clear whether "fail" means
    // "returns a nonzero value", but I assume it does.)
}

pub fn get_page_size() -> usize {
    // Fill the `SYSTEM_INFO` struct with zeroes. It will be filled by
    // `GetSystemInfo` later but Rust requires it to be initialized.
    let mut sysinfo = winapi::sysinfoapi::SYSTEM_INFO {
        wProcessorArchitecture: 0,
        wReserved: 0,
        dwPageSize: 0,
        lpMinimumApplicationAddress: ptr::null_mut(),
        lpMaximumApplicationAddress: ptr::null_mut(),
        dwActiveProcessorMask: 0,
        dwNumberOfProcessors: 0,
        dwProcessorType: 0,
        dwAllocationGranularity: 0,
        wProcessorLevel: 0,
        wProcessorRevision: 0
    };
    unsafe { kernel32::GetSystemInfo(&mut sysinfo); }
    sysinfo.dwPageSize as usize
}
<|endoftext|>


<commit_before>use dict::Dict;
use graph::{Graph, TextRange};

#[derive(Clone)]
pub struct Wordcut {
    dict: Dict
}

impl Wordcut {
    pub fn new(dict: Dict) -> Wordcut {
        Wordcut{dict: dict}
    }

    pub fn segment(&self, txt: &String) -> Vec<TextRange> {
        let g = Graph::build(&txt[..], &self.dict);
        g.to_ranges()
    }

    pub fn segment_into_strings(&self, txt: &String) -> Vec<String> {
        let g = Graph::build(&txt[..], &self.dict);
        g.to_str_vec()
    }

    pub fn put_delimiters(&self, txt: &String, delim: &str) -> String {
        self.segment_into_strings(txt).connect(delim)
    }
}<commit_msg>change connect to join<commit_after>use dict::Dict;
use graph::{Graph, TextRange};

#[derive(Clone)]
pub struct Wordcut {
    dict: Dict
}

impl Wordcut {
    pub fn new(dict: Dict) -> Wordcut {
        Wordcut{dict: dict}
    }

    pub fn segment(&self, txt: &String) -> Vec<TextRange> {
        let g = Graph::build(&txt[..], &self.dict);
        g.to_ranges()
    }

    pub fn segment_into_strings(&self, txt: &String) -> Vec<String> {
        let g = Graph::build(&txt[..], &self.dict);
        g.to_str_vec()
    }

    pub fn put_delimiters(&self, txt: &String, delim: &str) -> String {
        self.segment_into_strings(txt).join(delim)
    }
}
<|endoftext|>


<commit_before>#![cfg(test)]

// These tests are primarily targeting "abusive" producers that will
// try to drive the "collect consumer" incorrectly. These should
// result in panics.

use iter::internal::*;
use super::Collect;

/// Promises to produce 2 items, but then produces 3.  Does not do any
/// splits at all.
#[test]
#[should_panic(expected = "too many values")]
fn produce_too_many_items() {
    let mut v = vec![];
    let mut collect = Collect::new(&mut v, 2);
    let consumer = collect.as_consumer();
    let mut folder = consumer.into_folder();
    folder = folder.consume(22);
    folder = folder.consume(23);
    folder.consume(24);
}

/// Produces less items than promised. Does not do any
/// splits at all.
#[test]
#[should_panic(expected = "too few values")]
fn produce_too_few_items() {
    let mut vec = vec![];
    let mut collect = Collect::new(&mut vec, 5);
    let consumer =  collect.as_consumer();
    let mut folder = consumer.into_folder();
    folder = folder.consume(22);
    folder = folder.consume(23);
    folder.complete();
}
<commit_msg>add test for collect-consumer collection vector on failing to call complete function<commit_after>#![cfg(test)]

// These tests are primarily targeting "abusive" producers that will
// try to drive the "collect consumer" incorrectly. These should
// result in panics.

use iter::internal::*;
use super::Collect;

/// Promises to produce 2 items, but then produces 3.  Does not do any
/// splits at all.
#[test]
#[should_panic(expected = "too many values")]
fn produce_too_many_items() {
    let mut v = vec![];
    let mut collect = Collect::new(&mut v, 2);
    let consumer = collect.as_consumer();
    let mut folder = consumer.into_folder();
    folder = folder.consume(22);
    folder = folder.consume(23);
    folder.consume(24);
}

/// Produces less items than promised. Does not do any
/// splits at all.
#[test]
#[should_panic(expected = "too few values")]
fn produce_too_few_items() {
    let mut v = vec![];
    let mut collect = Collect::new(&mut v, 5);
    let consumer =  collect.as_consumer();
    let mut folder = consumer.into_folder();
    folder = folder.consume(22);
    folder = folder.consume(23);
    folder.complete();
}

// Complete is not called by the consumer.Hence,the collection vector is not fully initialized.
#[test]
#[should_panic(expected = "expected 4 total writes, but got 2")]
fn produce_items_with_split_no_complete() {
    let mut v = vec![];
    let mut collect = Collect::new(&mut v, 4);
	{
	    	let consumer =  collect.as_consumer();
	    	let (left_consumer,right_consumer,reducer) = consumer.split_at(2);
	    	let mut left_folder = left_consumer.into_folder();
	    	let mut right_folder = right_consumer.into_folder();
	    	left_folder = left_folder.consume(0).consume(1);
	    	right_folder = right_folder.consume(2).consume(3);
	    	right_folder.complete();
	}
    collect.complete();
}
<|endoftext|>


<commit_before>/// There are utilities that can be used to do an inner join between
/// ordered iterators. This can be useful to do selects between multiple
/// tables of items

use std::cmp::Ordering::{Less, Equal, Greater};
use std::iter::Peekable;
use std::collections::{
    btree_map, btree_set,
    vec_map,
    bit_set
};

#[cfg(feature="tree_map")]
use super::super::{tree_set, tree_map};
#[cfg(feature="trie_map")]
use super::super::{trie_set, trie_map};

/// Allows an iterator to be do an inner join with another
/// iterator to combine their values or filter based on their keys.
/// this trait is applied to an iterator over a map like structure
pub trait OrderedMapIterator<K, A>: Iterator<Item=(K, A)> + Sized {
    /// join two ordered maps together
    fn inner_join_map<B, T: OrderedMapIterator<K, B>>(self, map: T)
        -> InnerJoinMapIterator<Self, T> {
        InnerJoinMapIterator {
            a: self,
            b: map
        }
    }

    /// filter an ordered map with an ordered set
    fn inner_join_set<B, T: OrderedSetIterator<K>>(self, set: T)
        -> InnerJoinMapSetIterator<Self, T> {
        InnerJoinMapSetIterator {
            map: self,
            set: set
        }
    }

    /// Join an ordered iterator with the right ordered iterator. The
    /// new iterator will return a key value pair for every key in
    /// either iterator. If a key is present in both iterators they
    /// will be returned together (two values). If a value is in the Right,
    /// but not the left iterator it will be return without the value in the
    /// left iterator. If the value is in the left iterator by not the right
    /// that will be return without the value from the left iterator.
    fn outer_join<B, T: OrderedMapIterator<K, B>>(self, right: T)
        -> OuterJoinIterator<Self, T, (K, A), (K, B)> {
        OuterJoinIterator {
            left: self.peekable(),
            right: right.peekable()
        }
    }
}

/// Allows an iterator to be do an inner join with another
/// iterator to combine their values or filter based on their keys.
/// this trait is applied to an iterator over a set like structure
pub trait OrderedSetIterator<K>: Iterator<Item=K> + Sized {
    /// join two ordered maps together
    fn inner_join_map<B, T: OrderedMapIterator<K, B>>(self, map: T)
        -> InnerJoinMapSetIterator<T, Self> {
        InnerJoinMapSetIterator {
            map: map,
            set: self
        }
    }

    /// filter an ordered map with an ordered set
    fn inner_join_set<T: OrderedSetIterator<K>>(self, map: T)
        -> InnerJoinSetIterator<Self, T> {
        InnerJoinSetIterator {
            a: self,
            b: map
        }
    }
}

pub struct InnerJoinMapIterator<A, B> {a: A, b: B}
pub struct InnerJoinMapSetIterator<A, B> {map: A, set: B}
pub struct InnerJoinSetIterator<A, B> {a: A, b: B}
pub struct OuterJoinIterator<A: Iterator<Item=VA>, B: Iterator<Item=VB>, VA, VB> {
    left: Peekable<A>,
    right: Peekable<B>
}

#[old_impl_check]
impl<K: Ord, DataA, DataB,
     A: OrderedMapIterator<K, DataA>,
     B: OrderedMapIterator<K, DataB>>
     Iterator for InnerJoinMapIterator<A, B> {

    type Item = (K, (DataA, DataB));

    fn next(&mut self) -> Option<(K, (DataA, DataB))> {
        let (mut key_a, mut data_a) = match self.a.next() {
            None => return None,
            Some((key, data)) => (key, data)
        };

        let (mut key_b, mut data_b) = match self.b.next() {
            None => return None,
            Some((key, data)) => (key, data)
        };

        loop {
            match key_a.cmp(&key_b) {
                Less => {
                    match self.a.next() {
                        None => return None,
                        Some((key, data)) => {
                            key_a = key;
                            data_a = data;
                        }
                    };
                },
                Equal => return Some((key_a, (data_a, data_b))),
                Greater => {
                    match self.b.next() {
                        None => return None,
                        Some((key, data)) => {
                            key_b = key;
                            data_b = data;
                        }
                    };
                }
            }
        }
    }
}

#[old_impl_check]
impl<K: Ord,
     A: OrderedSetIterator<K>,
     B: OrderedSetIterator<K>>
     Iterator for InnerJoinSetIterator<A, B> {
    type Item = K;
    fn next(&mut self) -> Option<K> {
        let mut key_a = match self.a.next() {
            None => return None,
            Some(key) => key
        };

        let mut key_b = match self.b.next() {
            None => return None,
            Some(key) => key
        };

        loop {
            match key_a.cmp(&key_b) {
                Less => {
                    match self.a.next() {
                        None => return None,
                        Some(key) => { key_a = key; }
                    };
                },
                Equal => return Some(key_a),
                Greater => {
                    match self.b.next() {
                        None => return None,
                        Some(key) => { key_b = key; }
                    };
                }
            }
        }
    }
}

#[old_impl_check]
impl<K: Ord,
     V,
     SetIter: OrderedSetIterator<K>,
     MapIter: OrderedMapIterator<K, V>>
     Iterator for InnerJoinMapSetIterator<MapIter, SetIter> {
    type Item = (K, V);
    fn next(&mut self) -> Option<(K, V)> {
        let mut key_set = match self.set.next() {
            None => return None,
            Some(key) => key
        };

        let (mut key_map, mut data) = match self.map.next() {
            None => return None,
            Some((key, data)) => (key, data)
        };

        loop {
            match key_set.cmp(&key_map) {
                Less => {
                    match self.set.next() {
                        None => return None,
                        Some(key) => { key_set = key; }
                    };
                },
                Equal => return Some((key_set, data)),
                Greater => {
                    match self.map.next() {
                        None => return None,
                        Some((key, d)) => {
                            key_map = key;
                            data = d;
                        }
                    };
                }
            }
        }
    }
}

impl<K: Ord+Eq,
     VA, VB,
     A: OrderedMapIterator<K, VA>,
     B: OrderedMapIterator<K, VB>>
     Iterator for OuterJoinIterator<A, B, (K, VA), (K, VB)> {

    type Item = (K, (Option<VA>, Option<VB>));
    fn next(&mut self) -> Option<(K, (Option<VA>, Option<VB>))> {
        let which = match (self.left.peek(), self.right.peek()) {
            (Some(&(ref ka, _)), Some(&(ref kb, _))) => kb.cmp(ka),
            (None, Some(_)) => Less,
            (Some(_), None) => Greater,
            (None, None) => return None
        };

        match which {
            Equal => {
                let ((k, a), (_, b)) =
                    (self.left.next().expect("no value found"),
                     self.right.next().expect("no value found"));

                Some((k, (Some(a), Some(b))))
            }
            Less => {
                let (k, v) = self.right.next().expect("no value found");
                Some((k, (None, Some(v))))
            }
            Greater => {
                let (k, v) = self.left.next().expect("no value found");
                Some((k, (Some(v), None)))
            }
        }
    }
}

impl<'a, K: Ord> OrderedSetIterator<&'a K> for btree_set::Iter<'a, K> {}
impl<'a, K: Ord, V> OrderedMapIterator<&'a K, &'a V> for btree_map::Iter<'a, K, V> {}
#[cfg(feature="tree_map")]
impl<'a, K> OrderedSetIterator<&'a K> for tree_set::Iter<'a, K> {}
#[cfg(feature="tree_map")]
impl<'a, K, V> OrderedMapIterator<&'a K, &'a V> for tree_map::Iter<'a, K, V> {}
#[cfg(feature="trie_map")]
impl<'a> OrderedSetIterator<usize> for trie_set::Iter<'a> {}
#[cfg(feature="trie_map")]
impl<'a, V> OrderedMapIterator<usize, &'a V> for trie_map::Iter<'a, V> {}
impl<'a, V> OrderedMapIterator<usize, &'a V> for vec_map::Iter<'a, V> {}
impl<'a> OrderedSetIterator<usize> for bit_set::Iter<'a> {}

impl<K: Ord, VA, VB,
     A: OrderedMapIterator<K, VA>,
     B: OrderedMapIterator<K, VB>> OrderedMapIterator<K, (VA, VB)> for InnerJoinMapIterator<A, B> {}
impl<K: Ord, V,
     A: OrderedSetIterator<K>,
     B: OrderedMapIterator<K, V>> OrderedMapIterator<K, V> for InnerJoinMapSetIterator<B, A> {}
impl<K: Ord,
     A: OrderedSetIterator<K>,
     B: OrderedSetIterator<K>> OrderedSetIterator<K> for InnerJoinSetIterator<A, B> {}

#[cfg(test)]
mod tests {
    use test::Bencher;
    use test;

    use super::{OrderedSetIterator, OrderedMapIterator};

    #[test]
    fn join_two_sets() {
        use std::collections::BTreeSet;

        let powers_of_two: BTreeSet<i32> = range(1, 10).map(|x| x * 2).collect();
        let powers_of_three: BTreeSet<i32> = range(1, 10).map(|x| x * 3).collect();

        let expected = vec![6, 12, 18];

        let powers_of_two_and_three: Vec<i32> =
            powers_of_two.iter()
            .inner_join_set(powers_of_three.iter())
            .map(|&x| x)
            .collect();

        assert_eq!(expected, powers_of_two_and_three);
    }

    #[test]
    fn join_three_sets() {
        use std::collections::BTreeSet;

        let powers_of_two: BTreeSet<i32> = range(1, 100).map(|x| x * 2).collect();
        let powers_of_three: BTreeSet<i32> = range(1, 100).map(|x| x * 3).collect();
        let powers_of_five: BTreeSet<i32> = range(1, 100).map(|x| x * 5).collect();

        let expected = vec![30, 60, 90, 120, 150, 180];

        let powers_of_two_and_three: Vec<i32> =
            powers_of_two.iter()
            .inner_join_set(powers_of_three.iter())
            .inner_join_set(powers_of_five.iter())
            .map(|&x| x)
            .collect();

        assert_eq!(expected, powers_of_two_and_three);
    }

    #[test]
    fn join_two_maps() {
        use std::collections::BTreeMap;

        let powers_of_two: BTreeMap<i32, i32> = range(1, 10).map(|x| (x * 2, x)).collect();
        let powers_of_three: BTreeMap<i32, i32> = range(1, 10).map(|x| (x * 3, x)).collect();

        let mut powers_of_two_and_three =
            powers_of_two.iter().inner_join_map(powers_of_three.iter())
            .map(|(&k, (&a, &b))| (k, a, b));

        assert_eq!(Some((6, 3, 2)), powers_of_two_and_three.next());
        assert_eq!(Some((12, 6, 4)), powers_of_two_and_three.next());
        assert_eq!(Some((18, 9, 6)), powers_of_two_and_three.next());
        assert_eq!(None, powers_of_two_and_three.next());
    }

    #[test]
    fn join_two_maps_to_set() {
        use std::collections::{BTreeMap, BTreeSet};

        let powers_of_two: BTreeSet<i32> = range(1, 10).map(|x| x * 2).collect();
        let powers_of_three: BTreeMap<i32, i32> = range(1, 10).map(|x| (x * 3, x)).collect();

        let mut powers_of_two_and_three =
            powers_of_two.iter().inner_join_map(powers_of_three.iter())
            .map(|(&k, &a)| (k, a));

        assert_eq!(Some((6, 2)), powers_of_two_and_three.next());
        assert_eq!(Some((12, 4)), powers_of_two_and_three.next());
        assert_eq!(Some((18, 6)), powers_of_two_and_three.next());
        assert_eq!(None, powers_of_two_and_three.next());
    }

    #[test]
    fn outer_join_fizz_buzz() {
        use std::collections::BTreeMap;

        let mul_of_three: BTreeMap<i32, i32> = range(0, 100).map(|x| (x*3, x)).collect();
        let mul_of_five: BTreeMap<i32, i32> = range(0, 100).map(|x| (x*5, x)).collect();

        let mut fizz_buzz = BTreeMap::new();

        for (key, (three, five)) in mul_of_three.iter()
                                                .outer_join(mul_of_five.iter()) {
            fizz_buzz.insert(key, (three.is_some(), five.is_some()));
        }

        let res: BTreeMap<i32, String> = range(1, 100).map(|i|
            (i, match fizz_buzz.get(&i) {
                None => format!("{}", i),
                Some(&(true, false)) => format!("Fizz"),
                Some(&(false, true)) => format!("Buzz"),
                Some(&(true, true)) => format!("FizzBuzz"),
                Some(&(false, false)) => panic!("Outer join failed...")
            })).collect();

        for i in range(1, 100) {
            match (i % 3, i % 5) {
                (0, 0) => assert_eq!("FizzBuzz", res[i].as_slice()),
                (0, _) => assert_eq!("Fizz", res[i].as_slice()),
                (_, 0) => assert_eq!("Buzz", res[i].as_slice()),
                _ => assert_eq!(format!("{}", i).as_slice(), res[i].as_slice())
            }
        }
    }

    #[bench]
    pub fn inner_join_map(b: &mut test::Bencher) {
        use std::collections::BTreeSet;

        let powers_of_two: BTreeSet<u32> = range(1, 1000000).map(|x| x * 2).collect();
        let powers_of_three: BTreeSet<u32> = range(1, 1000000).map(|x| x * 3).collect();

        b.iter(||{
            for x in powers_of_two.iter()
                .inner_join_set(powers_of_three.iter()) {

                test::black_box(x);
            }
        })
    }
}
<commit_msg>WIP move ordered iterators to associated items<commit_after>/// There are utilities that can be used to do an inner join between
/// ordered iterators. This can be useful to do selects between multiple
/// tables of items

use std::cmp::Ordering::{Less, Equal, Greater};
use std::iter::Peekable;
use std::collections::{
    btree_map, btree_set,
    vec_map,
    bit_set
};

#[cfg(feature="tree_map")]
use super::super::{tree_set, tree_map};
#[cfg(feature="trie_map")]
use super::super::{trie_set, trie_map};

/// Allows an iterator to be do an inner join with another
/// iterator to combine their values or filter based on their keys.
/// this trait is applied to an iterator over a map like structure
pub trait OrderedMapIterator: Iterator<Item=(Self::Key, Self::Val)> + Sized {
    type Key;
    type Val;
    /// join two ordered maps together
    fn inner_join_map<I>(self, map: I) -> InnerJoinMapIterator<Self, I>
    where I: OrderedMapIterator<Key=Self::Key> {
        InnerJoinMapIterator {
            a: self,
            b: map
        }
    }

    /// filter an ordered map with an ordered set
    fn inner_join_set<I>(self, set: I) -> InnerJoinMapSetIterator<Self, I>
    where I: OrderedSetIterator<Item=Self::Key> {
        InnerJoinMapSetIterator {
            map: self,
            set: set
        }
    }

    /// Join an ordered iterator with the right ordered iterator. The
    /// new iterator will return a key value pair for every key in
    /// either iterator. If a key is present in both iterators they
    /// will be returned together (two values). If a value is in the Right,
    /// but not the left iterator it will be return without the value in the
    /// left iterator. If the value is in the left iterator by not the right
    /// that will be return without the value from the left iterator.
    fn outer_join<I>(self, right: I) -> OuterJoinIterator<Self, I>
    where I: OrderedMapIterator<Key=Self::Key> {
        OuterJoinIterator {
            left: self.peekable(),
            right: right.peekable()
        }
    }
}

/// Allows an iterator to be do an inner join with another
/// iterator to combine their values or filter based on their keys.
/// this trait is applied to an iterator over a set like structure
pub trait OrderedSetIterator: Iterator + Sized {
    /// join two ordered maps together
    fn inner_join_map<I>(self, map: I) -> InnerJoinMapSetIterator<I, Self>
    where I: OrderedMapIterator<Key=Self::Item> {
        InnerJoinMapSetIterator {
            map: map,
            set: self
        }
    }

    /// filter an ordered map with an ordered set
    fn inner_join_set<I>(self, map: I) -> InnerJoinSetIterator<Self, I>
    where I: OrderedSetIterator<Item=Self::Item> {
        InnerJoinSetIterator {
            a: self,
            b: map
        }
    }
}

pub struct InnerJoinMapIterator<A, B> {a: A, b: B}
pub struct InnerJoinMapSetIterator<A, B> {map: A, set: B}
pub struct InnerJoinSetIterator<A, B> {a: A, b: B}
pub struct OuterJoinIterator<A: Iterator, B: Iterator> {
    left: Peekable<A>,
    right: Peekable<B>,
}

#[old_impl_check]
impl<A, B> Iterator for InnerJoinMapIterator<A, B>
where A: OrderedMapIterator,
      B: OrderedMapIterator<Key=A::Key>,
      A::Key: Ord,
{

    type Item = (A::Key, (A::Val, B::Val));

    fn next(&mut self) -> Option<(A::Key, (A::Val, B::Val))> {
        let (mut key_a, mut data_a) = match self.a.next() {
            None => return None,
            Some((key, data)) => (key, data)
        };

        let (mut key_b, mut data_b) = match self.b.next() {
            None => return None,
            Some((key, data)) => (key, data)
        };

        loop {
            match key_a.cmp(&key_b) {
                Less => {
                    match self.a.next() {
                        None => return None,
                        Some((key, data)) => {
                            key_a = key;
                            data_a = data;
                        }
                    };
                },
                Equal => return Some((key_a, (data_a, data_b))),
                Greater => {
                    match self.b.next() {
                        None => return None,
                        Some((key, data)) => {
                            key_b = key;
                            data_b = data;
                        }
                    };
                }
            }
        }
    }
}

#[old_impl_check]
impl<A, B> Iterator for InnerJoinSetIterator<A, B>
where A: OrderedSetIterator,
      B: OrderedSetIterator<Item=A::Item>,
      A::Item: Ord,
{

    type Item = A::Item;

    fn next(&mut self) -> Option<A::Item> {
        let mut key_a = match self.a.next() {
            None => return None,
            Some(key) => key
        };

        let mut key_b = match self.b.next() {
            None => return None,
            Some(key) => key
        };

        loop {
            match key_a.cmp(&key_b) {
                Less => {
                    match self.a.next() {
                        None => return None,
                        Some(key) => { key_a = key; }
                    };
                },
                Equal => return Some(key_a),
                Greater => {
                    match self.b.next() {
                        None => return None,
                        Some(key) => { key_b = key; }
                    };
                }
            }
        }
    }
}

#[old_impl_check]
impl<MapIter, SetIter> Iterator for InnerJoinMapSetIterator<MapIter, SetIter>
where SetIter: OrderedSetIterator,
      MapIter: OrderedMapIterator<Key=SetIter::Item>,
      MapIter::Key: Ord,
{

    type Item = (MapIter::Key, MapIter::Val);

    fn next(&mut self) -> Option<(MapIter::Key, MapIter::Val)> {
        let mut key_set = match self.set.next() {
            None => return None,
            Some(key) => key
        };

        let (mut key_map, mut data) = match self.map.next() {
            None => return None,
            Some((key, data)) => (key, data)
        };

        loop {
            match key_set.cmp(&key_map) {
                Less => {
                    match self.set.next() {
                        None => return None,
                        Some(key) => { key_set = key; }
                    };
                },
                Equal => return Some((key_set, data)),
                Greater => {
                    match self.map.next() {
                        None => return None,
                        Some((key, d)) => {
                            key_map = key;
                            data = d;
                        }
                    };
                }
            }
        }
    }
}

impl<A, B> Iterator for OuterJoinIterator<A, B>
where A: OrderedMapIterator,
      B: OrderedMapIterator<Key=A::Key>,
      A::Key: Ord + Eq,
{

    type Item = (A::Key, (Option<A::Val>, Option<B::Val>));

    fn next(&mut self) -> Option<(A::Key, (Option<A::Val>, Option<B::Val>))> {
        let which = match (self.left.peek(), self.right.peek()) {
            (Some(&(ref ka, _)), Some(&(ref kb, _))) => kb.cmp(ka),
            (None, Some(_)) => Less,
            (Some(_), None) => Greater,
            (None, None) => return None
        };

        match which {
            Equal => {
                let ((k, a), (_, b)) =
                    (self.left.next().expect("no value found"),
                     self.right.next().expect("no value found"));

                Some((k, (Some(a), Some(b))))
            }
            Less => {
                let (k, v) = self.right.next().expect("no value found");
                Some((k, (None, Some(v))))
            }
            Greater => {
                let (k, v) = self.left.next().expect("no value found");
                Some((k, (Some(v), None)))
            }
        }
    }
}

impl<'a, K: Ord> OrderedSetIterator<Key=&'a K> for btree_set::Iter<'a, K> {}
impl<'a, K: Ord, V> OrderedMapIterator<Key=&'a K, Val=&'a V> for btree_map::Iter<'a, K, V> {}
#[cfg(feature="tree_map")]
impl<'a, K> OrderedSetIterator<Item=&'a K> for tree_set::Iter<'a, K> {}
#[cfg(feature="tree_map")]
impl<'a, K, V> OrderedMapIterator<Key=&'a K, Val=&'a V> for tree_map::Iter<'a, K, V> {}
#[cfg(feature="tree_map")]
impl<'a> OrderedSetIterator<Item=usize> for trie_set::Iter<'a> {}
#[cfg(feature="trie_map")]
impl<'a, V> OrderedMapIterator<Item=usize, Val=&'a V> for trie_map::Iter<'a, V> {}
impl<'a, V> OrderedMapIterator<Key=usize, Val=&'a V> for vec_map::Iter<'a, V> {}
impl<'a> OrderedSetIterator<Item=usize> for bitv_set::Iter<'a> {}

impl<A, B> OrderedMapIterator for InnerJoinMapIterator<A, B>
where A: OrderedMapIterator,
      B: OrderedMapIterator<Key=A::Key>,
      A::Key: Ord,
{
    type Key = A::Key;
    type Val = (A::Val, B::Val);
}

impl<A, B> OrderedMapIterator for InnerJoinMapSetIterator<A, B>
where A: OrderedMapIterator,
      B: OrderedSetIterator<Item=A::Key>,
      A::Key: Ord,
{
    type Key = A::Key;
    type Val = A::Val;
}

impl<A, B> OrderedSetIterator for InnerJoinSetIterator<A, B>
where A: OrderedMapIterator,
      B: OrderedMapIterator<Item=A::Item>,
      A::Item: Ord,
{}

#[cfg(test)]
mod tests {
    use test::Bencher;
    use test;

    use super::{OrderedSetIterator, OrderedMapIterator};

    #[test]
    fn join_two_sets() {
        use std::collections::BTreeSet;

        let powers_of_two: BTreeSet<i32> = range(1, 10).map(|x| x * 2).collect();
        let powers_of_three: BTreeSet<i32> = range(1, 10).map(|x| x * 3).collect();

        let expected = vec![6, 12, 18];

        let powers_of_two_and_three: Vec<i32> =
            powers_of_two.iter()
            .inner_join_set(powers_of_three.iter())
            .map(|&x| x)
            .collect();

        assert_eq!(expected, powers_of_two_and_three);
    }

    #[test]
    fn join_three_sets() {
        use std::collections::BTreeSet;

        let powers_of_two: BTreeSet<i32> = range(1, 100).map(|x| x * 2).collect();
        let powers_of_three: BTreeSet<i32> = range(1, 100).map(|x| x * 3).collect();
        let powers_of_five: BTreeSet<i32> = range(1, 100).map(|x| x * 5).collect();

        let expected = vec![30, 60, 90, 120, 150, 180];

        let powers_of_two_and_three: Vec<i32> =
            powers_of_two.iter()
            .inner_join_set(powers_of_three.iter())
            .inner_join_set(powers_of_five.iter())
            .map(|&x| x)
            .collect();

        assert_eq!(expected, powers_of_two_and_three);
    }

    #[test]
    fn join_two_maps() {
        use std::collections::BTreeMap;

        let powers_of_two: BTreeMap<i32, i32> = range(1, 10).map(|x| (x * 2, x)).collect();
        let powers_of_three: BTreeMap<i32, i32> = range(1, 10).map(|x| (x * 3, x)).collect();

        let mut powers_of_two_and_three =
            powers_of_two.iter().inner_join_map(powers_of_three.iter())
            .map(|(&k, (&a, &b))| (k, a, b));

        assert_eq!(Some((6, 3, 2)), powers_of_two_and_three.next());
        assert_eq!(Some((12, 6, 4)), powers_of_two_and_three.next());
        assert_eq!(Some((18, 9, 6)), powers_of_two_and_three.next());
        assert_eq!(None, powers_of_two_and_three.next());
    }

    #[test]
    fn join_two_maps_to_set() {
        use std::collections::{BTreeMap, BTreeSet};

        let powers_of_two: BTreeSet<i32> = range(1, 10).map(|x| x * 2).collect();
        let powers_of_three: BTreeMap<i32, i32> = range(1, 10).map(|x| (x * 3, x)).collect();

        let mut powers_of_two_and_three =
            powers_of_two.iter().inner_join_map(powers_of_three.iter())
            .map(|(&k, &a)| (k, a));

        assert_eq!(Some((6, 2)), powers_of_two_and_three.next());
        assert_eq!(Some((12, 4)), powers_of_two_and_three.next());
        assert_eq!(Some((18, 6)), powers_of_two_and_three.next());
        assert_eq!(None, powers_of_two_and_three.next());
    }

    #[test]
    fn outer_join_fizz_buzz() {
        use std::collections::BTreeMap;

        let mul_of_three: BTreeMap<i32, i32> = range(0, 100).map(|x| (x*3, x)).collect();
        let mul_of_five: BTreeMap<i32, i32> = range(0, 100).map(|x| (x*5, x)).collect();

        let mut fizz_buzz = BTreeMap::new();

        for (key, (three, five)) in mul_of_three.iter()
                                                .outer_join(mul_of_five.iter()) {
            fizz_buzz.insert(key, (three.is_some(), five.is_some()));
        }

        let res: BTreeMap<i32, String> = range(1, 100).map(|i|
            (i, match fizz_buzz.get(&i) {
                None => format!("{}", i),
                Some(&(true, false)) => format!("Fizz"),
                Some(&(false, true)) => format!("Buzz"),
                Some(&(true, true)) => format!("FizzBuzz"),
                Some(&(false, false)) => panic!("Outer join failed...")
            })).collect();

        for i in range(1, 100) {
            match (i % 3, i % 5) {
                (0, 0) => assert_eq!("FizzBuzz", res[i].as_slice()),
                (0, _) => assert_eq!("Fizz", res[i].as_slice()),
                (_, 0) => assert_eq!("Buzz", res[i].as_slice()),
                _ => assert_eq!(format!("{}", i).as_slice(), res[i].as_slice())
            }
        }
    }

    #[bench]
    pub fn inner_join_map(b: &mut test::Bencher) {
        use std::collections::BTreeSet;

        let powers_of_two: BTreeSet<u32> = range(1, 1000000).map(|x| x * 2).collect();
        let powers_of_three: BTreeSet<u32> = range(1, 1000000).map(|x| x * 3).collect();

        b.iter(||{
            for x in powers_of_two.iter()
                .inner_join_set(powers_of_three.iter()) {

                test::black_box(x);
            }
        })
    }
}
<|endoftext|>


<commit_before>//! Handles the `Enter` key press. At the momently, this only continues
//! comments, but should handle indent some time in the future as well.

use base_db::{FilePosition, SourceDatabase};
use ide_db::RootDatabase;
use syntax::{
    ast::{self, AstToken},
    AstNode, SmolStr, SourceFile,
    SyntaxKind::*,
    SyntaxToken, TextRange, TextSize, TokenAtOffset,
};
use test_utils::mark;
use text_edit::TextEdit;

// Feature: On Enter
//
// rust-analyzer can override kbd:[Enter] key to make it smarter:
//
// - kbd:[Enter] inside triple-slash comments automatically inserts `///`
// - kbd:[Enter] in the middle or after a trailing space in `//` inserts `//`
//
// This action needs to be assigned to shortcut explicitly.
//
// VS Code::
//
// Add the following to `keybindings.json`:
// [source,json]
// ----
// {
//   "key": "Enter",
//   "command": "rust-analyzer.onEnter",
//   "when": "editorTextFocus && !suggestWidgetVisible && editorLangId == rust"
// }
// ----
pub(crate) fn on_enter(db: &RootDatabase, position: FilePosition) -> Option<TextEdit> {
    let parse = db.parse(position.file_id);
    let file = parse.tree();
    let comment = file
        .syntax()
        .token_at_offset(position.offset)
        .left_biased()
        .and_then(ast::Comment::cast)?;

    if comment.kind().shape.is_block() {
        return None;
    }

    let prefix = comment.prefix();
    let comment_range = comment.syntax().text_range();
    if position.offset < comment_range.start() + TextSize::of(prefix) {
        return None;
    }

    let mut remove_last_space = false;
    // Continuing single-line non-doc comments (like this one :) ) is annoying
    if prefix == "//" && comment_range.end() == position.offset {
        if comment.text().ends_with(' ') {
            mark::hit!(continues_end_of_line_comment_with_space);
            remove_last_space = true;
        } else if !followed_by_comment(&comment) {
            return None;
        }
    }

    let indent = node_indent(&file, comment.syntax())?;
    let inserted = format!("\n{}{} $0", indent, prefix);
    let delete = if remove_last_space {
        TextRange::new(position.offset - TextSize::of(' '), position.offset)
    } else {
        TextRange::empty(position.offset)
    };
    let edit = TextEdit::replace(delete, inserted);
    Some(edit)
}

fn followed_by_comment(comment: &ast::Comment) -> bool {
    let ws = match comment.syntax().next_token().and_then(ast::Whitespace::cast) {
        Some(it) => it,
        None => return false,
    };
    if ws.spans_multiple_lines() {
        return false;
    }
    ws.syntax().next_token().and_then(ast::Comment::cast).is_some()
}

fn node_indent(file: &SourceFile, token: &SyntaxToken) -> Option<SmolStr> {
    let ws = match file.syntax().token_at_offset(token.text_range().start()) {
        TokenAtOffset::Between(l, r) => {
            assert!(r == *token);
            l
        }
        TokenAtOffset::Single(n) => {
            assert!(n == *token);
            return Some("".into());
        }
        TokenAtOffset::None => unreachable!(),
    };
    if ws.kind() != WHITESPACE {
        return None;
    }
    let text = ws.text();
    let pos = text.rfind('\n').map(|it| it + 1).unwrap_or(0);
    Some(text[pos..].into())
}

#[cfg(test)]
mod tests {
    use stdx::trim_indent;
    use test_utils::{assert_eq_text, mark};

    use crate::fixture;

    fn apply_on_enter(before: &str) -> Option<String> {
        let (analysis, position) = fixture::position(&before);
        let result = analysis.on_enter(position).unwrap()?;

        let mut actual = analysis.file_text(position.file_id).unwrap().to_string();
        result.apply(&mut actual);
        Some(actual)
    }

    fn do_check(ra_fixture_before: &str, ra_fixture_after: &str) {
        let ra_fixture_after = &trim_indent(ra_fixture_after);
        let actual = apply_on_enter(ra_fixture_before).unwrap();
        assert_eq_text!(ra_fixture_after, &actual);
    }

    fn do_check_noop(ra_fixture_text: &str) {
        assert!(apply_on_enter(ra_fixture_text).is_none())
    }

    #[test]
    fn continues_doc_comment() {
        do_check(
            r"
/// Some docs<|>
fn foo() {
}
",
            r"
/// Some docs
/// $0
fn foo() {
}
",
        );

        do_check(
            r"
impl S {
    /// Some<|> docs.
    fn foo() {}
}
",
            r"
impl S {
    /// Some
    /// $0 docs.
    fn foo() {}
}
",
        );

        do_check(
            r"
///<|> Some docs
fn foo() {
}
",
            r"
///
/// $0 Some docs
fn foo() {
}
",
        );
    }

    #[test]
    fn does_not_continue_before_doc_comment() {
        do_check_noop(r"<|>//! docz");
    }

    #[test]
    fn continues_code_comment_in_the_middle_of_line() {
        do_check(
            r"
fn main() {
    // Fix<|> me
    let x = 1 + 1;
}
",
            r"
fn main() {
    // Fix
    // $0 me
    let x = 1 + 1;
}
",
        );
    }

    #[test]
    fn continues_code_comment_in_the_middle_several_lines() {
        do_check(
            r"
fn main() {
    // Fix<|>
    // me
    let x = 1 + 1;
}
",
            r"
fn main() {
    // Fix
    // $0
    // me
    let x = 1 + 1;
}
",
        );
    }

    #[test]
    fn does_not_continue_end_of_line_comment() {
        do_check_noop(
            r"
fn main() {
    // Fix me<|>
    let x = 1 + 1;
}
",
        );
    }

    #[test]
    fn continues_end_of_line_comment_with_space() {
        mark::check!(continues_end_of_line_comment_with_space);
        do_check(
            r#"
fn main() {
    // Fix me <|>
    let x = 1 + 1;
}
"#,
            r#"
fn main() {
    // Fix me
    // $0
    let x = 1 + 1;
}
"#,
        );
    }
}
<commit_msg>Trim all trailing whitespace in onEnter<commit_after>//! Handles the `Enter` key press. At the momently, this only continues
//! comments, but should handle indent some time in the future as well.

use base_db::{FilePosition, SourceDatabase};
use ide_db::RootDatabase;
use syntax::{
    ast::{self, AstToken},
    AstNode, SmolStr, SourceFile,
    SyntaxKind::*,
    SyntaxToken, TextRange, TextSize, TokenAtOffset,
};
use test_utils::mark;
use text_edit::TextEdit;

// Feature: On Enter
//
// rust-analyzer can override kbd:[Enter] key to make it smarter:
//
// - kbd:[Enter] inside triple-slash comments automatically inserts `///`
// - kbd:[Enter] in the middle or after a trailing space in `//` inserts `//`
//
// This action needs to be assigned to shortcut explicitly.
//
// VS Code::
//
// Add the following to `keybindings.json`:
// [source,json]
// ----
// {
//   "key": "Enter",
//   "command": "rust-analyzer.onEnter",
//   "when": "editorTextFocus && !suggestWidgetVisible && editorLangId == rust"
// }
// ----
pub(crate) fn on_enter(db: &RootDatabase, position: FilePosition) -> Option<TextEdit> {
    let parse = db.parse(position.file_id);
    let file = parse.tree();
    let comment = file
        .syntax()
        .token_at_offset(position.offset)
        .left_biased()
        .and_then(ast::Comment::cast)?;

    if comment.kind().shape.is_block() {
        return None;
    }

    let prefix = comment.prefix();
    let comment_range = comment.syntax().text_range();
    if position.offset < comment_range.start() + TextSize::of(prefix) {
        return None;
    }

    let mut remove_trailing_whitespace = false;
    // Continuing single-line non-doc comments (like this one :) ) is annoying
    if prefix == "//" && comment_range.end() == position.offset {
        if comment.text().ends_with(' ') {
            mark::hit!(continues_end_of_line_comment_with_space);
            remove_trailing_whitespace = true;
        } else if !followed_by_comment(&comment) {
            return None;
        }
    }

    let indent = node_indent(&file, comment.syntax())?;
    let inserted = format!("\n{}{} $0", indent, prefix);
    let delete = if remove_trailing_whitespace {
        let trimmed_len = comment.text().trim_end().len() as u32;
        let trailing_whitespace_len = comment.text().len() as u32 - trimmed_len;
        TextRange::new(position.offset - TextSize::from(trailing_whitespace_len), position.offset)
    } else {
        TextRange::empty(position.offset)
    };
    let edit = TextEdit::replace(delete, inserted);
    Some(edit)
}

fn followed_by_comment(comment: &ast::Comment) -> bool {
    let ws = match comment.syntax().next_token().and_then(ast::Whitespace::cast) {
        Some(it) => it,
        None => return false,
    };
    if ws.spans_multiple_lines() {
        return false;
    }
    ws.syntax().next_token().and_then(ast::Comment::cast).is_some()
}

fn node_indent(file: &SourceFile, token: &SyntaxToken) -> Option<SmolStr> {
    let ws = match file.syntax().token_at_offset(token.text_range().start()) {
        TokenAtOffset::Between(l, r) => {
            assert!(r == *token);
            l
        }
        TokenAtOffset::Single(n) => {
            assert!(n == *token);
            return Some("".into());
        }
        TokenAtOffset::None => unreachable!(),
    };
    if ws.kind() != WHITESPACE {
        return None;
    }
    let text = ws.text();
    let pos = text.rfind('\n').map(|it| it + 1).unwrap_or(0);
    Some(text[pos..].into())
}

#[cfg(test)]
mod tests {
    use stdx::trim_indent;
    use test_utils::{assert_eq_text, mark};

    use crate::fixture;

    fn apply_on_enter(before: &str) -> Option<String> {
        let (analysis, position) = fixture::position(&before);
        let result = analysis.on_enter(position).unwrap()?;

        let mut actual = analysis.file_text(position.file_id).unwrap().to_string();
        result.apply(&mut actual);
        Some(actual)
    }

    fn do_check(ra_fixture_before: &str, ra_fixture_after: &str) {
        let ra_fixture_after = &trim_indent(ra_fixture_after);
        let actual = apply_on_enter(ra_fixture_before).unwrap();
        assert_eq_text!(ra_fixture_after, &actual);
    }

    fn do_check_noop(ra_fixture_text: &str) {
        assert!(apply_on_enter(ra_fixture_text).is_none())
    }

    #[test]
    fn continues_doc_comment() {
        do_check(
            r"
/// Some docs<|>
fn foo() {
}
",
            r"
/// Some docs
/// $0
fn foo() {
}
",
        );

        do_check(
            r"
impl S {
    /// Some<|> docs.
    fn foo() {}
}
",
            r"
impl S {
    /// Some
    /// $0 docs.
    fn foo() {}
}
",
        );

        do_check(
            r"
///<|> Some docs
fn foo() {
}
",
            r"
///
/// $0 Some docs
fn foo() {
}
",
        );
    }

    #[test]
    fn does_not_continue_before_doc_comment() {
        do_check_noop(r"<|>//! docz");
    }

    #[test]
    fn continues_code_comment_in_the_middle_of_line() {
        do_check(
            r"
fn main() {
    // Fix<|> me
    let x = 1 + 1;
}
",
            r"
fn main() {
    // Fix
    // $0 me
    let x = 1 + 1;
}
",
        );
    }

    #[test]
    fn continues_code_comment_in_the_middle_several_lines() {
        do_check(
            r"
fn main() {
    // Fix<|>
    // me
    let x = 1 + 1;
}
",
            r"
fn main() {
    // Fix
    // $0
    // me
    let x = 1 + 1;
}
",
        );
    }

    #[test]
    fn does_not_continue_end_of_line_comment() {
        do_check_noop(
            r"
fn main() {
    // Fix me<|>
    let x = 1 + 1;
}
",
        );
    }

    #[test]
    fn continues_end_of_line_comment_with_space() {
        mark::check!(continues_end_of_line_comment_with_space);
        do_check(
            r#"
fn main() {
    // Fix me <|>
    let x = 1 + 1;
}
"#,
            r#"
fn main() {
    // Fix me
    // $0
    let x = 1 + 1;
}
"#,
        );
    }

    #[test]
    fn trims_all_trailing_whitespace() {
        do_check(
            "
fn main() {
    // Fix me  \t\t   <|>
    let x = 1 + 1;
}
",
            "
fn main() {
    // Fix me
    // $0
    let x = 1 + 1;
}
",
        );
    }
}
<|endoftext|>