<commit_before>use {TypedDecider, DeciderImpl, MultiDeciderImpl, Decider, MultiDecider, Decision, Threadsafe,
     Result, ErrorKind};

use std::time::{Instant, Duration};
use std::cmp;

impl Decider for GCRA {}

/// This crate's GCRA implementation also allows checking multiple
/// cells at once, assuming that (counter the traffic-shaping
/// properties of GCRA) if a sufficiently long pause (`n*t`) has
/// occurred between cells, the algorithm can accomodate `n` cells.
///
/// As this assumption does not necessarily hold in all circumstances,
/// users of this trait on GCRA limiters should ensure that this is
/// ok.
impl MultiDecider for GCRA {}

impl TypedDecider for GCRA {
    /// In GCRA, negative decisions come with the time at which the
    /// next cell was expected to arrive; client code of GCRA can use
    /// this to decide what to do with the non-conforming cell.
    type T = Instant;
}

#[derive(Debug, Clone)]
/// Implements the virtual scheduling description of the Generic Cell
/// Rate Algorithm, attributed to ITU-T in recommendation I.371
/// Traffic control and congestion control in B-ISDN; from
/// [Wikipedia](https://en.wikipedia.org/wiki/Generic_cell_rate_algorithm).
///
///
/// While algorithms like leaky-bucket rate limiters allow cells to be
/// distributed across time in any way, GCRA is a rate-limiting *and*
/// traffic-shaping algorithm. It mandates that a minimum amount of
/// time passes between cells being measured. For example, if your API
/// mandates that only 20 requests can be made per second, GCRA will
/// ensure that each request is at least 50ms apart from the previous
/// request. This makes GCRA suitable for shaping traffic in
/// networking and telecom equipment (it was initially made for
/// asynchronous transfer mode networks), or for outgoing workloads on
/// *consumers* of attention, e.g. distributing outgoing emails across
/// a day.
///
/// In a blatant side-stepping of the above traffic-shaping criteria,
/// this implementation of GCRA comes with an extension that allows
/// measuring multiple cells at once, assuming that if a pause of
/// `n*(the minimum time between cells)` has passed, we can allow a
/// single big batch of `n` cells through. This assumption may not be
/// correct for your application, but if you depend on GCRA's
/// traffic-shaping properties, it's better to not use the `_n`
/// suffixed check functions.
///
/// # Example
/// In this example, we construct a rate-limiter with the GCR
/// algorithm that can accomodate 20 cells per second. This translates
/// to the GCRA parameters τ=1s, T=50ms (that's 1s / 20 cells).
///
/// ```
/// # use ratelimit_meter::{Decider, GCRA, Decision};
/// # use std::time::{Instant, Duration};
/// let mut limiter = GCRA::for_capacity(20).unwrap().cell_weight(1).unwrap().build();
/// let now = Instant::now();
/// let ms = Duration::from_millis(1);
/// assert_eq!(Decision::Yes, limiter.check_at(now).unwrap()); // the first cell is free
/// for i in 0..20 {
///     // Spam a lot:
///     assert_eq!(Decision::Yes, limiter.check_at(now).unwrap(), "at {}", i);
/// }
/// // We have exceeded the bucket capacity:
/// assert!(!limiter.check_at(now).unwrap().is_compliant());
///
/// // After a sufficient time period, cells are allowed again:
/// assert_eq!(Decision::Yes, limiter.check_at(now + ms*50).unwrap());
pub struct GCRA {
    // The "weight" of a single packet in units of time.
    t: Duration,

    // The "capacity" of the bucket.
    tau: Duration,

    // The theoretical arrival time of the next packet.
    tat: Option<Instant>,
}

/// A builder object that can be used to construct rate-limiters as
/// meters.
pub struct Builder {
    capacity: u32,
    cell_weight: u32,
    time_unit: Duration,
}

/// Constructs a concrete GCRA instance.
impl Builder {
    /// Sets the "weight" of each cell being checked against the
    /// bucket. Each cell fills the bucket by this much.
    pub fn cell_weight<'a>(&'a mut self, weight: u32) -> Result<&'a mut Builder> {
        if self.cell_weight > self.capacity {
            return Err(ErrorKind::InconsistentCapacity(self.capacity, weight).into());
        }
        self.cell_weight = weight;
        Ok(self)
    }

    /// Sets the "unit of time" within which the bucket drains.
    ///
    /// The assumption is that in a period of `time_unit` (if no cells
    /// are being checked), the bucket is fully drained.
    pub fn per<'a>(&'a mut self, time_unit: Duration) -> &'a mut Builder {
        self.time_unit = time_unit;
        self
    }

    /// Builds and returns a thread-safe GCRA decider.
    pub fn build_sync(&self) -> Threadsafe<GCRA> {
        Threadsafe::new(self.build())
    }

    /// Builds a single-threaded GCRA decider.
    pub fn build(&self) -> GCRA {
        GCRA {
            t: (self.time_unit / self.capacity) * self.cell_weight,
            tau: self.time_unit,
            tat: None,
        }
    }
}

impl GCRA {
    /// Constructs a builder object for a GCRA rate-limiter with the
    /// given capacity per second, at cell weight=1. See
    /// [`Builder`](gcra/struct.Builder.html) for options.
    pub fn for_capacity(capacity: u32) -> Result<Builder> {
        if capacity == 0 {
            return Err(ErrorKind::InconsistentCapacity(capacity, 0).into());
        }
        Ok(Builder {
            capacity: capacity,
            cell_weight: 1,
            time_unit: Duration::from_secs(1),
        })
    }

    /// Constructs a GCRA rate-limiter with the parameters T (the
    /// minimum amount of time that single cells are spaced apart),
    /// tau (τ, the number of cells that fit into this buffer), and an
    /// optional t_at (the earliest instant that the rate-limiter
    /// would accept another cell).
    pub fn with_parameters(t: Duration, tau: Duration, tat: Option<Instant>) -> GCRA {
        GCRA {
            t: t,
            tau: tau,
            tat: tat,
        }
    }
}

impl DeciderImpl for GCRA {
    /// Tests if a single cell can be accomodated by the
    /// rate-limiter. This is the method described directly in the
    /// GCRA algorithm, and is the fastest.
    fn test_and_update(&mut self, t0: Instant) -> Result<Decision<Instant>> {
        let tat = self.tat.unwrap_or(t0);

        if t0 < tat - self.tau {
            return Ok(Decision::No(tat));
        }
        self.tat = Some(cmp::max(tat, t0) + self.t);
        Ok(Decision::Yes)
    }
}

impl MultiDeciderImpl for GCRA {
    /// Tests if a `n` cells can be accomodated by the rate-limiter
    /// and updates rate limiter state iff they can be.
    ///
    /// As this method is an extension of GCRA (using multiplication),
    /// it is likely not as fast (and not as obviously "right") as the
    /// single-cell variant.
    fn test_n_and_update(&mut self, n: u32, t0: Instant) -> Result<Decision<Instant>> {
        let tat = self.tat.unwrap_or(t0);
        let tat = match n {
            0 => t0,
            1 => tat,
            _ => {
                let weight = self.t * (n - 1);
                if (weight + self.t) > self.tau {
                    // The bucket capacity can never accomodate this request
                    return Err(ErrorKind::InsufficientCapacity(n).into());
                }
                tat + weight
            }
        };

        if t0 < tat - self.tau {
            return Ok(Decision::No(tat));
        }
        let additional_weight = match n {
            0 => Duration::new(0, 0),
            1 => self.t,
            _ => self.t * n,
        };
        self.tat = Some(cmp::max(tat, t0) + additional_weight);
        Ok(Decision::Yes)
    }
}

/// Allows converting from a GCRA builder directly into a
/// GCRA decider. Same as
/// [the borrowed implementation](#impl-From<&'a Builder>), except for
/// owned `Builder`s.
/// # Example:
/// ```
/// use ratelimit_meter::{GCRA, Decider, Decision};
/// let mut gcra: GCRA = GCRA::for_capacity(50).unwrap().into();
/// assert_eq!(Decision::Yes, gcra.check().unwrap());
/// ```
impl From<Builder> for GCRA {
    fn from(b: Builder) -> Self {
        b.build()
    }
}

/// Allows converting a GCRA builder directly into a GCRA decider.
/// # Example:
/// ```
/// use ratelimit_meter::{GCRA, Decider, Decision};
/// let mut gcra: GCRA = GCRA::for_capacity(50).unwrap().cell_weight(2).unwrap().into();
/// assert_eq!(Decision::Yes, gcra.check().unwrap());
/// ```
impl<'a> From<&'a mut Builder> for GCRA {
    fn from(b: &'a mut Builder) -> Self {
        b.build()
    }
}

