<commit_before>#[cfg(test)]
mod tests;
mod response;

pub use message::response::*;
use notification::Notification;
use std::collections::HashMap;
use std::collections::BTreeMap;
use std::str;
use curl::http;
use rustc_serialize::json::{self, Json, ToJson};

#[derive(PartialEq, Debug, Clone)]
pub enum Priority {
  Normal, High
}

/// Represents a GCM message. Construct the GCM message
/// using various utility methods and finally send it.
/// # Examples:
/// ```rust
/// use gcm::Message;
///
/// let message = Message::new("<registration id>").dry_run(true);
/// ```
pub struct Message<'a> {
  to: &'a str,
  registration_ids: Option<Vec<String>>,
  collapse_key: Option<&'a str>,
  priority: Option<Priority>,
  content_available: Option<bool>,
  delay_while_idle: Option<bool>,
  time_to_live: Option<i32>,
  restricted_package_name: Option<&'a str>,
  dry_run: Option<bool>,
  data: Option<HashMap<String, String>>,
  notification: Option<Notification<'a>>,
}

impl <'a> ToJson for Message<'a> {
  fn to_json(&self) -> Json {
    let mut root = BTreeMap::new();

    root.insert("to".to_string(), self.to.to_json());

    if self.registration_ids.is_some() {
      root.insert("registration_ids".to_string(),
          self.registration_ids.clone().unwrap().to_json());
    }

    if self.collapse_key.is_some() {
      root.insert("collapse_key".to_string(), self.collapse_key.clone().unwrap().to_json());
    }

    if self.priority.is_some() {
      root.insert("priority".to_string(), match self.priority.clone().unwrap() {
        Priority::Normal => Json::String("normal".to_string()),
        Priority::High => Json::String("high".to_string()),
      });
    }

    if self.content_available.is_some() {
      root.insert("content_available".to_string(), self.content_available.unwrap().to_json());
    }

    if self.delay_while_idle.is_some() {
      root.insert("delay_while_idle".to_string(), self.delay_while_idle.unwrap().to_json());
    }

    if self.time_to_live.is_some() {
      root.insert("time_to_live".to_string(), self.time_to_live.unwrap().to_json());
    }

    if self.restricted_package_name.is_some() {
      root.insert("restricted_package_name".to_string(), self.restricted_package_name.clone().unwrap().to_json());
    }

    if self.dry_run.is_some() {
      root.insert("dry_run".to_string(), self.dry_run.unwrap().to_json());
    }

    if self.data.is_some() {
      root.insert("data".to_string(), self.data.clone().unwrap().to_json());
    }

    if self.notification.is_some() {
      root.insert("notification".to_string(), self.notification.clone().unwrap().to_json());
    }

    Json::Object(root)
  }
}

impl <'a> Message<'a> {
  /// Get a new instance of Message. You need to supply either
  /// a registration id, or a topic (/topic/...).
  pub fn new(to: &'a str) -> Message {
    Message {
      to: to,
      registration_ids: None,
      collapse_key: None,
      priority: None,
      content_available: None,
      delay_while_idle: None,
      time_to_live: None,
      restricted_package_name: None,
      dry_run: None,
      data: None,
      notification: None,
    }
  }

  /// Set various registration ids to which the message ought to be sent.
  pub fn registration_ids(mut self, ids: Vec<&'a str>) -> Message<'a> {
    self.registration_ids = Some(ids.iter().map(|s| s.to_string()).collect());
    self
  }

  /// Set this parameter to identify groups of messages that can be collapsed.
  pub fn collapse_key(mut self, collapse_key: &'a str) -> Message<'a> {
    self.collapse_key = Some(collapse_key);
    self
  }

  /// Set the priority of the message. You can set Normal or High priorities.
  /// # Examples:
  /// ```rust
  /// use gcm::{Message, Priority};
  ///
  /// let message = Message::new("<registration id>")
  ///     .priority(Priority::High);
  /// ```
  pub fn priority(mut self, priority: Priority) -> Message<'a> {
    self.priority = Some(priority);
    self
  }

  /// To set the `content-available` field on iOS
  pub fn content_available(mut self, content_available: bool) -> Message<'a> {
    self.content_available = Some(content_available);
    self
  }

  /// When set to `true`, sends the message only when the device is active.
  pub fn delay_while_idle(mut self, delay_while_idle: bool) -> Message<'a> {
    self.delay_while_idle = Some(delay_while_idle);
    self
  }

  /// How long (in seconds) to keep the message on GCM servers in case the device
  /// is offline. The maximum and default is 4 weeks.
  pub fn time_to_live(mut self, time_to_live: i32) -> Message<'a> {
    self.time_to_live = Some(time_to_live);
    self
  }

  /// Package name of the application where the registration tokens must match.
  pub fn restricted_package_name(mut self, restricted_package_name: &'a str) -> Message<'a> {
    self.restricted_package_name = Some(restricted_package_name);
    self
  }

  /// When set to `true`, allows you to test GCM without actually sending the message.
  pub fn dry_run(mut self, dry_run: bool) -> Message<'a> {
    self.dry_run = Some(dry_run);
    self
  }

  /// Use this to add custom key-value pairs to the message. This data
  /// must be handled appropriately on the client end.
  /// # Examples:
  /// ```rust
  /// use gcm::Message;
  /// use std::collections::HashMap;
  ///
  /// let mut map = HashMap::new();
  /// map.insert("message", "Howdy!");
  ///
  /// let message = Message::new("<registration id>").data(map);
  /// ```
  pub fn data(mut self, data: HashMap<&'a str, &'a str>) -> Message<'a> {
    let mut datamap: HashMap<String, String> = HashMap::new();
    for (key, val) in data.iter() {
      datamap.insert(key.to_string(), val.to_string());
    }

    self.data = Some(datamap);
    self
  }

  /// Use this to set a `Notification` for the message.
  /// # Examples:
  /// ```rust
  /// use gcm::{Message, NotificationBuilder};
  ///
  /// let notification = NotificationBuilder::new("Hey!")
  ///     .body("Do you want to catch up later?")
  ///     .finalize();
  ///
  /// let message = Message::new("<registration id>")
  ///     .notification(notification);
  /// ```
  pub fn notification(mut self, notification: Notification<'a>) -> Message<'a> {
    self.notification = Some(notification);
    self
  }

  /// Send the message using your GCM API Key.
  /// # Examples:
  /// ```no_run
  /// use gcm::Message;
  /// use std::collections::HashMap;
  ///
  /// let mut map = HashMap::new();
  /// map.insert("message", "Howdy!");
  ///
  /// let result = Message::new("<registration id>")
  ///     .data(map)
  ///     .send("<GCM API Key>");
  /// ```
  pub fn send(self, api_key: &'a str) -> Result<response::GcmResponse, response::GcmError> {
    let payload = self.to_json().to_string();
    let auth_header = "key=".to_string() + api_key;
    let res;
    let body;
    let code;

    let result = http::handle()
        .post("https://gcm-http.googleapis.com/gcm/send", &payload)
        .header("Authorization", &auth_header)
        .header("Content-Type", "application/json")
        .exec();

    match result {
      Ok(unwrapped) => {
        res = unwrapped;
        body = str::from_utf8(res.get_body()).unwrap();
        code = res.get_code();

        Message::parse_response(code, body)
      },
      Err(_) => {
        Message::parse_response(500, "Server Error")
      }
    }
  }

  fn parse_response(status: u32, body: &str) -> Result<response::GcmResponse, response::GcmError> {
    match status {
      200 => {
        Ok(json::decode(body).unwrap())
      },
      401 => Err(response::GcmError::Unauthorized),
      400 => Err(response::GcmError::InvalidMessage(body.to_string())),
      500...599 => Err(response::GcmError::ServerError),
      _ => Err(response::GcmError::InvalidMessage("Unknown Error".to_string())),
    }
  }
}<commit_msg>make mod response public<commit_after>#[cfg(test)]
mod tests;
pub mod response;

pub use message::response::*;
use notification::Notification;
use std::collections::HashMap;
use std::collections::BTreeMap;
use std::str;
use curl::http;
use rustc_serialize::json::{self, Json, ToJson};

#[derive(PartialEq, Debug, Clone)]
pub enum Priority {
  Normal, High
}

/// Represents a GCM message. Construct the GCM message
/// using various utility methods and finally send it.
/// # Examples:
/// ```rust
/// use gcm::Message;
///
/// let message = Message::new("<registration id>").dry_run(true);
/// ```
pub struct Message<'a> {
  to: &'a str,
  registration_ids: Option<Vec<String>>,
  collapse_key: Option<&'a str>,
  priority: Option<Priority>,
  content_available: Option<bool>,
  delay_while_idle: Option<bool>,
  time_to_live: Option<i32>,
  restricted_package_name: Option<&'a str>,
  dry_run: Option<bool>,
  data: Option<HashMap<String, String>>,
  notification: Option<Notification<'a>>,
}

impl <'a> ToJson for Message<'a> {
  fn to_json(&self) -> Json {
    let mut root = BTreeMap::new();

    root.insert("to".to_string(), self.to.to_json());

    if self.registration_ids.is_some() {
      root.insert("registration_ids".to_string(),
          self.registration_ids.clone().unwrap().to_json());
    }

    if self.collapse_key.is_some() {
      root.insert("collapse_key".to_string(), self.collapse_key.clone().unwrap().to_json());
    }

    if self.priority.is_some() {
      root.insert("priority".to_string(), match self.priority.clone().unwrap() {
        Priority::Normal => Json::String("normal".to_string()),
        Priority::High => Json::String("high".to_string()),
      });
    }

    if self.content_available.is_some() {
      root.insert("content_available".to_string(), self.content_available.unwrap().to_json());
    }

    if self.delay_while_idle.is_some() {
      root.insert("delay_while_idle".to_string(), self.delay_while_idle.unwrap().to_json());
    }

    if self.time_to_live.is_some() {
      root.insert("time_to_live".to_string(), self.time_to_live.unwrap().to_json());
    }

    if self.restricted_package_name.is_some() {
      root.insert("restricted_package_name".to_string(), self.restricted_package_name.clone().unwrap().to_json());
    }

    if self.dry_run.is_some() {
      root.insert("dry_run".to_string(), self.dry_run.unwrap().to_json());
    }

    if self.data.is_some() {
      root.insert("data".to_string(), self.data.clone().unwrap().to_json());
    }

    if self.notification.is_some() {
      root.insert("notification".to_string(), self.notification.clone().unwrap().to_json());
    }

    Json::Object(root)
  }
}

