<commit_before>// Copyright 2016 The rust-url developers.
//
// 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 parser::{self, SchemeType};
use std::str;
use Url;

/// Exposes methods to manipulate the path of an URL that is not cannot-be-base.
///
/// The path always starts with a `/` slash, and is made of slash-separated segments.
/// There is always at least one segment (which may be the empty string).
///
/// Examples:
///
/// ```rust
/// # use url::Url;
/// let mut url = Url::parse("mailto:me@example.com").unwrap();
/// assert!(url.path_segments_mut().is_err());
///
/// let mut url = Url::parse("http://example.net/foo/index.html").unwrap();
/// url.path_segments_mut().unwrap().pop().push("img").push("100%.png");
/// assert_eq!(url.as_str(), "http://example.net/foo/img/100%25.png");
/// ```
pub struct PathSegmentsMut<'a> {
    url: &'a mut Url,
    after_first_slash: usize,
    after_path: String,
    old_after_path_position: u32,
}

// Not re-exported outside the crate
pub fn new(url: &mut Url) -> PathSegmentsMut {
    let (old_after_path_position, after_path) = url.take_after_path();
    debug_assert!(url.byte_at(url.path_start) == b'/');
    PathSegmentsMut {
        after_first_slash: url.path_start as usize + "/".len(),
        url: url,
        old_after_path_position: old_after_path_position,
        after_path: after_path,
    }
}

impl<'a> Drop for PathSegmentsMut<'a> {
    fn drop(&mut self) {
        self.url.restore_after_path(self.old_after_path_position, &self.after_path)
    }
}

impl<'a> PathSegmentsMut<'a> {
    /// Remove all segments in the path, leaving the minimal `url.path() == "/"`.
    ///
    /// Returns `&mut Self` so that method calls can be chained.
    ///
    /// Example:
    ///
    /// ```rust
    /// # use url::Url;
    /// let mut url = Url::parse("https://github.com/servo/rust-url/").unwrap();
    /// url.path_segments_mut().unwrap().clear().push("logout");
    /// assert_eq!(url.as_str(), "https://github.com/logout");
    /// ```
    pub fn clear(&mut self) -> &mut Self {
        self.url.serialization.truncate(self.after_first_slash);
        self
    }

    /// Remove the last segment of this URL’s path if it is empty,
    /// except if these was only one segment to begin with.
    ///
    /// In other words, remove one path trailing slash, if any,
    /// unless it is also the initial slash (so this does nothing if `url.path() == "/")`.
    ///
    /// Returns `&mut Self` so that method calls can be chained.
    ///
    /// Example:
    ///
    /// ```rust
    /// # use url::Url;
    /// let mut url = Url::parse("https://github.com/servo/rust-url/").unwrap();
    /// url.path_segments_mut().unwrap().push("pulls");
    /// assert_eq!(url.as_str(), "https://github.com/servo/rust-url//pulls");
    ///
    /// let mut url = Url::parse("https://github.com/servo/rust-url/").unwrap();
    /// url.path_segments_mut().unwrap().pop_if_empty().push("pulls");
    /// assert_eq!(url.as_str(), "https://github.com/servo/rust-url/pulls");
    /// ```
    pub fn pop_if_empty(&mut self) -> &mut Self {
        if self.url.serialization[self.after_first_slash..].ends_with('/') {
            self.url.serialization.pop();
        }
        self
    }

    /// Remove the last segment of this URL’s path.
    ///
    /// If the path only has one segment, make it empty such that `url.path() == "/"`.
    ///
    /// Returns `&mut Self` so that method calls can be chained.
    pub fn pop(&mut self) -> &mut Self {
        let last_slash = self.url.serialization[self.after_first_slash..].rfind('/').unwrap_or(0);
        self.url.serialization.truncate(self.after_first_slash + last_slash);
        self
    }

    /// Append the given segment at the end of this URL’s path.
    ///
    /// See the documentation for `.extend()`.
    ///
    /// Returns `&mut Self` so that method calls can be chained.
    pub fn push(&mut self, segment: &str) -> &mut Self {
        self.extend(Some(segment))
    }

    /// Append each segment from the given iterator at the end of this URL’s path.
    ///
    /// Each segment is percent-encoded like in `Url::parse` or `Url::join`,
    /// except that `%` and `/` characters are also encoded (to `%25` and `%2F`).
    /// This is unlike `Url::parse` where `%` is left as-is in case some of the input
    /// is already percent-encoded, and `/` denotes a path segment separator.)
    ///
    /// Note that, in addition to slashes between new segments,
    /// this always adds a slash between the existing path and the new segments
    /// *except* if the existing path is `"/"`.
    /// If the previous last segment was empty (if the path had a trailing slash)
    /// the path after `.extend()` will contain two consecutive slashes.
    /// If that is undesired, call `.pop_if_empty()` first.
    ///
    /// To obtain a behavior similar to `Url::join`, call `.pop()` unconditionally first.
    ///
    /// Returns `&mut Self` so that method calls can be chained.
    ///
    /// Example:
    ///
    /// ```rust
    /// # use url::Url;
    /// let mut url = Url::parse("https://github.com/").unwrap();
    /// let org = "servo";
    /// let repo = "rust-url";
    /// let issue_number = "188";
    /// url.path_segments_mut().unwrap().extend(&[org, repo, "issues", issue_number]);
    /// assert_eq!(url.as_str(), "https://github.com/servo/rust-url/issues/188");
    /// ```
    pub fn extend<I>(&mut self, segments: I) -> &mut Self
    where I: IntoIterator, I::Item: AsRef<str> {
        let scheme_type = SchemeType::from(self.url.scheme());
        let path_start = self.url.path_start as usize;
        self.url.mutate(|parser| {
            parser.context = parser::Context::PathSegmentSetter;
            for segment in segments {
                if parser.serialization.len() > path_start + 1 {
                    parser.serialization.push('/');
                }
                let mut has_host = true;  // FIXME account for this?
                parser.parse_path(scheme_type, &mut has_host, path_start,
                                  parser::Input::new(segment.as_ref()));
            }
        });
        self
    }

    /// For internal testing, not part of the public API.
    #[doc(hidden)]
    pub fn assert_url_invariants(&mut self) -> &mut Self {
        self.url.assert_invariants();
        self
    }
}
<commit_msg>Make pushing a "." or ".." segment a no-op.<commit_after>// Copyright 2016 The rust-url developers.
//
// 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 parser::{self, SchemeType};
use std::str;
use Url;

/// Exposes methods to manipulate the path of an URL that is not cannot-be-base.
///
/// The path always starts with a `/` slash, and is made of slash-separated segments.
/// There is always at least one segment (which may be the empty string).
///
/// Examples:
///
/// ```rust
/// # use url::Url;
/// let mut url = Url::parse("mailto:me@example.com").unwrap();
/// assert!(url.path_segments_mut().is_err());
///
/// let mut url = Url::parse("http://example.net/foo/index.html").unwrap();
/// url.path_segments_mut().unwrap().pop().push("img").push("2/100%.png");
/// assert_eq!(url.as_str(), "http://example.net/foo/img/2%2F100%25.png");
/// ```
pub struct PathSegmentsMut<'a> {
    url: &'a mut Url,
    after_first_slash: usize,
    after_path: String,
    old_after_path_position: u32,
}

// Not re-exported outside the crate
pub fn new(url: &mut Url) -> PathSegmentsMut {
    let (old_after_path_position, after_path) = url.take_after_path();
    debug_assert!(url.byte_at(url.path_start) == b'/');
    PathSegmentsMut {
        after_first_slash: url.path_start as usize + "/".len(),
        url: url,
        old_after_path_position: old_after_path_position,
        after_path: after_path,
    }
}

impl<'a> Drop for PathSegmentsMut<'a> {
    fn drop(&mut self) {
        self.url.restore_after_path(self.old_after_path_position, &self.after_path)
    }
}

impl<'a> PathSegmentsMut<'a> {
    /// Remove all segments in the path, leaving the minimal `url.path() == "/"`.
    ///
    /// Returns `&mut Self` so that method calls can be chained.
    ///
    /// Example:
    ///
    /// ```rust
    /// # use url::Url;
    /// let mut url = Url::parse("https://github.com/servo/rust-url/").unwrap();
    /// url.path_segments_mut().unwrap().clear().push("logout");
    /// assert_eq!(url.as_str(), "https://github.com/logout");
    /// ```
    pub fn clear(&mut self) -> &mut Self {
        self.url.serialization.truncate(self.after_first_slash);
        self
    }

    /// Remove the last segment of this URL’s path if it is empty,
    /// except if these was only one segment to begin with.
    ///
    /// In other words, remove one path trailing slash, if any,
    /// unless it is also the initial slash (so this does nothing if `url.path() == "/")`.
    ///
    /// Returns `&mut Self` so that method calls can be chained.
    ///
    /// Example:
    ///
    /// ```rust
    /// # use url::Url;
    /// let mut url = Url::parse("https://github.com/servo/rust-url/").unwrap();
    /// url.path_segments_mut().unwrap().push("pulls");
    /// assert_eq!(url.as_str(), "https://github.com/servo/rust-url//pulls");
    ///
    /// let mut url = Url::parse("https://github.com/servo/rust-url/").unwrap();
    /// url.path_segments_mut().unwrap().pop_if_empty().push("pulls");
    /// assert_eq!(url.as_str(), "https://github.com/servo/rust-url/pulls");
    /// ```
    pub fn pop_if_empty(&mut self) -> &mut Self {
        if self.url.serialization[self.after_first_slash..].ends_with('/') {
            self.url.serialization.pop();
        }
        self
    }

    /// Remove the last segment of this URL’s path.
    ///
    /// If the path only has one segment, make it empty such that `url.path() == "/"`.
    ///
    /// Returns `&mut Self` so that method calls can be chained.
    pub fn pop(&mut self) -> &mut Self {
        let last_slash = self.url.serialization[self.after_first_slash..].rfind('/').unwrap_or(0);
        self.url.serialization.truncate(self.after_first_slash + last_slash);
        self
    }

    /// Append the given segment at the end of this URL’s path.
    ///
    /// See the documentation for `.extend()`.
    ///
    /// Returns `&mut Self` so that method calls can be chained.
    pub fn push(&mut self, segment: &str) -> &mut Self {
        self.extend(Some(segment))
    }

    /// Append each segment from the given iterator at the end of this URL’s path.
    ///
    /// Each segment is percent-encoded like in `Url::parse` or `Url::join`,
    /// except that `%` and `/` characters are also encoded (to `%25` and `%2F`).
    /// This is unlike `Url::parse` where `%` is left as-is in case some of the input
    /// is already percent-encoded, and `/` denotes a path segment separator.)
    ///
    /// Note that, in addition to slashes between new segments,
    /// this always adds a slash between the existing path and the new segments
    /// *except* if the existing path is `"/"`.
    /// If the previous last segment was empty (if the path had a trailing slash)
    /// the path after `.extend()` will contain two consecutive slashes.
    /// If that is undesired, call `.pop_if_empty()` first.
    ///
    /// To obtain a behavior similar to `Url::join`, call `.pop()` unconditionally first.
    ///
    /// Returns `&mut Self` so that method calls can be chained.
    ///
    /// Example:
    ///
    /// ```rust
    /// # use url::Url;
    /// let mut url = Url::parse("https://github.com/").unwrap();
    /// let org = "servo";
    /// let repo = "rust-url";
    /// let issue_number = "188";
    /// url.path_segments_mut().unwrap().extend(&[org, repo, "issues", issue_number]);
    /// assert_eq!(url.as_str(), "https://github.com/servo/rust-url/issues/188");
    /// ```
    ///
    /// In order to make sure that parsing the serialization of an URL gives the same URL,
    /// a segment is ignored if it is `"."` or `".."`:
    ///
    /// ```rust
    /// # use url::Url;
    /// let mut url = Url::parse("https://github.com/servo").unwrap();
    /// url.path_segments_mut().unwrap().extend(&["..", "rust-url", ".", "pulls"]);
    /// assert_eq!(url.as_str(), "https://github.com/servo/rust-url/pulls");
    /// ```
    pub fn extend<I>(&mut self, segments: I) -> &mut Self
    where I: IntoIterator, I::Item: AsRef<str> {
        let scheme_type = SchemeType::from(self.url.scheme());
        let path_start = self.url.path_start as usize;
        self.url.mutate(|parser| {
            parser.context = parser::Context::PathSegmentSetter;
            for segment in segments {
                let segment = segment.as_ref();
                if matches!(segment, "." | "..") {
                    continue
                }
                if parser.serialization.len() > path_start + 1 {
                    parser.serialization.push('/');
                }
                let mut has_host = true;  // FIXME account for this?
                parser.parse_path(scheme_type, &mut has_host, path_start,
                                  parser::Input::new(segment));
            }
        });
        self
    }

