<commit_before>// Copyright 2014-2016 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! Handling log-probabilities.

use std::mem;
use std::f64;
use std::iter;
use std::ops::{Add, Sub, Mul, Div};
use num::traits::cast;
use num::NumCast;

use itertools::linspace;
use itertools::Itertools;
use itertools::misc::ToFloat;

/// A factor to convert log-probabilities to PHRED-scale (phred = p * `LOG_TO_PHRED_FACTOR`).
const LOG_TO_PHRED_FACTOR: f64 = -4.3429448190325175; // -10 * 1 / ln(10)

/// A factor to convert PHRED-scale to log-probabilities (p = phred * `PHRED_TO_LOG_FACTOR`).
const PHRED_TO_LOG_FACTOR: f64 = -0.23025850929940456; // 1 / (-10 * log10(e))

/// Calculate log(1 - p) with p given in log space without loss of precision as described in
/// http://cran.r-project.org/web/packages/Rmpfr/vignettes/log1mexp-note.pdf.
fn ln_1m_exp(p: f64) -> f64 {
    assert!(p <= 0.0);
    if p < -0.693 {
        (-p.exp()).ln_1p()
    } else {
        (-p.exp_m1()).ln()
    }
}

custom_derive! {
    #[derive(
        NewtypeFrom,
        NewtypeDeref,
        NewtypeAdd(*),
        NewtypeSub(*),
        NewtypeMul(*),
        NewtypeDiv(*),
        PartialEq,
        PartialOrd,
        Copy,
        Clone,
        Debug,
        Default
    )]
    /// A newtype for probabilities.
    ///
    /// # Example
    ///
    /// ```
    /// #[macro_use]
    /// extern crate approx;
    /// # extern crate bio;
    /// # fn main() {
    /// use bio::stats::Prob;
    ///
    /// let p = Prob(0.5);
    /// let q = Prob(0.2);
    ///
    /// assert_relative_eq!(*(p + q), *Prob(0.7));
    /// # }
    /// ```
    pub struct Prob(pub f64);
}

custom_derive! {
    #[derive(
        NewtypeFrom,
        NewtypeDeref,
        NewtypeAdd(*),
        NewtypeSub(*),
        PartialEq,
        PartialOrd,
        Copy,
        Clone,
        Debug
    )]
    /// A newtype for log-scale probabilities.
    ///
    /// # Example
    ///
    /// ```
    /// #[macro_use]
    /// extern crate approx;
    /// # extern crate bio;
    /// # fn main() {
    /// use bio::stats::{LogProb, Prob};
    ///
    /// // convert from probability
    /// let p = LogProb::from(Prob(0.5));
    /// // convert manually
    /// let q = LogProb(0.2f64.ln());
    /// // obtain zero probability in log-space
    /// let o = LogProb::ln_one();
    ///
    /// assert_relative_eq!(*Prob::from(p.ln_add_exp(q) + o), *Prob(0.7));
    /// # }
    /// ```
    pub struct LogProb(pub f64);
}

custom_derive! {
    #[derive(
        NewtypeFrom,
        NewtypeDeref,
        NewtypeAdd(*),
        NewtypeSub(*),
        PartialEq,
        PartialOrd,
        Copy,
        Clone,
        Debug
    )]
    /// A newtype for PHRED-scale probabilities.
    ///
    /// # Example
    ///
    /// ```
    /// #[macro_use]
    /// extern crate approx;
    /// # extern crate bio;
    /// # fn main() {
    /// use bio::stats::{PHREDProb, Prob};
    ///
    /// let p = PHREDProb::from(Prob(0.5));
    ///
    /// assert_relative_eq!(*Prob::from(p), *Prob(0.5));
    /// # }
    /// ```
    pub struct PHREDProb(pub f64);
}

/// Iterator returned by scans over logprobs.
pub type ScanIter<I> = iter::Scan<<I as IntoIterator>::IntoIter, LogProb, fn(&mut LogProb, LogProb) -> Option<LogProb>>;

impl LogProb {
    /// Log-space representation of Pr=0
    pub fn ln_zero() -> LogProb {
        LogProb(f64::NEG_INFINITY)
    }

    /// Log-space representation of Pr=1
    pub fn ln_one() -> LogProb {
        LogProb(0.0)
    }

    /// Numerically stable calculation of 1 - p in log-space.
    pub fn ln_one_minus_exp(&self) -> LogProb {
        LogProb(ln_1m_exp(**self))
    }

    /// Numerically stable sum of probabilities in log-space.
    pub fn ln_sum_exp(probs: &[LogProb]) -> LogProb {
        if probs.is_empty() {
            Self::ln_zero()
        } else {
            let mut pmax = probs[0];
            let mut imax = 0;
            for (i, &p) in probs.iter().enumerate().skip(1) {
                if p > pmax {
                    pmax = p;
                    imax = i;
                }
            }
            if pmax == Self::ln_zero() {
                Self::ln_zero()
            } else if *pmax == f64::INFINITY {
                LogProb(f64::INFINITY)
            } else {
                // TODO use sum() once it has been stabilized: .sum::<usize>()
                pmax + LogProb(
                    (probs.iter()
                          .enumerate()
                          .filter_map(|(i, p)| {
                              if i == imax {
                                  None
                              } else {
                                  Some((p - pmax).exp())
                              }
                          })
                          .fold(0.0, |s, e| s + e)
                     ).ln_1p()
                 )
            }
        }
    }

    /// Numerically stable addition probabilities in log-space.
    pub fn ln_add_exp(self, other: LogProb) -> LogProb {
        let (mut p0, mut p1) = (self, other);
        if p1 > p0 {
            mem::swap(&mut p0, &mut p1);
        }
        if p0 == Self::ln_zero() {
            Self::ln_zero()
        } else if *p0 == f64::INFINITY {
            LogProb(f64::INFINITY)
        } else {
            p0 + LogProb((p1 - p0).exp().ln_1p())
        }
    }

    /// Numerically stable subtraction of probabilities in log-space.
    pub fn ln_sub_exp(self, other: LogProb) -> LogProb {
        let (p0, p1) = (self, other);
        assert!(p0 >= p1,
                "Subtraction would lead to negative probability, which is undefined in log space.");
        if relative_eq!(*p0, *p1) || p0 == Self::ln_zero() {
            // the first case leads to zero,
            // in the second case p0 and p1 are -inf, which is fine
            Self::ln_zero()
        } else if *p0 == f64::INFINITY {
            LogProb(f64::INFINITY)
        } else {
            p0 + (p1 - p0).ln_one_minus_exp()
        }
    }

    /// Calculate the cumulative sum of the given probabilities in a numerically stable way (Durbin 1998).
    pub fn ln_cumsum_exp<I: IntoIterator<Item = LogProb>>(probs: I) -> ScanIter<I> {
        probs.into_iter().scan(Self::ln_zero(), Self::scan_ln_add_exp)
    }

    /// Integrate numerically stable over given log-space density in the interval [a, b]. Uses the trapezoidal rule with n grid points.
    pub fn ln_integrate_exp<T, D>(density: &D, a: T, b: T, n: usize) -> LogProb
        where T: NumCast + Copy + Add<Output=T> + Sub<Output=T> + Div<Output=T> + Mul<Output=T>, D: Fn(T) -> LogProb, usize: ToFloat<T>
    {
        let mut probs = linspace(a, b, n).dropping(1).dropping_back(1).map(|v| LogProb(*density(v) + 2.0f64.ln())).collect_vec();
        probs.push(density(a));
        probs.push(density(b));
        let width: f64 = cast(b - a).unwrap();

        LogProb(*Self::ln_sum_exp(&probs) + width.ln() - (2.0 * (n - 1) as f64).ln())
    }

    fn scan_ln_add_exp(s: &mut LogProb, p: LogProb) -> Option<LogProb> {
        *s = s.ln_add_exp(p);
        Some(*s)
    }
}

impl From<LogProb> for Prob {
    fn from(p: LogProb) -> Prob {
        Prob(p.exp())
    }
}

impl From<PHREDProb> for Prob {
    fn from(p: PHREDProb) -> Prob {
        Prob(10.0f64.powf(-*p / 10.0))
    }
}

impl From<Prob> for LogProb {
    fn from(p: Prob) -> LogProb {
        LogProb(p.ln())
    }
}

impl From<PHREDProb> for LogProb {
    fn from(p: PHREDProb) -> LogProb {
        LogProb(*p * PHRED_TO_LOG_FACTOR)
    }
}

impl From<Prob> for PHREDProb {
    fn from(p: Prob) -> PHREDProb {
        PHREDProb(-10.0 * p.log10())
    }
}

impl From<LogProb> for PHREDProb {
    fn from(p: LogProb) -> PHREDProb {
        PHREDProb(*p * LOG_TO_PHRED_FACTOR)
    }
}

impl Default for LogProb {
    fn default() -> LogProb {
        LogProb::ln_zero()
    }
}