impl <'a> Message<'a> {
  /// Get a new instance of Message. You need to supply either
  /// a registration id, or a topic (/topic/...).
  pub fn new(to: &'a str) -> Message {
    Message {
      to: to,
      registration_ids: None,
      collapse_key: None,
      priority: None,
      content_available: None,
      delay_while_idle: None,
      time_to_live: None,
      restricted_package_name: None,
      dry_run: None,
      data: None,
      notification: None,
    }
  }

  /// Set various registration ids to which the message ought to be sent.
  pub fn registration_ids(mut self, ids: Vec<&'a str>) -> Message<'a> {
    self.registration_ids = Some(ids.iter().map(|s| s.to_string()).collect());
    self
  }

  /// Set this parameter to identify groups of messages that can be collapsed.
  pub fn collapse_key(mut self, collapse_key: &'a str) -> Message<'a> {
    self.collapse_key = Some(collapse_key);
    self
  }

  /// Set the priority of the message. You can set Normal or High priorities.
  /// # Examples:
  /// ```rust
  /// use gcm::{Message, Priority};
  ///
  /// let message = Message::new("<registration id>")
  ///     .priority(Priority::High);
  /// ```
  pub fn priority(mut self, priority: Priority) -> Message<'a> {
    self.priority = Some(priority);
    self
  }

  /// To set the `content-available` field on iOS
  pub fn content_available(mut self, content_available: bool) -> Message<'a> {
    self.content_available = Some(content_available);
    self
  }

  /// When set to `true`, sends the message only when the device is active.
  pub fn delay_while_idle(mut self, delay_while_idle: bool) -> Message<'a> {
    self.delay_while_idle = Some(delay_while_idle);
    self
  }

  /// How long (in seconds) to keep the message on GCM servers in case the device
  /// is offline. The maximum and default is 4 weeks.
  pub fn time_to_live(mut self, time_to_live: i32) -> Message<'a> {
    self.time_to_live = Some(time_to_live);
    self
  }

  /// Package name of the application where the registration tokens must match.
  pub fn restricted_package_name(mut self, restricted_package_name: &'a str) -> Message<'a> {
    self.restricted_package_name = Some(restricted_package_name);
    self
  }

  /// When set to `true`, allows you to test GCM without actually sending the message.
  pub fn dry_run(mut self, dry_run: bool) -> Message<'a> {
    self.dry_run = Some(dry_run);
    self
  }

  /// Use this to add custom key-value pairs to the message. This data
  /// must be handled appropriately on the client end.
  /// # Examples:
  /// ```rust
  /// use gcm::Message;
  /// use std::collections::HashMap;
  ///
  /// let mut map = HashMap::new();
  /// map.insert("message", "Howdy!");
  ///
  /// let message = Message::new("<registration id>").data(map);
  /// ```
  pub fn data(mut self, data: HashMap<&'a str, &'a str>) -> Message<'a> {
    let mut datamap: HashMap<String, String> = HashMap::new();
    for (key, val) in data.iter() {
      datamap.insert(key.to_string(), val.to_string());
    }

    self.data = Some(datamap);
    self
  }

  /// Use this to set a `Notification` for the message.
  /// # Examples:
  /// ```rust
  /// use gcm::{Message, NotificationBuilder};
  ///
  /// let notification = NotificationBuilder::new("Hey!")
  ///     .body("Do you want to catch up later?")
  ///     .finalize();
  ///
  /// let message = Message::new("<registration id>")
  ///     .notification(notification);
  /// ```
  pub fn notification(mut self, notification: Notification<'a>) -> Message<'a> {
    self.notification = Some(notification);
    self
  }

  /// Send the message using your GCM API Key.
  /// # Examples:
  /// ```no_run
  /// use gcm::Message;
  /// use std::collections::HashMap;
  ///
  /// let mut map = HashMap::new();
  /// map.insert("message", "Howdy!");
  ///
  /// let result = Message::new("<registration id>")
  ///     .data(map)
  ///     .send("<GCM API Key>");
  /// ```
  pub fn send(self, api_key: &'a str) -> Result<response::GcmResponse, response::GcmError> {
    let payload = self.to_json().to_string();
    let auth_header = "key=".to_string() + api_key;
    let res;
    let body;
    let code;

    let result = http::handle()
        .post("https://gcm-http.googleapis.com/gcm/send", &payload)
        .header("Authorization", &auth_header)
        .header("Content-Type", "application/json")
        .exec();

    match result {
      Ok(unwrapped) => {
        res = unwrapped;
        body = str::from_utf8(res.get_body()).unwrap();
        code = res.get_code();

        Message::parse_response(code, body)
      },
      Err(_) => {
        Message::parse_response(500, "Server Error")
      }
    }
  }

  fn parse_response(status: u32, body: &str) -> Result<response::GcmResponse, response::GcmError> {
    match status {
      200 => {
        Ok(json::decode(body).unwrap())
      },
      401 => Err(response::GcmError::Unauthorized),
      400 => Err(response::GcmError::InvalidMessage(body.to_string())),
      500...599 => Err(response::GcmError::ServerError),
      _ => Err(response::GcmError::InvalidMessage("Unknown Error".to_string())),
    }
  }
}
<|endoftext|>


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

//! Routine to compute the strongly connected components (SCCs) of a
//! graph, as well as the resulting DAG if each SCC is replaced with a
//! node in the graph. This uses Tarjan's algorithm that completes in
//! O(n) time.

use fx::FxHashSet;
use graph::{DirectedGraph, WithNumNodes, WithSuccessors};
use indexed_vec::{Idx, IndexVec};
use std::ops::Range;

mod test;

/// Strongly connected components (SCC) of a graph. The type `N` is
/// the index type for the graph nodes and `S` is the index type for
/// the SCCs. We can map from each node to the SCC that it
/// participates in, and we also have the successors of each SCC.
pub struct Sccs<N: Idx, S: Idx> {
    /// For each node, what is the SCC index of the SCC to which it
    /// belongs.
    scc_indices: IndexVec<N, S>,

    /// Data about each SCC.
    scc_data: SccData<S>,
}

struct SccData<S: Idx> {
    /// For each SCC, the range of `all_successors` where its
    /// successors can be found.
    ranges: IndexVec<S, Range<usize>>,

    /// Contains the succcessors for all the Sccs, concatenated. The
    /// range of indices corresponding to a given SCC is found in its
    /// SccData.
    all_successors: Vec<S>,
}

impl<N: Idx, S: Idx> Sccs<N, S> {
    pub fn new(graph: &(impl DirectedGraph<Node = N> + WithNumNodes + WithSuccessors)) -> Self {
        SccsConstruction::construct(graph)
    }

    /// Returns the number of SCCs in the graph.
    pub fn num_sccs(&self) -> usize {
        self.scc_data.len()
    }

    /// Returns the number of SCCs in the graph.
    pub fn all_sccs(&self) -> impl Iterator<Item = S> {
        (0 .. self.scc_data.len()).map(S::new)
    }

    /// Returns the SCC to which a node `r` belongs.
    pub fn scc(&self, r: N) -> S {
        self.scc_indices[r]
    }

    /// Returns the successors of the given SCC.
    pub fn successors(&self, scc: S) -> &[S] {
        self.scc_data.successors(scc)
    }
}

impl<S: Idx> SccData<S> {
    /// Number of SCCs,
    fn len(&self) -> usize {
        self.ranges.len()
    }

    /// Returns the successors of the given SCC.
    fn successors(&self, scc: S) -> &[S] {
        // Annoyingly, `range` does not implement `Copy`, so we have
        // to do `range.start..range.end`:
        let range = &self.ranges[scc];
        &self.all_successors[range.start..range.end]
    }

    /// Creates a new SCC with `successors` as its successors and
    /// returns the resulting index.
    fn create_scc(&mut self, successors: impl IntoIterator<Item = S>) -> S {
        // Store the successors on `scc_successors_vec`, remembering
        // the range of indices.
        let all_successors_start = self.all_successors.len();
        self.all_successors.extend(successors);
        let all_successors_end = self.all_successors.len();

        debug!(
            "create_scc({:?}) successors={:?}",
            self.ranges.len(),
            &self.all_successors[all_successors_start..all_successors_end],
        );

        self.ranges.push(all_successors_start..all_successors_end)
    }
}

struct SccsConstruction<'c, G: DirectedGraph + WithNumNodes + WithSuccessors + 'c, S: Idx> {
    graph: &'c G,

    /// The state of each node; used during walk to record the stack
    /// and after walk to record what cycle each node ended up being
    /// in.
    node_states: IndexVec<G::Node, NodeState<G::Node, S>>,

    /// The stack of nodes that we are visiting as part of the DFS.
    node_stack: Vec<G::Node>,

    /// The stack of successors: as we visit a node, we mark our
    /// position in this stack, and when we encounter a successor SCC,
    /// we push it on the stack. When we complete an SCC, we can pop
    /// everything off the stack that was found along the way.
    successors_stack: Vec<S>,

    /// A set used to strip duplicates. As we accumulate successors
    /// into the successors_stack, we sometimes get duplicate entries.
    /// We use this set to remove those -- we also keep its storage
    /// around between successors to amortize memory allocation costs.
    duplicate_set: FxHashSet<S>,

    scc_data: SccData<S>,
}

#[derive(Copy, Clone, Debug)]
enum NodeState<N, S> {
    /// This node has not yet been visited as part of the DFS.
    ///
    /// After SCC construction is complete, this state ought to be
    /// impossible.
    NotVisited,

    /// This node is currently being walk as part of our DFS. It is on
    /// the stack at the depth `depth`.
    ///
    /// After SCC construction is complete, this state ought to be
    /// impossible.
    BeingVisited { depth: usize },

    /// Indicates that this node is a member of the given cycle.
    InCycle { scc_index: S },