/// Allows converting a GCRA into a tuple containing its T (the
/// minimum amount of time that single cells are spaced apart), tau
/// (τ, the number of cells that fit into this buffer), and an
/// optional t_at (the earliest instant that the rate-limiter would
/// accept another cell).
///
/// These parameters can be used with
/// [`.with_parameters`](#method.with_parameters) to persist and
/// construct a copy of the GCRA rate-limiter.
impl<'a> Into<(Duration, Duration, Option<Instant>)> for &'a GCRA {
    fn into(self) -> (Duration, Duration, Option<Instant>) {
        (self.t, self.tau, self.tat)
    }
}

/// Allows converting the parameters returned from
/// [`Into<(Duration, Duration, Option<Instant>)>`](#impl-Into<(Duration, Duration, Option<Instant>)>)
/// back into a GCRA.
impl From<(Duration, Duration, Option<Instant>)> for GCRA {
    fn from(params: (Duration, Duration, Option<Instant>)) -> GCRA {
        let (t, tau, tat) = params;
        GCRA::with_parameters(t, tau, tat)
    }
}
<commit_msg>Clippy: Elide needless lifetimes.<commit_after>use {TypedDecider, DeciderImpl, MultiDeciderImpl, Decider, MultiDecider, Decision, Threadsafe,
     Result, ErrorKind};

use std::time::{Instant, Duration};
use std::cmp;

impl Decider for GCRA {}

/// This crate's GCRA implementation also allows checking multiple
/// cells at once, assuming that (counter the traffic-shaping
/// properties of GCRA) if a sufficiently long pause (`n*t`) has
/// occurred between cells, the algorithm can accomodate `n` cells.
///
/// As this assumption does not necessarily hold in all circumstances,
/// users of this trait on GCRA limiters should ensure that this is
/// ok.
impl MultiDecider for GCRA {}

impl TypedDecider for GCRA {
    /// In GCRA, negative decisions come with the time at which the
    /// next cell was expected to arrive; client code of GCRA can use
    /// this to decide what to do with the non-conforming cell.
    type T = Instant;
}

#[derive(Debug, Clone)]
/// Implements the virtual scheduling description of the Generic Cell
/// Rate Algorithm, attributed to ITU-T in recommendation I.371
/// Traffic control and congestion control in B-ISDN; from
/// [Wikipedia](https://en.wikipedia.org/wiki/Generic_cell_rate_algorithm).
///
///
/// While algorithms like leaky-bucket rate limiters allow cells to be
/// distributed across time in any way, GCRA is a rate-limiting *and*
/// traffic-shaping algorithm. It mandates that a minimum amount of
/// time passes between cells being measured. For example, if your API
/// mandates that only 20 requests can be made per second, GCRA will
/// ensure that each request is at least 50ms apart from the previous
/// request. This makes GCRA suitable for shaping traffic in
/// networking and telecom equipment (it was initially made for
/// asynchronous transfer mode networks), or for outgoing workloads on
/// *consumers* of attention, e.g. distributing outgoing emails across
/// a day.
///
/// In a blatant side-stepping of the above traffic-shaping criteria,
/// this implementation of GCRA comes with an extension that allows
/// measuring multiple cells at once, assuming that if a pause of
/// `n*(the minimum time between cells)` has passed, we can allow a
/// single big batch of `n` cells through. This assumption may not be
/// correct for your application, but if you depend on GCRA's
/// traffic-shaping properties, it's better to not use the `_n`
/// suffixed check functions.
///
/// # Example
/// In this example, we construct a rate-limiter with the GCR
/// algorithm that can accomodate 20 cells per second. This translates
/// to the GCRA parameters τ=1s, T=50ms (that's 1s / 20 cells).
///
/// ```
/// # use ratelimit_meter::{Decider, GCRA, Decision};
/// # use std::time::{Instant, Duration};
/// let mut limiter = GCRA::for_capacity(20).unwrap().cell_weight(1).unwrap().build();
/// let now = Instant::now();
/// let ms = Duration::from_millis(1);
/// assert_eq!(Decision::Yes, limiter.check_at(now).unwrap()); // the first cell is free
/// for i in 0..20 {
///     // Spam a lot:
///     assert_eq!(Decision::Yes, limiter.check_at(now).unwrap(), "at {}", i);
/// }
/// // We have exceeded the bucket capacity:
/// assert!(!limiter.check_at(now).unwrap().is_compliant());
///
/// // After a sufficient time period, cells are allowed again:
/// assert_eq!(Decision::Yes, limiter.check_at(now + ms*50).unwrap());
pub struct GCRA {
    // The "weight" of a single packet in units of time.
    t: Duration,

    // The "capacity" of the bucket.
    tau: Duration,

    // The theoretical arrival time of the next packet.
    tat: Option<Instant>,
}

/// A builder object that can be used to construct rate-limiters as
/// meters.
pub struct Builder {
    capacity: u32,
    cell_weight: u32,
    time_unit: Duration,
}

/// Constructs a concrete GCRA instance.
impl Builder {
    /// Sets the "weight" of each cell being checked against the
    /// bucket. Each cell fills the bucket by this much.
    pub fn cell_weight(&mut self, weight: u32) -> Result<&mut Builder> {
        if self.cell_weight > self.capacity {
            return Err(ErrorKind::InconsistentCapacity(self.capacity, weight).into());
        }
        self.cell_weight = weight;
        Ok(self)
    }

    /// Sets the "unit of time" within which the bucket drains.
    ///
    /// The assumption is that in a period of `time_unit` (if no cells
    /// are being checked), the bucket is fully drained.
    pub fn per(&mut self, time_unit: Duration) -> &mut Builder {
        self.time_unit = time_unit;
        self
    }

    /// Builds and returns a thread-safe GCRA decider.
    pub fn build_sync(&self) -> Threadsafe<GCRA> {
        Threadsafe::new(self.build())
    }

    /// Builds a single-threaded GCRA decider.
    pub fn build(&self) -> GCRA {
        GCRA {
            t: (self.time_unit / self.capacity) * self.cell_weight,
            tau: self.time_unit,
            tat: None,
        }
    }
}

impl GCRA {
    /// Constructs a builder object for a GCRA rate-limiter with the
    /// given capacity per second, at cell weight=1. See
    /// [`Builder`](gcra/struct.Builder.html) for options.
    pub fn for_capacity(capacity: u32) -> Result<Builder> {
        if capacity == 0 {
            return Err(ErrorKind::InconsistentCapacity(capacity, 0).into());
        }
        Ok(Builder {
            capacity: capacity,
            cell_weight: 1,
            time_unit: Duration::from_secs(1),
        })
    }

    /// Constructs a GCRA rate-limiter with the parameters T (the
    /// minimum amount of time that single cells are spaced apart),
    /// tau (τ, the number of cells that fit into this buffer), and an
    /// optional t_at (the earliest instant that the rate-limiter
    /// would accept another cell).
    pub fn with_parameters(t: Duration, tau: Duration, tat: Option<Instant>) -> GCRA {
        GCRA {
            t: t,
            tau: tau,
            tat: tat,
        }
    }
}

impl DeciderImpl for GCRA {
    /// Tests if a single cell can be accomodated by the
    /// rate-limiter. This is the method described directly in the
    /// GCRA algorithm, and is the fastest.
    fn test_and_update(&mut self, t0: Instant) -> Result<Decision<Instant>> {
        let tat = self.tat.unwrap_or(t0);

        if t0 < tat - self.tau {
            return Ok(Decision::No(tat));
        }
        self.tat = Some(cmp::max(tat, t0) + self.t);
        Ok(Decision::Yes)
    }
}

impl MultiDeciderImpl for GCRA {
    /// Tests if a `n` cells can be accomodated by the rate-limiter
    /// and updates rate limiter state iff they can be.
    ///
    /// As this method is an extension of GCRA (using multiplication),
    /// it is likely not as fast (and not as obviously "right") as the
    /// single-cell variant.
    fn test_n_and_update(&mut self, n: u32, t0: Instant) -> Result<Decision<Instant>> {
        let tat = self.tat.unwrap_or(t0);
        let tat = match n {
            0 => t0,
            1 => tat,
            _ => {
                let weight = self.t * (n - 1);
                if (weight + self.t) > self.tau {
                    // The bucket capacity can never accomodate this request
                    return Err(ErrorKind::InsufficientCapacity(n).into());
                }
                tat + weight
            }
        };

        if t0 < tat - self.tau {
            return Ok(Decision::No(tat));
        }
        let additional_weight = match n {
            0 => Duration::new(0, 0),
            1 => self.t,
            _ => self.t * n,
        };
        self.tat = Some(cmp::max(tat, t0) + additional_weight);
        Ok(Decision::Yes)
    }
}