    /// For internal testing, not part of the public API.
    #[doc(hidden)]
    pub fn assert_url_invariants(&mut self) -> &mut Self {
        self.url.assert_invariants();
        self
    }
}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate serde_json;
extern crate sqlite3;
extern crate util;
extern crate regex;

use hyper::Client;
use hyper::header::ContentType;
use serde_json::Value;
use sqlite3::DatabaseConnection;
use std::thread;
use std::collections::HashMap;

use util::*;

const EVENTS_URL: &'static str = "http://chat.stackoverflow.com/events";
const MAIN_URL: &'static str = "http://chat.stackoverflow.com/";

const ACTIVE_ROOMS: [i64; 1] = [10];

fn get_key() -> String {
   use std::io::Read;

   let client = Client::new();

   let mut res = client.get(MAIN_URL)
       .send().unwrap();

   let mut buffer = String::new();
   res.read_to_string(&mut buffer).unwrap();

   let re = regex::Regex::new(r##"<input id="fkey" name="fkey" type="hidden" value="([a-f0-9]{32})" />"##).unwrap();
   let groups = re.captures(&buffer).unwrap();

   groups.at(1).unwrap().to_owned()
}

fn get_data(key: &str, room_counters: &HashMap<i64, i64>) -> Value {
    use std::io::Read;

    let body = format!("fkey={}&{}",key, get_all_rooms_string(room_counters));

    let client = Client::new();

    let mut res = client.post(EVENTS_URL)
        .header(ContentType::form_url_encoded())
        .body(&body)
        .send().unwrap();

    let mut buffer = String::new();
    res.read_to_string(&mut buffer).unwrap();

    serde_json::from_str(&buffer).unwrap()
}

fn next_id(data: &Value) -> Option<i64> {
    data.find("t").and_then(|x| x.as_i64())
}

fn get_room_string(room_id: i64) -> String {
    format!("r{}", room_id)
}

fn get_all_rooms_string(room_counters: &HashMap<i64, i64>) -> String {
    room_counters
        .iter()
        .map(|(room_id, room_counter)| format!("{}={}", get_room_string(*room_id), room_counter))
        .collect::<Vec<String>>()
        .join("&")
}

fn update_room_counters(data: &Value, room_counters: &mut HashMap<i64, i64>) {
    for (room_id, current_id) in room_counters.iter_mut() {
        let next_id = data.find(&get_room_string(*room_id)).and_then(|data| next_id(data));
        *current_id = next_id.unwrap_or(*current_id);
    }
}

fn parse_event(event_data: Value) -> Option<Event> {
    let parsed = serde_json::from_value::<Event>(event_data.clone());

    if parsed.is_ok() {
        parsed.ok()
    } else {
        println!("Failed parsing {:?}, error: {:?}", event_data, parsed.err().unwrap());
        None
    }
}

fn get_events_for_room(data: &Value, room_id: i64) -> Vec<Event> {
    data.find(&get_room_string(room_id))
        .and_then(|data| data.find("e"))
        .and_then(|x| x.as_array())
        .map(|x| x.iter()
            .flat_map(|val| parse_event(val.clone()))
            .collect())
        .unwrap_or(Vec::new())
}

fn get_events(data: &Value) -> Vec<Event> {
    ACTIVE_ROOMS.iter().flat_map(|room_id| get_events_for_room(data, *room_id)).collect()
}

fn process_star_event(conn: &mut DatabaseConnection, event: &Event) {
    if let Some(old_event) = get_star_for_message_and_user(conn, event.message_id.unwrap(), event.user_id) {
        if old_event.id == event.id {
            // Repeat event somehow?
//            println!("Ignoring star {:?}", event);
            return;
        } else {
            // This user has added a star, so this must be the remove star event
//            println!("Removing star {:?}", event);
            remove_star_from_db(conn, old_event.id);
        }
    } else {
//        println!("Adding star {:?}", event);
        // Mark the user as starring this item
        add_star_to_db(conn, event);
    }
}

fn process_message_event(conn: &mut DatabaseConnection, event: &Event) {
    update_message(conn, event);
}

fn main() {
    let mut room_counters: HashMap<i64, i64> = ACTIVE_ROOMS.iter().map(|room| (*room, 0)).collect();
    let mut conn = open_connection();

    let key = get_key();

    loop {
        let data = get_data(&key, &room_counters);

        for event in get_events(&data) {
            if event.event_type.unwrap() == 6 {
                process_star_event(&mut conn, &event);
            } else if event.content.is_some() {
                process_message_event(&mut conn, &event);
            }
        }

        update_room_counters(&data, &mut room_counters);
        thread::sleep_ms(4000);
    }
}<commit_msg>Enable on sandbox<commit_after>extern crate hyper;
extern crate serde_json;
extern crate sqlite3;
extern crate util;
extern crate regex;

use hyper::Client;
use hyper::header::ContentType;
use serde_json::Value;
use sqlite3::DatabaseConnection;
use std::thread;
use std::collections::HashMap;

use util::*;

const EVENTS_URL: &'static str = "http://chat.stackoverflow.com/events";
const MAIN_URL: &'static str = "http://chat.stackoverflow.com/";

const ACTIVE_ROOMS: [i64; 1] = [10, 17, 1];

fn get_key() -> String {
   use std::io::Read;

   let client = Client::new();

   let mut res = client.get(MAIN_URL)
       .send().unwrap();

   let mut buffer = String::new();
   res.read_to_string(&mut buffer).unwrap();

   let re = regex::Regex::new(r##"<input id="fkey" name="fkey" type="hidden" value="([a-f0-9]{32})" />"##).unwrap();
   let groups = re.captures(&buffer).unwrap();

   groups.at(1).unwrap().to_owned()
}

fn get_data(key: &str, room_counters: &HashMap<i64, i64>) -> Value {
    use std::io::Read;

    let body = format!("fkey={}&{}",key, get_all_rooms_string(room_counters));

    let client = Client::new();

    let mut res = client.post(EVENTS_URL)
        .header(ContentType::form_url_encoded())
        .body(&body)
        .send().unwrap();

    let mut buffer = String::new();
    res.read_to_string(&mut buffer).unwrap();

    serde_json::from_str(&buffer).unwrap()
}

fn next_id(data: &Value) -> Option<i64> {
    data.find("t").and_then(|x| x.as_i64())
}

fn get_room_string(room_id: i64) -> String {
    format!("r{}", room_id)
}

fn get_all_rooms_string(room_counters: &HashMap<i64, i64>) -> String {
    room_counters
        .iter()
        .map(|(room_id, room_counter)| format!("{}={}", get_room_string(*room_id), room_counter))
        .collect::<Vec<String>>()
        .join("&")
}

fn update_room_counters(data: &Value, room_counters: &mut HashMap<i64, i64>) {
    for (room_id, current_id) in room_counters.iter_mut() {
        let next_id = data.find(&get_room_string(*room_id)).and_then(|data| next_id(data));
        *current_id = next_id.unwrap_or(*current_id);
    }
}

fn parse_event(event_data: Value) -> Option<Event> {
    let parsed = serde_json::from_value::<Event>(event_data.clone());

    if parsed.is_ok() {
        parsed.ok()
    } else {
        println!("Failed parsing {:?}, error: {:?}", event_data, parsed.err().unwrap());
        None
    }
}

fn get_events_for_room(data: &Value, room_id: i64) -> Vec<Event> {
    data.find(&get_room_string(room_id))
        .and_then(|data| data.find("e"))
        .and_then(|x| x.as_array())
        .map(|x| x.iter()
            .flat_map(|val| parse_event(val.clone()))
            .collect())
        .unwrap_or(Vec::new())
}

fn get_events(data: &Value) -> Vec<Event> {
    ACTIVE_ROOMS.iter().flat_map(|room_id| get_events_for_room(data, *room_id)).collect()
}

fn process_star_event(conn: &mut DatabaseConnection, event: &Event) {
    if let Some(old_event) = get_star_for_message_and_user(conn, event.message_id.unwrap(), event.user_id) {
        if old_event.id == event.id {
            // Repeat event somehow?
//            println!("Ignoring star {:?}", event);
            return;
        } else {
            // This user has added a star, so this must be the remove star event
//            println!("Removing star {:?}", event);
            remove_star_from_db(conn, old_event.id);
        }
    } else {
//        println!("Adding star {:?}", event);
        // Mark the user as starring this item
        add_star_to_db(conn, event);
    }
}

fn process_message_event(conn: &mut DatabaseConnection, event: &Event) {
    update_message(conn, event);
}

fn main() {
    let mut room_counters: HashMap<i64, i64> = ACTIVE_ROOMS.iter().map(|room| (*room, 0)).collect();
    let mut conn = open_connection();

    let key = get_key();

    loop {
        let data = get_data(&key, &room_counters);

        for event in get_events(&data) {
            if event.event_type.unwrap() == 6 {
                process_star_event(&mut conn, &event);
            } else if event.content.is_some() {
                process_message_event(&mut conn, &event);
            }
        }

        update_room_counters(&data, &mut room_counters);
        thread::sleep_ms(4000);
    }
}<|endoftext|>


<commit_before>use std::env;
use std::io;
use std::path::Path;
use std::process::Command;
use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions};

use Arch::*;

#[allow(non_camel_case_types)]
#[derive(Copy, Clone)]
pub enum Arch {
    Armv7,
    Armv7s,
    Arm64,
    I386,
    X86_64,
    X86_64_macabi,
}

impl Arch {
    pub fn to_string(self) -> &'static str {
        match self {
            Armv7 => "armv7",
            Armv7s => "armv7s",
            Arm64 => "arm64",
            I386 => "i386",
            X86_64 => "x86_64",
            X86_64_macabi => "x86_64"
        }
    }
}

pub fn get_sdk_root(sdk_name: &str) -> Result<String, String> {
    // Following what clang does
    // (https://github.com/llvm/llvm-project/blob/
    // 296a80102a9b72c3eda80558fb78a3ed8849b341/clang/lib/Driver/ToolChains/Darwin.cpp#L1661-L1678)
    // to allow the SDK path to be set. (For clang, xcrun sets
    // SDKROOT; for rustc, the user or build system can set it, or we
    // can fall back to checking for xcrun on PATH.)
    if let Some(sdkroot) = env::var("SDKROOT").ok() {
        let sdkroot_path = Path::new(&sdkroot);
        if sdkroot_path.is_absolute() && sdkroot_path != Path::new("/") && sdkroot_path.exists() {
            return Ok(sdkroot);
        }
    }
    let res = Command::new("xcrun")
                      .arg("--show-sdk-path")
                      .arg("-sdk")
                      .arg(sdk_name)
                      .output()
                      .and_then(|output| {
                          if output.status.success() {
                              Ok(String::from_utf8(output.stdout).unwrap())
                          } else {
                              let error = String::from_utf8(output.stderr);
                              let error = format!("process exit with error: {}",
                                                  error.unwrap());
                              Err(io::Error::new(io::ErrorKind::Other,
                                                 &error[..]))
                          }
                      });

    match res {
        Ok(output) => Ok(output.trim().to_string()),
        Err(e) => Err(format!("failed to get {} SDK path: {}", sdk_name, e))
    }
}