    /// Indicates that this node is a member of whatever cycle
    /// `parent` is a member of. This state is transient: whenever we
    /// see it, we try to overwrite it with the current state of
    /// `parent` (this is the "path compression" step of a union-find
    /// algorithm).
    InCycleWith { parent: N },
}

#[derive(Copy, Clone, Debug)]
enum WalkReturn<S> {
    Cycle { min_depth: usize },
    Complete { scc_index: S },
}

impl<'c, G, S> SccsConstruction<'c, G, S>
where
    G: DirectedGraph + WithNumNodes + WithSuccessors,
    S: Idx,
{
    /// Identifies SCCs in the graph `G` and computes the resulting
    /// DAG. This uses a variant of [Tarjan's
    /// algorithm][wikipedia]. The high-level summary of the algorithm
    /// is that we do a depth-first search. Along the way, we keep a
    /// stack of each node whose successors are being visited. We
    /// track the depth of each node on this stack (there is no depth
    /// if the node is not on the stack). When we find that some node
    /// N with depth D can reach some other node N' with lower depth
    /// D' (i.e., D' < D), we know that N, N', and all nodes in
    /// between them on the stack are part of an SCC.
    ///
    /// [wikipedia]: https://bit.ly/2EZIx84
    fn construct(graph: &'c G) -> Sccs<G::Node, S> {
        let num_nodes = graph.num_nodes();

        let mut this = Self {
            graph,
            node_states: IndexVec::from_elem_n(NodeState::NotVisited, num_nodes),
            node_stack: Vec::with_capacity(num_nodes),
            successors_stack: Vec::new(),
            scc_data: SccData {
                ranges: IndexVec::new(),
                all_successors: Vec::new(),
            },
            duplicate_set: FxHashSet::default(),
        };

        let scc_indices = (0..num_nodes)
            .map(G::Node::new)
            .map(|node| match this.walk_node(0, node) {
                WalkReturn::Complete { scc_index } => scc_index,
                WalkReturn::Cycle { min_depth } => panic!(
                    "`walk_node(0, {:?})` returned cycle with depth {:?}",
                    node, min_depth
                ),
            })
            .collect();

        Sccs {
            scc_indices,
            scc_data: this.scc_data,
        }
    }

    /// Visit a node during the DFS. We first examine its current
    /// state -- if it is not yet visited (`NotVisited`), we can push
    /// it onto the stack and start walking its successors.
    ///
    /// If it is already on the DFS stack it will be in the state
    /// `BeingVisited`. In that case, we have found a cycle and we
    /// return the depth from the stack.
    ///
    /// Otherwise, we are looking at a node that has already been
    /// completely visited. We therefore return `WalkReturn::Complete`
    /// with its associated SCC index.
    fn walk_node(&mut self, depth: usize, node: G::Node) -> WalkReturn<S> {
        debug!("walk_node(depth = {:?}, node = {:?})", depth, node);
        match self.find_state(node) {
            NodeState::InCycle { scc_index } => WalkReturn::Complete { scc_index },

            NodeState::BeingVisited { depth: min_depth } => WalkReturn::Cycle { min_depth },

            NodeState::NotVisited => self.walk_unvisited_node(depth, node),

            NodeState::InCycleWith { parent } => panic!(
                "`find_state` returned `InCycleWith({:?})`, which ought to be impossible",
                parent
            ),
        }
    }

    /// Fetches the state of the node `r`. If `r` is recorded as being
    /// in a cycle with some other node `r2`, then fetches the state
    /// of `r2` (and updates `r` to reflect current result). This is
    /// basically the "find" part of a standard union-find algorithm
    /// (with path compression).
    fn find_state(&mut self, r: G::Node) -> NodeState<G::Node, S> {
        debug!("find_state(r = {:?} in state {:?})", r, self.node_states[r]);
        match self.node_states[r] {
            NodeState::InCycle { scc_index } => NodeState::InCycle { scc_index },
            NodeState::BeingVisited { depth } => NodeState::BeingVisited { depth },
            NodeState::NotVisited => NodeState::NotVisited,
            NodeState::InCycleWith { parent } => {
                let parent_state = self.find_state(parent);
                debug!("find_state: parent_state = {:?}", parent_state);
                match parent_state {
                    NodeState::InCycle { .. } => {
                        self.node_states[r] = parent_state;
                        parent_state
                    }

                    NodeState::BeingVisited { depth } => {
                        self.node_states[r] = NodeState::InCycleWith {
                            parent: self.node_stack[depth],
                        };
                        parent_state
                    }

                    NodeState::NotVisited | NodeState::InCycleWith { .. } => {
                        panic!("invalid parent state: {:?}", parent_state)
                    }
                }
            }
        }
    }

    /// Walks a node that has never been visited before.
    fn walk_unvisited_node(&mut self, depth: usize, node: G::Node) -> WalkReturn<S> {
        debug!(
            "walk_unvisited_node(depth = {:?}, node = {:?})",
            depth, node
        );

        debug_assert!(match self.node_states[node] {
            NodeState::NotVisited => true,
            _ => false,
        });

        // Push `node` onto the stack.
        self.node_states[node] = NodeState::BeingVisited { depth };
        self.node_stack.push(node);

        // Walk each successor of the node, looking to see if any of
        // them can reach a node that is presently on the stack. If
        // so, that means they can also reach us.
        let mut min_depth = depth;
        let mut min_cycle_root = node;
        let successors_len = self.successors_stack.len();
        for successor_node in self.graph.successors(node) {
            debug!(
                "walk_unvisited_node: node = {:?} successor_ode = {:?}",
                node, successor_node
            );
            match self.walk_node(depth + 1, successor_node) {
                WalkReturn::Cycle {
                    min_depth: successor_min_depth,
                } => {
                    // Track the minimum depth we can reach.
                    assert!(successor_min_depth <= depth);
                    if successor_min_depth < min_depth {
                        debug!(
                            "walk_unvisited_node: node = {:?} successor_min_depth = {:?}",
                            node, successor_min_depth
                        );
                        min_depth = successor_min_depth;
                        min_cycle_root = successor_node;
                    }
                }

                WalkReturn::Complete {
                    scc_index: successor_scc_index,
                } => {
                    // Push the completed SCC indices onto
                    // the `successors_stack` for later.
                    debug!(
                        "walk_unvisited_node: node = {:?} successor_scc_index = {:?}",
                        node, successor_scc_index
                    );
                    self.successors_stack.push(successor_scc_index);
                }
            }
        }

        // Completed walk, remove `node` from the stack.
        let r = self.node_stack.pop();
        debug_assert_eq!(r, Some(node));

        // If `min_depth == depth`, then we are the root of the
        // cycle: we can't reach anyone further down the stack.
        if min_depth == depth {
            // Note that successor stack may have duplicates, so we
            // want to remove those:
            let deduplicated_successors = {
                let duplicate_set = &mut self.duplicate_set;
                duplicate_set.clear();
                self.successors_stack
                    .drain(successors_len..)
                    .filter(move |&i| duplicate_set.insert(i))
            };
            let scc_index = self.scc_data.create_scc(deduplicated_successors);
            self.node_states[node] = NodeState::InCycle { scc_index };
            WalkReturn::Complete { scc_index }
        } else {
            // We are not the head of the cycle. Return back to our
            // caller. They will take ownership of the
            // `self.successors` data that we pushed.
            self.node_states[node] = NodeState::InCycleWith {
                parent: min_cycle_root,
            };
            WalkReturn::Cycle { min_depth }
        }
    }
}
<commit_msg>nit: fix `all_sccs` comment<commit_after>// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Routine to compute the strongly connected components (SCCs) of a
//! graph, as well as the resulting DAG if each SCC is replaced with a
//! node in the graph. This uses Tarjan's algorithm that completes in
//! O(n) time.

use fx::FxHashSet;
use graph::{DirectedGraph, WithNumNodes, WithSuccessors};
use indexed_vec::{Idx, IndexVec};
use std::ops::Range;

mod test;

/// Strongly connected components (SCC) of a graph. The type `N` is
/// the index type for the graph nodes and `S` is the index type for
/// the SCCs. We can map from each node to the SCC that it
/// participates in, and we also have the successors of each SCC.
pub struct Sccs<N: Idx, S: Idx> {
    /// For each node, what is the SCC index of the SCC to which it
    /// belongs.
    scc_indices: IndexVec<N, S>,

    /// Data about each SCC.
    scc_data: SccData<S>,
}

struct SccData<S: Idx> {
    /// For each SCC, the range of `all_successors` where its
    /// successors can be found.
    ranges: IndexVec<S, Range<usize>>,

    /// Contains the succcessors for all the Sccs, concatenated. The
    /// range of indices corresponding to a given SCC is found in its
    /// SccData.
    all_successors: Vec<S>,
}

impl<N: Idx, S: Idx> Sccs<N, S> {
    pub fn new(graph: &(impl DirectedGraph<Node = N> + WithNumNodes + WithSuccessors)) -> Self {
        SccsConstruction::construct(graph)
    }

    /// Returns the number of SCCs in the graph.
    pub fn num_sccs(&self) -> usize {
        self.scc_data.len()
    }

    /// Returns an iterator over the SCCs in the graph.
    pub fn all_sccs(&self) -> impl Iterator<Item = S> {
        (0 .. self.scc_data.len()).map(S::new)
    }

    /// Returns the SCC to which a node `r` belongs.
    pub fn scc(&self, r: N) -> S {
        self.scc_indices[r]
    }

    /// Returns the successors of the given SCC.
    pub fn successors(&self, scc: S) -> &[S] {
        self.scc_data.successors(scc)
    }
}

impl<S: Idx> SccData<S> {
    /// Number of SCCs,
    fn len(&self) -> usize {
        self.ranges.len()
    }

    /// Returns the successors of the given SCC.
    fn successors(&self, scc: S) -> &[S] {
        // Annoyingly, `range` does not implement `Copy`, so we have
        // to do `range.start..range.end`:
        let range = &self.ranges[scc];
        &self.all_successors[range.start..range.end]
    }