/// Allows converting from a GCRA builder directly into a
/// GCRA decider. Same as
/// [the borrowed implementation](#impl-From<&'a Builder>), except for
/// owned `Builder`s.
/// # Example:
/// ```
/// use ratelimit_meter::{GCRA, Decider, Decision};
/// let mut gcra: GCRA = GCRA::for_capacity(50).unwrap().into();
/// assert_eq!(Decision::Yes, gcra.check().unwrap());
/// ```
impl From<Builder> for GCRA {
    fn from(b: Builder) -> Self {
        b.build()
    }
}

/// Allows converting a GCRA builder directly into a GCRA decider.
/// # Example:
/// ```
/// use ratelimit_meter::{GCRA, Decider, Decision};
/// let mut gcra: GCRA = GCRA::for_capacity(50).unwrap().cell_weight(2).unwrap().into();
/// assert_eq!(Decision::Yes, gcra.check().unwrap());
/// ```
impl<'a> From<&'a mut Builder> for GCRA {
    fn from(b: &'a mut Builder) -> Self {
        b.build()
    }
}

/// Allows converting a GCRA into a tuple containing its T (the
/// minimum amount of time that single cells are spaced apart), tau
/// (τ, the number of cells that fit into this buffer), and an
/// optional t_at (the earliest instant that the rate-limiter would
/// accept another cell).
///
/// These parameters can be used with
/// [`.with_parameters`](#method.with_parameters) to persist and
/// construct a copy of the GCRA rate-limiter.
impl<'a> Into<(Duration, Duration, Option<Instant>)> for &'a GCRA {
    fn into(self) -> (Duration, Duration, Option<Instant>) {
        (self.t, self.tau, self.tat)
    }
}

/// Allows converting the parameters returned from
/// [`Into<(Duration, Duration, Option<Instant>)>`](#impl-Into<(Duration, Duration, Option<Instant>)>)
/// back into a GCRA.
impl From<(Duration, Duration, Option<Instant>)> for GCRA {
    fn from(params: (Duration, Duration, Option<Instant>)) -> GCRA {
        let (t, tau, tat) = params;
        GCRA::with_parameters(t, tau, tat)
    }
}
<|endoftext|>


<commit_before>use serde_json::{self, Value};

/// Share Kind
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum Kind {
	/// `Send` shares are used to send files and folders to the specified users.
	Send,
	/// `Request` shares are used to allow users to upload files to the share owner chosen location.
	Request,
}

impl Kind {
	/// Test if type is `Send`
	pub fn is_send(&self) -> bool {
		match self {
			&Kind::Send => true,
			_ => false,
		}
	}

	/// Test if type is `Request`
	pub fn is_request(&self) -> bool {
		match self {
			&Kind::Request => true,
			_ => false,
		}
	}
}

// Convert User ID into JSON Value
impl serde_json::value::ToJson for Kind {
	fn to_json(&self) -> Value {
		match self {
			&Kind::Send => {
				Value::String(String::from("Send"))
			},
			&Kind::Request => {
				Value::String(String::from("Request"))
			}
		}
	}
}

#[cfg(test)]
mod tests {
	use super::Kind;
	use serde_json::value::ToJson;

	#[test]
	fn share_kind_send() {
		let share_kind = Kind::Send;
		assert_eq!(share_kind.is_send(), true);
		assert_eq!(share_kind.is_request(), false);
	}

	#[test]
	fn share_kind_send_to_json() {
		let share_kind = Kind::Send;
		let value = share_kind.to_json();
		assert!(value.is_string());

		if let Some(s) = value.as_str() {
			assert_eq!(s, "Send");
		}
		else {
			panic!("Cannot get contained value");
		}
	}

	#[test]
	fn share_kind_request() {
		let share_kind = Kind::Request;
		assert_eq!(share_kind.is_send(), false);
		assert_eq!(share_kind.is_request(), true);
	}

	#[test]
	fn share_kind_request_to_json() {
		let share_kind = Kind::Request;
		let value = share_kind.to_json();
		assert!(value.is_string());

		if let Some(s) = value.as_str() {
			assert_eq!(s, "Request");
		}
		else {
			panic!("Cannot get contained value");
		}
	}
}
<commit_msg>Change tabs to spaces<commit_after>use serde_json::{self, Value};

/// Share Kind
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum Kind {
    /// `Send` shares are used to send files and folders to the specified users.
    Send,
    /// `Request` shares are used to allow users to upload files to the share owner chosen location.
    Request,
}

impl Kind {
    /// Test if type is `Send`
    pub fn is_send(&self) -> bool {
        match self {
            &Kind::Send => true,
            _ => false,
        }
    }

    /// Test if type is `Request`
    pub fn is_request(&self) -> bool {
        match self {
            &Kind::Request => true,
            _ => false,
        }
    }
}