fn build_pre_link_args(arch: Arch) -> Result<LinkArgs, String> {
    let sdk_name = match arch {
        Armv7 | Armv7s | Arm64 => "iphoneos",
        I386 | X86_64 => "iphonesimulator",
        X86_64_macabi => "macosx10.15",
    };

    let arch_name = arch.to_string();

    let sdk_root = get_sdk_root(sdk_name)?;

    let mut args = LinkArgs::new();
    args.insert(LinkerFlavor::Gcc,
                vec!["-arch".to_string(),
                     arch_name.to_string(),
                     "-isysroot".to_string(),
                     sdk_root.clone(),
                     "-Wl,-syslibroot".to_string(),
                     sdk_root]);

    Ok(args)
}

fn target_cpu(arch: Arch) -> String {
    match arch {
        Armv7 => "cortex-a8", // iOS7 is supported on iPhone 4 and higher
        Armv7s => "cortex-a9",
        Arm64 => "cyclone",
        I386 => "yonah",
        X86_64 => "core2",
        X86_64_macabi => "core2",
    }.to_string()
}

pub fn opts(arch: Arch) -> Result<TargetOptions, String> {
    let pre_link_args = build_pre_link_args(arch)?;
    Ok(TargetOptions {
        cpu: target_cpu(arch),
        dynamic_linking: false,
        executables: true,
        pre_link_args,
        has_elf_tls: false,
        eliminate_frame_pointer: false,
        .. super::apple_base::opts()
    })
}
<commit_msg>Ignore linker env vars set for macOS on iOS targets<commit_after>use std::env;
use std::io;
use std::path::Path;
use std::process::Command;
use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions};

use Arch::*;

#[allow(non_camel_case_types)]
#[derive(Copy, Clone)]
pub enum Arch {
    Armv7,
    Armv7s,
    Arm64,
    I386,
    X86_64,
    X86_64_macabi,
}

impl Arch {
    pub fn to_string(self) -> &'static str {
        match self {
            Armv7 => "armv7",
            Armv7s => "armv7s",
            Arm64 => "arm64",
            I386 => "i386",
            X86_64 => "x86_64",
            X86_64_macabi => "x86_64"
        }
    }
}

pub fn get_sdk_root(sdk_name: &str) -> Result<String, String> {
    // Following what clang does
    // (https://github.com/llvm/llvm-project/blob/
    // 296a80102a9b72c3eda80558fb78a3ed8849b341/clang/lib/Driver/ToolChains/Darwin.cpp#L1661-L1678)
    // to allow the SDK path to be set. (For clang, xcrun sets
    // SDKROOT; for rustc, the user or build system can set it, or we
    // can fall back to checking for xcrun on PATH.)
    if let Some(sdkroot) = env::var("SDKROOT").ok() {
        let p = Path::new(&sdkroot);
        match sdk_name {
            // Ignore `SDKROOT` if it's clearly set for the wrong platform.
            "iphoneos" if sdkroot.contains("iPhoneSimulator.platform")
                       || sdkroot.contains("MacOSX.platform") => (),
            "iphonesimulator" if sdkroot.contains("iPhoneOS.platform")
                              || sdkroot.contains("MacOSX.platform") => (),
            "macosx10.15" if sdkroot.contains("iPhoneOS.platform")
                          || sdkroot.contains("iPhoneSimulator.platform") => (),
            // Ignore `SDKROOT` if it's not a valid path.
            _ if !p.is_absolute() || p == Path::new("/") || !p.exists() => (),
            _ => return Ok(sdkroot),
        }
    }
    let res = Command::new("xcrun")
                      .arg("--show-sdk-path")
                      .arg("-sdk")
                      .arg(sdk_name)
                      .output()
                      .and_then(|output| {
                          if output.status.success() {
                              Ok(String::from_utf8(output.stdout).unwrap())
                          } else {
                              let error = String::from_utf8(output.stderr);
                              let error = format!("process exit with error: {}",
                                                  error.unwrap());
                              Err(io::Error::new(io::ErrorKind::Other,
                                                 &error[..]))
                          }
                      });

    match res {
        Ok(output) => Ok(output.trim().to_string()),
        Err(e) => Err(format!("failed to get {} SDK path: {}", sdk_name, e))
    }
}

fn build_pre_link_args(arch: Arch) -> Result<LinkArgs, String> {
    let sdk_name = match arch {
        Armv7 | Armv7s | Arm64 => "iphoneos",
        I386 | X86_64 => "iphonesimulator",
        X86_64_macabi => "macosx10.15",
    };

    let arch_name = arch.to_string();

    let sdk_root = get_sdk_root(sdk_name)?;

    let mut args = LinkArgs::new();
    args.insert(LinkerFlavor::Gcc,
                vec!["-arch".to_string(),
                     arch_name.to_string(),
                     "-isysroot".to_string(),
                     sdk_root.clone(),
                     "-Wl,-syslibroot".to_string(),
                     sdk_root]);

    Ok(args)
}

fn target_cpu(arch: Arch) -> String {
    match arch {
        Armv7 => "cortex-a8", // iOS7 is supported on iPhone 4 and higher
        Armv7s => "cortex-a9",
        Arm64 => "cyclone",
        I386 => "yonah",
        X86_64 => "core2",
        X86_64_macabi => "core2",
    }.to_string()
}

fn link_env_remove(arch: Arch) -> Vec<String> {
    match arch {
        Armv7 | Armv7s | Arm64 | I386 | X86_64 => vec!["MACOSX_DEPLOYMENT_TARGET".to_string()],
        X86_64_macabi => vec!["IPHONEOS_DEPLOYMENT_TARGET".to_string()],
    }
}

pub fn opts(arch: Arch) -> Result<TargetOptions, String> {
    let pre_link_args = build_pre_link_args(arch)?;
    Ok(TargetOptions {
        cpu: target_cpu(arch),
        dynamic_linking: false,
        executables: true,
        pre_link_args,
        link_env_remove: link_env_remove(arch),
        has_elf_tls: false,
        eliminate_frame_pointer: false,
        .. super::apple_base::opts()
    })
}
<|endoftext|>


<commit_before>// Copyright (c) <2015> <lummax>
// Licensed under MIT (http://opensource.org/licenses/MIT)

mod immix_space;
mod collector;

use self::immix_space::ImmixSpace;
use self::collector::Collector;

use constants::LARGE_OBJECT;
use gc_object::{GCRTTI, GCObjectRef};
use stack;

pub enum CollectionType {
    RCCollection,
    RCEvacCollection,
    ImmixCollection,
    ImmixEvacCollection,
}

impl CollectionType {
    pub fn is_evac(&self) -> bool {
        use self::CollectionType::{RCEvacCollection, ImmixEvacCollection};
        return match *self {
            RCEvacCollection | ImmixEvacCollection => true,
            _ => false,
        }
    }

    pub fn is_immix(&self) -> bool {
        use self::CollectionType::{ImmixCollection, ImmixEvacCollection};
        return match *self {
            ImmixCollection | ImmixEvacCollection => true,
            _ => false,
        }
    }
}

pub struct Spaces {
    immix_space: ImmixSpace,
    collector: Collector,
    current_live_mark: bool,
}

impl Spaces {
    pub fn new() -> Spaces {
        return Spaces {
            immix_space: ImmixSpace::new(),
            collector: Collector::new(),
            current_live_mark: false,
        };
    }

    pub fn is_gc_object(&self, object: GCObjectRef) -> bool {
        return self.immix_space.is_gc_object(object);
    }

    pub fn write_barrier(&mut self, object: GCObjectRef) {
        if self.is_gc_object(object) {
            self.collector.write_barrier(object);
        }
    }

    pub fn allocate(&mut self, rtti: *const GCRTTI) -> Option<GCObjectRef>{
        let size = unsafe{ (*rtti).object_size() };
        debug!("Request to allocate an object of size {}", size);
        return self.immix_space.allocate(rtti)
               .or_else(|| { self.collect(true, true); self.allocate(rtti) });
    }

    pub fn collect(&mut self, evacuation: bool, cycle_collect: bool) {
        debug!("Requested collection (evacuation={}, cycle_collect={})",
               evacuation, cycle_collect);

        let roots = stack::enumerate_roots(self);
        self.collector.extend_all_blocks(self.immix_space.get_all_blocks());
        let collection_type = self.collector.prepare_collection(evacuation,
                                cycle_collect,
                                self.immix_space.available_blocks(),
                                self.immix_space.total_blocks(),
                                self.immix_space.evac_headroom());

        if collection_type.is_immix() {
            for root in roots.iter().map(|o| *o) {
                unsafe{ (*root).set_pinned(true); }
            }
        }

        self.collector.collect(&collection_type, roots.as_slice(),
                               &mut self.immix_space,
                               !self.current_live_mark);

        if collection_type.is_immix() {
            self.current_live_mark = !self.current_live_mark;
            self.immix_space.set_current_live_mark(self.current_live_mark);

            for root in roots.iter() {
                unsafe{ (**root).set_pinned(false); }
            }
        }

        self.collector.complete_collection(&collection_type, &mut self.immix_space);
        valgrind_assert_no_leaks!();
    }
}

<commit_msg>Implement LargeObjectSpace in Spaces<commit_after>// Copyright (c) <2015> <lummax>
// Licensed under MIT (http://opensource.org/licenses/MIT)

mod immix_space;
mod large_object_space;
mod collector;

use self::immix_space::ImmixSpace;
use self::large_object_space::LargeObjectSpace;
use self::collector::Collector;

use constants::LARGE_OBJECT;
use gc_object::{GCRTTI, GCObjectRef};
use stack;

pub enum CollectionType {
    RCCollection,
    RCEvacCollection,
    ImmixCollection,
    ImmixEvacCollection,
}

impl CollectionType {
    pub fn is_evac(&self) -> bool {
        use self::CollectionType::{RCEvacCollection, ImmixEvacCollection};
        return match *self {
            RCEvacCollection | ImmixEvacCollection => true,
            _ => false,
        }
    }

    pub fn is_immix(&self) -> bool {
        use self::CollectionType::{ImmixCollection, ImmixEvacCollection};
        return match *self {
            ImmixCollection | ImmixEvacCollection => true,
            _ => false,
        }
    }
}

pub struct Spaces {
    immix_space: ImmixSpace,
    large_object_space: LargeObjectSpace,
    collector: Collector,
    current_live_mark: bool,
}

impl Spaces {
    pub fn new() -> Spaces {
        return Spaces {
            immix_space: ImmixSpace::new(),
            large_object_space: LargeObjectSpace::new(),
            collector: Collector::new(),
            current_live_mark: false,
        };
    }

    pub fn is_gc_object(&self, object: GCObjectRef) -> bool {
        return self.immix_space.is_gc_object(object)
               || self.large_object_space.is_gc_object(object);
    }

    pub fn write_barrier(&mut self, object: GCObjectRef) {
        if self.is_gc_object(object) {
            self.collector.write_barrier(object);
        }
    }