impl Default for PHREDProb {
    fn default() -> PHREDProb {
        PHREDProb::from(Prob(0.0))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use itertools::Itertools;

    #[test]
    fn test_sum() {
        let probs = [LogProb::ln_zero(), LogProb::ln_one(), LogProb::ln_zero()];
        assert_eq!(LogProb::ln_sum_exp(&probs), LogProb::ln_one());
    }

    #[test]
    fn test_empty_sum() {
        assert_eq!(LogProb::ln_sum_exp(&[]), LogProb::ln_zero());
    }

    #[test]
    fn test_cumsum() {
        let probs = vec![LogProb::ln_zero(), LogProb(0.01f64.ln()), LogProb(0.001f64.ln())];
        assert_eq!(LogProb::ln_cumsum_exp(probs).collect_vec(),
                   [LogProb::ln_zero(), LogProb(0.01f64.ln()), LogProb(0.011f64.ln())]);
    }

    #[test]
    fn test_sub() {
        assert_eq!(LogProb::ln_one().ln_sub_exp(LogProb::ln_one()), LogProb::ln_zero());
        assert_relative_eq!(*LogProb::ln_one().ln_sub_exp(LogProb(0.5f64.ln())), *LogProb(0.5f64.ln()));
    }

    #[test]
    fn test_one_minus() {
        assert_eq!(LogProb::ln_zero().ln_one_minus_exp(), LogProb::ln_one());
        assert_eq!(LogProb::ln_one().ln_one_minus_exp(), LogProb::ln_zero());
    }

    #[test]
    fn test_integrate() {
        let density = |_| LogProb(0.1f64.ln());
        let prob = LogProb::ln_integrate_exp(&density, 0.0, 10.0, 5);
        assert_relative_eq!(*prob, *LogProb::ln_one(), epsilon=0.0000001);
    }
}
<commit_msg>Relocate doc comments.<commit_after>// Copyright 2014-2016 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! Handling log-probabilities.

use std::mem;
use std::f64;
use std::iter;
use std::ops::{Add, Sub, Mul, Div};
use num::traits::cast;
use num::NumCast;

use itertools::linspace;
use itertools::Itertools;
use itertools::misc::ToFloat;

/// A factor to convert log-probabilities to PHRED-scale (phred = p * `LOG_TO_PHRED_FACTOR`).
const LOG_TO_PHRED_FACTOR: f64 = -4.3429448190325175; // -10 * 1 / ln(10)

/// A factor to convert PHRED-scale to log-probabilities (p = phred * `PHRED_TO_LOG_FACTOR`).
const PHRED_TO_LOG_FACTOR: f64 = -0.23025850929940456; // 1 / (-10 * log10(e))

/// Calculate log(1 - p) with p given in log space without loss of precision as described in
/// http://cran.r-project.org/web/packages/Rmpfr/vignettes/log1mexp-note.pdf.
fn ln_1m_exp(p: f64) -> f64 {
    assert!(p <= 0.0);
    if p < -0.693 {
        (-p.exp()).ln_1p()
    } else {
        (-p.exp_m1()).ln()
    }
}

custom_derive! {
    /// A newtype for probabilities.
    ///
    /// # Example
    ///
    /// ```
    /// #[macro_use]
    /// extern crate approx;
    /// # extern crate bio;
    /// # fn main() {
    /// use bio::stats::Prob;
    ///
    /// let p = Prob(0.5);
    /// let q = Prob(0.2);
    ///
    /// assert_relative_eq!(*(p + q), *Prob(0.7));
    /// # }
    /// ```
    #[derive(
        NewtypeFrom,
        NewtypeDeref,
        NewtypeAdd(*),
        NewtypeSub(*),
        NewtypeMul(*),
        NewtypeDiv(*),
        PartialEq,
        PartialOrd,
        Copy,
        Clone,
        Debug,
        Default
    )]
    pub struct Prob(pub f64);
}

custom_derive! {
    /// A newtype for log-scale probabilities.
    ///
    /// # Example
    ///
    /// ```
    /// #[macro_use]
    /// extern crate approx;
    /// # extern crate bio;
    /// # fn main() {
    /// use bio::stats::{LogProb, Prob};
    ///
    /// // convert from probability
    /// let p = LogProb::from(Prob(0.5));
    /// // convert manually
    /// let q = LogProb(0.2f64.ln());
    /// // obtain zero probability in log-space
    /// let o = LogProb::ln_one();
    ///
    /// assert_relative_eq!(*Prob::from(p.ln_add_exp(q) + o), *Prob(0.7));
    /// # }
    /// ```
    #[derive(
        NewtypeFrom,
        NewtypeDeref,
        NewtypeAdd(*),
        NewtypeSub(*),
        PartialEq,
        PartialOrd,
        Copy,
        Clone,
        Debug
    )]
    pub struct LogProb(pub f64);
}

custom_derive! {
    /// A newtype for PHRED-scale probabilities.
    ///
    /// # Example
    ///
    /// ```
    /// #[macro_use]
    /// extern crate approx;
    /// # extern crate bio;
    /// # fn main() {
    /// use bio::stats::{PHREDProb, Prob};
    ///
    /// let p = PHREDProb::from(Prob(0.5));
    ///
    /// assert_relative_eq!(*Prob::from(p), *Prob(0.5));
    /// # }
    /// ```
    #[derive(
        NewtypeFrom,
        NewtypeDeref,
        NewtypeAdd(*),
        NewtypeSub(*),
        PartialEq,
        PartialOrd,
        Copy,
        Clone,
        Debug
    )]
    pub struct PHREDProb(pub f64);
}

/// Iterator returned by scans over logprobs.
pub type ScanIter<I> = iter::Scan<<I as IntoIterator>::IntoIter, LogProb, fn(&mut LogProb, LogProb) -> Option<LogProb>>;

impl LogProb {
    /// Log-space representation of Pr=0
    pub fn ln_zero() -> LogProb {
        LogProb(f64::NEG_INFINITY)
    }

    /// Log-space representation of Pr=1
    pub fn ln_one() -> LogProb {
        LogProb(0.0)
    }

    /// Numerically stable calculation of 1 - p in log-space.
    pub fn ln_one_minus_exp(&self) -> LogProb {
        LogProb(ln_1m_exp(**self))
    }

    /// Numerically stable sum of probabilities in log-space.
    pub fn ln_sum_exp(probs: &[LogProb]) -> LogProb {
        if probs.is_empty() {
            Self::ln_zero()
        } else {
            let mut pmax = probs[0];
            let mut imax = 0;
            for (i, &p) in probs.iter().enumerate().skip(1) {
                if p > pmax {
                    pmax = p;
                    imax = i;
                }
            }
            if pmax == Self::ln_zero() {
                Self::ln_zero()
            } else if *pmax == f64::INFINITY {
                LogProb(f64::INFINITY)
            } else {
                // TODO use sum() once it has been stabilized: .sum::<usize>()
                pmax + LogProb(
                    (probs.iter()
                          .enumerate()
                          .filter_map(|(i, p)| {
                              if i == imax {
                                  None
                              } else {
                                  Some((p - pmax).exp())
                              }
                          })
                          .fold(0.0, |s, e| s + e)
                     ).ln_1p()
                 )
            }
        }
    }

    /// Numerically stable addition probabilities in log-space.
    pub fn ln_add_exp(self, other: LogProb) -> LogProb {
        let (mut p0, mut p1) = (self, other);
        if p1 > p0 {
            mem::swap(&mut p0, &mut p1);
        }
        if p0 == Self::ln_zero() {
            Self::ln_zero()
        } else if *p0 == f64::INFINITY {
            LogProb(f64::INFINITY)
        } else {
            p0 + LogProb((p1 - p0).exp().ln_1p())
        }
    }

    /// Numerically stable subtraction of probabilities in log-space.
    pub fn ln_sub_exp(self, other: LogProb) -> LogProb {
        let (p0, p1) = (self, other);
        assert!(p0 >= p1,
                "Subtraction would lead to negative probability, which is undefined in log space.");
        if relative_eq!(*p0, *p1) || p0 == Self::ln_zero() {
            // the first case leads to zero,
            // in the second case p0 and p1 are -inf, which is fine
            Self::ln_zero()
        } else if *p0 == f64::INFINITY {
            LogProb(f64::INFINITY)
        } else {
            p0 + (p1 - p0).ln_one_minus_exp()
        }
    }

    /// Calculate the cumulative sum of the given probabilities in a numerically stable way (Durbin 1998).
    pub fn ln_cumsum_exp<I: IntoIterator<Item = LogProb>>(probs: I) -> ScanIter<I> {
        probs.into_iter().scan(Self::ln_zero(), Self::scan_ln_add_exp)
    }

    /// Integrate numerically stable over given log-space density in the interval [a, b]. Uses the trapezoidal rule with n grid points.
    pub fn ln_integrate_exp<T, D>(density: &D, a: T, b: T, n: usize) -> LogProb
        where T: NumCast + Copy + Add<Output=T> + Sub<Output=T> + Div<Output=T> + Mul<Output=T>, D: Fn(T) -> LogProb, usize: ToFloat<T>
    {
        let mut probs = linspace(a, b, n).dropping(1).dropping_back(1).map(|v| LogProb(*density(v) + 2.0f64.ln())).collect_vec();
        probs.push(density(a));
        probs.push(density(b));
        let width: f64 = cast(b - a).unwrap();

        LogProb(*Self::ln_sum_exp(&probs) + width.ln() - (2.0 * (n - 1) as f64).ln())
    }

    fn scan_ln_add_exp(s: &mut LogProb, p: LogProb) -> Option<LogProb> {
        *s = s.ln_add_exp(p);
        Some(*s)
    }
}