// Convert Share Kind into JSON Value
impl serde_json::value::ToJson for Kind {
    fn to_json(&self) -> Value {
        match self {
            &Kind::Send => {
                Value::String(String::from("Send"))
            },
            &Kind::Request => {
                Value::String(String::from("Request"))
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::Kind;
    use serde_json::value::ToJson;

    #[test]
    fn share_kind_send() {
        let share_kind = Kind::Send;
        assert_eq!(share_kind.is_send(), true);
        assert_eq!(share_kind.is_request(), false);
    }

    #[test]
    fn share_kind_send_to_json() {
        let share_kind = Kind::Send;
        let value = share_kind.to_json();
        assert!(value.is_string());

        if let Some(s) = value.as_str() {
            assert_eq!(s, "Send");
        }
        else {
            panic!("Cannot get contained value");
        }
    }

    #[test]
    fn share_kind_request() {
        let share_kind = Kind::Request;
        assert_eq!(share_kind.is_send(), false);
        assert_eq!(share_kind.is_request(), true);
    }

    #[test]
    fn share_kind_request_to_json() {
        let share_kind = Kind::Request;
        let value = share_kind.to_json();
        assert!(value.is_string());

        if let Some(s) = value.as_str() {
            assert_eq!(s, "Request");
        }
        else {
            panic!("Cannot get contained value");
        }
    }
}
<|endoftext|>


<commit_before>// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
// Version 2, December 2004

// Copyright (C) 2014 Nathan Sizemore <nathanrsizemore@gmail.com>

// Everyone is permitted to copy and distribute verbatim or modified
// copies of this license document, and changing it is allowed as long
// as the name is changed.

// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
// TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

// 0. You just DO WHAT THE FUCK YOU WANT TO.

extern crate rust_crypto = "rust-crypto";
extern crate serialize;

use std::str;
use std::io::{TcpListener, TcpStream};
use std::io::{Listener, Acceptor};
use self::rust_crypto::digest::Digest;
use self::rust_crypto::sha1::Sha1;
use self::serialize::base64::{ToBase64, STANDARD};
use self::server::Server;
use self::action::Action;
use self::server::socket::Socket;
use self::server::event::Event;

mod action;
pub mod server;

pub fn start(server: Server, ip: &str, port: u16) {

    /*
     * Communication channels
     *     - From HTTP Server to Connection Pool (Action Passed)
     *     - From Connection Pool to Event Loop (Vec<Sockets> Passed)
     */
    let (to_conn_pool, from_server): (Sender<Action>, Receiver<Action>) = channel();
    let (to_event_loop, from_conn_pool): (Sender<Vec<Socket>>, Receiver<Vec<Socket>>) = channel();

    // Connection Pool Task
    spawn(proc() {
        connection_pool(from_server, to_event_loop)
    });

    // Event Loop Task
    spawn(proc() {
        event_loop(server.events.clone(), from_conn_pool)
    });

    // TCP Server
    let listener = TcpListener::bind(ip, port);
    let mut acceptor = listener.listen();

    for stream in acceptor.incoming() {
        match stream {
            Err(e) => {
                println!("Error: {}", e)

                // TODO - Handle errors and shit
            }
            Ok(stream) => {
                spawn(proc() {
                    //process_new_connection(stream, to_conn_pool.clone())
                })
            }
        }
    }

    //Close when loop fails (Should be never)
    drop(acceptor);
}

/*
 * Connection Pool
 *     - Maintains all connections
 *     - On connect/disconnect - issues out new socket array to event loop
 */
fn connection_pool(from_server: Receiver<Action>, to_event_loop: Sender<Vec<Socket>>) {
    let mut connection_list: Vec<Socket> = Vec::new();
    loop {
        // Do all the things forever
    }
}

/*
 * Event Loop
 *     - Listens for new socket array generated from Connection Pool
 *     - Cycles through socket array's stream checking for data
 */
fn event_loop(events: Vec<Event>, from_conn_pool: Receiver<Vec<Socket>>) {
    // Wizard magic
}

<commit_msg>Added next steps to connection_pool task<commit_after>// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
// Version 2, December 2004

// Copyright (C) 2014 Nathan Sizemore <nathanrsizemore@gmail.com>

// Everyone is permitted to copy and distribute verbatim or modified
// copies of this license document, and changing it is allowed as long
// as the name is changed.

// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
// TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

// 0. You just DO WHAT THE FUCK YOU WANT TO.

extern crate rust_crypto = "rust-crypto";
extern crate serialize;

use std::str;
use std::io::{TcpListener, TcpStream};
use std::io::{Listener, Acceptor};
use self::rust_crypto::digest::Digest;
use self::rust_crypto::sha1::Sha1;
use self::serialize::base64::{ToBase64, STANDARD};
use self::server::Server;
use self::action::Action;
use self::server::socket::Socket;
use self::server::event::Event;

mod action;
pub mod server;

pub fn start(server: Server, ip: &str, port: u16) {

    /*
     * Communication channels
     *     - From HTTP Server to Connection Pool (Action Passed)
     *     - From Connection Pool to Event Loop (Vec<Sockets> Passed)
     */
    let (to_conn_pool, from_server): (Sender<Action>, Receiver<Action>) = channel();
    let (to_event_loop, from_conn_pool): (Sender<Vec<Socket>>, Receiver<Vec<Socket>>) = channel();

    // Connection Pool Task
    spawn(proc() {
        connection_pool(from_server, to_event_loop)
    });

    // Event Loop Task
    spawn(proc() {
        event_loop(server.events.clone(), from_conn_pool)
    });

    // TCP Server
    let listener = TcpListener::bind(ip, port);
    let mut acceptor = listener.listen();

    for stream in acceptor.incoming() {
        match stream {
            Err(e) => {
                println!("Error: {}", e)

                // TODO - Handle errors and shit
            }
            Ok(stream) => {
                spawn(proc() {
                    //process_new_connection(stream, to_conn_pool.clone())
                })
            }
        }
    }

    //Close when loop fails (Should be never)
    drop(acceptor);
}

/*
 * Connection Pool
 *     - Maintains all connections
 *     - On connect/disconnect - issues out new socket array to event loop
 */
fn connection_pool(from_server: Receiver<Action>, to_event_loop: Sender<Vec<Socket>>) {
    let mut connection_list: Vec<Socket> = Vec::new();
    loop {
        // from_server read (Blocking)

        // Match the result
        // - new_connection -> add socket to connection_list
        //      - send new list to event loop
    }
}

/*
 * Event Loop
 *     - Listens for new socket array generated from Connection Pool
 *     - Cycles through socket array's stream checking for data
 */
fn event_loop(events: Vec<Event>, from_conn_pool: Receiver<Vec<Socket>>) {

}

<|endoftext|>


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

use std::fmt;

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[allow(non_camel_case_types)]
pub enum Os {
    Windows,
    Macos,
    Linux,
    Android,
    Freebsd,
    iOS,
    Dragonfly,
    Bitrig,
    Netbsd,
    Openbsd,
    NaCl,
    Haiku,
    Solaris,
}

#[derive(PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Clone, Copy, Debug)]
pub enum Abi {
    // NB: This ordering MUST match the AbiDatas array below.
    // (This is ensured by the test indices_are_correct().)

    // Single platform ABIs
    Cdecl,
    Stdcall,
    Fastcall,
    Vectorcall,
    Aapcs,
    Win64,
    SysV64,
    PtxKernel,
    Msp430Interrupt,

    // Multiplatform / generic ABIs
    Rust,
    C,
    System,
    RustIntrinsic,
    RustCall,
    PlatformIntrinsic,
    Unadjusted
}

#[allow(non_camel_case_types)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum Architecture {
    X86,
    X86_64,
    Arm,
    Mips,
    Mipsel
}

#[derive(Copy, Clone)]
pub struct AbiData {
    abi: Abi,

    /// Name of this ABI as we like it called.
    name: &'static str,

    /// A generic ABI is supported on all platforms.
    generic: bool,
}

#[allow(non_upper_case_globals)]
const AbiDatas: &'static [AbiData] = &[
    // Platform-specific ABIs
    AbiData {abi: Abi::Cdecl, name: "cdecl", generic: false },
    AbiData {abi: Abi::Stdcall, name: "stdcall", generic: false },
    AbiData {abi: Abi::Fastcall, name: "fastcall", generic: false },
    AbiData {abi: Abi::Vectorcall, name: "vectorcall", generic: false},
    AbiData {abi: Abi::Aapcs, name: "aapcs", generic: false },
    AbiData {abi: Abi::Win64, name: "win64", generic: false },
    AbiData {abi: Abi::SysV64, name: "sysv64", generic: false },
    AbiData {abi: Abi::PtxKernel, name: "ptx-kernel", generic: false },
    AbiData {abi: Abi::Msp430Interrupt, name: "msp430-interrupt", generic: false },

    // Cross-platform ABIs
    AbiData {abi: Abi::Rust, name: "Rust", generic: true },
    AbiData {abi: Abi::C, name: "C", generic: true },
    AbiData {abi: Abi::System, name: "system", generic: true },
    AbiData {abi: Abi::RustIntrinsic, name: "rust-intrinsic", generic: true },
    AbiData {abi: Abi::RustCall, name: "rust-call", generic: true },
    AbiData {abi: Abi::PlatformIntrinsic, name: "platform-intrinsic", generic: true },
    AbiData {abi: Abi::Unadjusted, name: "unadjusted", generic: true },
];

/// Returns the ABI with the given name (if any).
pub fn lookup(name: &str) -> Option<Abi> {
    AbiDatas.iter().find(|abi_data| name == abi_data.name).map(|&x| x.abi)
}

pub fn all_names() -> Vec<&'static str> {
    AbiDatas.iter().map(|d| d.name).collect()
}

impl Abi {
    #[inline]
    pub fn index(&self) -> usize {
        *self as usize
    }

    #[inline]
    pub fn data(&self) -> &'static AbiData {
        &AbiDatas[self.index()]
    }

    pub fn name(&self) -> &'static str {
        self.data().name
    }

    pub fn generic(&self) -> bool {
        self.data().generic
    }
}

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

impl fmt::Display for Os {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Os::Linux => "linux".fmt(f),
            Os::Windows => "windows".fmt(f),
            Os::Macos => "macos".fmt(f),
            Os::iOS => "ios".fmt(f),
            Os::Android => "android".fmt(f),
            Os::Freebsd => "freebsd".fmt(f),
            Os::Dragonfly => "dragonfly".fmt(f),
            Os::Bitrig => "bitrig".fmt(f),
            Os::Netbsd => "netbsd".fmt(f),
            Os::Openbsd => "openbsd".fmt(f),
            Os::NaCl => "nacl".fmt(f),
            Os::Haiku => "haiku".fmt(f),
            Os::Solaris => "solaris".fmt(f),
        }
    }
}

#[allow(non_snake_case)]
#[test]
fn lookup_Rust() {
    let abi = lookup("Rust");
    assert!(abi.is_some() && abi.unwrap().data().name == "Rust");
}

#[test]
fn lookup_cdecl() {
    let abi = lookup("cdecl");
    assert!(abi.is_some() && abi.unwrap().data().name == "cdecl");
}

#[test]
fn lookup_baz() {
    let abi = lookup("baz");
    assert!(abi.is_none());
}

#[test]
fn indices_are_correct() {
    for (i, abi_data) in AbiDatas.iter().enumerate() {
        assert_eq!(i, abi_data.abi.index());
    }
}
<commit_msg>Auto merge of #39218 - xen0n:syntax-warts, r=alexcrichton<commit_after>// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::fmt;

#[derive(PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Clone, Copy, Debug)]
pub enum Abi {
    // NB: This ordering MUST match the AbiDatas array below.
    // (This is ensured by the test indices_are_correct().)

    // Single platform ABIs
    Cdecl,
    Stdcall,
    Fastcall,
    Vectorcall,
    Aapcs,
    Win64,
    SysV64,
    PtxKernel,
    Msp430Interrupt,

    // Multiplatform / generic ABIs
    Rust,
    C,
    System,
    RustIntrinsic,
    RustCall,
    PlatformIntrinsic,
    Unadjusted
}

#[derive(Copy, Clone)]
pub struct AbiData {
    abi: Abi,

    /// Name of this ABI as we like it called.
    name: &'static str,

    /// A generic ABI is supported on all platforms.
    generic: bool,
}