    pub fn allocate(&mut self, rtti: *const GCRTTI) -> Option<GCObjectRef>{
        let size = unsafe{ (*rtti).object_size() };
        debug!("Request to allocate an object of size {}", size);
        return if size < LARGE_OBJECT { self.immix_space.allocate(rtti) }
               else { self.large_object_space.allocate(rtti) }
               .or_else(|| { self.collect(true, true); self.allocate(rtti) });
    }

    pub fn collect(&mut self, evacuation: bool, cycle_collect: bool) {
        debug!("Requested collection (evacuation={}, cycle_collect={})",
               evacuation, cycle_collect);

        let roots = stack::enumerate_roots(self);
        self.collector.extend_all_blocks(self.immix_space.get_all_blocks());
        let collection_type = self.collector.prepare_collection(evacuation,
                                cycle_collect,
                                self.immix_space.available_blocks(),
                                self.immix_space.total_blocks(),
                                self.immix_space.evac_headroom());

        if collection_type.is_immix() {
            for root in roots.iter().map(|o| *o) {
                unsafe{ (*root).set_pinned(true); }
            }
        }

        self.collector.collect(&collection_type, roots.as_slice(),
                               &mut self.immix_space,
                               !self.current_live_mark);

        if collection_type.is_immix() {
            self.current_live_mark = !self.current_live_mark;
            self.immix_space.set_current_live_mark(self.current_live_mark);
            self.large_object_space.set_current_live_mark(self.current_live_mark);

            for root in roots.iter() {
                unsafe{ (**root).set_pinned(false); }
            }
        }

        self.collector.complete_collection(&collection_type, &mut self.immix_space);
        valgrind_assert_no_leaks!();
    }
}

<|endoftext|>


<commit_before>use std::{
    future::Future,
    pin::Pin,
    sync::{
        atomic::{AtomicBool, Ordering::Relaxed},
        mpsc::{sync_channel, Receiver, SyncSender, TryRecvError},
    },
    task::{Context, Poll, Waker},
};

#[cfg(not(feature = "testing"))]
use std::collections::HashMap as Map;

// we avoid HashMap while testing because
// it makes tests non-deterministic
#[cfg(feature = "testing")]
use std::collections::BTreeMap as Map;

use crate::*;

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

/// An event that happened to a key that a subscriber is interested in.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum Event {
    /// A new complete (key, value) pair
    Insert {
        /// The key that has been set
        key: IVec,
        /// The value that has been set
        value: IVec,
    },
    /// A deleted key
    Remove {
        /// The key that has been removed
        key: IVec,
    },
}

impl Event {
    /// Return the key associated with the `Event`
    pub fn key(&self) -> &IVec {
        match self {
            Event::Insert { key, .. } | Event::Remove { key } => key,
        }
    }
}

type Senders = Map<usize, (Option<Waker>, SyncSender<OneShot<Option<Event>>>)>;

/// A subscriber listening on a specified prefix
///
/// `Subscriber` implements both `Iterator<Item = Event>`
/// and `Future<Output=Option<Event>>`
///
/// # Examples
///
/// Synchronous, blocking subscriber:
/// ```
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// use sled::{Config, Event};
/// let config = Config::new().temporary(true);
///
/// let tree = config.open()?;
///
/// // watch all events by subscribing to the empty prefix
/// let mut subscriber = tree.watch_prefix(vec![]);
///
/// let tree_2 = tree.clone();
/// let thread = std::thread::spawn(move || {
///     tree.insert(vec![0], vec![1])
/// });
///
/// // `Subscription` implements `Iterator<Item=Event>`
/// for event in subscriber.take(1) {
///     match event {
///         Event::Insert{ key, value } => assert_eq!(key.as_ref(), &[0]),
///         Event::Remove {key } => {}
///     }
/// }
///
/// # thread.join().unwrap();
/// # Ok(())
/// # }
/// ```
/// Aynchronous, non-blocking subscriber:
///
/// `Subscription` implements `Future<Output=Option<Event>>`.
///
/// `while let Some(event) = (&mut subscriber).await { /* use it */ }`
pub struct Subscriber {
    id: usize,
    rx: Receiver<OneShot<Option<Event>>>,
    home: Arc<RwLock<Senders>>,
}

impl Drop for Subscriber {
    fn drop(&mut self) {
        let mut w_senders = self.home.write();
        w_senders.remove(&self.id);
    }
}

impl Future for Subscriber {
    type Output = Option<Event>;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        loop {
            match self.rx.try_recv() {
                Ok(mut future_rx) => {
                    #[allow(unsafe_code)]
                    let future_rx =
                        unsafe { std::pin::Pin::new_unchecked(&mut future_rx) };

                    match Future::poll(future_rx, cx) {
                        Poll::Ready(Some(event)) => {
                            return Poll::Ready(event);
                        }
                        Poll::Ready(None) => {
                            continue;
                        }
                        Poll::Pending => {
                            return Poll::Pending;
                        }
                    }
                }
                Err(TryRecvError::Empty) => break,
                Err(TryRecvError::Disconnected) => return Poll::Ready(None),
            }
        }
        let mut home = self.home.write();
        let entry = home.get_mut(&self.id).unwrap();
        entry.0 = Some(cx.waker().clone());
        Poll::Pending
    }
}

impl Iterator for Subscriber {
    type Item = Event;

    fn next(&mut self) -> Option<Event> {
        loop {
            let future_rx = self.rx.recv().ok()?;
            match future_rx.wait() {
                Some(Some(event)) => return Some(event),
                Some(None) => return None,
                None => continue,
            }
        }
    }
}

#[derive(Debug, Default)]
pub(crate) struct Subscribers {
    watched: RwLock<BTreeMap<Vec<u8>, Arc<RwLock<Senders>>>>,
    ever_used: AtomicBool,
}

impl Drop for Subscribers {
    fn drop(&mut self) {
        let watched = self.watched.read();

        for senders in watched.values() {
            let mut senders = senders.write();
            for (_, (waker, sender)) in senders.drain() {
                drop(sender);
                if let Some(waker) = waker {
                    waker.wake();
                }
            }
        }
    }
}

impl Subscribers {
    pub(crate) fn register(&self, prefix: &[u8]) -> Subscriber {
        self.ever_used.store(true, Relaxed);
        let r_mu = {
            let r_mu = self.watched.read();
            if r_mu.contains_key(prefix) {
                r_mu
            } else {
                drop(r_mu);
                let mut w_mu = self.watched.write();
                if !w_mu.contains_key(prefix) {
                    let old = w_mu.insert(
                        prefix.to_vec(),
                        Arc::new(RwLock::new(Map::default())),
                    );
                    assert!(old.is_none());
                }
                drop(w_mu);
                self.watched.read()
            }
        };

        let (tx, rx) = sync_channel(1024);

        let arc_senders = &r_mu[prefix];
        let mut w_senders = arc_senders.write();

        let id = ID_GEN.fetch_add(1, Relaxed);

        w_senders.insert(id, (None, tx));

        Subscriber { id, rx, home: arc_senders.clone() }
    }

    pub(crate) fn reserve<R: AsRef<[u8]>>(
        &self,
        key: R,
    ) -> Option<ReservedBroadcast> {
        if !self.ever_used.load(Relaxed) {
            return None;
        }

        let r_mu = self.watched.read();
        let prefixes = r_mu.iter().filter(|(k, _)| key.as_ref().starts_with(k));

        let mut subscribers = vec![];

        for (_, subs_rwl) in prefixes {
            let subs = subs_rwl.read();

            for (_id, (waker, sender)) in subs.iter() {
                let (tx, rx) = OneShot::pair();
                if sender.send(rx).is_err() {
                    continue;
                }
                subscribers.push((waker.clone(), tx));
            }
        }

        if subscribers.is_empty() {
            None
        } else {
            Some(ReservedBroadcast { subscribers })
        }
    }
}

pub(crate) struct ReservedBroadcast {
    subscribers: Vec<(Option<Waker>, OneShotFiller<Option<Event>>)>,
}

impl ReservedBroadcast {
    pub fn complete(self, event: &Event) {
        let iter = self.subscribers.into_iter();

        for (waker, tx) in iter {
            tx.fill(Some(event.clone()));
            if let Some(waker) = waker {
                waker.wake();
            }
        }
    }
}

#[test]
fn basic_subscriber() {
    let subs = Subscribers::default();

    let mut s2 = subs.register(&[0]);
    let mut s3 = subs.register(&[0, 1]);
    let mut s4 = subs.register(&[1, 2]);

    let r1 = subs.reserve(b"awft");
    assert!(r1.is_none());

    let mut s1 = subs.register(&[]);

    let k2: IVec = vec![].into();
    let r2 = subs.reserve(&k2).unwrap();
    r2.complete(&Event::Insert {
        key: k2.clone(),
        value: IVec::from(k2.clone()),
    });

    let k3: IVec = vec![0].into();
    let r3 = subs.reserve(&k3).unwrap();
    r3.complete(&Event::Insert {
        key: k3.clone(),
        value: IVec::from(k3.clone()),
    });

    let k4: IVec = vec![0, 1].into();
    let r4 = subs.reserve(&k4).unwrap();
    r4.complete(&Event::Remove { key: k4.clone() });

    let k5: IVec = vec![0, 1, 2].into();
    let r5 = subs.reserve(&k5).unwrap();
    r5.complete(&Event::Insert {
        key: k5.clone(),
        value: IVec::from(k5.clone()),
    });

    let k6: IVec = vec![1, 1, 2].into();
    let r6 = subs.reserve(&k6).unwrap();
    r6.complete(&Event::Remove { key: k6.clone() });

    let k7: IVec = vec![1, 1, 2].into();
    let r7 = subs.reserve(&k7).unwrap();
    drop(r7);

    let k8: IVec = vec![1, 2, 2].into();
    let r8 = subs.reserve(&k8).unwrap();
    r8.complete(&Event::Insert {
        key: k8.clone(),
        value: IVec::from(k8.clone()),
    });

    assert_eq!(s1.next().unwrap().key(), &*k2);
    assert_eq!(s1.next().unwrap().key(), &*k3);
    assert_eq!(s1.next().unwrap().key(), &*k4);
    assert_eq!(s1.next().unwrap().key(), &*k5);
    assert_eq!(s1.next().unwrap().key(), &*k6);
    assert_eq!(s1.next().unwrap().key(), &*k8);

    assert_eq!(s2.next().unwrap().key(), &*k3);
    assert_eq!(s2.next().unwrap().key(), &*k4);
    assert_eq!(s2.next().unwrap().key(), &*k5);

    assert_eq!(s3.next().unwrap().key(), &*k4);
    assert_eq!(s3.next().unwrap().key(), &*k5);

    assert_eq!(s4.next().unwrap().key(), &*k8);
}
<commit_msg>Fix swappable-map related issue in subscribers<commit_after>use std::{
    future::Future,
    pin::Pin,
    sync::{
        atomic::{AtomicBool, Ordering::Relaxed},
        mpsc::{sync_channel, Receiver, SyncSender, TryRecvError},
    },
    task::{Context, Poll, Waker},
};

#[cfg(not(feature = "testing"))]
use std::collections::HashMap as Map;

// we avoid HashMap while testing because
// it makes tests non-deterministic
#[cfg(feature = "testing")]
use std::collections::BTreeMap as Map;

use crate::*;

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

/// An event that happened to a key that a subscriber is interested in.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum Event {
    /// A new complete (key, value) pair
    Insert {
        /// The key that has been set
        key: IVec,
        /// The value that has been set
        value: IVec,
    },
    /// A deleted key
    Remove {
        /// The key that has been removed
        key: IVec,
    },
}

impl Event {
    /// Return the key associated with the `Event`
    pub fn key(&self) -> &IVec {
        match self {
            Event::Insert { key, .. } | Event::Remove { key } => key,
        }
    }
}