    /// Creates a new SCC with `successors` as its successors and
    /// returns the resulting index.
    fn create_scc(&mut self, successors: impl IntoIterator<Item = S>) -> S {
        // Store the successors on `scc_successors_vec`, remembering
        // the range of indices.
        let all_successors_start = self.all_successors.len();
        self.all_successors.extend(successors);
        let all_successors_end = self.all_successors.len();

        debug!(
            "create_scc({:?}) successors={:?}",
            self.ranges.len(),
            &self.all_successors[all_successors_start..all_successors_end],
        );

        self.ranges.push(all_successors_start..all_successors_end)
    }
}

struct SccsConstruction<'c, G: DirectedGraph + WithNumNodes + WithSuccessors + 'c, S: Idx> {
    graph: &'c G,

    /// The state of each node; used during walk to record the stack
    /// and after walk to record what cycle each node ended up being
    /// in.
    node_states: IndexVec<G::Node, NodeState<G::Node, S>>,

    /// The stack of nodes that we are visiting as part of the DFS.
    node_stack: Vec<G::Node>,

    /// The stack of successors: as we visit a node, we mark our
    /// position in this stack, and when we encounter a successor SCC,
    /// we push it on the stack. When we complete an SCC, we can pop
    /// everything off the stack that was found along the way.
    successors_stack: Vec<S>,

    /// A set used to strip duplicates. As we accumulate successors
    /// into the successors_stack, we sometimes get duplicate entries.
    /// We use this set to remove those -- we also keep its storage
    /// around between successors to amortize memory allocation costs.
    duplicate_set: FxHashSet<S>,

    scc_data: SccData<S>,
}

#[derive(Copy, Clone, Debug)]
enum NodeState<N, S> {
    /// This node has not yet been visited as part of the DFS.
    ///
    /// After SCC construction is complete, this state ought to be
    /// impossible.
    NotVisited,

    /// This node is currently being walk as part of our DFS. It is on
    /// the stack at the depth `depth`.
    ///
    /// After SCC construction is complete, this state ought to be
    /// impossible.
    BeingVisited { depth: usize },

    /// Indicates that this node is a member of the given cycle.
    InCycle { scc_index: S },

    /// Indicates that this node is a member of whatever cycle
    /// `parent` is a member of. This state is transient: whenever we
    /// see it, we try to overwrite it with the current state of
    /// `parent` (this is the "path compression" step of a union-find
    /// algorithm).
    InCycleWith { parent: N },
}

#[derive(Copy, Clone, Debug)]
enum WalkReturn<S> {
    Cycle { min_depth: usize },
    Complete { scc_index: S },
}

impl<'c, G, S> SccsConstruction<'c, G, S>
where
    G: DirectedGraph + WithNumNodes + WithSuccessors,
    S: Idx,
{
    /// Identifies SCCs in the graph `G` and computes the resulting
    /// DAG. This uses a variant of [Tarjan's
    /// algorithm][wikipedia]. The high-level summary of the algorithm
    /// is that we do a depth-first search. Along the way, we keep a
    /// stack of each node whose successors are being visited. We
    /// track the depth of each node on this stack (there is no depth
    /// if the node is not on the stack). When we find that some node
    /// N with depth D can reach some other node N' with lower depth
    /// D' (i.e., D' < D), we know that N, N', and all nodes in
    /// between them on the stack are part of an SCC.
    ///
    /// [wikipedia]: https://bit.ly/2EZIx84
    fn construct(graph: &'c G) -> Sccs<G::Node, S> {
        let num_nodes = graph.num_nodes();

        let mut this = Self {
            graph,
            node_states: IndexVec::from_elem_n(NodeState::NotVisited, num_nodes),
            node_stack: Vec::with_capacity(num_nodes),
            successors_stack: Vec::new(),
            scc_data: SccData {
                ranges: IndexVec::new(),
                all_successors: Vec::new(),
            },
            duplicate_set: FxHashSet::default(),
        };

        let scc_indices = (0..num_nodes)
            .map(G::Node::new)
            .map(|node| match this.walk_node(0, node) {
                WalkReturn::Complete { scc_index } => scc_index,
                WalkReturn::Cycle { min_depth } => panic!(
                    "`walk_node(0, {:?})` returned cycle with depth {:?}",
                    node, min_depth
                ),
            })
            .collect();

        Sccs {
            scc_indices,
            scc_data: this.scc_data,
        }
    }

    /// Visit a node during the DFS. We first examine its current
    /// state -- if it is not yet visited (`NotVisited`), we can push
    /// it onto the stack and start walking its successors.
    ///
    /// If it is already on the DFS stack it will be in the state
    /// `BeingVisited`. In that case, we have found a cycle and we
    /// return the depth from the stack.
    ///
    /// Otherwise, we are looking at a node that has already been
    /// completely visited. We therefore return `WalkReturn::Complete`
    /// with its associated SCC index.
    fn walk_node(&mut self, depth: usize, node: G::Node) -> WalkReturn<S> {
        debug!("walk_node(depth = {:?}, node = {:?})", depth, node);
        match self.find_state(node) {
            NodeState::InCycle { scc_index } => WalkReturn::Complete { scc_index },

            NodeState::BeingVisited { depth: min_depth } => WalkReturn::Cycle { min_depth },

            NodeState::NotVisited => self.walk_unvisited_node(depth, node),

            NodeState::InCycleWith { parent } => panic!(
                "`find_state` returned `InCycleWith({:?})`, which ought to be impossible",
                parent
            ),
        }
    }

    /// Fetches the state of the node `r`. If `r` is recorded as being
    /// in a cycle with some other node `r2`, then fetches the state
    /// of `r2` (and updates `r` to reflect current result). This is
    /// basically the "find" part of a standard union-find algorithm
    /// (with path compression).
    fn find_state(&mut self, r: G::Node) -> NodeState<G::Node, S> {
        debug!("find_state(r = {:?} in state {:?})", r, self.node_states[r]);
        match self.node_states[r] {
            NodeState::InCycle { scc_index } => NodeState::InCycle { scc_index },
            NodeState::BeingVisited { depth } => NodeState::BeingVisited { depth },
            NodeState::NotVisited => NodeState::NotVisited,
            NodeState::InCycleWith { parent } => {
                let parent_state = self.find_state(parent);
                debug!("find_state: parent_state = {:?}", parent_state);
                match parent_state {
                    NodeState::InCycle { .. } => {
                        self.node_states[r] = parent_state;
                        parent_state
                    }

                    NodeState::BeingVisited { depth } => {
                        self.node_states[r] = NodeState::InCycleWith {
                            parent: self.node_stack[depth],
                        };
                        parent_state
                    }

                    NodeState::NotVisited | NodeState::InCycleWith { .. } => {
                        panic!("invalid parent state: {:?}", parent_state)
                    }
                }
            }
        }
    }

    /// Walks a node that has never been visited before.
    fn walk_unvisited_node(&mut self, depth: usize, node: G::Node) -> WalkReturn<S> {
        debug!(
            "walk_unvisited_node(depth = {:?}, node = {:?})",
            depth, node
        );

        debug_assert!(match self.node_states[node] {
            NodeState::NotVisited => true,
            _ => false,
        });

        // Push `node` onto the stack.
        self.node_states[node] = NodeState::BeingVisited { depth };
        self.node_stack.push(node);

        // Walk each successor of the node, looking to see if any of
        // them can reach a node that is presently on the stack. If
        // so, that means they can also reach us.
        let mut min_depth = depth;
        let mut min_cycle_root = node;
        let successors_len = self.successors_stack.len();
        for successor_node in self.graph.successors(node) {
            debug!(
                "walk_unvisited_node: node = {:?} successor_ode = {:?}",
                node, successor_node
            );
            match self.walk_node(depth + 1, successor_node) {
                WalkReturn::Cycle {
                    min_depth: successor_min_depth,
                } => {
                    // Track the minimum depth we can reach.
                    assert!(successor_min_depth <= depth);
                    if successor_min_depth < min_depth {
                        debug!(
                            "walk_unvisited_node: node = {:?} successor_min_depth = {:?}",
                            node, successor_min_depth
                        );
                        min_depth = successor_min_depth;
                        min_cycle_root = successor_node;
                    }
                }

                WalkReturn::Complete {
                    scc_index: successor_scc_index,
                } => {
                    // Push the completed SCC indices onto
                    // the `successors_stack` for later.
                    debug!(
                        "walk_unvisited_node: node = {:?} successor_scc_index = {:?}",
                        node, successor_scc_index
                    );
                    self.successors_stack.push(successor_scc_index);
                }
            }
        }

        // Completed walk, remove `node` from the stack.
        let r = self.node_stack.pop();
        debug_assert_eq!(r, Some(node));

        // If `min_depth == depth`, then we are the root of the
        // cycle: we can't reach anyone further down the stack.
        if min_depth == depth {
            // Note that successor stack may have duplicates, so we
            // want to remove those:
            let deduplicated_successors = {
                let duplicate_set = &mut self.duplicate_set;
                duplicate_set.clear();
                self.successors_stack
                    .drain(successors_len..)
                    .filter(move |&i| duplicate_set.insert(i))
            };
            let scc_index = self.scc_data.create_scc(deduplicated_successors);
            self.node_states[node] = NodeState::InCycle { scc_index };
            WalkReturn::Complete { scc_index }
        } else {
            // We are not the head of the cycle. Return back to our
            // caller. They will take ownership of the
            // `self.successors` data that we pushed.
            self.node_states[node] = NodeState::InCycleWith {
                parent: min_cycle_root,
            };
            WalkReturn::Cycle { min_depth }
        }
    }
}
<|endoftext|>


<commit_before>use crate::spec::{LinkArgs, LinkerFlavor, PanicStrategy, RelocModel, RelroLevel, TargetOptions};

pub fn opts() -> TargetOptions {
    let mut pre_link_args = LinkArgs::new();
    pre_link_args.insert(
        LinkerFlavor::Gcc,
        vec!["-Wl,--as-needed".to_string(), "-Wl,-z,noexecstack".to_string()],
    );

    TargetOptions {
        disable_redzone: true,
        panic_strategy: PanicStrategy::Abort,
        stack_probes: true,
        eliminate_frame_pointer: false,
        linker_is_gnu: true,
        position_independent_executables: true,
        needs_plt: true,
        relro_level: RelroLevel::Full,
        relocation_model: RelocModel::Static,
        target_family: Some("unix".to_string()),
        pre_link_args,

        ..Default::default()
    }
}
<commit_msg>Rollup merge of #74257 - alex:patch-1, r=joshtriplett<commit_after>use crate::spec::{LinkArgs, LinkerFlavor, PanicStrategy, RelocModel, RelroLevel, TargetOptions};