#[allow(non_upper_case_globals)]
const AbiDatas: &'static [AbiData] = &[
    // Platform-specific ABIs
    AbiData {abi: Abi::Cdecl, name: "cdecl", generic: false },
    AbiData {abi: Abi::Stdcall, name: "stdcall", generic: false },
    AbiData {abi: Abi::Fastcall, name: "fastcall", generic: false },
    AbiData {abi: Abi::Vectorcall, name: "vectorcall", generic: false},
    AbiData {abi: Abi::Aapcs, name: "aapcs", generic: false },
    AbiData {abi: Abi::Win64, name: "win64", generic: false },
    AbiData {abi: Abi::SysV64, name: "sysv64", generic: false },
    AbiData {abi: Abi::PtxKernel, name: "ptx-kernel", generic: false },
    AbiData {abi: Abi::Msp430Interrupt, name: "msp430-interrupt", generic: false },

    // Cross-platform ABIs
    AbiData {abi: Abi::Rust, name: "Rust", generic: true },
    AbiData {abi: Abi::C, name: "C", generic: true },
    AbiData {abi: Abi::System, name: "system", generic: true },
    AbiData {abi: Abi::RustIntrinsic, name: "rust-intrinsic", generic: true },
    AbiData {abi: Abi::RustCall, name: "rust-call", generic: true },
    AbiData {abi: Abi::PlatformIntrinsic, name: "platform-intrinsic", generic: true },
    AbiData {abi: Abi::Unadjusted, name: "unadjusted", generic: true },
];

/// Returns the ABI with the given name (if any).
pub fn lookup(name: &str) -> Option<Abi> {
    AbiDatas.iter().find(|abi_data| name == abi_data.name).map(|&x| x.abi)
}

pub fn all_names() -> Vec<&'static str> {
    AbiDatas.iter().map(|d| d.name).collect()
}

impl Abi {
    #[inline]
    pub fn index(&self) -> usize {
        *self as usize
    }

    #[inline]
    pub fn data(&self) -> &'static AbiData {
        &AbiDatas[self.index()]
    }

    pub fn name(&self) -> &'static str {
        self.data().name
    }

    pub fn generic(&self) -> bool {
        self.data().generic
    }
}

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

#[allow(non_snake_case)]
#[test]
fn lookup_Rust() {
    let abi = lookup("Rust");
    assert!(abi.is_some() && abi.unwrap().data().name == "Rust");
}

#[test]
fn lookup_cdecl() {
    let abi = lookup("cdecl");
    assert!(abi.is_some() && abi.unwrap().data().name == "cdecl");
}

#[test]
fn lookup_baz() {
    let abi = lookup("baz");
    assert!(abi.is_none());
}