impl From<LogProb> for Prob {
    fn from(p: LogProb) -> Prob {
        Prob(p.exp())
    }
}

impl From<PHREDProb> for Prob {
    fn from(p: PHREDProb) -> Prob {
        Prob(10.0f64.powf(-*p / 10.0))
    }
}

impl From<Prob> for LogProb {
    fn from(p: Prob) -> LogProb {
        LogProb(p.ln())
    }
}

impl From<PHREDProb> for LogProb {
    fn from(p: PHREDProb) -> LogProb {
        LogProb(*p * PHRED_TO_LOG_FACTOR)
    }
}

impl From<Prob> for PHREDProb {
    fn from(p: Prob) -> PHREDProb {
        PHREDProb(-10.0 * p.log10())
    }
}

impl From<LogProb> for PHREDProb {
    fn from(p: LogProb) -> PHREDProb {
        PHREDProb(*p * LOG_TO_PHRED_FACTOR)
    }
}

impl Default for LogProb {
    fn default() -> LogProb {
        LogProb::ln_zero()
    }
}

impl Default for PHREDProb {
    fn default() -> PHREDProb {
        PHREDProb::from(Prob(0.0))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use itertools::Itertools;

    #[test]
    fn test_sum() {
        let probs = [LogProb::ln_zero(), LogProb::ln_one(), LogProb::ln_zero()];
        assert_eq!(LogProb::ln_sum_exp(&probs), LogProb::ln_one());
    }

    #[test]
    fn test_empty_sum() {
        assert_eq!(LogProb::ln_sum_exp(&[]), LogProb::ln_zero());
    }

    #[test]
    fn test_cumsum() {
        let probs = vec![LogProb::ln_zero(), LogProb(0.01f64.ln()), LogProb(0.001f64.ln())];
        assert_eq!(LogProb::ln_cumsum_exp(probs).collect_vec(),
                   [LogProb::ln_zero(), LogProb(0.01f64.ln()), LogProb(0.011f64.ln())]);
    }

    #[test]
    fn test_sub() {
        assert_eq!(LogProb::ln_one().ln_sub_exp(LogProb::ln_one()), LogProb::ln_zero());
        assert_relative_eq!(*LogProb::ln_one().ln_sub_exp(LogProb(0.5f64.ln())), *LogProb(0.5f64.ln()));
    }

    #[test]
    fn test_one_minus() {
        assert_eq!(LogProb::ln_zero().ln_one_minus_exp(), LogProb::ln_one());
        assert_eq!(LogProb::ln_one().ln_one_minus_exp(), LogProb::ln_zero());
    }

    #[test]
    fn test_integrate() {
        let density = |_| LogProb(0.1f64.ln());
        let prob = LogProb::ln_integrate_exp(&density, 0.0, 10.0, 5);
        assert_relative_eq!(*prob, *LogProb::ln_one(), epsilon=0.0000001);
    }
}
<|endoftext|>


<commit_before><commit_msg>Add Unit Descriptions as Tooltips to Service Labels<commit_after><|endoftext|>


<commit_before><commit_msg>get all configs<commit_after><|endoftext|>


<commit_before><commit_msg>Removed import of Schedulererror variants<commit_after><|endoftext|>


<commit_before><commit_msg>Add a comment about why from_buffer is private.<commit_after><|endoftext|>


<commit_before>use log::{debug, error, trace};
use std::io::Write;
use std::net::SocketAddr;
use std::sync::Arc;
use tokio::net::UdpSocket;

use serde::{Deserialize, Serialize};

use crate::config::Configuration;
use crate::stackvec::StackVec;
use crate::tracker;
use bincode::Options;

// maximum MTU is usually 1500, but our stack allows us to allocate the maximum - so why not?
const MAX_PACKET_SIZE: usize = 0xffff;

// protocol contants
const PROTOCOL_ID: u64 = 0x0000041727101980;

#[repr(u32)]
#[derive(Serialize, Deserialize)]
enum Actions {
    Connect = 0,
    Announce = 1,
    Scrape = 2,
    Error = 3,
}

#[repr(u32)]
#[derive(Serialize, Deserialize, Clone, Copy)]
pub enum Events {
    None = 0,
    Complete = 1,
    Started = 2,
    Stopped = 3,
}

fn pack_into<T: Serialize, W: std::io::Write>(w: &mut W, data: &T) -> Result<(), ()> {
    let config = bincode::options().with_big_endian().with_fixint_encoding();

    match config.serialize_into(w, data) {
        Ok(_) => Ok(()),
        Err(_) => Err(()),
    }
}

fn unpack<'a, T: Deserialize<'a>>(data: &'a [u8]) -> Option<T> {
    let config = bincode::options().with_big_endian().allow_trailing_bytes();

    match config.deserialize(data) {
        Ok(obj) => Some(obj),
        Err(_) => None,
    }
}

#[derive(Serialize, Deserialize)]
struct UDPRequestHeader {
    connection_id: u64,
    action: Actions,
    transaction_id: u32,
}

#[derive(Serialize, Deserialize)]
struct UDPResponseHeader {
    action: Actions,
    transaction_id: u32,
}

#[derive(Serialize, Deserialize)]
struct UDPConnectionResponse {
    header: UDPResponseHeader,
    connection_id: u64,
}

#[derive(Serialize, Deserialize)]
struct UDPAnnounceRequest {
    header: UDPRequestHeader,

    info_hash: [u8; 20],
    peer_id: [u8; 20],
    downloaded: u64,
    left: u64,
    uploaded: u64,
    event: Events,
    ip_address: u32,
    key: u32,
    num_want: i32,
    port: u16,
}

#[derive(Serialize, Deserialize)]
struct UDPAnnounceResponse {
    header: UDPResponseHeader,

    interval: u32,
    leechers: u32,
    seeders: u32,
}

#[derive(Serialize)]
struct UDPScrapeResponseEntry {
    seeders: u32,
    completed: u32,
    leechers: u32,
}

pub struct UDPTracker {
    srv: tokio::net::UdpSocket,
    tracker: std::sync::Arc<tracker::TorrentTracker>,
    config: Arc<Configuration>,
}

impl UDPTracker {
    pub async fn new(
        config: Arc<Configuration>, tracker: std::sync::Arc<tracker::TorrentTracker>,
    ) -> Result<UDPTracker, std::io::Error> {
        let cfg = config.clone();

        let srv = UdpSocket::bind(cfg.get_udp_config().get_address()).await?;

        Ok(UDPTracker {
            srv,
            tracker,
            config: cfg,
        })
    }

    async fn handle_packet(&self, remote_address: &SocketAddr, payload: &[u8]) {
        let header: UDPRequestHeader = match unpack(payload) {
            Some(val) => val,
            None => {
                trace!("failed to parse packet from {}", remote_address);
                return;
            }
        };

        match header.action {
            Actions::Connect => self.handle_connect(remote_address, &header, payload).await,
            Actions::Announce => self.handle_announce(remote_address, &header, payload).await,
            Actions::Scrape => self.handle_scrape(remote_address, &header, payload).await,
            _ => {
                trace!("invalid action from {}", remote_address);
                // someone is playing around... ignore request.
            }
        }
    }

    async fn handle_connect(&self, remote_addr: &SocketAddr, header: &UDPRequestHeader, _payload: &[u8]) {
        if header.connection_id != PROTOCOL_ID {
            trace!("Bad protocol magic from {}", remote_addr);
            return;
        }

        // send response...
        let conn_id = self.get_connection_id(remote_addr);

        let response = UDPConnectionResponse {
            header: UDPResponseHeader {
                transaction_id: header.transaction_id,
                action: Actions::Connect,
            },
            connection_id: conn_id,
        };

        let mut payload_buffer = vec![0u8; MAX_PACKET_SIZE];
        let mut payload = StackVec::from(payload_buffer.as_mut_slice());

        if pack_into(&mut payload, &response).is_ok() {
            let _ = self.send_packet(remote_addr, payload.as_slice()).await;
        }
    }