type Senders = Map<usize, (Option<Waker>, SyncSender<OneShot<Option<Event>>>)>;

/// A subscriber listening on a specified prefix
///
/// `Subscriber` implements both `Iterator<Item = Event>`
/// and `Future<Output=Option<Event>>`
///
/// # Examples
///
/// Synchronous, blocking subscriber:
/// ```
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// use sled::{Config, Event};
/// let config = Config::new().temporary(true);
///
/// let tree = config.open()?;
///
/// // watch all events by subscribing to the empty prefix
/// let mut subscriber = tree.watch_prefix(vec![]);
///
/// let tree_2 = tree.clone();
/// let thread = std::thread::spawn(move || {
///     tree.insert(vec![0], vec![1])
/// });
///
/// // `Subscription` implements `Iterator<Item=Event>`
/// for event in subscriber.take(1) {
///     match event {
///         Event::Insert{ key, value } => assert_eq!(key.as_ref(), &[0]),
///         Event::Remove {key } => {}
///     }
/// }
///
/// # thread.join().unwrap();
/// # Ok(())
/// # }
/// ```
/// Aynchronous, non-blocking subscriber:
///
/// `Subscription` implements `Future<Output=Option<Event>>`.
///
/// `while let Some(event) = (&mut subscriber).await { /* use it */ }`
pub struct Subscriber {
    id: usize,
    rx: Receiver<OneShot<Option<Event>>>,
    home: Arc<RwLock<Senders>>,
}

impl Drop for Subscriber {
    fn drop(&mut self) {
        let mut w_senders = self.home.write();
        w_senders.remove(&self.id);
    }
}

impl Future for Subscriber {
    type Output = Option<Event>;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        loop {
            match self.rx.try_recv() {
                Ok(mut future_rx) => {
                    #[allow(unsafe_code)]
                    let future_rx =
                        unsafe { std::pin::Pin::new_unchecked(&mut future_rx) };

                    match Future::poll(future_rx, cx) {
                        Poll::Ready(Some(event)) => {
                            return Poll::Ready(event);
                        }
                        Poll::Ready(None) => {
                            continue;
                        }
                        Poll::Pending => {
                            return Poll::Pending;
                        }
                    }
                }
                Err(TryRecvError::Empty) => break,
                Err(TryRecvError::Disconnected) => return Poll::Ready(None),
            }
        }
        let mut home = self.home.write();
        let entry = home.get_mut(&self.id).unwrap();
        entry.0 = Some(cx.waker().clone());
        Poll::Pending
    }
}

impl Iterator for Subscriber {
    type Item = Event;

    fn next(&mut self) -> Option<Event> {
        loop {
            let future_rx = self.rx.recv().ok()?;
            match future_rx.wait() {
                Some(Some(event)) => return Some(event),
                Some(None) => return None,
                None => continue,
            }
        }
    }
}

#[derive(Debug, Default)]
pub(crate) struct Subscribers {
    watched: RwLock<BTreeMap<Vec<u8>, Arc<RwLock<Senders>>>>,
    ever_used: AtomicBool,
}

impl Drop for Subscribers {
    fn drop(&mut self) {
        let watched = self.watched.read();

        for senders in watched.values() {
            let senders =
                std::mem::replace(&mut *senders.write(), Map::default());
            for (_, (waker, sender)) in senders {
                drop(sender);
                if let Some(waker) = waker {
                    waker.wake();
                }
            }
        }
    }
}

impl Subscribers {
    pub(crate) fn register(&self, prefix: &[u8]) -> Subscriber {
        self.ever_used.store(true, Relaxed);
        let r_mu = {
            let r_mu = self.watched.read();
            if r_mu.contains_key(prefix) {
                r_mu
            } else {
                drop(r_mu);
                let mut w_mu = self.watched.write();
                if !w_mu.contains_key(prefix) {
                    let old = w_mu.insert(
                        prefix.to_vec(),
                        Arc::new(RwLock::new(Map::default())),
                    );
                    assert!(old.is_none());
                }
                drop(w_mu);
                self.watched.read()
            }
        };

        let (tx, rx) = sync_channel(1024);

        let arc_senders = &r_mu[prefix];
        let mut w_senders = arc_senders.write();

        let id = ID_GEN.fetch_add(1, Relaxed);

        w_senders.insert(id, (None, tx));

        Subscriber { id, rx, home: arc_senders.clone() }
    }

    pub(crate) fn reserve<R: AsRef<[u8]>>(
        &self,
        key: R,
    ) -> Option<ReservedBroadcast> {
        if !self.ever_used.load(Relaxed) {
            return None;
        }

        let r_mu = self.watched.read();
        let prefixes = r_mu.iter().filter(|(k, _)| key.as_ref().starts_with(k));

        let mut subscribers = vec![];

        for (_, subs_rwl) in prefixes {
            let subs = subs_rwl.read();

            for (_id, (waker, sender)) in subs.iter() {
                let (tx, rx) = OneShot::pair();
                if sender.send(rx).is_err() {
                    continue;
                }
                subscribers.push((waker.clone(), tx));
            }
        }

        if subscribers.is_empty() {
            None
        } else {
            Some(ReservedBroadcast { subscribers })
        }
    }
}

pub(crate) struct ReservedBroadcast {
    subscribers: Vec<(Option<Waker>, OneShotFiller<Option<Event>>)>,
}

impl ReservedBroadcast {
    pub fn complete(self, event: &Event) {
        let iter = self.subscribers.into_iter();

        for (waker, tx) in iter {
            tx.fill(Some(event.clone()));
            if let Some(waker) = waker {
                waker.wake();
            }
        }
    }
}

#[test]
fn basic_subscriber() {
    let subs = Subscribers::default();

    let mut s2 = subs.register(&[0]);
    let mut s3 = subs.register(&[0, 1]);
    let mut s4 = subs.register(&[1, 2]);

    let r1 = subs.reserve(b"awft");
    assert!(r1.is_none());

    let mut s1 = subs.register(&[]);

    let k2: IVec = vec![].into();
    let r2 = subs.reserve(&k2).unwrap();
    r2.complete(&Event::Insert {
        key: k2.clone(),
        value: IVec::from(k2.clone()),
    });

    let k3: IVec = vec![0].into();
    let r3 = subs.reserve(&k3).unwrap();
    r3.complete(&Event::Insert {
        key: k3.clone(),
        value: IVec::from(k3.clone()),
    });

    let k4: IVec = vec![0, 1].into();
    let r4 = subs.reserve(&k4).unwrap();
    r4.complete(&Event::Remove { key: k4.clone() });

    let k5: IVec = vec![0, 1, 2].into();
    let r5 = subs.reserve(&k5).unwrap();
    r5.complete(&Event::Insert {
        key: k5.clone(),
        value: IVec::from(k5.clone()),
    });

    let k6: IVec = vec![1, 1, 2].into();
    let r6 = subs.reserve(&k6).unwrap();
    r6.complete(&Event::Remove { key: k6.clone() });

    let k7: IVec = vec![1, 1, 2].into();
    let r7 = subs.reserve(&k7).unwrap();
    drop(r7);

    let k8: IVec = vec![1, 2, 2].into();
    let r8 = subs.reserve(&k8).unwrap();
    r8.complete(&Event::Insert {
        key: k8.clone(),
        value: IVec::from(k8.clone()),
    });

    assert_eq!(s1.next().unwrap().key(), &*k2);
    assert_eq!(s1.next().unwrap().key(), &*k3);
    assert_eq!(s1.next().unwrap().key(), &*k4);
    assert_eq!(s1.next().unwrap().key(), &*k5);
    assert_eq!(s1.next().unwrap().key(), &*k6);
    assert_eq!(s1.next().unwrap().key(), &*k8);

    assert_eq!(s2.next().unwrap().key(), &*k3);
    assert_eq!(s2.next().unwrap().key(), &*k4);
    assert_eq!(s2.next().unwrap().key(), &*k5);

    assert_eq!(s3.next().unwrap().key(), &*k4);
    assert_eq!(s3.next().unwrap().key(), &*k5);

    assert_eq!(s4.next().unwrap().key(), &*k8);
}
<|endoftext|>


<commit_before>extern crate polydraw;

use std::cmp::{Ordering, min, max};
use std::i64;

use polydraw::geom::point::Point;
use polydraw::{Application, Renderer, Frame};
use polydraw::raster::{Scene, Rasterizer, EdgeType, Poly, create_default_vec};

#[derive(Debug, Clone, Copy)]
pub struct Edge {
   pub edge_type: EdgeType,
   pub p1: Point,
   pub p2: Point,
}

impl Edge {
   #[inline]
   pub fn new(edge_type: EdgeType, x1: i64, y1: i64, x2: i64, y2: i64) -> Self {
      Edge {
         edge_type: edge_type,
         p1: Point::new(x1, y1),
         p2: Point::new(x2, y2),
      }
   }

   #[inline]
   pub fn vert_top(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LVT, x1, y1, x2, y2)
   }

   #[inline]
   pub fn vert_bottom(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LVB, x1, y1, x2, y2)
   }

   #[inline]
   pub fn hori_right(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LHR, x1, y1, x2, y2)
   }

   #[inline]
   pub fn hori_left(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LHL, x1, y1, x2, y2)
   }

   #[inline]
   pub fn top_right(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LTR, x1, y1, x2, y2)
   }

   #[inline]
   pub fn top_left(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LTL, x1, y1, x2, y2)
   }

   #[inline]
   pub fn bottom_right(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LBR, x1, y1, x2, y2)
   }

   #[inline]
   pub fn bottom_left(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LBL, x1, y1, x2, y2)
   }
}

#[derive(Debug, Clone, Copy, Default)]
pub struct Section {
   pub edge_type: EdgeType,
   pub p1: Point,
   pub p2: Point,
   pub edge: usize,
   pub poly: usize,
}

impl Section {
   fn set_bottom(&mut self, point: &Point) {
      if self.edge_type.reversed() {
         self.p2 = *point;
      } else {
         self.p1 = *point;
      }
   }

   fn set_top(&mut self, point: &Point) {
      if self.edge_type.reversed() {
         self.p1 = *point;
      } else {
         self.p2 = *point;
      }
   }
}

struct ClipRenderer {
   rasterizer: Rasterizer,
   div_per_pixel: i64,

   edges: Vec<Edge>,
   polys: Vec<Poly>,

   sections: Vec<Section>,
   sections_end: usize,

   sections_min_y: Vec<i64>,
   sections_max_y: Vec<i64>,
   sections_order: Vec<usize>,

   active: Vec<Section>,
   active_source: Vec<usize>,
   active_end: usize,
}

impl ClipRenderer {
   fn new() -> Self {
      let div_per_pixel = 1000;

      let mut edges = vec![
         Edge::top_left(5, 1, 1, 6),       // 0
         Edge::top_right(1, 6, 8, 9),      // 1
         Edge::bottom_right(8, 9, 9, 6),   // 2
         Edge::bottom_left(9, 6, 5, 1),    // 3
         Edge::top_right(1, 1, 3, 8),      // 4
         Edge::bottom_right(3, 8, 10, 4),  // 5
         Edge::bottom_left(10, 4, 1, 1),   // 6
      ];

      for edge in edges.iter_mut() {
         edge.p1.x *= div_per_pixel;
         edge.p1.y *= div_per_pixel;
         edge.p2.x *= div_per_pixel;
         edge.p2.y *= div_per_pixel;
      }

      let polys = vec![
         Poly::new(0, 4, 0),    // 0
         Poly::new(4, 7, 1),    // 1
      ];

      let sections = create_default_vec(65536);

      let sections_min_y = create_default_vec(65536);
      let sections_max_y = create_default_vec(65536);
      let sections_order = create_default_vec(65536);

      let active = create_default_vec(65536);
      let active_source = create_default_vec(65536);

      ClipRenderer {
         rasterizer: Rasterizer::new(),
         div_per_pixel: div_per_pixel,

         edges: edges,
         polys: polys,

         sections: sections,
         sections_end: 0,

         sections_min_y: sections_min_y,
         sections_max_y: sections_max_y,
         sections_order: sections_order,

         active: active,
         active_source: active_source,
         active_end: 0,
      }
   }