pub fn opts() -> TargetOptions {
    let mut pre_link_args = LinkArgs::new();
    pre_link_args.insert(
        LinkerFlavor::Gcc,
        vec!["-Wl,--as-needed".to_string(), "-Wl,-z,noexecstack".to_string()],
    );

    TargetOptions {
        disable_redzone: true,
        panic_strategy: PanicStrategy::Abort,
        stack_probes: true,
        eliminate_frame_pointer: false,
        linker_is_gnu: true,
        position_independent_executables: true,
        needs_plt: true,
        relro_level: RelroLevel::Full,
        relocation_model: RelocModel::Static,
        pre_link_args,

        ..Default::default()
    }
}
<|endoftext|>


<commit_before>use std::ops;
use std::{f64, i32};

use glib::object::ObjectClass;
use glib::subclass;
use glib::subclass::object::ObjectClassSubclassExt;
use glib::subclass::prelude::*;
use glib::translate::*;
use glib::{ParamFlags, ParamSpec};

use glib_sys;
use gobject_sys;

use handle::Handle;

extern "C" {
    fn rsvg_handle_flags_get_type() -> glib_sys::GType;
}

// Keep this in sync with rsvg.h:RsvgHandleClass
#[repr(C)]
pub struct RsvgHandleClass {
    parent: gobject_sys::GObjectClass,

    _abi_padding: [glib_sys::gpointer; 15],
}

// Keep this in sync with rsvg.h:RsvgHandle
#[repr(C)]
pub struct RsvgHandle {
    parent: gobject_sys::GObject,

    _abi_padding: [glib_sys::gpointer; 16],
}

unsafe impl ClassStruct for RsvgHandleClass {
    type Type = Handle;
}

unsafe impl InstanceStruct for RsvgHandle {
    type Type = Handle;
}

impl ops::Deref for RsvgHandleClass {
    type Target = ObjectClass;

    fn deref(&self) -> &Self::Target {
        unsafe { &*(self as *const _ as *const Self::Target) }
    }
}

impl ops::DerefMut for RsvgHandleClass {
    fn deref_mut(&mut self) -> &mut Self::Target {
        unsafe { &mut *(self as *mut _ as *mut Self::Target) }
    }
}

static PROPERTIES: [subclass::Property; 11] = [
    subclass::Property("flags", |name| {
        ParamSpec::flags(
            name,
            "Flags",
            "Loading flags",
            from_glib(unsafe { rsvg_handle_flags_get_type() }),
            0,
            ParamFlags::READWRITE | ParamFlags::CONSTRUCT_ONLY,
        )
    }),
    subclass::Property("dpi-x", |name| {
        ParamSpec::double(
            name,
            "Horizontal DPI",
            "Horizontal resolution in dots per inch",
            0.0,
            f64::MAX,
            0.0,
            ParamFlags::READWRITE | ParamFlags::CONSTRUCT,
        )
    }),
    subclass::Property("dpi-y", |name| {
        ParamSpec::double(
            name,
            "Vertical DPI",
            "Vertical resolution in dots per inch",
            0.0,
            f64::MAX,
            0.0,
            ParamFlags::READWRITE | ParamFlags::CONSTRUCT,
        )
    }),
    subclass::Property("base-uri", |name| {
        ParamSpec::string(
            name,
            "Base URI",
            "Base URI for resolving relative references",
            None,
            ParamFlags::READWRITE | ParamFlags::CONSTRUCT,
        )
    }),
    subclass::Property("width", |name| {
        ParamSpec::int(
            name,
            "Image width",
            "Image width",
            0,
            i32::MAX,
            0,
            ParamFlags::READABLE,
        )
    }),
    subclass::Property("height", |name| {
        ParamSpec::int(
            name,
            "Image height",
            "Image height",
            0,
            i32::MAX,
            0,
            ParamFlags::READABLE,
        )
    }),
    subclass::Property("em", |name| {
        ParamSpec::double(name, "em", "em", 0.0, f64::MAX, 0.0, ParamFlags::READABLE)
    }),
    subclass::Property("ex", |name| {
        ParamSpec::double(name, "ex", "ex", 0.0, f64::MAX, 0.0, ParamFlags::READABLE)
    }),
    subclass::Property("title", |name| {
        ParamSpec::string(name, "deprecated", "deprecated", None, ParamFlags::READABLE)
    }),
    subclass::Property("desc", |name| {
        ParamSpec::string(name, "deprecated", "deprecated", None, ParamFlags::READABLE)
    }),
    subclass::Property("metadata", |name| {
        ParamSpec::string(name, "deprecated", "deprecated", None, ParamFlags::READABLE)
    }),
];

impl ObjectSubclass for Handle {
    const NAME: &'static str = "RsvgHandle";

    type ParentType = glib::Object;

    // We don't use subclass:simple::InstanceStruct and ClassStruct
    // because we need to maintain the respective _abi_padding of each
    // of RsvgHandleClass and RsvgHandle.

    type Instance = RsvgHandle;
    type Class = RsvgHandleClass;

    glib_object_subclass!();

    fn class_init(klass: &mut RsvgHandleClass) {
        klass.install_properties(&PROPERTIES);
    }

    fn new() -> Self {
        Handle::new()
    }
}

impl ObjectImpl for Handle {
    glib_object_impl!();

    fn set_property(&self, _obj: &glib::Object, id: usize, value: &glib::Value) {
        let prop = &PROPERTIES[id];

        match *prop {
            subclass::Property("flags", ..) => {
                self.set_load_flags(value.get().expect("flags value has incorrect type"));
            }

            subclass::Property("dpi-x", ..) => {
                self.set_dpi_x(value.get().expect("dpi-x value has incorrect type"));
            }

            subclass::Property("dpi-y", ..) => {
                self.set_dpi_y(value.get().expect("dpi-y value has incorrect type"));
            }

            subclass::Property("base-uri", ..) => {
                self.set_base_url(value.get().expect("base-uri should be a non-NULL string"));
            }

            _ => unimplemented!("invalid property id {}", id),
        }
    }

    fn get_property(&self, _obj: &glib::Object, id: usize) -> Result<glib::Value, ()> {
        //         let prop = &PROPERTIES[id];
        //
        //         match *prop {
        //             subclass::Property("name", ..) => Ok(self.name.borrow().to_value()),
        //             _ => unimplemented!(),
        //         }
        unimplemented!();
    }

    fn constructed(&self, obj: &glib::Object) {
        //         // Chain up to the parent type's implementation of this virtual
        //         // method.
        //         self.parent_constructed(obj);
        //
        //         // And here we could do our own initialization.
        unimplemented!();
    }
}
<commit_msg>Use unreachable!() for invalid property IDs<commit_after>use std::ops;
use std::{f64, i32};

use glib::object::ObjectClass;
use glib::subclass;
use glib::subclass::object::ObjectClassSubclassExt;
use glib::subclass::prelude::*;
use glib::translate::*;
use glib::{ParamFlags, ParamSpec};

use glib_sys;
use gobject_sys;

use handle::Handle;

extern "C" {
    fn rsvg_handle_flags_get_type() -> glib_sys::GType;
}

// Keep this in sync with rsvg.h:RsvgHandleClass
#[repr(C)]
pub struct RsvgHandleClass {
    parent: gobject_sys::GObjectClass,

    _abi_padding: [glib_sys::gpointer; 15],
}

// Keep this in sync with rsvg.h:RsvgHandle
#[repr(C)]
pub struct RsvgHandle {
    parent: gobject_sys::GObject,

    _abi_padding: [glib_sys::gpointer; 16],
}

unsafe impl ClassStruct for RsvgHandleClass {
    type Type = Handle;
}

unsafe impl InstanceStruct for RsvgHandle {
    type Type = Handle;
}

impl ops::Deref for RsvgHandleClass {
    type Target = ObjectClass;

    fn deref(&self) -> &Self::Target {
        unsafe { &*(self as *const _ as *const Self::Target) }
    }
}

impl ops::DerefMut for RsvgHandleClass {
    fn deref_mut(&mut self) -> &mut Self::Target {
        unsafe { &mut *(self as *mut _ as *mut Self::Target) }
    }
}

static PROPERTIES: [subclass::Property; 11] = [
    subclass::Property("flags", |name| {
        ParamSpec::flags(
            name,
            "Flags",
            "Loading flags",
            from_glib(unsafe { rsvg_handle_flags_get_type() }),
            0,
            ParamFlags::READWRITE | ParamFlags::CONSTRUCT_ONLY,
        )
    }),
    subclass::Property("dpi-x", |name| {
        ParamSpec::double(
            name,
            "Horizontal DPI",
            "Horizontal resolution in dots per inch",
            0.0,
            f64::MAX,
            0.0,
            ParamFlags::READWRITE | ParamFlags::CONSTRUCT,
        )
    }),
    subclass::Property("dpi-y", |name| {
        ParamSpec::double(
            name,
            "Vertical DPI",
            "Vertical resolution in dots per inch",
            0.0,
            f64::MAX,
            0.0,
            ParamFlags::READWRITE | ParamFlags::CONSTRUCT,
        )
    }),
    subclass::Property("base-uri", |name| {
        ParamSpec::string(
            name,
            "Base URI",
            "Base URI for resolving relative references",
            None,
            ParamFlags::READWRITE | ParamFlags::CONSTRUCT,
        )
    }),
    subclass::Property("width", |name| {
        ParamSpec::int(
            name,
            "Image width",
            "Image width",
            0,
            i32::MAX,
            0,
            ParamFlags::READABLE,
        )
    }),
    subclass::Property("height", |name| {
        ParamSpec::int(
            name,
            "Image height",
            "Image height",
            0,
            i32::MAX,
            0,
            ParamFlags::READABLE,
        )
    }),
    subclass::Property("em", |name| {
        ParamSpec::double(name, "em", "em", 0.0, f64::MAX, 0.0, ParamFlags::READABLE)
    }),
    subclass::Property("ex", |name| {
        ParamSpec::double(name, "ex", "ex", 0.0, f64::MAX, 0.0, ParamFlags::READABLE)
    }),
    subclass::Property("title", |name| {
        ParamSpec::string(name, "deprecated", "deprecated", None, ParamFlags::READABLE)
    }),
    subclass::Property("desc", |name| {
        ParamSpec::string(name, "deprecated", "deprecated", None, ParamFlags::READABLE)
    }),
    subclass::Property("metadata", |name| {
        ParamSpec::string(name, "deprecated", "deprecated", None, ParamFlags::READABLE)
    }),
];