    async fn handle_announce(&self, remote_addr: &SocketAddr, header: &UDPRequestHeader, payload: &[u8]) {
        if header.connection_id != self.get_connection_id(remote_addr) {
            return;
        }

        let packet: UDPAnnounceRequest = match unpack(payload) {
            Some(v) => v,
            None => {
                trace!("failed to unpack announce request from {}", remote_addr);
                return;
            }
        };

        if let Ok(_plen) = bincode::serialized_size(&packet) {
            let plen = _plen as usize;
            if payload.len() > plen {
                let bep41_payload = &payload[plen..];

                // TODO: process BEP0041 payload.
                trace!("BEP0041 payload of {} bytes from {}", bep41_payload.len(), remote_addr);
            }
        }

        if packet.ip_address != 0 {
            // TODO: allow configurability of ip address
            // for now, ignore request.
            trace!("announce request for other IP ignored. (from {})", remote_addr);
            return;
        }

        let client_addr = SocketAddr::new(remote_addr.ip(), packet.port);
        let info_hash = packet.info_hash.into();

        let peer_id: &tracker::PeerId = tracker::PeerId::from_array(&packet.peer_id);

        match self
            .tracker
            .update_torrent_and_get_stats(
                &info_hash,
                peer_id,
                &client_addr,
                packet.uploaded,
                packet.downloaded,
                packet.left,
                packet.event,
            )
            .await
        {
            tracker::TorrentStats::Stats {
                leechers,
                complete: _,
                seeders,
            } => {
                let peers = match self.tracker.get_torrent_peers(&info_hash, &client_addr).await {
                    Some(v) => v,
                    None => {
                        return;
                    }
                };

                let mut payload_buffer = vec![0u8; MAX_PACKET_SIZE];
                let mut payload = StackVec::from(&mut payload_buffer);

                match pack_into(&mut payload, &UDPAnnounceResponse {
                    header: UDPResponseHeader {
                        action: Actions::Announce,
                        transaction_id: packet.header.transaction_id,
                    },
                    seeders,
                    interval: self.config.get_udp_config().get_announce_interval(),
                    leechers,
                }) {
                    Ok(_) => {}
                    Err(_) => {
                        return;
                    }
                };

                for peer in peers {
                    match peer {
                        SocketAddr::V4(ipv4) => {
                            let _ = payload.write(&ipv4.ip().octets());
                        }
                        SocketAddr::V6(ipv6) => {
                            let _ = payload.write(&ipv6.ip().octets());
                        }
                    };

                    let port_hton = client_addr.port().to_be();
                    let _ = payload.write(&[(port_hton & 0xff) as u8, ((port_hton >> 8) & 0xff) as u8]);
                }

                let _ = self.send_packet(&client_addr, payload.as_slice()).await;
            }
            tracker::TorrentStats::TorrentFlagged => {
                self.send_error(&client_addr, &packet.header, "torrent flagged.").await;
            }
            tracker::TorrentStats::TorrentNotRegistered => {
                self.send_error(&client_addr, &packet.header, "torrent not registered.").await;
            }
        }
    }

    async fn handle_scrape(&self, remote_addr: &SocketAddr, header: &UDPRequestHeader, payload: &[u8]) {
        if header.connection_id != self.get_connection_id(remote_addr) {
            return;
        }

        const MAX_SCRAPE: usize = 74;

        let mut response_buffer = [0u8; 8 + MAX_SCRAPE * 12];
        let mut response = StackVec::from(&mut response_buffer);

        if pack_into(&mut response, &UDPResponseHeader {
            action: Actions::Scrape,
            transaction_id: header.transaction_id,
        })
        .is_err()
        {
            // not much we can do...
            error!("failed to encode udp scrape response header.");
            return;
        }

        // skip first 16 bytes for header...
        let info_hash_array = &payload[16..];

        if info_hash_array.len() % 20 != 0 {
            trace!("received weird length for scrape info_hash array (!mod20).");
        }

        {
            let db = self.tracker.get_database().await;

            for torrent_index in 0..MAX_SCRAPE {
                let info_hash_start = torrent_index * 20;
                let info_hash_end = (torrent_index + 1) * 20;

                if info_hash_end > info_hash_array.len() {
                    break;
                }

                let info_hash = &info_hash_array[info_hash_start..info_hash_end];
                let ih = tracker::InfoHash::from(info_hash);
                let result = match db.get(&ih) {
                    Some(torrent_info) => {
                        let (seeders, completed, leechers) = torrent_info.get_stats();

                        UDPScrapeResponseEntry {
                            seeders,
                            completed,
                            leechers,
                        }
                    }
                    None => {
                        UDPScrapeResponseEntry {
                            seeders: 0,
                            completed: 0,
                            leechers: 0,
                        }
                    }
                };

                if pack_into(&mut response, &result).is_err() {
                    debug!("failed to encode scrape entry.");
                    return;
                }
            }
        }

        // if sending fails, not much we can do...
        let _ = self.send_packet(remote_addr, response.as_slice()).await;
    }

    fn get_connection_id(&self, remote_address: &SocketAddr) -> u64 {
        match std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH) {
            Ok(duration) => (duration.as_secs() / 3600) | ((remote_address.port() as u64) << 36),
            Err(_) => 0x8000000000000000,
        }
    }

    async fn send_packet(&self, remote_addr: &SocketAddr, payload: &[u8]) -> Result<usize, std::io::Error> {
        match self.srv.send_to(payload, remote_addr).await {
            Err(err) => {
                debug!("failed to send a packet: {}", err);
                Err(err)
            },
            Ok(sz) => Ok(sz),
        }
    }

    async fn send_error(&self, remote_addr: &SocketAddr, header: &UDPRequestHeader, error_msg: &str) {
        let mut payload_buffer = vec![0u8; MAX_PACKET_SIZE];
        let mut payload = StackVec::from(&mut payload_buffer);

        if pack_into(&mut payload, &UDPResponseHeader {
            transaction_id: header.transaction_id,
            action: Actions::Error,
        }).is_ok() {
            let msg_bytes = Vec::from(error_msg.as_bytes());
            payload.extend(msg_bytes);

            let _ = self.send_packet(remote_addr, payload.as_slice()).await;
        }
    }