   fn create_scene(&self) -> Scene {
      let points = vec![];

      let segments = vec![];

      let circles = vec![];

      let edges = vec![];

      let polys = vec![];

      let colors = vec![];

      Scene {
         points: points,
         segments: segments,
         circles: circles,
         edges: edges,
         polys: polys,
         colors: colors,
      }
   }

   fn eval_sections_min_max_y(&mut self) {
      for section_index in 0..self.sections_end {
         let ref section = self.sections[section_index];

         let mut min_y = i64::MAX;
         let mut max_y = i64::MIN;

         let (section_min_y, section_max_y) = if section.edge_type.reversed() {
            (section.p2.y, section.p1.y)
         } else {
            (section.p1.y, section.p2.y)
         };

         if section_min_y < min_y  {
            min_y = section_min_y;
         }

         if section_max_y > max_y {
            max_y = section_max_y;
         }

         self.sections_min_y[section_index] = min_y;
         self.sections_max_y[section_index] = max_y;
         self.sections_order[section_index] = section_index;
      }

      self.sort_sections_order();

      println!("MIN Y {:?}", &self.sections_min_y[..self.sections_end]);
      println!("MAX Y {:?}", &self.sections_max_y[..self.sections_end]);
      println!("ORDER {:?}", &self.sections_order[..self.sections_end]);

      self.iterate_sections();
   }

   fn sort_sections_order(&mut self) {
      let sections_order = &mut self.sections_order[..self.sections_end];
      let sections_min_y = &self.sections_min_y;
      let sections_max_y = &self.sections_max_y;

      sections_order.sort_by(|a, b| {
         match sections_min_y[*a].cmp(&sections_min_y[*b]) {
            Ordering::Less => Ordering::Less,
            Ordering::Greater => Ordering::Greater,
            Ordering::Equal => sections_max_y[*a].cmp(&sections_max_y[*b])
         }
      });
   }

   fn iterate_sections(&self) {
      let mut prev_y = i64::MIN;
      for order_index in 0..self.sections_end {
         let section_index = self.sections_order[order_index];
         let min_y = self.sections_min_y[section_index];

         println!("I MIN Y {:?} {:?}", section_index, min_y);

         if min_y != prev_y {
            println!("HOR {:?}", min_y);
            prev_y = min_y;
         }
      }
   }

   fn transfer_sections(&mut self) {
      self.sections_end = 0;

      for poly_index in 0..self.polys.len() {
         let ref poly = self.polys[poly_index];

         for edge_index in poly.start..poly.end {
            let ref edge = self.edges[edge_index];

            self.sections[self.sections_end] = Section {
               edge_type: edge.edge_type,
               p1: edge.p1,
               p2: edge.p2,
               edge: edge_index,
               poly: poly_index,
            };

            self.sections_end += 1;
         }
      }

      println!("SECTIONS {:?}", &self.sections[..self.sections_end]);
   }

   fn clip_sections(&mut self) {
      let sections_target = self.sections_order[0];
      let sections_clipper = self.sections_order[1];

      let active_target = self.copy_to_active(sections_target);
      let active_clipper = self.copy_to_active(sections_clipper);

      println!("TARGET {:?}", self.active[active_target]);
      println!("CLIPPER {:?}", self.active[active_clipper]);

      let intersection = self.intersect_sections(
         &self.active[active_target],
         &self.active[active_clipper]
      );
      println!("INTERSECTION {:?}", intersection);

      match intersection {
         Some(pt) => {
            self.sections[sections_clipper].set_bottom(&pt);
            self.change_section_order(1, pt.y);

            self.sections[sections_target].set_bottom(&pt);
            self.change_section_order(0, pt.y);

            self.active[active_target].set_top(&pt);
            self.active[active_clipper].set_top(&pt);
         },
         None => {}
      }

      for index in 0..self.sections_end {
         println!("SECTIONS [{}] - {:?}", index, self.sections[index]);
      }

      for index in 0..self.active_end {
         println!("ACTIVE   [{}] - {:?}", index, self.active[index]);
      }
   }

   fn copy_to_active(&mut self, sections_index: usize) -> usize {
      let active_index = self.active_end;

      self.active_source[active_index] = sections_index;
      self.active[active_index] = self.sections[sections_index];

      self.active_end += 1;

      active_index
   }

   fn change_section_order(&mut self, order_index: usize, new_min_y: i64) {
      println!("NEW MIN Y {:?}", new_min_y);

      let sections_index = self.sections_order[order_index];
      self.sections_min_y[sections_index] = new_min_y;

      let mut current_order_index = order_index;
      let mut next_order_index = order_index + 1;

      while next_order_index < self.sections_end {
         let next_index = self.sections_order[next_order_index];

         if new_min_y > self.sections_min_y[next_index] {
            self.sections_order[current_order_index] = next_index;
            println!("Passing {:?} / {:?}", next_index, self.sections_min_y[next_index]);
         } else {
            break;
         }

         current_order_index = next_order_index;
         next_order_index += 1;
      }

      if current_order_index != order_index {
         self.sections_order[current_order_index] = sections_index;
         println!("Setting {:?}", sections_index);
      }

      for i in 0..self.sections_end {
         let si = self.sections_order[i];
         let min_y = self.sections_min_y[si];
         println!("[I] {:?} {:?} {:?}", i, si, min_y);
      }
   }

   fn intersect_sections(&self, s1: &Section, s2: &Section) -> Option<Point> {
      let s1_a = (s1.p2.y - s1.p1.y) as f64;
      let s1_b = (s1.p1.x - s1.p2.x) as f64;
      let s1_c = (s1.p2.x * s1.p1.y - s1.p1.x * s1.p2.y) as f64;

      let s2_a = (s2.p2.y - s2.p1.y) as f64;
      let s2_b = (s2.p1.x - s2.p2.x) as f64;
      let s2_c = (s2.p2.x * s2.p1.y - s2.p1.x * s2.p2.y) as f64;

      let denominator = s1_a * s2_b - s2_a * s1_b;

      if denominator == 0. {
         return None;
      }

      let x = (s2_c * s1_b - s1_c * s2_b) / denominator;
      let y = (s2_a * s1_c - s1_a * s2_c) / denominator;

      let x = x.round() as i64;
      let y = y.round() as i64;

      let x1 = max(min(s1.p1.x, s1.p2.x), min(s2.p1.x, s2.p2.x));
      let x2 = min(max(s1.p1.x, s1.p2.x), max(s2.p1.x, s2.p2.x));
      let y1 = max(min(s1.p1.y, s1.p2.y), min(s2.p1.y, s2.p2.y));
      let y2 = min(max(s1.p1.y, s1.p2.y), max(s2.p1.y, s2.p2.y));

      if x < x1 || x > x2 || y < y1 || y > y2 {
         return None;
      }

      return Some(Point::new(x, y));
   }
}

impl Renderer for ClipRenderer {
   fn render(&mut self, frame: &mut Frame) {
      frame.clear();

      self.transfer_sections();

      self.eval_sections_min_max_y();

      self.clip_sections();

      let scene = self.create_scene();

      self.rasterizer.render(&scene, frame, self.div_per_pixel);

      panic!("END");
   }
}

fn main() {
   let mut renderer = ClipRenderer::new();

   Application::new()
      .renderer(&mut renderer)
      .title("Clip")
      .run();
}
<commit_msg>Clear the println debugging statements<commit_after>extern crate polydraw;

use std::cmp::{Ordering, min, max};
use std::i64;

use polydraw::geom::point::Point;
use polydraw::{Application, Renderer, Frame};
use polydraw::raster::{Scene, Rasterizer, EdgeType, Poly, create_default_vec};

#[derive(Debug, Clone, Copy)]
pub struct Edge {
   pub edge_type: EdgeType,
   pub p1: Point,
   pub p2: Point,
}

impl Edge {
   #[inline]
   pub fn new(edge_type: EdgeType, x1: i64, y1: i64, x2: i64, y2: i64) -> Self {
      Edge {
         edge_type: edge_type,
         p1: Point::new(x1, y1),
         p2: Point::new(x2, y2),
      }
   }

   #[inline]
   pub fn vert_top(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LVT, x1, y1, x2, y2)
   }

   #[inline]
   pub fn vert_bottom(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LVB, x1, y1, x2, y2)
   }

   #[inline]
   pub fn hori_right(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LHR, x1, y1, x2, y2)
   }

   #[inline]
   pub fn hori_left(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LHL, x1, y1, x2, y2)
   }

   #[inline]
   pub fn top_right(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LTR, x1, y1, x2, y2)
   }

   #[inline]
   pub fn top_left(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LTL, x1, y1, x2, y2)
   }

   #[inline]
   pub fn bottom_right(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LBR, x1, y1, x2, y2)
   }

   #[inline]
   pub fn bottom_left(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LBL, x1, y1, x2, y2)
   }
}

#[derive(Debug, Clone, Copy, Default)]
pub struct Section {
   pub edge_type: EdgeType,
   pub p1: Point,
   pub p2: Point,
   pub edge: usize,
   pub poly: usize,
}

impl Section {
   fn set_bottom(&mut self, point: &Point) {
      if self.edge_type.reversed() {
         self.p2 = *point;
      } else {
         self.p1 = *point;
      }
   }

   fn set_top(&mut self, point: &Point) {
      if self.edge_type.reversed() {
         self.p1 = *point;
      } else {
         self.p2 = *point;
      }
   }
}

struct ClipRenderer {
   rasterizer: Rasterizer,
   div_per_pixel: i64,

   edges: Vec<Edge>,
   polys: Vec<Poly>,

   sections: Vec<Section>,
   sections_end: usize,

   sections_min_y: Vec<i64>,
   sections_max_y: Vec<i64>,
   sections_order: Vec<usize>,

   active: Vec<Section>,
   active_source: Vec<usize>,
   active_end: usize,
}

impl ClipRenderer {
   fn new() -> Self {
      let div_per_pixel = 1000;

      let mut edges = vec![
         Edge::top_left(5, 1, 1, 6),       // 0
         Edge::top_right(1, 6, 8, 9),      // 1
         Edge::bottom_right(8, 9, 9, 6),   // 2
         Edge::bottom_left(9, 6, 5, 1),    // 3
         Edge::top_right(1, 1, 3, 8),      // 4
         Edge::bottom_right(3, 8, 10, 4),  // 5
         Edge::bottom_left(10, 4, 1, 1),   // 6
      ];

      for edge in edges.iter_mut() {
         edge.p1.x *= div_per_pixel;
         edge.p1.y *= div_per_pixel;
         edge.p2.x *= div_per_pixel;
         edge.p2.y *= div_per_pixel;
      }

      let polys = vec![
         Poly::new(0, 4, 0),    // 0
         Poly::new(4, 7, 1),    // 1
      ];

      let sections = create_default_vec(65536);

      let sections_min_y = create_default_vec(65536);
      let sections_max_y = create_default_vec(65536);
      let sections_order = create_default_vec(65536);

      let active = create_default_vec(65536);
      let active_source = create_default_vec(65536);

      ClipRenderer {
         rasterizer: Rasterizer::new(),
         div_per_pixel: div_per_pixel,

         edges: edges,
         polys: polys,

         sections: sections,
         sections_end: 0,

         sections_min_y: sections_min_y,
         sections_max_y: sections_max_y,
         sections_order: sections_order,

         active: active,
         active_source: active_source,
         active_end: 0,
      }
   }