impl ObjectSubclass for Handle {
    const NAME: &'static str = "RsvgHandle";

    type ParentType = glib::Object;

    // We don't use subclass:simple::InstanceStruct and ClassStruct
    // because we need to maintain the respective _abi_padding of each
    // of RsvgHandleClass and RsvgHandle.

    type Instance = RsvgHandle;
    type Class = RsvgHandleClass;

    glib_object_subclass!();

    fn class_init(klass: &mut RsvgHandleClass) {
        klass.install_properties(&PROPERTIES);
    }

    fn new() -> Self {
        Handle::new()
    }
}

impl ObjectImpl for Handle {
    glib_object_impl!();

    fn set_property(&self, _obj: &glib::Object, id: usize, value: &glib::Value) {
        let prop = &PROPERTIES[id];

        match *prop {
            subclass::Property("flags", ..) => {
                self.set_load_flags(value.get().expect("flags value has incorrect type"));
            }

            subclass::Property("dpi-x", ..) => {
                self.set_dpi_x(value.get().expect("dpi-x value has incorrect type"));
            }

            subclass::Property("dpi-y", ..) => {
                self.set_dpi_y(value.get().expect("dpi-y value has incorrect type"));
            }

            subclass::Property("base-uri", ..) => {
                self.set_base_url(value.get().expect("base-uri should be a non-NULL string"));
            }

            _ => unreachable!("invalid property id {}", id),
        }
    }

    fn get_property(&self, _obj: &glib::Object, id: usize) -> Result<glib::Value, ()> {
        //         let prop = &PROPERTIES[id];
        //
        //         match *prop {
        //             subclass::Property("name", ..) => Ok(self.name.borrow().to_value()),
        //             _ => unimplemented!(),
        //         }
        unimplemented!();
    }

    fn constructed(&self, obj: &glib::Object) {
        //         // Chain up to the parent type's implementation of this virtual
        //         // method.
        //         self.parent_constructed(obj);
        //
        //         // And here we could do our own initialization.
        unimplemented!();
    }
}
<|endoftext|>


<commit_before>struct Board {
    field: Vec<Vec<char>>,
}

impl Board {
    fn new(minefield: &[&str]) -> Self {
        let mut field: Vec<Vec<char>> = Vec::new();

        for row in minefield {
            field.push(row.chars().collect());
        }
        Board { field }
    }

    fn annotated(&self) -> Vec<String> {
        let mut annotated: Vec<String> = Vec::new();

        for (y, row) in self.field.iter().enumerate() {
            let mut annotated_row = String::new();
            for (x, token) in row.iter().enumerate() {
                match token {
                    '*' => annotated_row.push('*'),
                    ' ' => {
                        let neighbor_mines = self.num_neighbor_mines(y as u32, x as u32);
                        let annotated_location = if neighbor_mines == 0 {
                            " ".to_string()
                        } else {
                            neighbor_mines.to_string()
                        };
                        annotated_row.push_str(&annotated_location)
                    }
                    _ => panic!("unsupported token"),
                }
            }
            annotated.push(annotated_row)
        }

        annotated
    }

    fn num_neighbor_mines(&self, y: u32, x: u32) -> usize {
        return self
            .get_neighbors(y, x)
            .iter()
            .filter(|neighbor| neighbor == &&&'*')
            .count();
    }

    fn get_neighbors(&self, y: u32, x: u32) -> Vec<&char> {
        let mut neighbors = Vec::new();
        let y = y as i32;
        let x = x as i32;

        let delta_ys: Vec<i32> = (-1..=1).collect();
        for delta_y in delta_ys {
            let delta_xs: Vec<i32> = (-1..=1).collect();
            for delta_x in delta_xs {
                if delta_y == 0 && delta_x == 0 {
                    continue;
                }
                if y + delta_y < 0 || y + delta_y >= self.field.len() as i32 {
                    continue;
                }
                if x + delta_x < 0 || x + delta_x >= self.field[0].len() as i32 {
                    continue;
                }
                let neighbor = &self.field[(y + delta_y) as usize][(x + delta_x) as usize];
                neighbors.push(neighbor)
            }
        }

        neighbors
    }
}

pub fn annotate(minefield: &[&str]) -> Vec<String> {
    let board = Board::new(minefield);
    return board.annotated();
}
<commit_msg>WIP attempt to extract a Token enum<commit_after>enum Token {
    Mine,
    Empty,
}

impl Token {
    fn from(c: char) -> Result<Token, ()> {
        match c {
            '*' => Ok(Token::Mine),
            ' ' => Ok(Token::Empty),
            _ => Err(()),
        }
    }
}

struct Board {
    field: Vec<Vec<char>>,
}

// Board tokens
const MINE: char = '*';
const EMPTY: char = ' ';

impl Board {
    fn new(minefield: &[&str]) -> Self {
        let mut field: Vec<Vec<char>> = Vec::new();

        for row in minefield {
            field.push(row.chars().collect());
        }
        Board { field }
    }

    fn annotated(&self) -> Vec<String> {
        let mut annotated: Vec<String> = Vec::new();

        for (y, row) in self.field.iter().enumerate() {
            let mut annotated_row = String::new();
            for (x, token) in row.iter().enumerate() {
                match token {
                    &MINE => annotated_row.push(MINE),
                    &EMPTY => {
                        let neighbor_mines = self.num_neighbor_mines(y as u32, x as u32);
                        let annotated_location = if neighbor_mines == 0 {
                            " ".to_string()
                        } else {
                            neighbor_mines.to_string()
                        };
                        annotated_row.push_str(&annotated_location)
                    }
                    _ => panic!("unsupported token"),
                }
            }
            annotated.push(annotated_row)
        }

        annotated
    }

    fn num_neighbor_mines(&self, y: u32, x: u32) -> usize {
        return self
            .get_neighbors(y, x)
            .iter()
            .filter(|neighbor| neighbor == &&&MINE)
            .count();
    }

    fn get_neighbors(&self, y: u32, x: u32) -> Vec<&char> {
        let mut neighbors = Vec::new();
        let y = y as i32;
        let x = x as i32;

        let delta_ys: Vec<i32> = (-1..=1).collect();
        for delta_y in delta_ys {
            let delta_xs: Vec<i32> = (-1..=1).collect();
            for delta_x in delta_xs {
                if delta_y == 0 && delta_x == 0 {
                    continue;
                }
                if y + delta_y < 0 || y + delta_y >= self.field.len() as i32 {
                    continue;
                }
                if x + delta_x < 0 || x + delta_x >= self.field[0].len() as i32 {
                    continue;
                }
                let neighbor = &self.field[(y + delta_y) as usize][(x + delta_x) as usize];
                neighbors.push(neighbor)
            }
        }

        neighbors
    }
}

pub fn annotate(minefield: &[&str]) -> Vec<String> {
    let board = Board::new(minefield);
    return board.annotated();
}
<|endoftext|>


<commit_before>pub fn annotate(minefield: &[&str]) -> Vec<String> {
    let field = split(minefield);
    let mut annotated: Vec<String> = Vec::new();

    for (y, row) in field.iter().enumerate() {
        let mut annotated_row = String::new();
        for (x, token) in row.iter().enumerate() {
            match token {
                '*' => annotated_row.push('*'),
                ' ' => {
                    let neighbor_mines = num_neighbor_mines(&field, y as u32, x as u32);
                    let annotated_location = if neighbor_mines == 0 {
                        " ".to_string()
                    } else {
                        neighbor_mines.to_string()
                    };
                    annotated_row.push_str(&annotated_location)
                }
                _ => panic!("unsupported token"),
            }
        }
        annotated.push(annotated_row)
    }

    annotated
}

fn split(minefield: &[&str]) -> Vec<Vec<char>> {
    let mut field: Vec<Vec<char>> = Vec::new();

    for row in minefield {
        field.push(row.chars().collect());
    }
    field
}

fn num_neighbor_mines(field: &Vec<Vec<char>>, y: u32, x: u32) -> usize {
    return get_neighbors(field, y, x)
        .iter()
        .filter(|neighbor| neighbor == &&'*')
        .count();
}

fn get_neighbors(field: &Vec<Vec<char>>, y: u32, x: u32) -> Vec<char> {
    let mut neighbors = Vec::new();
    let y = y as i32;
    let x = x as i32;

    let delta_ys: Vec<i32> = (-1..=1).collect();
    for delta_y in delta_ys {
        let delta_xs: Vec<i32> = (-1..=1).collect();
        for delta_x in delta_xs {
            if delta_y == 0 && delta_x == 0 {
                continue;
            }
            if y + delta_y < 0 || y + delta_y >= field.len() as i32 {
                continue;
            }
            if x + delta_x < 0 || x + delta_x >= field[0].len() as i32 {
                continue;
            }
            let neighbor = field[(y + delta_y) as usize][(x + delta_x) as usize];
            neighbors.push(neighbor)
        }
    }

    neighbors
}
<commit_msg>Create Board struct<commit_after>struct Board {
    field: Vec<Vec<char>>,
}

impl Board {
    fn new(minefield: &[&str]) -> Self {
        let mut field: Vec<Vec<char>> = Vec::new();

        for row in minefield {
            field.push(row.chars().collect());
        }
        Board { field }
    }