#[test]
fn indices_are_correct() {
    for (i, abi_data) in AbiDatas.iter().enumerate() {
        assert_eq!(i, abi_data.abi.index());
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use platform::{Application, Window};

use windowing::{ApplicationMethods, WindowEvent, WindowMethods};
use windowing::{IdleWindowEvent, ResizeWindowEvent, LoadUrlWindowEvent, MouseWindowEventClass};
use windowing::{ScrollWindowEvent, ZoomWindowEvent, NavigationWindowEvent, FinishedWindowEvent};
use windowing::{QuitWindowEvent, MouseWindowClickEvent, MouseWindowMouseDownEvent, MouseWindowMouseUpEvent};

use servo_msg::constellation_msg::{ConstellationChan, NavigateMsg, ResizedWindowMsg, LoadUrlMsg};
use servo_msg::constellation_msg;

use azure::azure_hl::SourceSurfaceMethods;
use azure::azure_hl;
use std::comm::Port;
use std::num::Orderable;
use std::vec;
use std::path::Path;
use std::rt::io::timer::Timer;
use geom::matrix::identity;
use geom::point::Point2D;
use geom::size::Size2D;
use geom::rect::Rect;
use layers::layers::{ContainerLayer, ContainerLayerKind};
use layers::rendergl;
use layers::scene::Scene;
use opengles::gl2;
use png;
use servo_util::{time, url};
use servo_util::time::profile;

use extra::future::Future;
use extra::time::precise_time_s;

use compositing::compositor_layer::CompositorLayer;

use compositing::*;

/// Starts the compositor, which listens for messages on the specified port.
pub fn run_compositor(compositor: &CompositorTask) {
    let app: Application = ApplicationMethods::new();
    let window: @mut Window = WindowMethods::new(&app);

    // Create an initial layer tree.
    //
    // TODO: There should be no initial layer tree until the renderer creates one from the display
    // list. This is only here because we don't have that logic in the renderer yet.
    let context = rendergl::init_render_context();
    let root_layer = @mut ContainerLayer();
    let window_size = window.size();
    let mut scene = Scene(ContainerLayerKind(root_layer), window_size, identity());
    let mut window_size = Size2D(window_size.width as uint, window_size.height as uint);
    let mut done = false;
    let mut recomposite = false;
    let graphics_context = CompositorTask::create_graphics_context();

    // Keeps track of the current zoom factor
    let mut world_zoom = 1f32;
    let mut zoom_action = false;
    let mut zoom_time = 0f64;

    // The root CompositorLayer
    let mut compositor_layer: Option<CompositorLayer> = None;
    let mut constellation_chan: Option<ConstellationChan> = None;

    // Get BufferRequests from each layer.
    let ask_for_tiles = || {
        let window_size_page = Size2D(window_size.width as f32 / world_zoom,
                                      window_size.height as f32 / world_zoom);
        for layer in compositor_layer.mut_iter() {
            if !layer.hidden {
                let rect = Rect(Point2D(0f32, 0f32), window_size_page);
                recomposite = layer.get_buffer_request(&graphics_context, rect, world_zoom) ||
                    recomposite;
            } else {
                debug!("Compositor: root layer is hidden!");
            }
        }
    };

    let check_for_messages: &fn(&Port<Msg>) = |port: &Port<Msg>| {
        // Handle messages
        while port.peek() {
            match port.recv() {
                Exit => done = true,

                ChangeReadyState(ready_state) => window.set_ready_state(ready_state),
                ChangeRenderState(render_state) => window.set_render_state(render_state),

                SetIds(frame_tree, response_chan, new_constellation_chan) => {
                    response_chan.send(());

                    // This assumes there is at most one child, which should be the case.
                    match root_layer.first_child {
                        Some(old_layer) => root_layer.remove_child(old_layer),
                        None => {}
                    }

                    let layer = CompositorLayer::from_frame_tree(frame_tree,
                                                                 compositor.opts.tile_size,
                                                                 Some(10000000u),
                                                                 compositor.opts.cpu_painting);
                    root_layer.add_child_start(ContainerLayerKind(layer.root_layer));

                    // If there's already a root layer, destroy it cleanly.
                    match compositor_layer {
                        None => {}
                        Some(ref mut compositor_layer) => compositor_layer.clear_all(),
                    }

                    compositor_layer = Some(layer);
                    constellation_chan = Some(new_constellation_chan);
                }

                GetSize(chan) => {
                    let size = window.size();
                    chan.send(Size2D(size.width as int, size.height as int));
                }

                GetGraphicsMetadata(chan) => chan.send(azure_hl::current_graphics_metadata()),

                NewLayer(_id, new_size) => {
                    // FIXME: This should create an additional layer instead of replacing the current one.
                    // Once ResizeLayer messages are set up, we can switch to the new functionality.

                    let p = match compositor_layer {
                        Some(ref compositor_layer) => compositor_layer.pipeline.clone(),
                        None => fail!("Compositor: Received new layer without initialized pipeline"),
                    };
                    let page_size = Size2D(new_size.width as f32, new_size.height as f32);
                    let new_layer = CompositorLayer::new(p,
                                                         Some(page_size),
                                                         compositor.opts.tile_size,
                                                         Some(10000000u),
                                                         compositor.opts.cpu_painting);

                    let current_child = root_layer.first_child;
                    // This assumes there is at most one child, which should be the case.
                    match current_child {
                        Some(old_layer) => root_layer.remove_child(old_layer),
                        None => {}
                    }
                    root_layer.add_child_start(ContainerLayerKind(new_layer.root_layer));
                    compositor_layer = Some(new_layer);

                    ask_for_tiles();
                }

                SetLayerPageSize(id, new_size, epoch) => {
                    match compositor_layer {
                        Some(ref mut layer) => {
                            let page_window = Size2D(window_size.width as f32 / world_zoom,
                                                     window_size.height as f32 / world_zoom);
                            assert!(layer.resize(id, new_size, page_window, epoch));
                            ask_for_tiles();
                        }
                        None => {}
                    }
                }

                SetLayerClipRect(id, new_rect) => {
                    match compositor_layer {
                        Some(ref mut layer) => {
                            assert!(layer.set_clipping_rect(id, new_rect));
                            ask_for_tiles();
                        }
                        None => {}
                    }
                }

                DeleteLayer(id) => {
                    match compositor_layer {
                        Some(ref mut layer) => {
                            assert!(layer.delete(&graphics_context, id));
                            ask_for_tiles();
                        }
                        None => {}
                    }
                }

                Paint(id, new_layer_buffer_set, epoch) => {
                    debug!("osmain: received new frame");

                    // From now on, if we destroy the buffers, they will leak.
                    let mut new_layer_buffer_set = new_layer_buffer_set;
                    new_layer_buffer_set.mark_will_leak();

                    match compositor_layer {
                        Some(ref mut layer) => {
                            assert!(layer.add_buffers(&graphics_context,
                                                      id,
                                                      new_layer_buffer_set,
                                                      epoch).is_none());
                            recomposite = true;
                        }
                        None => {
                            fail!("Compositor: given paint command with no CompositorLayer initialized");
                        }
                    }
                    // TODO: Recycle the old buffers; send them back to the renderer to reuse if
                    // it wishes.
                }

                InvalidateRect(id, rect) => {
                    match compositor_layer {
                        Some(ref mut layer) => {
                            layer.invalidate_rect(id, Rect(Point2D(rect.origin.x as f32,
                                                                   rect.origin.y as f32),
                                                           Size2D(rect.size.width as f32,
                                                                  rect.size.height as f32)));
                            ask_for_tiles();
                        }
                        None => {} // Nothing to do
                    }
                }
            }
        }
    };

    let check_for_window_messages: &fn(WindowEvent) = |event| {
        match event {
            IdleWindowEvent => {}

            ResizeWindowEvent(width, height) => {
                let new_size = Size2D(width, height);
                if window_size != new_size {
                    debug!("osmain: window resized to %ux%u", width, height);
                    window_size = new_size;
                    match constellation_chan {
                        Some(ref chan) => chan.send(ResizedWindowMsg(new_size)),
                        None => error!("Compositor: Recieved resize event without initialized layout chan"),
                    }
                } else {
                    debug!("osmain: dropping window resize since size is still %ux%u", width, height);
                }
            }

            LoadUrlWindowEvent(url_string) => {
                debug!("osmain: loading URL `%s`", url_string);
                let root_pipeline_id = match compositor_layer {
                    Some(ref layer) => layer.pipeline.id.clone(),
                    None => fail!("Compositor: Received LoadUrlWindowEvent without initialized compositor layers"),
                };
                match constellation_chan {
                    Some(ref chan) => chan.send(LoadUrlMsg(root_pipeline_id,
                                                           url::make_url(url_string.to_str(), None),
                                                           Future::from_value(window_size))),
                    None => error!("Compositor: Recieved loadurl event without initialized layout chan"),
                }
            }

            MouseWindowEventClass(mouse_window_event) => {
                let point = match mouse_window_event {
                    MouseWindowClickEvent(_, p) => Point2D(p.x / world_zoom, p.y / world_zoom),
                    MouseWindowMouseDownEvent(_, p) => Point2D(p.x / world_zoom, p.y / world_zoom),
                    MouseWindowMouseUpEvent(_, p) => Point2D(p.x / world_zoom, p.y / world_zoom),
                };
                for layer in compositor_layer.iter() {
                    layer.send_mouse_event(mouse_window_event, point);
                }
            }

            ScrollWindowEvent(delta, cursor) => {
                // TODO: modify delta to snap scroll to pixels.
                let page_delta = Point2D(delta.x as f32 / world_zoom, delta.y as f32 / world_zoom);
                let page_cursor: Point2D<f32> = Point2D(cursor.x as f32 / world_zoom,
                                                        cursor.y as f32 / world_zoom);
                let page_window = Size2D(window_size.width as f32 / world_zoom,
                                         window_size.height as f32 / world_zoom);
                for layer in compositor_layer.mut_iter() {
                    recomposite = layer.scroll(page_delta, page_cursor, page_window) || recomposite;
                }
                ask_for_tiles();
            }

            ZoomWindowEvent(magnification) => {
                zoom_action = true;
                zoom_time = precise_time_s();
                let old_world_zoom = world_zoom;

                // Determine zoom amount
                world_zoom = (world_zoom * magnification).max(&1.0);
                root_layer.common.set_transform(identity().scale(world_zoom, world_zoom, 1f32));

                // Scroll as needed
                let page_delta = Point2D(window_size.width as f32 * (1.0 / world_zoom - 1.0 / old_world_zoom) * 0.5,
                                         window_size.height as f32 * (1.0 / world_zoom - 1.0 / old_world_zoom) * 0.5);
                // TODO: modify delta to snap scroll to pixels.
                let page_cursor = Point2D(-1f32, -1f32); // Make sure this hits the base layer
                let page_window = Size2D(window_size.width as f32 / world_zoom,
                                         window_size.height as f32 / world_zoom);
                for layer in compositor_layer.mut_iter() {
                    layer.scroll(page_delta, page_cursor, page_window);
                }

                recomposite = true;
            }

            NavigationWindowEvent(direction) => {
                let direction = match direction {
                    windowing::Forward => constellation_msg::Forward,
                    windowing::Back => constellation_msg::Back,
                };
                match constellation_chan {
                    Some(ref chan) => chan.send(NavigateMsg(direction)),
                    None => error!("Compositor: Recieved navigation event without initialized layout chan"),
                }
            }

            FinishedWindowEvent => {
                if compositor.opts.exit_after_load {
                    done = true;
                }
            }

            QuitWindowEvent => {
                done = true;
            }
        }
    };

    let profiler_chan = compositor.profiler_chan.clone();
    let write_png = compositor.opts.output_file.is_some();
    let exit = compositor.opts.exit_after_load;
    let composite = || {
        do profile(time::CompositingCategory, profiler_chan.clone()) {
            debug!("compositor: compositing");
            // Adjust the layer dimensions as necessary to correspond to the size of the window.
            scene.size = window.size();

            // Render the scene.
            rendergl::render_scene(context, &scene);
        }

        // Render to PNG. We must read from the back buffer (ie, before
        // window.present()) as OpenGL ES 2 does not have glReadBuffer().
        if write_png {
            let (width, height) = (window_size.width as uint, window_size.height as uint);
            let path = from_str::<Path>(*compositor.opts.output_file.get_ref()).unwrap();
            let mut pixels = gl2::read_pixels(0, 0,
                                              width as gl2::GLsizei,
                                              height as gl2::GLsizei,
                                              gl2::RGB, gl2::UNSIGNED_BYTE);
            // flip image vertically (texture is upside down)
            let orig_pixels = pixels.clone();
            let stride = width * 3;
            for y in range(0, height) {
                let dst_start = y * stride;
                let src_start = (height - y - 1) * stride;
                vec::bytes::copy_memory(pixels.mut_slice(dst_start, dst_start + stride),
                                        orig_pixels.slice(src_start, src_start + stride),
                                        stride);
            }
            let img = png::Image {
                width: width as u32,
                height: height as u32,
                color_type: png::RGB8,
                pixels: pixels,
            };
            let res = png::store_png(&img, &path);
            assert!(res.is_ok());

            done = true;
        }

        window.present();

        if exit { done = true; }
    };

    // Enter the main event loop.
    let mut tm = Timer::new().unwrap();
    while !done {
        // Check for new messages coming from the rendering task.
        check_for_messages(&compositor.port);

        // Check for messages coming from the windowing system.
        check_for_window_messages(window.recv());

        if recomposite {
            recomposite = false;
            composite();
        }

        tm.sleep(10);

        // If a pinch-zoom happened recently, ask for tiles at the new resolution
        if zoom_action && precise_time_s() - zoom_time > 0.3 {
            zoom_action = false;
            ask_for_tiles();
        }

    }

    compositor.shutdown_chan.send(());

    // Clear out the compositor layers so that painting tasks can destroy the buffers.
    match compositor_layer {
        None => {}
        Some(ref mut layer) => layer.forget_all_tiles(),
    }
}
<commit_msg>Fix some typos in error messages<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use platform::{Application, Window};

use windowing::{ApplicationMethods, WindowEvent, WindowMethods};
use windowing::{IdleWindowEvent, ResizeWindowEvent, LoadUrlWindowEvent, MouseWindowEventClass};
use windowing::{ScrollWindowEvent, ZoomWindowEvent, NavigationWindowEvent, FinishedWindowEvent};
use windowing::{QuitWindowEvent, MouseWindowClickEvent, MouseWindowMouseDownEvent, MouseWindowMouseUpEvent};

use servo_msg::constellation_msg::{ConstellationChan, NavigateMsg, ResizedWindowMsg, LoadUrlMsg};
use servo_msg::constellation_msg;

use azure::azure_hl::SourceSurfaceMethods;
use azure::azure_hl;
use std::comm::Port;
use std::num::Orderable;
use std::vec;
use std::path::Path;
use std::rt::io::timer::Timer;
use geom::matrix::identity;
use geom::point::Point2D;
use geom::size::Size2D;
use geom::rect::Rect;
use layers::layers::{ContainerLayer, ContainerLayerKind};
use layers::rendergl;
use layers::scene::Scene;
use opengles::gl2;
use png;
use servo_util::{time, url};
use servo_util::time::profile;

use extra::future::Future;
use extra::time::precise_time_s;

use compositing::compositor_layer::CompositorLayer;

use compositing::*;

/// Starts the compositor, which listens for messages on the specified port.
pub fn run_compositor(compositor: &CompositorTask) {
    let app: Application = ApplicationMethods::new();
    let window: @mut Window = WindowMethods::new(&app);

    // Create an initial layer tree.
    //
    // TODO: There should be no initial layer tree until the renderer creates one from the display
    // list. This is only here because we don't have that logic in the renderer yet.
    let context = rendergl::init_render_context();
    let root_layer = @mut ContainerLayer();
    let window_size = window.size();
    let mut scene = Scene(ContainerLayerKind(root_layer), window_size, identity());
    let mut window_size = Size2D(window_size.width as uint, window_size.height as uint);
    let mut done = false;
    let mut recomposite = false;
    let graphics_context = CompositorTask::create_graphics_context();

    // Keeps track of the current zoom factor
    let mut world_zoom = 1f32;
    let mut zoom_action = false;
    let mut zoom_time = 0f64;

    // The root CompositorLayer
    let mut compositor_layer: Option<CompositorLayer> = None;
    let mut constellation_chan: Option<ConstellationChan> = None;

    // Get BufferRequests from each layer.
    let ask_for_tiles = || {
        let window_size_page = Size2D(window_size.width as f32 / world_zoom,
                                      window_size.height as f32 / world_zoom);
        for layer in compositor_layer.mut_iter() {
            if !layer.hidden {
                let rect = Rect(Point2D(0f32, 0f32), window_size_page);
                recomposite = layer.get_buffer_request(&graphics_context, rect, world_zoom) ||
                    recomposite;
            } else {
                debug!("Compositor: root layer is hidden!");
            }
        }
    };

    let check_for_messages: &fn(&Port<Msg>) = |port: &Port<Msg>| {
        // Handle messages
        while port.peek() {
            match port.recv() {
                Exit => done = true,

                ChangeReadyState(ready_state) => window.set_ready_state(ready_state),
                ChangeRenderState(render_state) => window.set_render_state(render_state),

                SetIds(frame_tree, response_chan, new_constellation_chan) => {
                    response_chan.send(());

                    // This assumes there is at most one child, which should be the case.
                    match root_layer.first_child {
                        Some(old_layer) => root_layer.remove_child(old_layer),
                        None => {}
                    }

                    let layer = CompositorLayer::from_frame_tree(frame_tree,
                                                                 compositor.opts.tile_size,
                                                                 Some(10000000u),
                                                                 compositor.opts.cpu_painting);
                    root_layer.add_child_start(ContainerLayerKind(layer.root_layer));

                    // If there's already a root layer, destroy it cleanly.
                    match compositor_layer {
                        None => {}
                        Some(ref mut compositor_layer) => compositor_layer.clear_all(),
                    }

                    compositor_layer = Some(layer);
                    constellation_chan = Some(new_constellation_chan);
                }

                GetSize(chan) => {
                    let size = window.size();
                    chan.send(Size2D(size.width as int, size.height as int));
                }

                GetGraphicsMetadata(chan) => chan.send(azure_hl::current_graphics_metadata()),

                NewLayer(_id, new_size) => {
                    // FIXME: This should create an additional layer instead of replacing the current one.
                    // Once ResizeLayer messages are set up, we can switch to the new functionality.

                    let p = match compositor_layer {
                        Some(ref compositor_layer) => compositor_layer.pipeline.clone(),
                        None => fail!("Compositor: Received new layer without initialized pipeline"),
                    };
                    let page_size = Size2D(new_size.width as f32, new_size.height as f32);
                    let new_layer = CompositorLayer::new(p,
                                                         Some(page_size),
                                                         compositor.opts.tile_size,
                                                         Some(10000000u),
                                                         compositor.opts.cpu_painting);

                    let current_child = root_layer.first_child;
                    // This assumes there is at most one child, which should be the case.
                    match current_child {
                        Some(old_layer) => root_layer.remove_child(old_layer),
                        None => {}
                    }
                    root_layer.add_child_start(ContainerLayerKind(new_layer.root_layer));
                    compositor_layer = Some(new_layer);

                    ask_for_tiles();
                }

                SetLayerPageSize(id, new_size, epoch) => {
                    match compositor_layer {
                        Some(ref mut layer) => {
                            let page_window = Size2D(window_size.width as f32 / world_zoom,
                                                     window_size.height as f32 / world_zoom);
                            assert!(layer.resize(id, new_size, page_window, epoch));
                            ask_for_tiles();
                        }
                        None => {}
                    }
                }

                SetLayerClipRect(id, new_rect) => {
                    match compositor_layer {
                        Some(ref mut layer) => {
                            assert!(layer.set_clipping_rect(id, new_rect));
                            ask_for_tiles();
                        }
                        None => {}
                    }
                }

                DeleteLayer(id) => {
                    match compositor_layer {
                        Some(ref mut layer) => {
                            assert!(layer.delete(&graphics_context, id));
                            ask_for_tiles();
                        }
                        None => {}
                    }
                }

                Paint(id, new_layer_buffer_set, epoch) => {
                    debug!("osmain: received new frame");

                    // From now on, if we destroy the buffers, they will leak.
                    let mut new_layer_buffer_set = new_layer_buffer_set;
                    new_layer_buffer_set.mark_will_leak();

                    match compositor_layer {
                        Some(ref mut layer) => {
                            assert!(layer.add_buffers(&graphics_context,
                                                      id,
                                                      new_layer_buffer_set,
                                                      epoch).is_none());
                            recomposite = true;
                        }
                        None => {
                            fail!("Compositor: given paint command with no CompositorLayer initialized");
                        }
                    }
                    // TODO: Recycle the old buffers; send them back to the renderer to reuse if
                    // it wishes.
                }

                InvalidateRect(id, rect) => {
                    match compositor_layer {
                        Some(ref mut layer) => {
                            layer.invalidate_rect(id, Rect(Point2D(rect.origin.x as f32,
                                                                   rect.origin.y as f32),
                                                           Size2D(rect.size.width as f32,
                                                                  rect.size.height as f32)));
                            ask_for_tiles();
                        }
                        None => {} // Nothing to do
                    }
                }
            }
        }
    };

    let check_for_window_messages: &fn(WindowEvent) = |event| {
        match event {
            IdleWindowEvent => {}

            ResizeWindowEvent(width, height) => {
                let new_size = Size2D(width, height);
                if window_size != new_size {
                    debug!("osmain: window resized to %ux%u", width, height);
                    window_size = new_size;
                    match constellation_chan {
                        Some(ref chan) => chan.send(ResizedWindowMsg(new_size)),
                        None => error!("Compositor: Received resize event without initialized layout chan"),
                    }
                } else {
                    debug!("osmain: dropping window resize since size is still %ux%u", width, height);
                }
            }

            LoadUrlWindowEvent(url_string) => {
                debug!("osmain: loading URL `%s`", url_string);
                let root_pipeline_id = match compositor_layer {
                    Some(ref layer) => layer.pipeline.id.clone(),
                    None => fail!("Compositor: Received LoadUrlWindowEvent without initialized compositor layers"),
                };
                match constellation_chan {
                    Some(ref chan) => chan.send(LoadUrlMsg(root_pipeline_id,
                                                           url::make_url(url_string.to_str(), None),
                                                           Future::from_value(window_size))),
                    None => error!("Compositor: Received loadurl event without initialized layout chan"),
                }
            }

            MouseWindowEventClass(mouse_window_event) => {
                let point = match mouse_window_event {
                    MouseWindowClickEvent(_, p) => Point2D(p.x / world_zoom, p.y / world_zoom),
                    MouseWindowMouseDownEvent(_, p) => Point2D(p.x / world_zoom, p.y / world_zoom),
                    MouseWindowMouseUpEvent(_, p) => Point2D(p.x / world_zoom, p.y / world_zoom),
                };
                for layer in compositor_layer.iter() {
                    layer.send_mouse_event(mouse_window_event, point);
                }
            }

            ScrollWindowEvent(delta, cursor) => {
                // TODO: modify delta to snap scroll to pixels.
                let page_delta = Point2D(delta.x as f32 / world_zoom, delta.y as f32 / world_zoom);
                let page_cursor: Point2D<f32> = Point2D(cursor.x as f32 / world_zoom,
                                                        cursor.y as f32 / world_zoom);
                let page_window = Size2D(window_size.width as f32 / world_zoom,
                                         window_size.height as f32 / world_zoom);
                for layer in compositor_layer.mut_iter() {
                    recomposite = layer.scroll(page_delta, page_cursor, page_window) || recomposite;
                }
                ask_for_tiles();
            }

            ZoomWindowEvent(magnification) => {
                zoom_action = true;
                zoom_time = precise_time_s();
                let old_world_zoom = world_zoom;

                // Determine zoom amount
                world_zoom = (world_zoom * magnification).max(&1.0);
                root_layer.common.set_transform(identity().scale(world_zoom, world_zoom, 1f32));

                // Scroll as needed
                let page_delta = Point2D(window_size.width as f32 * (1.0 / world_zoom - 1.0 / old_world_zoom) * 0.5,
                                         window_size.height as f32 * (1.0 / world_zoom - 1.0 / old_world_zoom) * 0.5);
                // TODO: modify delta to snap scroll to pixels.
                let page_cursor = Point2D(-1f32, -1f32); // Make sure this hits the base layer
                let page_window = Size2D(window_size.width as f32 / world_zoom,
                                         window_size.height as f32 / world_zoom);
                for layer in compositor_layer.mut_iter() {
                    layer.scroll(page_delta, page_cursor, page_window);
                }

                recomposite = true;
            }

            NavigationWindowEvent(direction) => {
                let direction = match direction {
                    windowing::Forward => constellation_msg::Forward,
                    windowing::Back => constellation_msg::Back,
                };
                match constellation_chan {
                    Some(ref chan) => chan.send(NavigateMsg(direction)),
                    None => error!("Compositor: Received navigation event without initialized layout chan"),
                }
            }

            FinishedWindowEvent => {
                if compositor.opts.exit_after_load {
                    done = true;
                }
            }

            QuitWindowEvent => {
                done = true;
            }
        }
    };

    let profiler_chan = compositor.profiler_chan.clone();
    let write_png = compositor.opts.output_file.is_some();
    let exit = compositor.opts.exit_after_load;
    let composite = || {
        do profile(time::CompositingCategory, profiler_chan.clone()) {
            debug!("compositor: compositing");
            // Adjust the layer dimensions as necessary to correspond to the size of the window.
            scene.size = window.size();

            // Render the scene.
            rendergl::render_scene(context, &scene);
        }

        // Render to PNG. We must read from the back buffer (ie, before
        // window.present()) as OpenGL ES 2 does not have glReadBuffer().
        if write_png {
            let (width, height) = (window_size.width as uint, window_size.height as uint);
            let path = from_str::<Path>(*compositor.opts.output_file.get_ref()).unwrap();
            let mut pixels = gl2::read_pixels(0, 0,
                                              width as gl2::GLsizei,
                                              height as gl2::GLsizei,
                                              gl2::RGB, gl2::UNSIGNED_BYTE);
            // flip image vertically (texture is upside down)
            let orig_pixels = pixels.clone();
            let stride = width * 3;
            for y in range(0, height) {
                let dst_start = y * stride;
                let src_start = (height - y - 1) * stride;
                vec::bytes::copy_memory(pixels.mut_slice(dst_start, dst_start + stride),
                                        orig_pixels.slice(src_start, src_start + stride),
                                        stride);
            }
            let img = png::Image {
                width: width as u32,
                height: height as u32,
                color_type: png::RGB8,
                pixels: pixels,
            };
            let res = png::store_png(&img, &path);
            assert!(res.is_ok());

            done = true;
        }

        window.present();

        if exit { done = true; }
    };

    // Enter the main event loop.
    let mut tm = Timer::new().unwrap();
    while !done {
        // Check for new messages coming from the rendering task.
        check_for_messages(&compositor.port);

        // Check for messages coming from the windowing system.
        check_for_window_messages(window.recv());

        if recomposite {
            recomposite = false;
            composite();
        }

        tm.sleep(10);

        // If a pinch-zoom happened recently, ask for tiles at the new resolution
        if zoom_action && precise_time_s() - zoom_time > 0.3 {
            zoom_action = false;
            ask_for_tiles();
        }

    }

    compositor.shutdown_chan.send(());

    // Clear out the compositor layers so that painting tasks can destroy the buffers.
    match compositor_layer {
        None => {}
        Some(ref mut layer) => layer.forget_all_tiles(),
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)] // not used on all platforms

use crate::collections::BTreeMap;
use crate::ptr;
use crate::sync::atomic::{AtomicUsize, Ordering};

pub type Key = usize;

type Dtor = unsafe extern fn(*mut u8);

static NEXT_KEY: AtomicUsize = AtomicUsize::new(0);

static mut KEYS: *mut BTreeMap<Key, Option<Dtor>> = ptr::null_mut();

#[thread_local]
static mut LOCALS: *mut BTreeMap<Key, *mut u8> = ptr::null_mut();

unsafe fn keys() -> &'static mut BTreeMap<Key, Option<Dtor>> {
    if KEYS == ptr::null_mut() {
        KEYS = Box::into_raw(Box::new(BTreeMap::new()));
    }
    &mut *KEYS
}

unsafe fn locals() -> &'static mut BTreeMap<Key, *mut u8> {
    if LOCALS == ptr::null_mut() {
        LOCALS = Box::into_raw(Box::new(BTreeMap::new()));
    }
    &mut *LOCALS
}