    pub async fn accept_packets(self) -> Result<(), std::io::Error> {
        let tracker = Arc::new(self);

        loop {
            let mut packet = vec![0u8; MAX_PACKET_SIZE];
            let (size, remote_address) = tracker.srv.recv_from(packet.as_mut_slice()).await?;

            let tracker = tracker.clone();
            tokio::spawn(async move {
                debug!("Received {} bytes from {}", size, remote_address);
                tracker.handle_packet(&remote_address, &packet[..size]).await;
            });
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn pack() {
        let mystruct = super::UDPRequestHeader {
            connection_id: 200,
            action: super::Actions::Connect,
            transaction_id: 77771,
        };
        let mut buffer = [0u8; MAX_PACKET_SIZE];
        let mut payload = StackVec::from(&mut buffer);

        assert!(pack_into(&mut payload, &mystruct).is_ok());
        assert_eq!(payload.as_slice().len(), 16);
        assert_eq!(payload.as_slice(), &[0, 0, 0, 0, 0, 0, 0, 200u8, 0, 0, 0, 0, 0, 1, 47, 203]);
    }

    #[test]
    fn unpack() {
        let buf = [0u8, 0, 0, 0, 0, 0, 0, 200, 0, 0, 0, 1, 0, 1, 47, 203];
        match super::unpack(&buf) {
            Some(obj) => {
                let x: super::UDPResponseHeader = obj;
                println!("conn_id={}", x.action as u32);
            }
            None => {
                unreachable!();
            }
        }
    }
}
<commit_msg>fix issue #114<commit_after>use log::{debug, error, trace};
use std::io::Write;
use std::net::SocketAddr;
use std::sync::Arc;
use tokio::net::UdpSocket;

use serde::{Deserialize, Serialize};

use crate::config::Configuration;
use crate::stackvec::StackVec;
use crate::tracker;
use bincode::Options;

// maximum MTU is usually 1500, but our stack allows us to allocate the maximum - so why not?
const MAX_PACKET_SIZE: usize = 0xffff;

// protocol contants
const PROTOCOL_ID: u64 = 0x0000041727101980;

#[repr(u32)]
#[derive(Serialize, Deserialize)]
enum Actions {
    Connect = 0,
    Announce = 1,
    Scrape = 2,
    Error = 3,
}

#[repr(u32)]
#[derive(Serialize, Deserialize, Clone, Copy)]
pub enum Events {
    None = 0,
    Complete = 1,
    Started = 2,
    Stopped = 3,
}

fn bincode_config() -> impl bincode::Options {
    bincode::options()
        .with_big_endian()
        .with_fixint_encoding()
        .allow_trailing_bytes()
}

fn pack_into<T: Serialize, W: std::io::Write>(w: &mut W, data: &T) -> Result<(), ()> {
    let config = bincode_config();

    match config.serialize_into(w, data) {
        Ok(_) => Ok(()),
        Err(_) => Err(()),
    }
}

fn unpack<'a, T: Deserialize<'a>>(data: &'a [u8]) -> Option<T> {
    let config = bincode_config();

    match config.deserialize(data) {
        Ok(obj) => Some(obj),
        Err(_) => None,
    }
}

#[derive(Serialize, Deserialize)]
struct UDPRequestHeader {
    connection_id: u64,
    action: Actions,
    transaction_id: u32,
}

#[derive(Serialize, Deserialize)]
struct UDPResponseHeader {
    action: Actions,
    transaction_id: u32,
}

#[derive(Serialize, Deserialize)]
struct UDPConnectionResponse {
    header: UDPResponseHeader,
    connection_id: u64,
}

#[derive(Serialize, Deserialize)]
struct UDPAnnounceRequest {
    header: UDPRequestHeader,

    info_hash: [u8; 20],
    peer_id: [u8; 20],
    downloaded: u64,
    left: u64,
    uploaded: u64,
    event: Events,
    ip_address: u32,
    key: u32,
    num_want: i32,
    port: u16,
}

#[derive(Serialize, Deserialize)]
struct UDPAnnounceResponse {
    header: UDPResponseHeader,

    interval: u32,
    leechers: u32,
    seeders: u32,
}

#[derive(Serialize)]
struct UDPScrapeResponseEntry {
    seeders: u32,
    completed: u32,
    leechers: u32,
}

pub struct UDPTracker {
    srv: tokio::net::UdpSocket,
    tracker: std::sync::Arc<tracker::TorrentTracker>,
    config: Arc<Configuration>,
}

impl UDPTracker {
    pub async fn new(
        config: Arc<Configuration>, tracker: std::sync::Arc<tracker::TorrentTracker>,
    ) -> Result<UDPTracker, std::io::Error> {
        let cfg = config.clone();

        let srv = UdpSocket::bind(cfg.get_udp_config().get_address()).await?;

        Ok(UDPTracker {
            srv,
            tracker,
            config: cfg,
        })
    }

    async fn handle_packet(&self, remote_address: &SocketAddr, payload: &[u8]) {
        let header: UDPRequestHeader = match unpack(payload) {
            Some(val) => val,
            None => {
                trace!("failed to parse packet from {}", remote_address);
                return;
            }
        };

        match header.action {
            Actions::Connect => self.handle_connect(remote_address, &header, payload).await,
            Actions::Announce => self.handle_announce(remote_address, &header, payload).await,
            Actions::Scrape => self.handle_scrape(remote_address, &header, payload).await,
            _ => {
                trace!("invalid action from {}", remote_address);
                // someone is playing around... ignore request.
            }
        }
    }

    async fn handle_connect(&self, remote_addr: &SocketAddr, header: &UDPRequestHeader, _payload: &[u8]) {
        if header.connection_id != PROTOCOL_ID {
            trace!("Bad protocol magic from {}", remote_addr);
            return;
        }

        // send response...
        let conn_id = self.get_connection_id(remote_addr);

        let response = UDPConnectionResponse {
            header: UDPResponseHeader {
                transaction_id: header.transaction_id,
                action: Actions::Connect,
            },
            connection_id: conn_id,
        };

        let mut payload_buffer = vec![0u8; MAX_PACKET_SIZE];
        let mut payload = StackVec::from(payload_buffer.as_mut_slice());

        if pack_into(&mut payload, &response).is_ok() {
            let _ = self.send_packet(remote_addr, payload.as_slice()).await;
        }
    }

    async fn handle_announce(&self, remote_addr: &SocketAddr, header: &UDPRequestHeader, payload: &[u8]) {
        if header.connection_id != self.get_connection_id(remote_addr) {
            return;
        }

        let packet: UDPAnnounceRequest = match unpack(payload) {
            Some(v) => v,
            None => {
                trace!("failed to unpack announce request from {}", remote_addr);
                return;
            }
        };

        if let Ok(_plen) = bincode::serialized_size(&packet) {
            let plen = _plen as usize;
            if payload.len() > plen {
                let bep41_payload = &payload[plen..];

                // TODO: process BEP0041 payload.
                trace!("BEP0041 payload of {} bytes from {}", bep41_payload.len(), remote_addr);
            }
        }

        if packet.ip_address != 0 {
            // TODO: allow configurability of ip address
            // for now, ignore request.
            trace!("announce request for other IP ignored. (from {})", remote_addr);
            return;
        }

        let client_addr = SocketAddr::new(remote_addr.ip(), packet.port);
        let info_hash = packet.info_hash.into();

        let peer_id: &tracker::PeerId = tracker::PeerId::from_array(&packet.peer_id);

        match self
            .tracker
            .update_torrent_and_get_stats(
                &info_hash,
                peer_id,
                &client_addr,
                packet.uploaded,
                packet.downloaded,
                packet.left,
                packet.event,
            )
            .await
        {
            tracker::TorrentStats::Stats {
                leechers,
                complete: _,
                seeders,
            } => {
                let peers = match self.tracker.get_torrent_peers(&info_hash, &client_addr).await {
                    Some(v) => v,
                    None => {
                        return;
                    }
                };

                let mut payload_buffer = vec![0u8; MAX_PACKET_SIZE];
                let mut payload = StackVec::from(&mut payload_buffer);

                match pack_into(&mut payload, &UDPAnnounceResponse {
                    header: UDPResponseHeader {
                        action: Actions::Announce,
                        transaction_id: packet.header.transaction_id,
                    },
                    seeders,
                    interval: self.config.get_udp_config().get_announce_interval(),
                    leechers,
                }) {
                    Ok(_) => {}
                    Err(_) => {
                        return;
                    }
                };

                for peer in peers {
                    match peer {
                        SocketAddr::V4(ipv4) => {
                            let _ = payload.write(&ipv4.ip().octets());
                        }
                        SocketAddr::V6(ipv6) => {
                            let _ = payload.write(&ipv6.ip().octets());
                        }
                    };

                    let port_hton = client_addr.port().to_be();
                    let _ = payload.write(&[(port_hton & 0xff) as u8, ((port_hton >> 8) & 0xff) as u8]);
                }

                let _ = self.send_packet(&client_addr, payload.as_slice()).await;
            }
            tracker::TorrentStats::TorrentFlagged => {
                self.send_error(&client_addr, &packet.header, "torrent flagged.").await;
            }
            tracker::TorrentStats::TorrentNotRegistered => {
                self.send_error(&client_addr, &packet.header, "torrent not registered.").await;
            }
        }
    }

    async fn handle_scrape(&self, remote_addr: &SocketAddr, header: &UDPRequestHeader, payload: &[u8]) {
        if header.connection_id != self.get_connection_id(remote_addr) {
            return;
        }

        const MAX_SCRAPE: usize = 74;

        let mut response_buffer = [0u8; 8 + MAX_SCRAPE * 12];
        let mut response = StackVec::from(&mut response_buffer);

        if pack_into(&mut response, &UDPResponseHeader {
            action: Actions::Scrape,
            transaction_id: header.transaction_id,
        })
        .is_err()
        {
            // not much we can do...
            error!("failed to encode udp scrape response header.");
            return;
        }

        // skip first 16 bytes for header...
        let info_hash_array = &payload[16..];

        if info_hash_array.len() % 20 != 0 {
            trace!("received weird length for scrape info_hash array (!mod20).");
        }

        {
            let db = self.tracker.get_database().await;

            for torrent_index in 0..MAX_SCRAPE {
                let info_hash_start = torrent_index * 20;
                let info_hash_end = (torrent_index + 1) * 20;

                if info_hash_end > info_hash_array.len() {
                    break;
                }

                let info_hash = &info_hash_array[info_hash_start..info_hash_end];
                let ih = tracker::InfoHash::from(info_hash);
                let result = match db.get(&ih) {
                    Some(torrent_info) => {
                        let (seeders, completed, leechers) = torrent_info.get_stats();

                        UDPScrapeResponseEntry {
                            seeders,
                            completed,
                            leechers,
                        }
                    }
                    None => {
                        UDPScrapeResponseEntry {
                            seeders: 0,
                            completed: 0,
                            leechers: 0,
                        }
                    }
                };

                if pack_into(&mut response, &result).is_err() {
                    debug!("failed to encode scrape entry.");
                    return;
                }
            }
        }

        // if sending fails, not much we can do...
        let _ = self.send_packet(remote_addr, response.as_slice()).await;
    }

    fn get_connection_id(&self, remote_address: &SocketAddr) -> u64 {
        match std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH) {
            Ok(duration) => (duration.as_secs() / 3600) | ((remote_address.port() as u64) << 36),
            Err(_) => 0x8000000000000000,
        }
    }

    async fn send_packet(&self, remote_addr: &SocketAddr, payload: &[u8]) -> Result<usize, std::io::Error> {
        match self.srv.send_to(payload, remote_addr).await {
            Err(err) => {
                debug!("failed to send a packet: {}", err);
                Err(err)
            },
            Ok(sz) => Ok(sz),
        }
    }

    async fn send_error(&self, remote_addr: &SocketAddr, header: &UDPRequestHeader, error_msg: &str) {
        let mut payload_buffer = vec![0u8; MAX_PACKET_SIZE];
        let mut payload = StackVec::from(&mut payload_buffer);

        if pack_into(&mut payload, &UDPResponseHeader {
            transaction_id: header.transaction_id,
            action: Actions::Error,
        }).is_ok() {
            let msg_bytes = Vec::from(error_msg.as_bytes());
            payload.extend(msg_bytes);

            let _ = self.send_packet(remote_addr, payload.as_slice()).await;
        }
    }

    pub async fn accept_packets(self) -> Result<(), std::io::Error> {
        let tracker = Arc::new(self);

        loop {
            let mut packet = vec![0u8; MAX_PACKET_SIZE];
            let (size, remote_address) = tracker.srv.recv_from(packet.as_mut_slice()).await?;

            let tracker = tracker.clone();
            tokio::spawn(async move {
                debug!("Received {} bytes from {}", size, remote_address);
                tracker.handle_packet(&remote_address, &packet[..size]).await;
            });
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn pack() {
        let mystruct = super::UDPRequestHeader {
            connection_id: 0xc0c1c2c3c4c5c6c7,
            action: super::Actions::Connect,
            transaction_id: 77771,
        };
        let mut buffer = [0u8; MAX_PACKET_SIZE];
        let mut payload = StackVec::from(&mut buffer);

        assert!(pack_into(&mut payload, &mystruct).is_ok());
        assert_eq!(payload.as_slice().len(), 16);
        assert_eq!(payload.as_slice(), &[0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0, 0, 0, 0, 0, 1, 47, 203]);
    }

    #[test]
    fn unpack() {
        let buf = [0xc0u8, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0, 0, 0, 1, 0, 1, 47, 203];
        match super::unpack(&buf) {
            Some(obj) => {
                let x: super::UDPRequestHeader = obj;
                assert_eq!(x.connection_id, 0xc0c1c2c3c4c5c6c7);
            }
            None => {
                unreachable!();
            }
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Implement PredDouble for type int<commit_after><|endoftext|>


<commit_before><commit_msg>Switch TestUser to always use static lifetime for &str.<commit_after><|endoftext|>


<commit_before>//! Window abstraction

use std::cell::RefCell;
use input::InputEvent;
use current::{ Get, Modifier, Set, Usage };

use GenericEvent;

/// Whether window should close or not.
pub struct ShouldClose(pub bool);

/// Work-around trait for `Get<ShouldClose>`.
/// Used to support generic constraints.
pub trait GetShouldClose: Get<ShouldClose> {
    /// Returns whether window should close.
    fn get_should_close(&self) -> ShouldClose {
        self.get()
    }
}

impl<T: Get<ShouldClose>> GetShouldClose for T {}

/// Work-around trait for `Set<ShouldClose>`.
/// Used to support generic constraints.
/// This must be implemented for every `Modifier` impl.
pub trait SetShouldClose: Set<ShouldClose> {
    /// Sets whether window should close.
    fn set_should_close(&mut self, val: ShouldClose);
}

/// The size of the window.
pub struct Size(pub [u32, ..2]);

/// Work-around trait for `Get<Size>`.
/// Used to support generic constraints.
pub trait GetSize: Get<Size> {
    /// Returns the size of window.
    fn get_size(&self) -> Size {
        self.get()
    }
}

impl<T: Get<Size>> GetSize for T {}

/// Work-around trait for `Set<Size>`.
/// Used to support generic constraints.
/// This must be implemented for every `Modifier` impl.
pub trait SetSize: Set<Size> {
    /// Sets size of window.
    fn set_size(&mut self, val: Size);
}

/// The title of the window.
pub struct Title(pub String);

/// Work-around trait for `Get<Title>`.
/// Used to support generic constraints.
pub trait GetTitle: Get<Title> {
    /// Returns the title of the window.
    fn get_title(&self) -> Title {
        self.get()
    }
}

impl<T: Get<Title>> GetTitle for T {}

/// Work-around trait for `Set<Title>`.
/// Used to support generic constraints.
/// This must be implemented for every `Modifier` impl.
pub trait SetTitle: Set<Title> {
    /// Sets title of window.
    fn set_title(&mut self, val: Title);
}

/// The anti-aliasing samples when rendering.
pub struct Samples(pub u8);

/// Work-around trait for `Get<Samples>`.
/// Used to support generic constraints.
pub trait GetSamples: Get<Samples> {
    /// Returns the antialiasing samples when rendering.
    fn get_samples(&self) -> Samples {
        self.get()
    }
}

impl<T: Get<Samples>> GetSamples for T {}

/// Work-around trait for `Set<Samples>`.
/// Used to support generic constraints.
/// This must be implemented for every `Modifier` impl.
pub trait SetSamples: Set<Samples> {
    /// Sets antialiasing samples of window.
    fn set_samples(&mut self, val: Samples);
}

/// Whether window is opened in full screen mode.
pub struct Fullscreen(pub bool);

/// Work-around trait for `Get<Fullscreen>`.
/// Used to support generic constraints.
pub trait GetFullscreen: Get<Fullscreen> {
    /// Returns whether window is in full screen mode.
    fn get_fullscreen(&self) -> Fullscreen {
        self.get()
    }
}

impl<T: Get<Fullscreen>> GetFullscreen for T {}

/// Work-around trait for `Set<Fullscreen>`.
/// Used to support generic constraints.
/// This must be implemented for every `Modifier` impl.
pub trait SetFullscreen: Set<Fullscreen> {
    /// Sets window to fullscreen mode.
    fn set_fullscreen(&mut self, val: Fullscreen);
}

/// Whether to exit when pressing the Esc keyboard button.
pub struct ExitOnEsc(pub bool);

/// Work-around trait for `Get<ExitOnEsc>`.
/// Used to support generic constraints.
pub trait GetExitOnEsc: Get<ExitOnEsc> {
    /// Returns whether window exits when pressing Esc.
    fn get_exit_on_esc(&self) -> ExitOnEsc {
        self.get()
    }
}

impl<T: Get<ExitOnEsc>> GetExitOnEsc for T {}

/// Work-around trait for `Set<ExitOnEsc>`.
/// Used to support generic constraints.
/// This must be implemented for every `Modifier` impl.
pub trait SetExitOnEsc: Set<ExitOnEsc> {
    /// Sets exit when pressing Esc.
    fn set_exit_on_esc(&mut self, val: ExitOnEsc);
}

/// Whether to capture the mouse cursor.
pub struct CaptureCursor(pub bool);

/// Work-around trait for `Get<CaptureCursor>`.
/// Used to support generic constraints.
pub trait GetCaptureCursor: Get<CaptureCursor> {
    /// Returns whether window captures cursor.
    fn get_capture_cursor(&self) -> CaptureCursor {
        self.get()
    }
}

impl<T: Get<CaptureCursor>> GetCaptureCursor for T {}

/// Work-around trait for `Set<CaptureCursor>`.
/// Used to support generic constraints.
/// This must be implemented for every `Modifier` impl.
pub trait SetCaptureCursor: Set<CaptureCursor> {
    /// Sets capture cursor.
    fn set_capture_cursor(&mut self, val: CaptureCursor);
}

/// The draw size of the window.
pub struct DrawSize(pub [u32, ..2]);

/// Work-around trait for `Get<DrawSize>`.
/// Used to support generic constraints.
pub trait GetDrawSize: Get<DrawSize> {
    /// Returns the draw size of window.
    fn get_draw_size(&self) -> DrawSize {
        self.get()
    }
}

impl<T: Get<DrawSize>> GetDrawSize for T {}

/// Work-around trait for `Set<DrawSize>`.
/// Used to support generic constraints.
/// This must be implemented for every `Modifier` impl.
pub trait SetDrawSize: Set<DrawSize> {
    /// Sets draw size.
    fn set_draw_size(&mut self, val: DrawSize);
}

#[test]
fn test_methods() {
    use current::Modifier;

    struct Obj;

    impl Get<ShouldClose> for Obj {
        fn get(&self) -> ShouldClose { ShouldClose(false) }
    }

    impl Modifier<Obj> for ShouldClose {
        fn modify(self, _obj: &mut Obj) {}
    }

    impl SetShouldClose for Obj {
        fn set_should_close(&mut self, val: ShouldClose) {
            self.set_mut(val);
        }
    }

    impl Get<Size> for Obj {
        fn get(&self) -> Size { Size([0, 0]) }
    }

    impl Modifier<Obj> for Size {
        fn modify(self, _obj: &mut Obj) {}
    }

    impl SetSize for Obj {
        fn set_size(&mut self, val: Size) {
            self.set_mut(val);
        }
    }

    impl Get<Title> for Obj {
        fn get(&self) -> Title { Title("hello".to_string()) }
    }

    impl Modifier<Obj> for Title {
        fn modify(self, _obj: &mut Obj) {}
    }

    impl SetTitle for Obj {
        fn set_title(&mut self, val: Title) {
            self.set_mut(val);
        }
    }

    impl Get<Samples> for Obj {
        fn get(&self) -> Samples { Samples(0) }
    }

    impl Modifier<Obj> for Samples {
        fn modify(self, _obj: &mut Obj) {}
    }

    impl SetSamples for Obj {
        fn set_samples(&mut self, val: Samples) {
            self.set_mut(val);
        }
    }

    impl Get<Fullscreen> for Obj {
        fn get(&self) -> Fullscreen { Fullscreen(false) }
    }

    impl Modifier<Obj> for Fullscreen {
        fn modify(self, _obj: &mut Obj) {}
    }

    impl SetFullscreen for Obj {
        fn set_fullscreen(&mut self, val: Fullscreen) {
            self.set_mut(val);
        }
    }

    impl Get<ExitOnEsc> for Obj {
        fn get(&self) -> ExitOnEsc { ExitOnEsc(true) }
    }

    impl Modifier<Obj> for ExitOnEsc {
        fn modify(self, _obj: &mut Obj) {}
    }

    impl SetExitOnEsc for Obj {
        fn set_exit_on_esc(&mut self, val: ExitOnEsc) {
            self.set_mut(val);
        }
    }

    impl Get<CaptureCursor> for Obj {
        fn get(&self) -> CaptureCursor { CaptureCursor(false) }
    }

    impl Modifier<Obj> for CaptureCursor {
        fn modify(self, _obj: &mut Obj) {}
    }

    impl SetCaptureCursor for Obj {
        fn set_capture_cursor(&mut self, val: CaptureCursor) {
            self.set_mut(val);
        }
    }

    impl Get<DrawSize> for Obj {
        fn get(&self) -> DrawSize { DrawSize([0, 0]) }
    }

    impl Modifier<Obj> for DrawSize {
        fn modify(self, _obj: &mut Obj) {}
    }

    impl SetDrawSize for Obj {
        fn set_draw_size(&mut self, val: DrawSize) {
            self.set_mut(val);
        }
    }

    fn foo<T: GetShouldClose + SetShouldClose
            + GetSize + SetSize
            + GetTitle + SetTitle
            + GetSamples + SetSamples
            + GetFullscreen + SetFullscreen
            + GetExitOnEsc + SetExitOnEsc
            + GetCaptureCursor + SetCaptureCursor
            + GetDrawSize + SetDrawSize>(_obj: T) {}

    foo(Obj);
}

/// Implemented by windows that can swap buffers.
pub trait SwapBuffers {
    /// Swaps the buffers.
    fn swap_buffers(&mut self);
}

impl<'a, W: 'a + SwapBuffers> SwapBuffers for Usage<'a, W> {
    #[inline(always)]
    fn swap_buffers(&mut self) {
        self.with_unwrap(|window: &RefCell<W>| {
            window.borrow_mut().deref_mut().swap_buffers()
        })
    }
}

impl<'a, W: 'a + SwapBuffers> SwapBuffers for &'a RefCell<W> {
    #[inline(always)]
    fn swap_buffers(&mut self) {
        self.borrow_mut().deref_mut().swap_buffers()
    }
}

/// Implemented by windows that can pull events.
pub trait PollEvent<E: GenericEvent> {
    /// Polls event from window.
    fn poll_event(&mut self) -> Option<E>;
}

impl<'a, W: 'a + PollEvent<I>, I: GenericEvent> PollEvent<I> for Usage<'a, W> {
    #[inline(always)]
    fn poll_event(&mut self) -> Option<I> {
        self.with_unwrap(|window: &RefCell<W>| {
            window.borrow_mut().deref_mut().poll_event()
        })
    }
}

impl<'a, W: 'a + PollEvent<I>, I: GenericEvent> PollEvent<I> for &'a RefCell<W> {
    #[inline(always)]
    fn poll_event(&mut self) -> Option<I> {
        self.borrow_mut().deref_mut().poll_event()
    }
}

/// Settings for window behavior.
pub struct WindowSettings {
    /// Title of the window.
    pub title: String,
    /// The size of the window.
    pub size: [u32, ..2],
    /// Number samples per pixel (anti-aliasing).
    pub samples: u8,
    /// If true, the window is fullscreen.
    pub fullscreen: bool,
    /// If true, exit when pressing Esc.
    pub exit_on_esc: bool,
}

impl WindowSettings {
    /// Gets default settings.
    ///
    /// This exits the window when pressing `Esc`.
    /// The background color is set to black.
    pub fn default() -> WindowSettings {
        WindowSettings {
            title: "Piston".to_string(),
            size: [640, 480],
            samples: 0,
            fullscreen: false,
            exit_on_esc: true,
        }
    }
}

/// Implemented by window back-end.
pub trait Window<E: GenericEvent = InputEvent>:
    SwapBuffers
  + PollEvent<E>
  + GetShouldClose
  + GetSize
  + SetCaptureCursor {
    /// Get the window's settings.
    fn get_settings<'a>(&'a self) -> &'a WindowSettings;

    /// Inform the window that it should close.
    fn close(&mut self);

    /// Get the size in drawing coordinates.
    fn get_draw_size(&self) -> (u32, u32);
}

/// An implementation of Window that runs without a window at all.
pub struct NoWindow {
    settings: WindowSettings,
    should_close: bool
}

impl NoWindow {
    /// Returns a new `NoWindow`.
    pub fn new(settings: WindowSettings) -> NoWindow {
         NoWindow {
             settings: settings,
             should_close: false
         }
    }
}

impl SwapBuffers for NoWindow {
    fn swap_buffers(&mut self) {}
}

impl PollEvent<InputEvent> for NoWindow {
    fn poll_event(&mut self) -> Option<InputEvent> { None }
}

impl Get<ShouldClose> for NoWindow {
    fn get(&self) -> ShouldClose {
        ShouldClose(self.should_close)
    }
}

impl Get<Size> for NoWindow {
    fn get(&self) -> Size {
        Size([0, 0])
    }
}

impl Modifier<NoWindow> for CaptureCursor {
    fn modify(self, _window: &mut NoWindow) {}
}

impl SetCaptureCursor for NoWindow {
    fn set_capture_cursor(&mut self, val: CaptureCursor) {
        self.set_mut(val);
    }
}

impl Window<InputEvent> for NoWindow {
     fn get_settings<'a>(&'a self) -> &'a WindowSettings {
        &self.settings
     }

    fn close(&mut self) {
        self.should_close = true
    }

    fn get_draw_size(&self) -> (u32, u32) {
        let Size([w, h]) = self.get_size();
        (w, h)
    }
}