    fn annotated(&self) -> Vec<String> {
        let mut annotated: Vec<String> = Vec::new();

        for (y, row) in self.field.iter().enumerate() {
            let mut annotated_row = String::new();
            for (x, token) in row.iter().enumerate() {
                match token {
                    '*' => annotated_row.push('*'),
                    ' ' => {
                        let neighbor_mines = self.num_neighbor_mines(y as u32, x as u32);
                        let annotated_location = if neighbor_mines == 0 {
                            " ".to_string()
                        } else {
                            neighbor_mines.to_string()
                        };
                        annotated_row.push_str(&annotated_location)
                    }
                    _ => panic!("unsupported token"),
                }
            }
            annotated.push(annotated_row)
        }

        annotated
    }

    fn num_neighbor_mines(&self, y: u32, x: u32) -> usize {
        return self
            .get_neighbors(y, x)
            .iter()
            .filter(|neighbor| neighbor == &&&'*')
            .count();
    }

    fn get_neighbors(&self, y: u32, x: u32) -> Vec<&char> {
        let mut neighbors = Vec::new();
        let y = y as i32;
        let x = x as i32;

        let delta_ys: Vec<i32> = (-1..=1).collect();
        for delta_y in delta_ys {
            let delta_xs: Vec<i32> = (-1..=1).collect();
            for delta_x in delta_xs {
                if delta_y == 0 && delta_x == 0 {
                    continue;
                }
                if y + delta_y < 0 || y + delta_y >= self.field.len() as i32 {
                    continue;
                }
                if x + delta_x < 0 || x + delta_x >= self.field[0].len() as i32 {
                    continue;
                }
                let neighbor = &self.field[(y + delta_y) as usize][(x + delta_x) as usize];
                neighbors.push(neighbor)
            }
        }

        neighbors
    }
}

pub fn annotate(minefield: &[&str]) -> Vec<String> {
    let board = Board::new(minefield);
    return board.annotated();
}
<|endoftext|>


<commit_before>use lapin_async::connection::*;
use std::io::{Error,ErrorKind,Read,Write};
use futures::{Async,Poll};
use futures::future::Future;

pub struct Client<'consumer, T:Read+Write+Send> {
  pub connection: Connection<'consumer>,
  pub stream:     T,
}

impl<'consumer, T:Read+Write+Send+'consumer> Client<'consumer, T> {
  pub fn new(stream: T) -> Box<Future<Item=Client<'consumer, T>, Error=Error>+'consumer> {
    let mut client = Client {
      connection: Connection::new(),
      stream:     stream,
    };

    let connector = Connector { client: Some(client) };
    println!("created connector");
    Box::new(connector)
  }
}

pub struct Connector<'consumer, T:Read+Write+Send> {
  client: Option<Client<'consumer, T>>,
}

impl<'consumer, T:Read+Write+Send> Future for Connector<'consumer, T> {
  type Item  = Client<'consumer, T>;
  type Error = Error;

  fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
    let mut client = self.client.take().unwrap();

    let state = client.connection.state;

    println!("POLL state = {:?}", state);
    match state {
      ConnectionState::Initial => {
        client.connection.connect(&mut client.stream);
        match client.connection.run(&mut client.stream) {
          Ok(ConnectionState::Connected) => {
            Ok(Async::Ready(client))
          },
          Ok(_) => {
            self.client = Some(client);
            Ok(Async::NotReady)
          },
          Err(e) => return Err(e),
        }
      }
      ConnectionState::Connecting(_) => {
        match client.connection.run(&mut client.stream) {
          Ok(ConnectionState::Connected) => {
            Ok(Async::Ready(client))
          },
          Ok(_) => {
            self.client = Some(client);
            Ok(Async::NotReady)
          },
          Err(e) => Err(e),
        }
      }
      s => {
        Err(Error::new(ErrorKind::ConnectionAborted, format!("could not connect: state={:?}", s)))
      }
    }
  }

}
<commit_msg>use an inner object for borrows<commit_after>use lapin_async::connection::*;
use std::io::{Error,ErrorKind,Read,Result,Write};
use futures::{Async,Poll};
use futures::future::Future;
use std::rc::Rc;
use std::cell::RefCell;

pub struct InnerClient<'consumer, T:Read+Write> {
  pub connection: Connection<'consumer>,
  pub stream:     T,
}

impl<'consumer, T:Read+Write> InnerClient<'consumer, T> {
  pub fn run(&mut self) -> Result<ConnectionState> {
    self.connection.run(&mut self.stream)
  }

  pub fn connect(&mut self) {
    self.connection.connect(&mut self.stream);
  }
}

pub struct Client<'consumer, T:Read+Write> {
  pub inner: Rc<RefCell<InnerClient<'consumer, T>>>
}

impl<'consumer, T:Read+Write+'consumer> Client<'consumer, T> {
  pub fn new(stream: T) -> Box<Future<Item=Client<'consumer, T>, Error=Error>+'consumer> {
    let mut client = Client {
        inner: Rc::new(RefCell::new(InnerClient {
        connection: Connection::new(),
        stream:     stream,
      }))
    };

    let connector = Connector { client: Some(client) };
    println!("created connector");
    Box::new(connector)
  }
}

pub struct Connector<'consumer, T:Read+Write> {
  client: Option<Client<'consumer, T>>,
}

impl<'consumer, T:Read+Write> Future for Connector<'consumer, T> {
  type Item  = Client<'consumer, T>;
  type Error = Error;

  fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
    let mut client = self.client.take().unwrap();

    let state = client.inner.borrow().connection.state;

    println!("POLL state = {:?}", state);
    match state {
      ConnectionState::Initial => {
        let res = {
          let mut inner = client.inner.borrow_mut();
          inner.connect();
          inner.run()
        };
        match res {
          Ok(ConnectionState::Connected) => {
            return Ok(Async::Ready(client));
          },
          Ok(_) => {
            self.client = Some(client);
            Ok(Async::NotReady)
          },
          Err(e) => return Err(e),
        }
      }
      ConnectionState::Connecting(_) => {
        let res = {
          let mut inner = client.inner.borrow_mut();
          inner.run()
        };
        match res {
          Ok(ConnectionState::Connected) => {
            return Ok(Async::Ready(client));
          },
          Ok(_) => {
            self.client = Some(client);
            Ok(Async::NotReady)
          },
          Err(e) => {return Err(e);},
        }
      }
      s => {
        Err(Error::new(ErrorKind::ConnectionAborted, format!("could not connect: state={:?}", s)))
      }
    }
  }

}
<|endoftext|>


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

//! Numeric traits for generic mathematics

use std::ops::{Add, Sub, Mul, Div, Rem};

pub use bounds::Bounded;
pub use float::Float;
pub use identities::{Zero, One};
pub use ops::checked::*;
pub use ops::saturating::Saturating;
pub use sign::{Signed, Unsigned};
pub use int::PrimInt;
pub use cast::*;

pub mod identities;
pub mod sign;
pub mod ops;
pub mod bounds;
pub mod float;
pub mod int;
pub mod cast;

/// The base trait for numeric types
pub trait Num: PartialEq + Zero + One
    + Add<Output = Self> + Sub<Output = Self>
    + Mul<Output = Self> + Div<Output = Self> + Rem<Output = Self>
{
    type FromStrRadixErr;

    /// Convert from a string and radix <= 36.
    fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr>;
}

macro_rules! int_trait_impl {
    ($name:ident for $($t:ty)*) => ($(
        impl $name for $t {
            type FromStrRadixErr = ::std::num::ParseIntError;
            fn from_str_radix(s: &str, radix: u32)
                              -> Result<Self, ::std::num::ParseIntError>
            {
                <$t>::from_str_radix(s, radix)
            }
        }
    )*)
}
int_trait_impl!(Num for usize u8 u16 u32 u64 isize i8 i16 i32 i64);

#[derive(Debug)]
pub enum FloatErrorKind {
    Empty,
    Invalid,
}
// FIXME: std::num::ParseFloatError is stable in 1.0, but opaque to us,
// so there's not really any way for us to reuse it.
#[derive(Debug)]
pub struct ParseFloatError {
    pub kind: FloatErrorKind,
}