#[inline]
pub unsafe fn create(dtor: Option<Dtor>) -> Key {
    let key = NEXT_KEY.fetch_add(1, Ordering::SeqCst);
    keys().insert(key, dtor);
    key
}

#[inline]
pub unsafe fn get(key: Key) -> *mut u8 {
    if let Some(&entry) = locals().get(&key) {
        entry
    } else {
        ptr::null_mut()
    }
}

#[inline]
pub unsafe fn set(key: Key, value: *mut u8) {
    locals().insert(key, value);
}

#[inline]
pub unsafe fn destroy(key: Key) {
    keys().remove(&key);
}

#[inline]
pub fn requires_synchronized_create() -> bool {
    false
}
<commit_msg>Rollup merge of #66350 - hermitcore:hermit, r=rkruppe<commit_after>#![allow(dead_code)] // not used on all platforms

use crate::collections::BTreeMap;
use crate::ptr;
use crate::sync::atomic::{AtomicUsize, Ordering};
use crate::sys_common::mutex::Mutex;

pub type Key = usize;

type Dtor = unsafe extern fn(*mut u8);

static NEXT_KEY: AtomicUsize = AtomicUsize::new(0);

static mut KEYS: *mut BTreeMap<Key, Option<Dtor>> = ptr::null_mut();
static KEYS_LOCK: Mutex = Mutex::new();