   fn create_scene(&self) -> Scene {
      let points = vec![];

      let segments = vec![];

      let circles = vec![];

      let edges = vec![];

      let polys = vec![];

      let colors = vec![];

      Scene {
         points: points,
         segments: segments,
         circles: circles,
         edges: edges,
         polys: polys,
         colors: colors,
      }
   }

   fn eval_sections_min_max_y(&mut self) {
      for section_index in 0..self.sections_end {
         let ref section = self.sections[section_index];

         let mut min_y = i64::MAX;
         let mut max_y = i64::MIN;

         let (section_min_y, section_max_y) = if section.edge_type.reversed() {
            (section.p2.y, section.p1.y)
         } else {
            (section.p1.y, section.p2.y)
         };

         if section_min_y < min_y  {
            min_y = section_min_y;
         }

         if section_max_y > max_y {
            max_y = section_max_y;
         }

         self.sections_min_y[section_index] = min_y;
         self.sections_max_y[section_index] = max_y;
         self.sections_order[section_index] = section_index;
      }

      self.sort_sections_order();

      self.iterate_sections();
   }

   fn sort_sections_order(&mut self) {
      let sections_order = &mut self.sections_order[..self.sections_end];
      let sections_min_y = &self.sections_min_y;
      let sections_max_y = &self.sections_max_y;

      sections_order.sort_by(|a, b| {
         match sections_min_y[*a].cmp(&sections_min_y[*b]) {
            Ordering::Less => Ordering::Less,
            Ordering::Greater => Ordering::Greater,
            Ordering::Equal => sections_max_y[*a].cmp(&sections_max_y[*b])
         }
      });
   }

   fn iterate_sections(&self) {
      let mut prev_y = i64::MIN;
      for order_index in 0..self.sections_end {
         let section_index = self.sections_order[order_index];
         let min_y = self.sections_min_y[section_index];

         if min_y != prev_y {
            prev_y = min_y;
         }
      }
   }

   fn transfer_sections(&mut self) {
      self.sections_end = 0;

      for poly_index in 0..self.polys.len() {
         let ref poly = self.polys[poly_index];

         for edge_index in poly.start..poly.end {
            let ref edge = self.edges[edge_index];

            self.sections[self.sections_end] = Section {
               edge_type: edge.edge_type,
               p1: edge.p1,
               p2: edge.p2,
               edge: edge_index,
               poly: poly_index,
            };

            self.sections_end += 1;
         }
      }
   }

   fn clip_sections(&mut self) {
      let sections_target = self.sections_order[0];
      let sections_clipper = self.sections_order[1];

      let active_target = self.copy_to_active(sections_target);
      let active_clipper = self.copy_to_active(sections_clipper);

      let intersection = self.intersect_sections(
         &self.active[active_target],
         &self.active[active_clipper]
      );

      match intersection {
         Some(pt) => {
            self.sections[sections_clipper].set_bottom(&pt);
            self.change_section_order(1, pt.y);

            self.sections[sections_target].set_bottom(&pt);
            self.change_section_order(0, pt.y);

            self.active[active_target].set_top(&pt);
            self.active[active_clipper].set_top(&pt);
         },
         None => {}
      }
   }

   fn copy_to_active(&mut self, sections_index: usize) -> usize {
      let active_index = self.active_end;

      self.active_source[active_index] = sections_index;
      self.active[active_index] = self.sections[sections_index];

      self.active_end += 1;

      active_index
   }

   fn change_section_order(&mut self, order_index: usize, new_min_y: i64) {
      let sections_index = self.sections_order[order_index];
      self.sections_min_y[sections_index] = new_min_y;

      let mut current_order_index = order_index;
      let mut next_order_index = order_index + 1;

      while next_order_index < self.sections_end {
         let next_index = self.sections_order[next_order_index];

         if new_min_y > self.sections_min_y[next_index] {
            self.sections_order[current_order_index] = next_index;
         } else {
            break;
         }

         current_order_index = next_order_index;
         next_order_index += 1;
      }

      if current_order_index != order_index {
         self.sections_order[current_order_index] = sections_index;
      }
   }

   fn intersect_sections(&self, s1: &Section, s2: &Section) -> Option<Point> {
      let s1_a = (s1.p2.y - s1.p1.y) as f64;
      let s1_b = (s1.p1.x - s1.p2.x) as f64;
      let s1_c = (s1.p2.x * s1.p1.y - s1.p1.x * s1.p2.y) as f64;

      let s2_a = (s2.p2.y - s2.p1.y) as f64;
      let s2_b = (s2.p1.x - s2.p2.x) as f64;
      let s2_c = (s2.p2.x * s2.p1.y - s2.p1.x * s2.p2.y) as f64;

      let denominator = s1_a * s2_b - s2_a * s1_b;

      if denominator == 0. {
         return None;
      }

      let x = (s2_c * s1_b - s1_c * s2_b) / denominator;
      let y = (s2_a * s1_c - s1_a * s2_c) / denominator;

      let x = x.round() as i64;
      let y = y.round() as i64;

      let x1 = max(min(s1.p1.x, s1.p2.x), min(s2.p1.x, s2.p2.x));
      let x2 = min(max(s1.p1.x, s1.p2.x), max(s2.p1.x, s2.p2.x));
      let y1 = max(min(s1.p1.y, s1.p2.y), min(s2.p1.y, s2.p2.y));
      let y2 = min(max(s1.p1.y, s1.p2.y), max(s2.p1.y, s2.p2.y));

      if x < x1 || x > x2 || y < y1 || y > y2 {
         return None;
      }

      return Some(Point::new(x, y));
   }
}

impl Renderer for ClipRenderer {
   fn render(&mut self, frame: &mut Frame) {
      frame.clear();

      self.transfer_sections();

      self.eval_sections_min_max_y();

      self.clip_sections();

      let scene = self.create_scene();

      self.rasterizer.render(&scene, frame, self.div_per_pixel);

      panic!("END");
   }
}

fn main() {
   let mut renderer = ClipRenderer::new();

   Application::new()
      .renderer(&mut renderer)
      .title("Clip")
      .run();
}
<|endoftext|>


<commit_before>//! A "souped up" echo server example.
//!
//! Very similar to the example at https://tokio.rs

#![feature(proc_macro, conservative_impl_trait, generators)]

extern crate futures_await as futures;
extern crate tokio_core;
extern crate tokio_io;

use std::io::{self, BufReader};

use futures::prelude::*;
use tokio_core::net::{TcpListener, TcpStream};
use tokio_core::reactor::Core;
use tokio_io::{AsyncRead};

fn main() {
    // Create the event loop that will drive this server
    let mut core = Core::new().unwrap();
    let handle = core.handle();

    // Bind the server's socket
    let addr = "127.0.0.1:12345".parse().unwrap();
    let tcp = TcpListener::bind(&addr, &handle).expect("failed to bind listener");
    println!("listening for connections on {}",
             tcp.local_addr().unwrap());

    let server = async_block! {
        #[async]
        for (client, _) in tcp.incoming() {
            handle.spawn(handle_client(client).for_each(|n| {
                println!("wrote {} bytes", n);
                Ok(())
            }).map_err(|e| {
                println!("IO error {:?}", e);
            }));
        }

        Ok::<(), io::Error>(())
    };
    core.run(server).unwrap();
}

#[async_stream(item = u64)]
fn handle_client(socket: TcpStream) -> io::Result<()> {
    let (reader, mut writer) = socket.split();
    let input = BufReader::new(reader);

    #[async]
    for line in tokio_io::io::lines(input) {
        println!("got client line: {}", line);
        stream_yield!(line.len() as u64);
        writer = await!(tokio_io::io::write_all(writer, line))?.0;
    }

    Ok(())
}
<commit_msg>Revert echo example stream changes<commit_after>//! A "souped up" echo server example.
//!
//! Very similar to the example at https://tokio.rs

#![feature(proc_macro, conservative_impl_trait, generators)]

extern crate futures_await as futures;
extern crate tokio_core;
extern crate tokio_io;

use std::io::{self, BufReader};

use futures::prelude::*;
use tokio_core::net::{TcpListener, TcpStream};
use tokio_core::reactor::Core;
use tokio_io::{AsyncRead};

fn main() {
    // Create the event loop that will drive this server
    let mut core = Core::new().unwrap();
    let handle = core.handle();

    // Bind the server's socket
    let addr = "127.0.0.1:12345".parse().unwrap();
    let tcp = TcpListener::bind(&addr, &handle).expect("failed to bind listener");
    println!("listening for connections on {}",
             tcp.local_addr().unwrap());

    let server = async_block! {
        #[async]
        for (client, _) in tcp.incoming() {
            handle.spawn(handle_client(client).then(|result| {
                match result {
                    Ok(n) => println!("wrote {} bytes", n),
                    Err(e) => println!("IO error {:?}", e),
                }
                Ok(())
            }));
        }

        Ok::<(), io::Error>(())
    };
    core.run(server).unwrap();
}

#[async]
fn handle_client(socket: TcpStream) -> io::Result<u64> {
    let (reader, mut writer) = socket.split();
    let input = BufReader::new(reader);

    let mut total = 0;

    #[async]
    for line in tokio_io::io::lines(input) {
        println!("got client line: {}", line);
        total += line.len() as u64;
        writer = await!(tokio_io::io::write_all(writer, line))?.0;
    }

    Ok(total)
}
<|endoftext|>


<commit_before>use std::collections::VecDeque;
use std::io;
use std::net::SocketAddr;
use std::sync::{Arc, Mutex};

use futures::{Future, Sink, Stream};
use futures::sync::{mpsc, oneshot};

use tokio_core::net::TcpStream;
use tokio_core::reactor::Core;
use tokio_io::AsyncRead;

use super::{error, resp};

/// TODO: comeback and optimise this number
const DEFAULT_BUFFER_SIZE:usize = 100;

/// Connect to a Redis server and return paired Sink and Stream for reading and writing
/// asynchronously.
fn connect(addr: &SocketAddr, core: &Core) -> Box<Future<Item=ClientConnection, Error=io::Error>> {
    let handle = core.handle();
    let client_con = TcpStream::connect(addr, &handle).map(move |socket| {
        let framed = socket.framed(resp::RespCodec);
        let (write_f, read_f) = framed.split();
        let write_b = write_f.buffer(DEFAULT_BUFFER_SIZE);
        ClientConnection {
            sender: ClientSink(Box::new(write_b)),
            receiver: ClientStream(Box::new(read_f))
        }
    });
    Box::new(client_con)
}

/// TODO - is the boxing necessary?  It makes the type signature much simpler
struct ClientSink(Box<Sink<SinkItem=resp::RespValue, SinkError=io::Error>>);
struct ClientStream(Box<Stream<Item=resp::RespValue, Error=error::Error>>);

/// A low-level client connection representing a sender and a receiver.
///
/// The two halves operate independently from one another
struct ClientConnection {
    sender: ClientSink,
    receiver: ClientStream
}

fn paired_connect(addr: &SocketAddr, core: &Core) -> Box<Future<Item=PairedConnection, Error=error::Error>> {
    let handle = core.handle();
    let paired_con = connect(addr, core).map(move |connection| {
        let ClientConnection { sender, receiver } = connection;
        let (out_tx, out_rx) = mpsc::unbounded();
        let sender = out_rx.fold(sender.0, |sender, msg| {
            sender.send(msg).map_err(|_| ())
        });
        let resp_queue:Arc<Mutex<VecDeque<oneshot::Sender<resp::RespValue>>>> = Arc::new(Mutex::new(VecDeque::new()));
        let receiver_queue = resp_queue.clone();
        let receiver = receiver.0.for_each(move |msg| {
            let mut queue = receiver_queue.lock().expect("Lock is tainted");
            let dest = queue.pop_front().expect("Queue is empty");
            match dest.send(msg) {
                Ok(()) => Ok(()),
                Err(_) => Ok(())
            }
        });
        handle.spawn(sender.map(|_| ()));
        handle.spawn(receiver.map_err(|_| ()));
        PairedConnection {
            out_tx: out_tx,
            resp_queue: resp_queue
        }
    }).map_err(|e| e.into());
    Box::new(paired_con)
}