// FIXME: The standard library from_str_radix on floats was deprecated, so we're stuck
// with this implementation ourselves until we want to make a breaking change.
// (would have to drop it from `Num` though)
macro_rules! float_trait_impl {
    ($name:ident for $($t:ty)*) => ($(
        impl $name for $t {
            type FromStrRadixErr = ParseFloatError;

            fn from_str_radix(src: &str, radix: u32)
                              -> Result<Self, Self::FromStrRadixErr>
            {
                use self::FloatErrorKind::*;
                use self::ParseFloatError as PFE;

                // Special values
                match src {
                    "inf"   => return Ok(Float::infinity()),
                    "-inf"  => return Ok(Float::neg_infinity()),
                    "NaN"   => return Ok(Float::nan()),
                    _       => {},
                }

                fn slice_shift_char(src: &str) -> Option<(char, &str)> {
                    src.chars().nth(0).map(|ch| (ch, &src[1..]))
                }

                let (is_positive, src) =  match slice_shift_char(src) {
                    None             => return Err(PFE { kind: Empty }),
                    Some(('-', ""))  => return Err(PFE { kind: Empty }),
                    Some(('-', src)) => (false, src),
                    Some((_, _))     => (true,  src),
                };

                // The significand to accumulate
                let mut sig = if is_positive { 0.0 } else { -0.0 };
                // Necessary to detect overflow
                let mut prev_sig = sig;
                let mut cs = src.chars().enumerate();
                // Exponent prefix and exponent index offset
                let mut exp_info = None::<(char, usize)>;

                // Parse the integer part of the significand
                for (i, c) in cs.by_ref() {
                    match c.to_digit(radix) {
                        Some(digit) => {
                            // shift significand one digit left
                            sig = sig * (radix as $t);

                            // add/subtract current digit depending on sign
                            if is_positive {
                                sig = sig + ((digit as isize) as $t);
                            } else {
                                sig = sig - ((digit as isize) as $t);
                            }

                            // Detect overflow by comparing to last value, except
                            // if we've not seen any non-zero digits.
                            if prev_sig != 0.0 {
                                if is_positive && sig <= prev_sig
                                    { return Ok(Float::infinity()); }
                                if !is_positive && sig >= prev_sig
                                    { return Ok(Float::neg_infinity()); }

                                // Detect overflow by reversing the shift-and-add process
                                if is_positive && (prev_sig != (sig - digit as $t) / radix as $t)
                                    { return Ok(Float::infinity()); }
                                if !is_positive && (prev_sig != (sig + digit as $t) / radix as $t)
                                    { return Ok(Float::neg_infinity()); }
                            }
                            prev_sig = sig;
                        },
                        None => match c {
                            'e' | 'E' | 'p' | 'P' => {
                                exp_info = Some((c, i + 1));
                                break;  // start of exponent
                            },
                            '.' => {
                                break;  // start of fractional part
                            },
                            _ => {
                                return Err(PFE { kind: Invalid });
                            },
                        },
                    }
                }

                // If we are not yet at the exponent parse the fractional
                // part of the significand
                if exp_info.is_none() {
                    let mut power = 1.0;
                    for (i, c) in cs.by_ref() {
                        match c.to_digit(radix) {
                            Some(digit) => {
                                // Decrease power one order of magnitude
                                power = power / (radix as $t);
                                // add/subtract current digit depending on sign
                                sig = if is_positive {
                                    sig + (digit as $t) * power
                                } else {
                                    sig - (digit as $t) * power
                                };
                                // Detect overflow by comparing to last value
                                if is_positive && sig < prev_sig
                                    { return Ok(Float::infinity()); }
                                if !is_positive && sig > prev_sig
                                    { return Ok(Float::neg_infinity()); }
                                prev_sig = sig;
                            },
                            None => match c {
                                'e' | 'E' | 'p' | 'P' => {
                                    exp_info = Some((c, i + 1));
                                    break; // start of exponent
                                },
                                _ => {
                                    return Err(PFE { kind: Invalid });
                                },
                            },
                        }
                    }
                }

                // Parse and calculate the exponent
                let exp = match exp_info {
                    Some((c, offset)) => {
                        let base = match c {
                            'E' | 'e' if radix == 10 => 10.0,
                            'P' | 'p' if radix == 16 => 2.0,
                            _ => return Err(PFE { kind: Invalid }),
                        };

                        // Parse the exponent as decimal integer
                        let src = &src[offset..];
                        let (is_positive, exp) = match slice_shift_char(src) {
                            Some(('-', src)) => (false, src.parse::<usize>()),
                            Some(('+', src)) => (true,  src.parse::<usize>()),
                            Some((_, _))     => (true,  src.parse::<usize>()),
                            None             => return Err(PFE { kind: Invalid }),
                        };

                        match (is_positive, exp) {
                            (true,  Ok(exp)) => base.powi(exp as i32),
                            (false, Ok(exp)) => 1.0 / base.powi(exp as i32),
                            (_, Err(_))      => return Err(PFE { kind: Invalid }),
                        }
                    },
                    None => 1.0, // no exponent
                };

                Ok(sig * exp)
            }
        }
    )*)
}
float_trait_impl!(Num for f32 f64);

#[test]
fn from_str_radix_unwrap() {
    // The Result error must impl Debug to allow unwrap()

    let i: i32 = Num::from_str_radix("0", 10).unwrap();
    assert_eq!(i, 0);

    let f: f32 = Num::from_str_radix("0.0", 10).unwrap();
    assert_eq!(f, 0.0);
}
<commit_msg>traits: use `cast` items before `int`<commit_after>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Numeric traits for generic mathematics

use std::ops::{Add, Sub, Mul, Div, Rem};

pub use bounds::Bounded;
pub use float::Float;
pub use identities::{Zero, One};
pub use ops::checked::*;
pub use ops::saturating::Saturating;
pub use sign::{Signed, Unsigned};
pub use cast::*;
pub use int::PrimInt;

pub mod identities;
pub mod sign;
pub mod ops;
pub mod bounds;
pub mod float;
pub mod cast;
pub mod int;

/// The base trait for numeric types
pub trait Num: PartialEq + Zero + One
    + Add<Output = Self> + Sub<Output = Self>
    + Mul<Output = Self> + Div<Output = Self> + Rem<Output = Self>
{
    type FromStrRadixErr;

    /// Convert from a string and radix <= 36.
    fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr>;
}

macro_rules! int_trait_impl {
    ($name:ident for $($t:ty)*) => ($(
        impl $name for $t {
            type FromStrRadixErr = ::std::num::ParseIntError;
            fn from_str_radix(s: &str, radix: u32)
                              -> Result<Self, ::std::num::ParseIntError>
            {
                <$t>::from_str_radix(s, radix)
            }
        }
    )*)
}
int_trait_impl!(Num for usize u8 u16 u32 u64 isize i8 i16 i32 i64);

#[derive(Debug)]
pub enum FloatErrorKind {
    Empty,
    Invalid,
}
// FIXME: std::num::ParseFloatError is stable in 1.0, but opaque to us,
// so there's not really any way for us to reuse it.
#[derive(Debug)]
pub struct ParseFloatError {
    pub kind: FloatErrorKind,
}

// FIXME: The standard library from_str_radix on floats was deprecated, so we're stuck
// with this implementation ourselves until we want to make a breaking change.
// (would have to drop it from `Num` though)
macro_rules! float_trait_impl {
    ($name:ident for $($t:ty)*) => ($(
        impl $name for $t {
            type FromStrRadixErr = ParseFloatError;

            fn from_str_radix(src: &str, radix: u32)
                              -> Result<Self, Self::FromStrRadixErr>
            {
                use self::FloatErrorKind::*;
                use self::ParseFloatError as PFE;

                // Special values
                match src {
                    "inf"   => return Ok(Float::infinity()),
                    "-inf"  => return Ok(Float::neg_infinity()),
                    "NaN"   => return Ok(Float::nan()),
                    _       => {},
                }

                fn slice_shift_char(src: &str) -> Option<(char, &str)> {
                    src.chars().nth(0).map(|ch| (ch, &src[1..]))
                }

                let (is_positive, src) =  match slice_shift_char(src) {
                    None             => return Err(PFE { kind: Empty }),
                    Some(('-', ""))  => return Err(PFE { kind: Empty }),
                    Some(('-', src)) => (false, src),
                    Some((_, _))     => (true,  src),
                };

                // The significand to accumulate
                let mut sig = if is_positive { 0.0 } else { -0.0 };
                // Necessary to detect overflow
                let mut prev_sig = sig;
                let mut cs = src.chars().enumerate();
                // Exponent prefix and exponent index offset
                let mut exp_info = None::<(char, usize)>;

                // Parse the integer part of the significand
                for (i, c) in cs.by_ref() {
                    match c.to_digit(radix) {
                        Some(digit) => {
                            // shift significand one digit left
                            sig = sig * (radix as $t);

                            // add/subtract current digit depending on sign
                            if is_positive {
                                sig = sig + ((digit as isize) as $t);
                            } else {
                                sig = sig - ((digit as isize) as $t);
                            }

                            // Detect overflow by comparing to last value, except
                            // if we've not seen any non-zero digits.
                            if prev_sig != 0.0 {
                                if is_positive && sig <= prev_sig
                                    { return Ok(Float::infinity()); }
                                if !is_positive && sig >= prev_sig
                                    { return Ok(Float::neg_infinity()); }

                                // Detect overflow by reversing the shift-and-add process
                                if is_positive && (prev_sig != (sig - digit as $t) / radix as $t)
                                    { return Ok(Float::infinity()); }
                                if !is_positive && (prev_sig != (sig + digit as $t) / radix as $t)
                                    { return Ok(Float::neg_infinity()); }
                            }
                            prev_sig = sig;
                        },
                        None => match c {
                            'e' | 'E' | 'p' | 'P' => {
                                exp_info = Some((c, i + 1));
                                break;  // start of exponent
                            },
                            '.' => {
                                break;  // start of fractional part
                            },
                            _ => {
                                return Err(PFE { kind: Invalid });
                            },
                        },
                    }
                }

                // If we are not yet at the exponent parse the fractional
                // part of the significand
                if exp_info.is_none() {
                    let mut power = 1.0;
                    for (i, c) in cs.by_ref() {
                        match c.to_digit(radix) {
                            Some(digit) => {
                                // Decrease power one order of magnitude
                                power = power / (radix as $t);
                                // add/subtract current digit depending on sign
                                sig = if is_positive {
                                    sig + (digit as $t) * power
                                } else {
                                    sig - (digit as $t) * power
                                };
                                // Detect overflow by comparing to last value
                                if is_positive && sig < prev_sig
                                    { return Ok(Float::infinity()); }
                                if !is_positive && sig > prev_sig
                                    { return Ok(Float::neg_infinity()); }
                                prev_sig = sig;
                            },
                            None => match c {
                                'e' | 'E' | 'p' | 'P' => {
                                    exp_info = Some((c, i + 1));
                                    break; // start of exponent
                                },
                                _ => {
                                    return Err(PFE { kind: Invalid });
                                },
                            },
                        }
                    }
                }

                // Parse and calculate the exponent
                let exp = match exp_info {
                    Some((c, offset)) => {
                        let base = match c {
                            'E' | 'e' if radix == 10 => 10.0,
                            'P' | 'p' if radix == 16 => 2.0,
                            _ => return Err(PFE { kind: Invalid }),
                        };

                        // Parse the exponent as decimal integer
                        let src = &src[offset..];
                        let (is_positive, exp) = match slice_shift_char(src) {
                            Some(('-', src)) => (false, src.parse::<usize>()),
                            Some(('+', src)) => (true,  src.parse::<usize>()),
                            Some((_, _))     => (true,  src.parse::<usize>()),
                            None             => return Err(PFE { kind: Invalid }),
                        };

                        match (is_positive, exp) {
                            (true,  Ok(exp)) => base.powi(exp as i32),
                            (false, Ok(exp)) => 1.0 / base.powi(exp as i32),
                            (_, Err(_))      => return Err(PFE { kind: Invalid }),
                        }
                    },
                    None => 1.0, // no exponent
                };

                Ok(sig * exp)
            }
        }
    )*)
}
float_trait_impl!(Num for f32 f64);

#[test]
fn from_str_radix_unwrap() {
    // The Result error must impl Debug to allow unwrap()

    let i: i32 = Num::from_str_radix("0", 10).unwrap();
    assert_eq!(i, 0);

    let f: f32 = Num::from_str_radix("0.0", 10).unwrap();
    assert_eq!(f, 0.0);
}
<|endoftext|>