#[thread_local]
static mut LOCALS: *mut BTreeMap<Key, *mut u8> = ptr::null_mut();

unsafe fn keys() -> &'static mut BTreeMap<Key, Option<Dtor>> {
    if KEYS == ptr::null_mut() {
        KEYS = Box::into_raw(Box::new(BTreeMap::new()));
    }
    &mut *KEYS
}

unsafe fn locals() -> &'static mut BTreeMap<Key, *mut u8> {
    if LOCALS == ptr::null_mut() {
        LOCALS = Box::into_raw(Box::new(BTreeMap::new()));
    }
    &mut *LOCALS
}

#[inline]
pub unsafe fn create(dtor: Option<Dtor>) -> Key {
    let key = NEXT_KEY.fetch_add(1, Ordering::SeqCst);
    let _guard = KEYS_LOCK.lock();
    keys().insert(key, dtor);
    key
}

#[inline]
pub unsafe fn get(key: Key) -> *mut u8 {
    if let Some(&entry) = locals().get(&key) {
        entry
    } else {
        ptr::null_mut()
    }
}

#[inline]
pub unsafe fn set(key: Key, value: *mut u8) {
    locals().insert(key, value);
}

#[inline]
pub unsafe fn destroy(key: Key) {
    keys().remove(&key);
}

#[inline]
pub fn requires_synchronized_create() -> bool {
    false
}
<|endoftext|>


<commit_before>import bar::baz;
import foo::zed;
mod foo {
    mod zed {
        fn baz() { #debug("baz"); }
    }
}
mod bar {
    import zed::baz;
    export baz;
}
fn main() { baz(); }
<commit_msg>test: Swap the order of two imports in import6 to eliminate a cycle<commit_after>import foo::zed;
import bar::baz;
mod foo {
    mod zed {
        fn baz() { #debug("baz"); }
    }
}
mod bar {
    import zed::baz;
    export baz;
}
fn main() { baz(); }
<|endoftext|>