<commit_msg>Replaced `close` on Window trait with `Set<ShouldClose>`<commit_after>//! Window abstraction

use std::cell::RefCell;
use input::InputEvent;
use current::{ Get, Modifier, Set, Usage };

use GenericEvent;

/// Whether window should close or not.
pub struct ShouldClose(pub bool);

/// Work-around trait for `Get<ShouldClose>`.
/// Used to support generic constraints.
pub trait GetShouldClose: Get<ShouldClose> {
    /// Returns whether window should close.
    fn get_should_close(&self) -> ShouldClose {
        self.get()
    }
}

impl<T: Get<ShouldClose>> GetShouldClose for T {}

/// Work-around trait for `Set<ShouldClose>`.
/// Used to support generic constraints.
/// This must be implemented for every `Modifier` impl.
pub trait SetShouldClose: Set<ShouldClose> {
    /// Sets whether window should close.
    fn set_should_close(&mut self, val: ShouldClose);
}

/// The size of the window.
pub struct Size(pub [u32, ..2]);

/// Work-around trait for `Get<Size>`.
/// Used to support generic constraints.
pub trait GetSize: Get<Size> {
    /// Returns the size of window.
    fn get_size(&self) -> Size {
        self.get()
    }
}

impl<T: Get<Size>> GetSize for T {}