struct PairedConnection {
    out_tx: mpsc::UnboundedSender<resp::RespValue>,
    resp_queue: Arc<Mutex<VecDeque<oneshot::Sender<resp::RespValue>>>>
}

impl PairedConnection {
    fn send<R>(&self, msg: R) -> Box<Future<Item=resp::RespValue, Error=error::Error>>
    where R: Into<resp::RespValue> {
        let (tx, rx) = oneshot::channel();
        let mut queue = self.resp_queue.lock().expect("Tainted queue");
        queue.push_back(tx);
        mpsc::UnboundedSender::send(&self.out_tx, msg.into()).expect("Successful send");
        Box::new(rx.map_err(|e| e.into()))
    }
}

#[cfg(test)]
mod test {
    use std::io;

    use futures::{Future, Sink, Stream};
    use futures::stream;

    use tokio_core::reactor::Core;

    use super::resp;

    #[test]
    fn can_connect() {
        let mut core = Core::new().unwrap();
        let addr = "127.0.0.1:6379".parse().unwrap();

        let connection = super::connect(&addr, &core).map_err(|e| e.into()).and_then(|connection| {
            let a = connection.sender.0.send(["PING", "TEST"].as_ref().into()).map_err(|e| e.into());
            let b = connection.receiver.0.take(1).collect();
            a.join(b)
        });

        let (_, values) = core.run(connection).unwrap();
        assert_eq!(values.len(), 1);
        assert_eq!(values[0], "TEST".into());
    }

    #[test]
    fn complex_test() {
        let mut core = Core::new().unwrap();
        let addr = "127.0.0.1:6379".parse().unwrap();
        let connection = super::connect(&addr, &core).map_err(|e| e.into()).and_then(|connection| {
            let mut ops = Vec::<resp::RespValue>::new();
            ops.push(["FLUSH"].as_ref().into());
            ops.extend((0..1000).map(|i| ["SADD", "test_set", &format!("VALUE: {}", i)].as_ref().into()));
            ops.push(["SMEMBERS", "test_set"].as_ref().into());
            let ops_r:Vec<Result<resp::RespValue, io::Error>> = ops.into_iter().map(Result::Ok).collect();
            let send = connection.sender.0.send_all(stream::iter(ops_r)).map_err(|e| e.into());
            let receive = connection.receiver.0.skip(1001).take(1).collect();
            send.join(receive)
        });
        let (_, values) = core.run(connection).unwrap();
        assert_eq!(values.len(), 1);
        let values = match &values[0] {
            &resp::RespValue::Array(ref values) => values.clone(),
            _ => panic!("Not an array")
        };
        assert_eq!(values.len(), 1000);
    }

    #[test]
    fn can_paired_connect() {
        let mut core = Core::new().unwrap();
        let addr = "127.0.0.1:6379".parse().unwrap();

        let connect_f = super::paired_connect(&addr, &core).and_then(|connection| {
            let res_f = connection.send(vec!["PING", "TEST"]);
            connection.send(vec!["SET", "X", "123"]);
            let wait_f = connection.send(vec!["GET", "X"]);
            res_f.join(wait_f)
        });
        let (result_1, result_2) = core.run(connect_f).unwrap();
        assert_eq!(result_1, "TEST".into());
        assert_eq!(result_2, "123".into());
    }

    #[test]
    fn complex_paired_connect() {
        let mut core = Core::new().unwrap();
        let addr = "127.0.0.1:6379".parse().unwrap();

        let connect_f = super::paired_connect(&addr, &core).and_then(|connection| {
            connection.send(vec!["INCR", "CTR"]).and_then(move |value| {
                let value_str = value.into_string().expect("A string");
                connection.send(vec!["SET", "LASTCTR", &value_str])
            })
        });
        let result = core.run(connect_f).unwrap();
        assert_eq!(result, resp::RespValue::SimpleString("OK".into()));
    }
}<commit_msg>Sending a lot of data to test pipelining<commit_after>use std::collections::VecDeque;
use std::io;
use std::net::SocketAddr;
use std::sync::{Arc, Mutex};

use futures::{Future, Sink, Stream};
use futures::sync::{mpsc, oneshot};

use tokio_core::net::TcpStream;
use tokio_core::reactor::Core;
use tokio_io::AsyncRead;

use super::{error, resp};

/// TODO: comeback and optimise this number
const DEFAULT_BUFFER_SIZE:usize = 100;

/// Connect to a Redis server and return paired Sink and Stream for reading and writing
/// asynchronously.
fn connect(addr: &SocketAddr, core: &Core) -> Box<Future<Item=ClientConnection, Error=io::Error>> {
    let handle = core.handle();
    let client_con = TcpStream::connect(addr, &handle).map(move |socket| {
        let framed = socket.framed(resp::RespCodec);
        let (write_f, read_f) = framed.split();
        let write_b = write_f.buffer(DEFAULT_BUFFER_SIZE);
        ClientConnection {
            sender: ClientSink(Box::new(write_b)),
            receiver: ClientStream(Box::new(read_f))
        }
    });
    Box::new(client_con)
}

/// TODO - is the boxing necessary?  It makes the type signature much simpler
struct ClientSink(Box<Sink<SinkItem=resp::RespValue, SinkError=io::Error>>);
struct ClientStream(Box<Stream<Item=resp::RespValue, Error=error::Error>>);

/// A low-level client connection representing a sender and a receiver.
///
/// The two halves operate independently from one another
struct ClientConnection {
    sender: ClientSink,
    receiver: ClientStream
}

fn paired_connect(addr: &SocketAddr, core: &Core) -> Box<Future<Item=PairedConnection, Error=error::Error>> {
    let handle = core.handle();
    let paired_con = connect(addr, core).map(move |connection| {
        let ClientConnection { sender, receiver } = connection;
        let (out_tx, out_rx) = mpsc::unbounded();
        let sender = out_rx.fold(sender.0, |sender, msg| {
            sender.send(msg).map_err(|_| ())
        });
        let resp_queue:Arc<Mutex<VecDeque<oneshot::Sender<resp::RespValue>>>> = Arc::new(Mutex::new(VecDeque::new()));
        let receiver_queue = resp_queue.clone();
        let receiver = receiver.0.for_each(move |msg| {
            let mut queue = receiver_queue.lock().expect("Lock is tainted");
            let dest = queue.pop_front().expect("Queue is empty");
            match dest.send(msg) {
                Ok(()) => Ok(()),
                Err(_) => Ok(())
            }
        });
        handle.spawn(sender.map(|_| ()));
        handle.spawn(receiver.map_err(|_| ()));
        PairedConnection {
            out_tx: out_tx,
            resp_queue: resp_queue
        }
    }).map_err(|e| e.into());
    Box::new(paired_con)
}

struct PairedConnection {
    out_tx: mpsc::UnboundedSender<resp::RespValue>,
    resp_queue: Arc<Mutex<VecDeque<oneshot::Sender<resp::RespValue>>>>
}

impl PairedConnection {
    fn send<R>(&self, msg: R) -> Box<Future<Item=resp::RespValue, Error=error::Error>>
    where R: Into<resp::RespValue> {
        let (tx, rx) = oneshot::channel();
        let mut queue = self.resp_queue.lock().expect("Tainted queue");
        queue.push_back(tx);
        mpsc::UnboundedSender::send(&self.out_tx, msg.into()).expect("Successful send");
        Box::new(rx.map_err(|e| e.into()))
    }
}

#[cfg(test)]
mod test {
    use std::io;

    use futures::{Future, Sink, Stream};
    use futures::stream;

    use tokio_core::reactor::Core;

    use super::resp;

    #[test]
    fn can_connect() {
        let mut core = Core::new().unwrap();
        let addr = "127.0.0.1:6379".parse().unwrap();

        let connection = super::connect(&addr, &core).map_err(|e| e.into()).and_then(|connection| {
            let a = connection.sender.0.send(["PING", "TEST"].as_ref().into()).map_err(|e| e.into());
            let b = connection.receiver.0.take(1).collect();
            a.join(b)
        });

        let (_, values) = core.run(connection).unwrap();
        assert_eq!(values.len(), 1);
        assert_eq!(values[0], "TEST".into());
    }

    #[test]
    fn complex_test() {
        let mut core = Core::new().unwrap();
        let addr = "127.0.0.1:6379".parse().unwrap();
        let connection = super::connect(&addr, &core).map_err(|e| e.into()).and_then(|connection| {
            let mut ops = Vec::<resp::RespValue>::new();
            ops.push(["FLUSH"].as_ref().into());
            ops.extend((0..1000).map(|i| ["SADD", "test_set", &format!("VALUE: {}", i)].as_ref().into()));
            ops.push(["SMEMBERS", "test_set"].as_ref().into());
            let ops_r:Vec<Result<resp::RespValue, io::Error>> = ops.into_iter().map(Result::Ok).collect();
            let send = connection.sender.0.send_all(stream::iter(ops_r)).map_err(|e| e.into());
            let receive = connection.receiver.0.skip(1001).take(1).collect();
            send.join(receive)
        });
        let (_, values) = core.run(connection).unwrap();
        assert_eq!(values.len(), 1);
        let values = match &values[0] {
            &resp::RespValue::Array(ref values) => values.clone(),
            _ => panic!("Not an array")
        };
        assert_eq!(values.len(), 1000);
    }

    #[test]
    fn can_paired_connect() {
        let mut core = Core::new().unwrap();
        let addr = "127.0.0.1:6379".parse().unwrap();

        let connect_f = super::paired_connect(&addr, &core).and_then(|connection| {
            let res_f = connection.send(vec!["PING", "TEST"]);
            connection.send(vec!["SET", "X", "123"]);
            let wait_f = connection.send(vec!["GET", "X"]);
            res_f.join(wait_f)
        });
        let (result_1, result_2) = core.run(connect_f).unwrap();
        assert_eq!(result_1, "TEST".into());
        assert_eq!(result_2, "123".into());
    }

    #[test]
    fn complex_paired_connect() {
        let mut core = Core::new().unwrap();
        let addr = "127.0.0.1:6379".parse().unwrap();

        let connect_f = super::paired_connect(&addr, &core).and_then(|connection| {
            connection.send(vec!["INCR", "CTR"]).and_then(move |value| {
                let value_str = value.into_string().expect("A string");
                connection.send(vec!["SET", "LASTCTR", &value_str])
            })
        });
        let result = core.run(connect_f).unwrap();
        assert_eq!(result, resp::RespValue::SimpleString("OK".into()));
    }

    #[test]
    fn sending_a_lot_of_data_test() {
        let mut core = Core::new().unwrap();
        let addr = "127.0.0.1:6379".parse().unwrap();

        let test_f = super::paired_connect(&addr, &core);
        let send_data = test_f.and_then(|connection| {
            let mut futures = Vec::with_capacity(1000);
            for i in 0..1000 {
                let key = format!("X_{}", i);
                connection.send(vec!["SET", &key, &i.to_string()]);
                futures.push(connection.send(vec!["GET", &key]));
            }
            futures.remove(999)
        });
        let result = core.run(send_data).unwrap();
        assert_eq!(result.into_string().unwrap(), "999");
    }
}<|endoftext|>