/// Work-around trait for `Set<Size>`.
/// Used to support generic constraints.
/// This must be implemented for every `Modifier` impl.
pub trait SetSize: Set<Size> {
    /// Sets size of window.
    fn set_size(&mut self, val: Size);
}

/// The title of the window.
pub struct Title(pub String);

/// Work-around trait for `Get<Title>`.
/// Used to support generic constraints.
pub trait GetTitle: Get<Title> {
    /// Returns the title of the window.
    fn get_title(&self) -> Title {
        self.get()
    }
}

impl<T: Get<Title>> GetTitle for T {}

/// Work-around trait for `Set<Title>`.
/// Used to support generic constraints.
/// This must be implemented for every `Modifier` impl.
pub trait SetTitle: Set<Title> {
    /// Sets title of window.
    fn set_title(&mut self, val: Title);
}

/// The anti-aliasing samples when rendering.
pub struct Samples(pub u8);

/// Work-around trait for `Get<Samples>`.
/// Used to support generic constraints.
pub trait GetSamples: Get<Samples> {
    /// Returns the antialiasing samples when rendering.
    fn get_samples(&self) -> Samples {
        self.get()
    }
}

impl<T: Get<Samples>> GetSamples for T {}

/// Work-around trait for `Set<Samples>`.
/// Used to support generic constraints.
/// This must be implemented for every `Modifier` impl.
pub trait SetSamples: Set<Samples> {
    /// Sets antialiasing samples of window.
    fn set_samples(&mut self, val: Samples);
}

/// Whether window is opened in full screen mode.
pub struct Fullscreen(pub bool);

/// Work-around trait for `Get<Fullscreen>`.
/// Used to support generic constraints.
pub trait GetFullscreen: Get<Fullscreen> {
    /// Returns whether window is in full screen mode.
    fn get_fullscreen(&self) -> Fullscreen {
        self.get()
    }
}

impl<T: Get<Fullscreen>> GetFullscreen for T {}

/// Work-around trait for `Set<Fullscreen>`.
/// Used to support generic constraints.
/// This must be implemented for every `Modifier` impl.
pub trait SetFullscreen: Set<Fullscreen> {
    /// Sets window to fullscreen mode.
    fn set_fullscreen(&mut self, val: Fullscreen);
}

/// Whether to exit when pressing the Esc keyboard button.
pub struct ExitOnEsc(pub bool);

/// Work-around trait for `Get<ExitOnEsc>`.
/// Used to support generic constraints.
pub trait GetExitOnEsc: Get<ExitOnEsc> {
    /// Returns whether window exits when pressing Esc.
    fn get_exit_on_esc(&self) -> ExitOnEsc {
        self.get()
    }
}

impl<T: Get<ExitOnEsc>> GetExitOnEsc for T {}

/// Work-around trait for `Set<ExitOnEsc>`.
/// Used to support generic constraints.
/// This must be implemented for every `Modifier` impl.
pub trait SetExitOnEsc: Set<ExitOnEsc> {
    /// Sets exit when pressing Esc.
    fn set_exit_on_esc(&mut self, val: ExitOnEsc);
}

/// Whether to capture the mouse cursor.
pub struct CaptureCursor(pub bool);

/// Work-around trait for `Get<CaptureCursor>`.
/// Used to support generic constraints.
pub trait GetCaptureCursor: Get<CaptureCursor> {
    /// Returns whether window captures cursor.
    fn get_capture_cursor(&self) -> CaptureCursor {
        self.get()
    }
}

impl<T: Get<CaptureCursor>> GetCaptureCursor for T {}

/// Work-around trait for `Set<CaptureCursor>`.
/// Used to support generic constraints.
/// This must be implemented for every `Modifier` impl.
pub trait SetCaptureCursor: Set<CaptureCursor> {
    /// Sets capture cursor.
    fn set_capture_cursor(&mut self, val: CaptureCursor);
}

/// The draw size of the window.
pub struct DrawSize(pub [u32, ..2]);

/// Work-around trait for `Get<DrawSize>`.
/// Used to support generic constraints.
pub trait GetDrawSize: Get<DrawSize> {
    /// Returns the draw size of window.
    fn get_draw_size(&self) -> DrawSize {
        self.get()
    }
}

impl<T: Get<DrawSize>> GetDrawSize for T {}

/// Work-around trait for `Set<DrawSize>`.
/// Used to support generic constraints.
/// This must be implemented for every `Modifier` impl.
pub trait SetDrawSize: Set<DrawSize> {
    /// Sets draw size.
    fn set_draw_size(&mut self, val: DrawSize);
}

#[test]
fn test_methods() {
    use current::Modifier;

    struct Obj;

    impl Get<ShouldClose> for Obj {
        fn get(&self) -> ShouldClose { ShouldClose(false) }
    }

    impl Modifier<Obj> for ShouldClose {
        fn modify(self, _obj: &mut Obj) {}
    }

    impl SetShouldClose for Obj {
        fn set_should_close(&mut self, val: ShouldClose) {
            self.set_mut(val);
        }
    }

    impl Get<Size> for Obj {
        fn get(&self) -> Size { Size([0, 0]) }
    }

    impl Modifier<Obj> for Size {
        fn modify(self, _obj: &mut Obj) {}
    }

    impl SetSize for Obj {
        fn set_size(&mut self, val: Size) {
            self.set_mut(val);
        }
    }

    impl Get<Title> for Obj {
        fn get(&self) -> Title { Title("hello".to_string()) }
    }

    impl Modifier<Obj> for Title {
        fn modify(self, _obj: &mut Obj) {}
    }

    impl SetTitle for Obj {
        fn set_title(&mut self, val: Title) {
            self.set_mut(val);
        }
    }

    impl Get<Samples> for Obj {
        fn get(&self) -> Samples { Samples(0) }
    }

    impl Modifier<Obj> for Samples {
        fn modify(self, _obj: &mut Obj) {}
    }

    impl SetSamples for Obj {
        fn set_samples(&mut self, val: Samples) {
            self.set_mut(val);
        }
    }

    impl Get<Fullscreen> for Obj {
        fn get(&self) -> Fullscreen { Fullscreen(false) }
    }

    impl Modifier<Obj> for Fullscreen {
        fn modify(self, _obj: &mut Obj) {}
    }

    impl SetFullscreen for Obj {
        fn set_fullscreen(&mut self, val: Fullscreen) {
            self.set_mut(val);
        }
    }

    impl Get<ExitOnEsc> for Obj {
        fn get(&self) -> ExitOnEsc { ExitOnEsc(true) }
    }

    impl Modifier<Obj> for ExitOnEsc {
        fn modify(self, _obj: &mut Obj) {}
    }

    impl SetExitOnEsc for Obj {
        fn set_exit_on_esc(&mut self, val: ExitOnEsc) {
            self.set_mut(val);
        }
    }

    impl Get<CaptureCursor> for Obj {
        fn get(&self) -> CaptureCursor { CaptureCursor(false) }
    }

    impl Modifier<Obj> for CaptureCursor {
        fn modify(self, _obj: &mut Obj) {}
    }

    impl SetCaptureCursor for Obj {
        fn set_capture_cursor(&mut self, val: CaptureCursor) {
            self.set_mut(val);
        }
    }

    impl Get<DrawSize> for Obj {
        fn get(&self) -> DrawSize { DrawSize([0, 0]) }
    }

    impl Modifier<Obj> for DrawSize {
        fn modify(self, _obj: &mut Obj) {}
    }

    impl SetDrawSize for Obj {
        fn set_draw_size(&mut self, val: DrawSize) {
            self.set_mut(val);
        }
    }

    fn foo<T: GetShouldClose + SetShouldClose
            + GetSize + SetSize
            + GetTitle + SetTitle
            + GetSamples + SetSamples
            + GetFullscreen + SetFullscreen
            + GetExitOnEsc + SetExitOnEsc
            + GetCaptureCursor + SetCaptureCursor
            + GetDrawSize + SetDrawSize>(_obj: T) {}

    foo(Obj);
}

/// Implemented by windows that can swap buffers.
pub trait SwapBuffers {
    /// Swaps the buffers.
    fn swap_buffers(&mut self);
}

impl<'a, W: 'a + SwapBuffers> SwapBuffers for Usage<'a, W> {
    #[inline(always)]
    fn swap_buffers(&mut self) {
        self.with_unwrap(|window: &RefCell<W>| {
            window.borrow_mut().deref_mut().swap_buffers()
        })
    }
}

impl<'a, W: 'a + SwapBuffers> SwapBuffers for &'a RefCell<W> {
    #[inline(always)]
    fn swap_buffers(&mut self) {
        self.borrow_mut().deref_mut().swap_buffers()
    }
}

/// Implemented by windows that can pull events.
pub trait PollEvent<E: GenericEvent> {
    /// Polls event from window.
    fn poll_event(&mut self) -> Option<E>;
}

impl<'a, W: 'a + PollEvent<I>, I: GenericEvent> PollEvent<I> for Usage<'a, W> {
    #[inline(always)]
    fn poll_event(&mut self) -> Option<I> {
        self.with_unwrap(|window: &RefCell<W>| {
            window.borrow_mut().deref_mut().poll_event()
        })
    }
}

impl<'a, W: 'a + PollEvent<I>, I: GenericEvent> PollEvent<I> for &'a RefCell<W> {
    #[inline(always)]
    fn poll_event(&mut self) -> Option<I> {
        self.borrow_mut().deref_mut().poll_event()
    }
}

/// Settings for window behavior.
pub struct WindowSettings {
    /// Title of the window.
    pub title: String,
    /// The size of the window.
    pub size: [u32, ..2],
    /// Number samples per pixel (anti-aliasing).
    pub samples: u8,
    /// If true, the window is fullscreen.
    pub fullscreen: bool,
    /// If true, exit when pressing Esc.
    pub exit_on_esc: bool,
}

impl WindowSettings {
    /// Gets default settings.
    ///
    /// This exits the window when pressing `Esc`.
    /// The background color is set to black.
    pub fn default() -> WindowSettings {
        WindowSettings {
            title: "Piston".to_string(),
            size: [640, 480],
            samples: 0,
            fullscreen: false,
            exit_on_esc: true,
        }
    }
}

/// Implemented by window back-end.
pub trait Window<E: GenericEvent = InputEvent>:
    SwapBuffers
  + PollEvent<E>
  + GetShouldClose
  + SetShouldClose
  + GetSize
  + SetCaptureCursor {
    /// Get the window's settings.
    fn get_settings<'a>(&'a self) -> &'a WindowSettings;

    /// Get the size in drawing coordinates.
    fn get_draw_size(&self) -> (u32, u32);
}

/// An implementation of Window that runs without a window at all.
pub struct NoWindow {
    settings: WindowSettings,
    should_close: bool
}

impl NoWindow {
    /// Returns a new `NoWindow`.
    pub fn new(settings: WindowSettings) -> NoWindow {
         NoWindow {
             settings: settings,
             should_close: false
         }
    }
}

impl SwapBuffers for NoWindow {
    fn swap_buffers(&mut self) {}
}

impl PollEvent<InputEvent> for NoWindow {
    fn poll_event(&mut self) -> Option<InputEvent> { None }
}

impl Get<ShouldClose> for NoWindow {
    fn get(&self) -> ShouldClose {
        ShouldClose(self.should_close)
    }
}

impl Get<Size> for NoWindow {
    fn get(&self) -> Size {
        Size([0, 0])
    }
}

impl Modifier<NoWindow> for CaptureCursor {
    fn modify(self, _window: &mut NoWindow) {}
}

impl SetCaptureCursor for NoWindow {
    fn set_capture_cursor(&mut self, val: CaptureCursor) {
        self.set_mut(val);
    }
}

impl Modifier<NoWindow> for ShouldClose {
    fn modify(self, window: &mut NoWindow) {
        let ShouldClose(val) = self;
        window.should_close = val;
    }
}

impl SetShouldClose for NoWindow {
    fn set_should_close(&mut self, val: ShouldClose) {
        self.set_mut(val);
    }
}

impl Window<InputEvent> for NoWindow {
     fn get_settings<'a>(&'a self) -> &'a WindowSettings {
        &self.settings
     }

    fn get_draw_size(&self) -> (u32, u32) {
        let Size([w, h]) = self.get_size();
        (w, h)
    }
}

<|endoftext|>


<commit_before><commit_msg>Drop MemWriter in favor of Vec<u8>.<commit_after><|endoftext|>


<commit_before><commit_msg>Add thread example<commit_after>extern crate fruently;
use fruently::fluent::Fluent;
use std::thread;
use std::collections::HashMap;
use fruently::forwardable::JsonForwardable;

fn main() {
    let fruently = Fluent::new("0.0.0.0:24224", "test");
    let mut obj: HashMap<String, String> = HashMap::new();
    obj.insert("name".to_string(), "fruently".to_string());
    let child = thread::spawn(move || {
            let _ = fruently.post(&obj);
    });
    child.join().unwrap();
}
<|endoftext|>