<commit_before>use std::rc::{Rc};
use std::cell::{RefCell};
use std::collections::HashMap;

//is same identity
fn is_same<T>(lhs: &T, rhs: &T) -> bool {
    lhs as *const T as i64 == rhs as *const T as i64
}

//the code below is horrible
//borrow doesn't return T, it returns Ref<T>
//we need to dereference it to get to the T inside
//is_same takes borrow so reapply the ampersand
fn is_same_subscriber<T: Subscriber>(lhs: Rc<RefCell<T>>, rhs: Rc<RefCell<T>>) -> bool {
    let lhs = lhs.clone();
    let rhs = rhs.clone();
    let res = is_same(&*lhs.borrow(), &*rhs.borrow()); //needed to live long enough
    res
}

pub trait Subscriber {
    fn new_message(&mut self, bytes: &[u8]);
}

pub struct Broker<T: Subscriber> {
    tree: Node<T>,
}

struct Node<T: Subscriber> {
    children: HashMap<String, Node<T>>,
    leaves: Vec<Subscription<T>>,
}

struct Subscription<T: Subscriber> {
    subscriber: Rc<RefCell<T>>,
    topic: String,
}

impl<T: Subscriber> Subscription<T> {
    fn new(subscriber: Rc<RefCell<T>>, topic: &str) -> Self {
        Subscription { subscriber: subscriber.clone(), topic: topic.to_string() }
    }
}

impl<T: Subscriber> Node<T> {
    fn new() -> Self {
        Node { children: HashMap::new(), leaves: vec![] }
    }

    fn add_subscription(&mut self, subscription: Subscription<T>) {
        self.leaves.push(subscription);
    }
}

impl<T: Subscriber> Broker<T> {
    pub fn new() -> Self {
        Broker { tree: Node::new() }
    }

    pub fn subscribe(&mut self, subscriber: Rc<RefCell<T>>, topics: &[&str]) {
        for topic in topics {
            let sub_parts : Vec<&str> = topic.split("/").collect();
            Self::ensure_node_exists(&sub_parts, &mut self.tree);
            Self::add_subscription_to_node(&mut self.tree, subscriber.clone(), &sub_parts, topic);
        }
    }

    pub fn unsubscribe_all(&mut self, subscriber: Rc<RefCell<T>>) {
        Self::unsubscribe_all_impl(&mut self.tree, subscriber.clone());
    }

    pub fn unsubscribe(&mut self, subscriber: Rc<RefCell<T>>, topics: &[&str]) {
        Self::unsubscribe_impl(&mut self.tree, subscriber.clone(), topics);
    }

    pub fn publish(&self, topic: &str, payload: &[u8]) {
        let pub_parts : Vec<&str> = topic.split("/").collect();
        Self::publish_impl(&self.tree, &pub_parts, &payload);
    }

    fn ensure_node_exists(sub_parts: &[&str], node: &mut Node<T>) {
        if sub_parts.len() == 0 {
            return;
        }

        let part = &sub_parts[0][..];
        if !node.children.contains_key(part) {
            node.children.insert(sub_parts[0].to_string(), Node::new());
        }

        Self::ensure_node_exists(&sub_parts[1..], node.children.get_mut(part).unwrap());
    }

    fn add_subscription_to_node(tree: &mut Node<T>, subscriber: Rc<RefCell<T>>, sub_parts: &[&str], topic: &str) {
        if sub_parts.len() < 1 {
            panic!("oops");
        }

        let part = &sub_parts[0][..];
        let node = tree.children.get_mut(part).unwrap();
        let sub_parts = &sub_parts[1..];

        if sub_parts.len() == 0 {
            node.add_subscription(Subscription::new(subscriber.clone(), topic));
        } else {
            Self::add_subscription_to_node(node, subscriber, sub_parts, topic);
        }
    }

    fn publish_impl(tree: &Node<T>, pub_parts: &[&str], payload: &[u8]) {
        if pub_parts.len() < 1 {
            panic!("oops");
        }

        let part = &pub_parts[0][..];
        let node = tree.children.get(part);
        let pub_parts = &pub_parts[1..];

        match node {
            None => {
                return; //didn't find a subscriber
            },
            Some(node) => {
                if pub_parts.len() == 0 {
                    for subscription in &node.leaves {
                        let subscriber = subscription.subscriber.clone();
                        subscriber.borrow_mut().new_message(payload);
                    }
                } else {
                    Self::publish_impl(node, pub_parts, payload);
                }
            }
        }
    }

    fn unsubscribe_all_impl(tree: &mut Node<T>, subscriber: Rc<RefCell<T>>) {
        tree.leaves.retain(|s| !is_same_subscriber(s.subscriber.clone(), subscriber.clone()));

        if tree.children.len() == 0 {
            return;
        }

        for (_, node) in tree.children.iter_mut() {
            Self::unsubscribe_all_impl(node, subscriber.clone());
        }
    }

    fn unsubscribe_impl(tree: &mut Node<T>, subscriber: Rc<RefCell<T>>, topics: &[&str]) {
        tree.leaves.retain(|s| {
            let is_same_subscriber = is_same_subscriber(s.subscriber.clone(), subscriber.clone());
            //I have no idea why t below is &&&str, I added a tripe deref cos the compiler told me to
            let is_same_topic = topics.into_iter().find(|t| ***t == s.topic).is_some();
            !is_same_subscriber || !is_same_topic
        });

        if tree.children.len() == 0 {
            return;
        }

        for (_, node) in tree.children.iter_mut() {
            Self::unsubscribe_impl(node, subscriber.clone(), topics);
        }
    }
}

#[cfg(test)]
struct TestSubscriber {
    msgs: Vec<Vec<u8>>,
}

#[cfg(test)]
impl TestSubscriber {
    fn new() -> Self {
        TestSubscriber{msgs: vec![]}
    }
}

#[cfg(test)]
impl Subscriber for TestSubscriber {
    fn new_message(&mut self, bytes: &[u8]) {
        self.msgs.push(bytes.to_vec());
    }
}

#[test]
fn test_subscribe() {
    let mut broker = Broker::<TestSubscriber>::new();
    let sub_rc = Rc::new(RefCell::new(TestSubscriber::new()));
    let subscriber = sub_rc.clone();
    broker.publish("topics/foo", &[0, 1, 2]);
    assert_eq!(subscriber.borrow().msgs.len(), 0);

    broker.subscribe(subscriber.clone(), &["topics/foo"]);
    broker.publish("topics/foo", &[0, 1, 9]); //should get this
    broker.publish("topics/bar", &[2, 4, 6]); //shouldn't get this
    assert_eq!(subscriber.borrow().msgs.len(), 1);
    assert_eq!(subscriber.borrow().msgs[0], &[0, 1, 9]);

    broker.subscribe(subscriber.clone(), &["topics/bar"]);
    broker.publish("topics/foo", &[1, 3, 5, 7]);
    broker.publish("topics/bar", &[2, 4]);
    assert_eq!(subscriber.borrow().msgs.len(), 3);
    assert_eq!(subscriber.borrow().msgs[0], &[0, 1, 9]);
    assert_eq!(subscriber.borrow().msgs[1], &[1, 3, 5, 7]);
    assert_eq!(subscriber.borrow().msgs[2], &[2, 4]);
}

#[test]
fn test_unsubscribe_all() {
    let mut broker = Broker::<TestSubscriber>::new();
    let sub_rc = Rc::new(RefCell::new(TestSubscriber::new()));
    let subscriber = sub_rc.clone();

    broker.subscribe(subscriber.clone(), &["topics/foo"]);
    broker.publish("topics/foo", &[0, 1, 9]); //should get this
    broker.publish("topics/bar", &[2, 4, 6]); //shouldn't get this
    assert_eq!(subscriber.borrow().msgs.len(), 1);
    assert_eq!(subscriber.borrow().msgs[0], &[0, 1, 9]);

    broker.unsubscribe_all(subscriber.clone());
    broker.publish("topics/foo", &[0, 1, 9]);
    broker.publish("topics/bar", &[2, 4]);
    broker.publish("topics/baz", &[2, 4, 7, 11]);

    //shouldn't have changed
    assert_eq!(subscriber.borrow().msgs.len(), 1);
    assert_eq!(subscriber.borrow().msgs[0], &[0, 1, 9]);
}

#[test]
fn test_unsubscribe_one() {
    let mut broker = Broker::<TestSubscriber>::new();
    let sub_rc = Rc::new(RefCell::new(TestSubscriber::new()));
    let subscriber = sub_rc.clone();

    broker.subscribe(subscriber.clone(), &["topics/foo", "topics/bar"]);
    broker.publish("topics/foo", &[0, 1, 9]); //should get this
    broker.publish("topics/bar", &[2, 4]); //should get this
    broker.publish("topics/baz", &[2, 4, 7, 11]); //shouldn't get this
    assert_eq!(subscriber.borrow().msgs.len(), 2);
    assert_eq!(subscriber.borrow().msgs[0], &[0, 1, 9]);
    assert_eq!(subscriber.borrow().msgs[1], &[2, 4]);

    broker.unsubscribe(subscriber.clone(), &["topics/foo"]);
    broker.publish("topics/foo", &[0, 1, 9]); //shouldn't get this
    broker.publish("topics/bar", &[2, 4]); //should get this
    broker.publish("topics/baz", &[2, 4, 7, 11]); //shouldn't get this

    assert_eq!(subscriber.borrow().msgs.len(), 3);
    assert_eq!(subscriber.borrow().msgs[0], &[0, 1, 9]);
    assert_eq!(subscriber.borrow().msgs[1], &[2, 4]);
    assert_eq!(subscriber.borrow().msgs[2], &[2, 4]);
}

#[cfg(test)]
fn test_matches(pub_topic: &str, sub_topic: &str) -> bool {
    let mut broker = Broker::<TestSubscriber>::new();
    let sub_rc = Rc::new(RefCell::new(TestSubscriber::new()));
    let subscriber = sub_rc.clone();

    broker.subscribe(subscriber.clone(), &[sub_topic]);
    broker.publish(pub_topic, &[0, 1, 2]);
    let subscriber = subscriber.borrow();
    subscriber.msgs.len() == 1
}

#[test]
fn test_wildcards() {
    assert_eq!(test_matches("foo/bar/baz", "foo/bar/baz"), true);
    assert_eq!(test_matches("foo/bar", "foo/+"), true);
    assert_eq!(test_matches("foo/baz", "foo/+"), true);
    assert_eq!(test_matches("foo/bar/baz", "foo/+"), false);
    assert_eq!(test_matches("foo/bar", "foo/#"), true);
    assert_eq!(test_matches("foo/bar/baz", "foo/#"), true);
    assert_eq!(test_matches("foo/bar/baz/boo", "foo/#"), true);
    assert_eq!(test_matches("foo/bla/bar/baz/boo/bogadog", "foo/+/bar/baz/#"), true);
    assert_eq!(test_matches("finance", "finance/#"), true);
    assert_eq!(test_matches("finance", "finance#"), false);
    assert_eq!(test_matches("finance", "#"), true);
    assert_eq!(test_matches("finance/stock", "#"), true);
    assert_eq!(test_matches("finance/stock", "finance/stock/ibm"), false);
    assert_eq!(test_matches("topics/foo/bar", "topics/foo/#"), true);
    assert_eq!(test_matches("topics/bar/baz/boo", "topics/foo/#"), false);
}
<commit_msg>Passing wildcard test<commit_after>use std::rc::{Rc};
use std::cell::{RefCell};
use std::collections::HashMap;

//is same identity
fn is_same<T>(lhs: &T, rhs: &T) -> bool {
    lhs as *const T as i64 == rhs as *const T as i64
}

//the code below is horrible
//borrow doesn't return T, it returns Ref<T>
//we need to dereference it to get to the T inside
//is_same takes borrow so reapply the ampersand
fn is_same_subscriber<T: Subscriber>(lhs: Rc<RefCell<T>>, rhs: Rc<RefCell<T>>) -> bool {
    let lhs = lhs.clone();
    let rhs = rhs.clone();
    let res = is_same(&*lhs.borrow(), &*rhs.borrow()); //needed to live long enough
    res
}

pub trait Subscriber {
    fn new_message(&mut self, bytes: &[u8]);
}

pub struct Broker<T: Subscriber> {
    tree: Node<T>,
}

struct Node<T: Subscriber> {
    children: HashMap<String, Node<T>>,
    leaves: Vec<Subscription<T>>,
}

struct Subscription<T: Subscriber> {
    subscriber: Rc<RefCell<T>>,
    topic: String,
}

impl<T: Subscriber> Subscription<T> {
    fn new(subscriber: Rc<RefCell<T>>, topic: &str) -> Self {
        Subscription { subscriber: subscriber.clone(), topic: topic.to_string() }
    }
}

impl<T: Subscriber> Node<T> {
    fn new() -> Self {
        Node { children: HashMap::new(), leaves: vec![] }
    }

    fn add_subscription(&mut self, subscription: Subscription<T>) {
        self.leaves.push(subscription);
    }
}

impl<T: Subscriber> Broker<T> {
    pub fn new() -> Self {
        Broker { tree: Node::new() }
    }

    pub fn subscribe(&mut self, subscriber: Rc<RefCell<T>>, topics: &[&str]) {
        for topic in topics {
            let sub_parts : Vec<&str> = topic.split("/").collect();
            Self::ensure_node_exists(&sub_parts, &mut self.tree);
            Self::add_subscription_to_node(&mut self.tree, subscriber.clone(), &sub_parts, topic);
        }
    }

    pub fn unsubscribe_all(&mut self, subscriber: Rc<RefCell<T>>) {
        Self::unsubscribe_all_impl(&mut self.tree, subscriber.clone());
    }

    pub fn unsubscribe(&mut self, subscriber: Rc<RefCell<T>>, topics: &[&str]) {
        Self::unsubscribe_impl(&mut self.tree, subscriber.clone(), topics);
    }

    pub fn publish(&self, topic: &str, payload: &[u8]) {
        let pub_parts : Vec<&str> = topic.split("/").collect();
        Self::publish_impl(&self.tree, &pub_parts, &payload);
    }

    fn ensure_node_exists(sub_parts: &[&str], node: &mut Node<T>) {
        if sub_parts.len() == 0 {
            return;
        }

        let part = &sub_parts[0][..];
        if !node.children.contains_key(part) {
            node.children.insert(sub_parts[0].to_string(), Node::new());
        }

        Self::ensure_node_exists(&sub_parts[1..], node.children.get_mut(part).unwrap());
    }

    fn add_subscription_to_node(tree: &mut Node<T>, subscriber: Rc<RefCell<T>>, sub_parts: &[&str], topic: &str) {
        if sub_parts.len() < 1 {
            panic!("oops");
        }

        let part = &sub_parts[0][..];
        let node = tree.children.get_mut(part).unwrap();
        let sub_parts = &sub_parts[1..];

        if sub_parts.len() == 0 {
            node.add_subscription(Subscription::new(subscriber.clone(), topic));
        } else {
            Self::add_subscription_to_node(node, subscriber, sub_parts, topic);
        }
    }

    fn publish_impl(tree: &Node<T>, pub_parts: &[&str], payload: &[u8]) {
        if pub_parts.len() < 1 {
            return;
        }

        let part = &pub_parts[0][..];
        let pub_parts = &pub_parts[1..];

        for part in vec![part, "#", "+"] {

            let node = tree.children.get(part);

            match node {
                None => {
                    continue; //didn't find a subscriber
                },
                Some(node) => {
                    //so that "finance/#" matches "finance"
                    if pub_parts.len() == 0 && node.children.contains_key("#") {
                        let node = node.children.get("#").unwrap();
                        for subscription in &node.leaves {
                            let subscriber = subscription.subscriber.clone();
                            subscriber.borrow_mut().new_message(payload);
                        }
                    }

                    if pub_parts.len() == 0 || part == "#" {
                        for subscription in &node.leaves {
                            let subscriber = subscription.subscriber.clone();
                            subscriber.borrow_mut().new_message(payload);
                        }
                    }
                    Self::publish_impl(node, pub_parts, payload);
                }
            }
        }
    }

    fn unsubscribe_all_impl(tree: &mut Node<T>, subscriber: Rc<RefCell<T>>) {
        tree.leaves.retain(|s| !is_same_subscriber(s.subscriber.clone(), subscriber.clone()));

        if tree.children.len() == 0 {
            return;
        }

        for (_, node) in tree.children.iter_mut() {
            Self::unsubscribe_all_impl(node, subscriber.clone());
        }
    }

    fn unsubscribe_impl(tree: &mut Node<T>, subscriber: Rc<RefCell<T>>, topics: &[&str]) {
        tree.leaves.retain(|s| {
            let is_same_subscriber = is_same_subscriber(s.subscriber.clone(), subscriber.clone());
            //I have no idea why t below is &&&str, I added a tripe deref cos the compiler told me to
            let is_same_topic = topics.into_iter().find(|t| ***t == s.topic).is_some();
            !is_same_subscriber || !is_same_topic
        });

        if tree.children.len() == 0 {
            return;
        }

        for (_, node) in tree.children.iter_mut() {
            Self::unsubscribe_impl(node, subscriber.clone(), topics);
        }
    }
}

#[cfg(test)]
struct TestSubscriber {
    msgs: Vec<Vec<u8>>,
}

#[cfg(test)]
impl TestSubscriber {
    fn new() -> Self {
        TestSubscriber{msgs: vec![]}
    }
}

#[cfg(test)]
impl Subscriber for TestSubscriber {
    fn new_message(&mut self, bytes: &[u8]) {
        self.msgs.push(bytes.to_vec());
    }
}

#[test]
fn test_subscribe() {
    let mut broker = Broker::<TestSubscriber>::new();
    let sub_rc = Rc::new(RefCell::new(TestSubscriber::new()));
    let subscriber = sub_rc.clone();
    broker.publish("topics/foo", &[0, 1, 2]);
    assert_eq!(subscriber.borrow().msgs.len(), 0);

    broker.subscribe(subscriber.clone(), &["topics/foo"]);
    broker.publish("topics/foo", &[0, 1, 9]); //should get this
    broker.publish("topics/bar", &[2, 4, 6]); //shouldn't get this
    assert_eq!(subscriber.borrow().msgs.len(), 1);
    assert_eq!(subscriber.borrow().msgs[0], &[0, 1, 9]);

    broker.subscribe(subscriber.clone(), &["topics/bar"]);
    broker.publish("topics/foo", &[1, 3, 5, 7]);
    broker.publish("topics/bar", &[2, 4]);
    assert_eq!(subscriber.borrow().msgs.len(), 3);
    assert_eq!(subscriber.borrow().msgs[0], &[0, 1, 9]);
    assert_eq!(subscriber.borrow().msgs[1], &[1, 3, 5, 7]);
    assert_eq!(subscriber.borrow().msgs[2], &[2, 4]);
}

#[test]
fn test_unsubscribe_all() {
    let mut broker = Broker::<TestSubscriber>::new();
    let sub_rc = Rc::new(RefCell::new(TestSubscriber::new()));
    let subscriber = sub_rc.clone();

    broker.subscribe(subscriber.clone(), &["topics/foo"]);
    broker.publish("topics/foo", &[0, 1, 9]); //should get this
    broker.publish("topics/bar", &[2, 4, 6]); //shouldn't get this
    assert_eq!(subscriber.borrow().msgs.len(), 1);
    assert_eq!(subscriber.borrow().msgs[0], &[0, 1, 9]);

    broker.unsubscribe_all(subscriber.clone());
    broker.publish("topics/foo", &[0, 1, 9]);
    broker.publish("topics/bar", &[2, 4]);
    broker.publish("topics/baz", &[2, 4, 7, 11]);

    //shouldn't have changed
    assert_eq!(subscriber.borrow().msgs.len(), 1);
    assert_eq!(subscriber.borrow().msgs[0], &[0, 1, 9]);
}

#[test]
fn test_unsubscribe_one() {
    let mut broker = Broker::<TestSubscriber>::new();
    let sub_rc = Rc::new(RefCell::new(TestSubscriber::new()));
    let subscriber = sub_rc.clone();

    broker.subscribe(subscriber.clone(), &["topics/foo", "topics/bar"]);
    broker.publish("topics/foo", &[0, 1, 9]); //should get this
    broker.publish("topics/bar", &[2, 4]); //should get this
    broker.publish("topics/baz", &[2, 4, 7, 11]); //shouldn't get this
    assert_eq!(subscriber.borrow().msgs.len(), 2);
    assert_eq!(subscriber.borrow().msgs[0], &[0, 1, 9]);
    assert_eq!(subscriber.borrow().msgs[1], &[2, 4]);

    broker.unsubscribe(subscriber.clone(), &["topics/foo"]);
    broker.publish("topics/foo", &[0, 1, 9]); //shouldn't get this
    broker.publish("topics/bar", &[2, 4]); //should get this
    broker.publish("topics/baz", &[2, 4, 7, 11]); //shouldn't get this

    assert_eq!(subscriber.borrow().msgs.len(), 3);
    assert_eq!(subscriber.borrow().msgs[0], &[0, 1, 9]);
    assert_eq!(subscriber.borrow().msgs[1], &[2, 4]);
    assert_eq!(subscriber.borrow().msgs[2], &[2, 4]);
}

#[cfg(test)]
fn test_matches(pub_topic: &str, sub_topic: &str) -> bool {
    let mut broker = Broker::<TestSubscriber>::new();
    let sub_rc = Rc::new(RefCell::new(TestSubscriber::new()));
    let subscriber = sub_rc.clone();

    broker.subscribe(subscriber.clone(), &[sub_topic]);
    broker.publish(pub_topic, &[0, 1, 2]);
    let subscriber = subscriber.borrow();
    subscriber.msgs.len() == 1
}

#[test]
fn test_wildcards() {
    assert_eq!(test_matches("foo/bar/baz", "foo/bar/baz"), true);
    assert_eq!(test_matches("foo/bar", "foo/+"), true);
    assert_eq!(test_matches("foo/baz", "foo/+"), true);
    assert_eq!(test_matches("foo/bar/baz", "foo/+"), false);
    assert_eq!(test_matches("foo/bar", "foo/#"), true);
    assert_eq!(test_matches("foo/bar/baz", "foo/#"), true);
    assert_eq!(test_matches("foo/bar/baz/boo", "foo/#"), true);
    assert_eq!(test_matches("foo/bla/bar/baz/boo/bogadog", "foo/+/bar/baz/#"), true);
    assert_eq!(test_matches("finance", "finance/#"), true);
    assert_eq!(test_matches("finance", "finance#"), false);
    assert_eq!(test_matches("finance", "#"), true);
    assert_eq!(test_matches("finance/stock", "#"), true);
    assert_eq!(test_matches("finance/stock", "finance/stock/ibm"), false);
    assert_eq!(test_matches("topics/foo/bar", "topics/foo/#"), true);
    assert_eq!(test_matches("topics/bar/baz/boo", "topics/foo/#"), false);
}
<|endoftext|>


<commit_before>use core::num::{One, Zero};
use core::rand::{Rand, Rng, RngUtil};
use std::cmp::FuzzyEq;
use traits::dim::Dim;
use traits::inv::Inv;
use traits::rotation::Rotation;
use traits::translation::Translation;
use traits::transpose::Transpose;
use traits::workarounds::rlmul::{RMul, LMul};

pub struct Transform<M, V>
{
  submat   : M,
  subtrans : V
}

pub fn transform<M: Copy, V: Copy>(mat: &M, trans: &V) -> Transform<M, V>
{ Transform { submat: *mat, subtrans: *trans } }

impl<M:Dim, V> Dim for Transform<M, V>
{
  fn dim() -> uint
  { Dim::dim::<M>() }
}

impl<M:Copy + One, V:Copy + Zero> One for Transform<M, V>
{
  fn one() -> Transform<M, V>
  { Transform { submat: One::one(), subtrans: Zero::zero() } }
}

impl<M:Copy + Zero, V:Copy + Zero> Zero for Transform<M, V>
{
  fn zero() -> Transform<M, V>
  { Transform { submat: Zero::zero(), subtrans: Zero::zero() } }

  fn is_zero(&self) -> bool
  { self.submat.is_zero() && self.subtrans.is_zero() }
}

impl<M:Copy + RMul<V> + Mul<M, M>, V:Copy + Add<V, V>>
Mul<Transform<M, V>, Transform<M, V>> for Transform<M, V>
{
  fn mul(&self, other: &Transform<M, V>) -> Transform<M, V>
  {
    Transform { submat: self.submat * other.submat,
                subtrans: self.subtrans + self.submat.rmul(&other.subtrans) }
  }
}

impl<M: RMul<V>, V> RMul<V> for Transform<M, V>
{
  fn rmul(&self, other: &V) -> V
  { self.submat.rmul(other) }
}

impl<M: LMul<V>, V> LMul<V> for Transform<M, V>
{
  fn lmul(&self, other: &V) -> V
  { self.submat.lmul(other) }
}

impl<M: Copy, V: Copy + Translation<V>> Translation<V> for Transform<M, V>
{
  fn translation(&self) -> V
  { self.subtrans.translation() }

  fn translated(&self, t: &V) -> Transform<M, V>
  { transform(&self.submat, &self.subtrans.translated(t)) }

  fn translate(&mut self, t: &V)
  { self.subtrans.translate(t) }
}

impl<M: Rotation<V> + Copy, V: Copy> Rotation<V> for Transform<M, V>
{
  fn rotation(&self) -> V
  { self.submat.rotation() }

  fn rotated(&self, rot: &V) -> Transform<M, V>
  { transform(&self.submat.rotated(rot), &self.subtrans) }

  fn rotate(&mut self, rot: &V)
  { self.submat.rotate(rot) }
}

impl<M:Copy + Transpose + Inv + RMul<V>, V:Copy + Neg<V>>
Inv for Transform<M, V>
{
  fn invert(&mut self)
  {
    self.submat.invert();
    self.subtrans = self.submat.rmul(&-self.subtrans);
  }

  fn inverse(&self) -> Transform<M, V>
  {
    let mut res = *self;

    res.invert();

    res
  }
}

impl<T, M:FuzzyEq<T>, V:FuzzyEq<T>> FuzzyEq<T> for Transform<M, V>
{
  fn fuzzy_eq(&self, other: &Transform<M, V>) -> bool
  {
    self.submat.fuzzy_eq(&other.submat) &&
    self.subtrans.fuzzy_eq(&other.subtrans)
  }

  fn fuzzy_eq_eps(&self, other: &Transform<M, V>, epsilon: &T) -> bool
  {
    self.submat.fuzzy_eq_eps(&other.submat, epsilon) &&
    self.subtrans.fuzzy_eq_eps(&other.subtrans, epsilon)
  }
}

impl<M: Rand + Copy, V: Rand + Copy> Rand for Transform<M, V>
{
  fn rand<R: Rng>(rng: &R) -> Transform<M, V>
  { transform(&rng.gen(), &rng.gen()) }
}

impl<M:ToStr, V:ToStr> ToStr for Transform<M, V>
{
  fn to_str(&self) -> ~str
  {
    ~"Transform {" + " submat: "    + self.submat.to_str()    +
                     " subtrans: "  + self.subtrans.to_str()  + " }"
  }
}
<commit_msg>Fix rotation for transform adaptor.<commit_after>use core::num::{One, Zero};
use core::rand::{Rand, Rng, RngUtil};
use std::cmp::FuzzyEq;
use traits::dim::Dim;
use traits::inv::Inv;
use traits::rotation::Rotation;
use traits::translation::Translation;
use traits::transpose::Transpose;
use traits::workarounds::rlmul::{RMul, LMul};

pub struct Transform<M, V>
{
  submat   : M,
  subtrans : V
}

pub fn transform<M: Copy, V: Copy>(mat: &M, trans: &V) -> Transform<M, V>
{ Transform { submat: *mat, subtrans: *trans } }

impl<M:Dim, V> Dim for Transform<M, V>
{
  fn dim() -> uint
  { Dim::dim::<M>() }
}

impl<M:Copy + One, V:Copy + Zero> One for Transform<M, V>
{
  fn one() -> Transform<M, V>
  { Transform { submat: One::one(), subtrans: Zero::zero() } }
}

impl<M:Copy + Zero, V:Copy + Zero> Zero for Transform<M, V>
{
  fn zero() -> Transform<M, V>
  { Transform { submat: Zero::zero(), subtrans: Zero::zero() } }

  fn is_zero(&self) -> bool
  { self.submat.is_zero() && self.subtrans.is_zero() }
}

impl<M:Copy + RMul<V> + Mul<M, M>, V:Copy + Add<V, V>>
Mul<Transform<M, V>, Transform<M, V>> for Transform<M, V>
{
  fn mul(&self, other: &Transform<M, V>) -> Transform<M, V>
  {
    Transform { submat: self.submat * other.submat,
                subtrans: self.subtrans + self.submat.rmul(&other.subtrans) }
  }
}

impl<M: RMul<V>, V> RMul<V> for Transform<M, V>
{
  fn rmul(&self, other: &V) -> V
  { self.submat.rmul(other) }
}

impl<M: LMul<V>, V> LMul<V> for Transform<M, V>
{
  fn lmul(&self, other: &V) -> V
  { self.submat.lmul(other) }
}

impl<M: Copy, V: Copy + Translation<V>> Translation<V> for Transform<M, V>
{
  fn translation(&self) -> V
  { self.subtrans.translation() }

  fn translated(&self, t: &V) -> Transform<M, V>
  { transform(&self.submat, &self.subtrans.translated(t)) }

  fn translate(&mut self, t: &V)
  { self.subtrans.translate(t) }
}

impl<M: Rotation<V> + Copy + RMul<V> + One, V: Copy>
Rotation<V> for Transform<M, V>
{
  fn rotation(&self) -> V
  { self.submat.rotation() }

  fn rotated(&self, rot: &V) -> Transform<M, V>
  {
    // FIXME: this does not seem opitmal
    let delta = One::one::<M>().rotated(rot);

    transform(&self.submat.rotated(rot), &delta.rmul(&self.subtrans))
  }

  fn rotate(&mut self, rot: &V)
  {
    // FIXME: this does not seem opitmal
    let delta = One::one::<M>().rotated(rot);
    self.submat.rotate(rot);
    self.subtrans = delta.rmul(&self.subtrans);
  }
}

impl<M:Copy + Transpose + Inv + RMul<V>, V:Copy + Neg<V>>
Inv for Transform<M, V>
{
  fn invert(&mut self)
  {
    self.submat.invert();
    self.subtrans = self.submat.rmul(&-self.subtrans);
  }

  fn inverse(&self) -> Transform<M, V>
  {
    let mut res = *self;

    res.invert();

    res
  }
}

impl<T, M:FuzzyEq<T>, V:FuzzyEq<T>> FuzzyEq<T> for Transform<M, V>
{
  fn fuzzy_eq(&self, other: &Transform<M, V>) -> bool
  {
    self.submat.fuzzy_eq(&other.submat) &&
    self.subtrans.fuzzy_eq(&other.subtrans)
  }

  fn fuzzy_eq_eps(&self, other: &Transform<M, V>, epsilon: &T) -> bool
  {
    self.submat.fuzzy_eq_eps(&other.submat, epsilon) &&
    self.subtrans.fuzzy_eq_eps(&other.subtrans, epsilon)
  }
}

impl<M: Rand + Copy, V: Rand + Copy> Rand for Transform<M, V>
{
  fn rand<R: Rng>(rng: &R) -> Transform<M, V>
  { transform(&rng.gen(), &rng.gen()) }
}

impl<M:ToStr, V:ToStr> ToStr for Transform<M, V>
{
  fn to_str(&self) -> ~str
  {
    ~"Transform {" + " submat: "    + self.submat.to_str()    +
                     " subtrans: "  + self.subtrans.to_str()  + " }"
  }
}
<|endoftext|>


<commit_before>use std::fmt::Debug;
use std::ops::{Add, AddAssign, Range, Sub};

#[derive(Derivative)]
#[derivative(Debug)]
pub struct RangeAllocator<T> {
    /// The range this allocator covers.
    initial_range: Range<T>,
    /// A Vec of ranges in this heap which are unused.
    /// Must be ordered with ascending range start to permit short circuiting allocation.
    /// No two ranges in this vec may overlap.
    free_ranges: Vec<Range<T>>,
}

impl<T> RangeAllocator<T>
where
    T: Clone + Copy + Add<Output = T> + AddAssign + Sub<Output = T> + Eq + PartialOrd + Debug,
{
    pub fn new(range: Range<T>) -> Self {
        RangeAllocator {
            initial_range: range.clone(),
            free_ranges: vec![range.clone()],
        }
    }

    pub fn allocate_range(&mut self, length: T) -> Option<Range<T>> {
        let mut best_fit: Option<(usize, Range<T>)> = None;
        for (index, range) in self.free_ranges.iter().cloned().enumerate() {
            let range_length = range.end - range.start;
            if range_length < length {
                continue;
            } else if range_length == length {
                // Found a perfect fit, so stop looking.
                best_fit = Some((index, range));
                break;
            }
            best_fit = Some(match best_fit {
                Some((best_index, best_range)) => {
                    // Find best fit for this allocation to reduce memory fragmentation.
                    if range_length < best_range.end - best_range.start {
                        (index, range)
                    } else {
                        (best_index, best_range.clone())
                    }
                }
                None => {
                    (index, range)
                }
            });
        }
        best_fit.map(|(index, range)| {
            if range.end - range.start == length {
                self.free_ranges.remove(index);
            } else {
                self.free_ranges[index].start += length;
            }
            range.start..(range.start + length)
        })
    }

    pub fn free_range(&mut self, range: Range<T>) {
        assert!(self.initial_range.start <= range.start && range.end <= self.initial_range.end);
        assert!(range.start < range.end);

        // Get insertion position.
        let i = self.free_ranges.iter()
            .position(|r| r.start > range.start)
            .unwrap_or(self.free_ranges.len());

        // Try merging with neighboring ranges in the free list.
        // Before: |left|-(range)-|right|
        if i > 0 && range.start == self.free_ranges[i - 1].end {
            // Merge with |left|.
            self.free_ranges[i - 1].end = range.end;
            // Check for possibly merge with |right| also.
            if i < self.free_ranges.len()
                && self.free_ranges[i - 1].end == self.free_ranges[i].start
            {
                let right = self.free_ranges.remove(i);
                self.free_ranges[i - 1].end = right.end;
            }
            return;
        } else if i < self.free_ranges.len() && range.end == self.free_ranges[i].start {
            // Merge with |right|.
            self.free_ranges[i].start = range.start;
            // Check for possibly merge with |left| also.
            if i > 0 && self.free_ranges[i].start == self.free_ranges[i - 1].end {
                let left = self.free_ranges.remove(i - 1);
                self.free_ranges[i].start = left.start;
            }
            return;
        }

        // Debug checks
        if i > 0 {
            assert!(self.free_ranges[i - 1].end < range.start);
        }
        if i < self.free_ranges.len() {
            assert!(range.end < self.free_ranges[i].start);
        }

        self.free_ranges.insert(i, range);
    }

    pub fn reset(&mut self) {
        self.free_ranges.clear();
        self.free_ranges.push(self.initial_range.clone());
    }
}

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

    #[test]
    fn test_basic_allocation() {
        let mut alloc = RangeAllocator::new(0..10);
        // Test if an allocation works
        assert_eq!(alloc.allocate_range(4), Some(0..4));
        // Free the prior allocation
        alloc.free_range(0..4);
        // Make sure the free actually worked
        assert_eq!(alloc.free_ranges, vec![0..10]);
    }

    #[test]
    fn test_out_of_space() {
        let mut alloc = RangeAllocator::new(0..10);
        // Test if the allocator runs out of space correctly
        assert_eq!(alloc.allocate_range(10), Some(0..10));
        assert!(alloc.allocate_range(4).is_none());
        alloc.free_range(0..10);
    }

    #[test]
    fn test_dont_use_block_that_is_too_small() {
        let mut alloc = RangeAllocator::new(0..10);
        // Allocate three blocks then free the middle one and check for correct state
        assert_eq!(alloc.allocate_range(3), Some(0..3));
        assert_eq!(alloc.allocate_range(3), Some(3..6));
        assert_eq!(alloc.allocate_range(3), Some(6..9));
        alloc.free_range(3..6);
        assert_eq!(alloc.free_ranges, vec![3..6, 9..10]);
        // Now request space that the middle block can fill, but the end one can't.
        assert_eq!(alloc.allocate_range(3), Some(3..6));
    }

    #[test]
    fn test_free_blocks_in_middle() {
        let mut alloc = RangeAllocator::new(0..100);
        // Allocate many blocks then free every other block.
        assert_eq!(alloc.allocate_range(10), Some(0..10));
        assert_eq!(alloc.allocate_range(10), Some(10..20));
        assert_eq!(alloc.allocate_range(10), Some(20..30));
        assert_eq!(alloc.allocate_range(10), Some(30..40));
        assert_eq!(alloc.allocate_range(10), Some(40..50));
        assert_eq!(alloc.allocate_range(10), Some(50..60));
        assert_eq!(alloc.allocate_range(10), Some(60..70));
        assert_eq!(alloc.allocate_range(10), Some(70..80));
        assert_eq!(alloc.allocate_range(10), Some(80..90));
        assert_eq!(alloc.allocate_range(10), Some(90..100));
        assert_eq!(alloc.free_ranges, vec![]);
        alloc.free_range(10..20);
        alloc.free_range(30..40);
        alloc.free_range(50..60);
        alloc.free_range(70..80);
        alloc.free_range(90..100);
        // Check that the right blocks were freed.
        assert_eq!(alloc.free_ranges, vec![10..20, 30..40, 50..60, 70..80, 90..100]);
        // Fragment the memory on purpose a bit.
        assert_eq!(alloc.allocate_range(6), Some(10..16));
        assert_eq!(alloc.allocate_range(6), Some(30..36));
        assert_eq!(alloc.allocate_range(6), Some(50..56));
        assert_eq!(alloc.allocate_range(6), Some(70..76));
        assert_eq!(alloc.allocate_range(6), Some(90..96));
        // Check for fragmentation.
        assert_eq!(alloc.free_ranges, vec![16..20, 36..40, 56..60, 76..80, 96..100]);
        // Fill up the fragmentation
        assert_eq!(alloc.allocate_range(4), Some(16..20));
        assert_eq!(alloc.allocate_range(4), Some(36..40));
        assert_eq!(alloc.allocate_range(4), Some(56..60));
        assert_eq!(alloc.allocate_range(4), Some(76..80));
        assert_eq!(alloc.allocate_range(4), Some(96..100));
        // Check that nothing is free.
        assert_eq!(alloc.free_ranges, vec![]);
    }

    #[test]
    fn test_ignore_block_if_another_fits_better() {
        let mut alloc = RangeAllocator::new(0..10);
        // Allocate blocks such that the only free spaces available are 3..6 and 9..10
        // in order to prepare for the next test.
        assert_eq!(alloc.allocate_range(3), Some(0..3));
        assert_eq!(alloc.allocate_range(3), Some(3..6));
        assert_eq!(alloc.allocate_range(3), Some(6..9));
        alloc.free_range(3..6);
        assert_eq!(alloc.free_ranges, vec![3..6, 9..10]);
        // Now request space that can be filled by 3..6 but should be filled by 9..10
        // because 9..10 is a perfect fit.
        assert_eq!(alloc.allocate_range(1), Some(9..10));
    }

    #[test]
    fn test_merge_neighbors() {
        let mut alloc = RangeAllocator::new(0..9);
        assert_eq!(alloc.allocate_range(3), Some(0..3));
        assert_eq!(alloc.allocate_range(3), Some(3..6));
        assert_eq!(alloc.allocate_range(3), Some(6..9));
        alloc.free_range(0..3);
        alloc.free_range(6..9);
        alloc.free_range(3..6);
        assert_eq!(alloc.free_ranges, vec![0..9]);
    }
}
<commit_msg>auxil: Simplify range free implementation<commit_after>use std::fmt::Debug;
use std::ops::{Add, AddAssign, Range, Sub};

#[derive(Derivative)]
#[derivative(Debug)]
pub struct RangeAllocator<T> {
    /// The range this allocator covers.
    initial_range: Range<T>,
    /// A Vec of ranges in this heap which are unused.
    /// Must be ordered with ascending range start to permit short circuiting allocation.
    /// No two ranges in this vec may overlap.
    free_ranges: Vec<Range<T>>,
}

impl<T> RangeAllocator<T>
where
    T: Clone + Copy + Add<Output = T> + AddAssign + Sub<Output = T> + Eq + PartialOrd + Debug,
{
    pub fn new(range: Range<T>) -> Self {
        RangeAllocator {
            initial_range: range.clone(),
            free_ranges: vec![range.clone()],
        }
    }

    pub fn allocate_range(&mut self, length: T) -> Option<Range<T>> {
        let mut best_fit: Option<(usize, Range<T>)> = None;
        for (index, range) in self.free_ranges.iter().cloned().enumerate() {
            let range_length = range.end - range.start;
            if range_length < length {
                continue;
            } else if range_length == length {
                // Found a perfect fit, so stop looking.
                best_fit = Some((index, range));
                break;
            }
            best_fit = Some(match best_fit {
                Some((best_index, best_range)) => {
                    // Find best fit for this allocation to reduce memory fragmentation.
                    if range_length < best_range.end - best_range.start {
                        (index, range)
                    } else {
                        (best_index, best_range.clone())
                    }
                }
                None => {
                    (index, range)
                }
            });
        }
        best_fit.map(|(index, range)| {
            if range.end - range.start == length {
                self.free_ranges.remove(index);
            } else {
                self.free_ranges[index].start += length;
            }
            range.start..(range.start + length)
        })
    }

    pub fn free_range(&mut self, range: Range<T>) {
        assert!(self.initial_range.start <= range.start && range.end <= self.initial_range.end);
        assert!(range.start < range.end);

        // Get insertion position.
        let i = self.free_ranges.iter()
            .position(|r| r.start > range.start)
            .unwrap_or(self.free_ranges.len());

        // Try merging with neighboring ranges in the free list.
        // Before: |left|-(range)-|right|
        if i > 0 && range.start == self.free_ranges[i - 1].end {
            // Merge with |left|.
            self.free_ranges[i - 1].end =
                if i < self.free_ranges.len() && range.end == self.free_ranges[i].start {
                    // Check for possible merge with |left| and |right|.
                    let right = self.free_ranges.remove(i);
                    right.end
                } else {
                    range.end
                };

            return;
        } else if i < self.free_ranges.len() && range.end == self.free_ranges[i].start {
            // Merge with |right|.
            self.free_ranges[i].start =
                if i > 0 && range.start == self.free_ranges[i - 1].end {
                    // Check for possible merge with |left| and |right|.
                    let left = self.free_ranges.remove(i - 1);
                    left.start
                } else {
                    range.start
                };

            return;
        }

        // Debug checks
        assert!(
            (i == 0 || self.free_ranges[i - 1].end < range.start) &&
            (i >= self.free_ranges.len() || range.end < self.free_ranges[i].start)
        );

        self.free_ranges.insert(i, range);
    }

    pub fn reset(&mut self) {
        self.free_ranges.clear();
        self.free_ranges.push(self.initial_range.clone());
    }
}

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

    #[test]
    fn test_basic_allocation() {
        let mut alloc = RangeAllocator::new(0..10);
        // Test if an allocation works
        assert_eq!(alloc.allocate_range(4), Some(0..4));
        // Free the prior allocation
        alloc.free_range(0..4);
        // Make sure the free actually worked
        assert_eq!(alloc.free_ranges, vec![0..10]);
    }

    #[test]
    fn test_out_of_space() {
        let mut alloc = RangeAllocator::new(0..10);
        // Test if the allocator runs out of space correctly
        assert_eq!(alloc.allocate_range(10), Some(0..10));
        assert!(alloc.allocate_range(4).is_none());
        alloc.free_range(0..10);
    }

    #[test]
    fn test_dont_use_block_that_is_too_small() {
        let mut alloc = RangeAllocator::new(0..10);
        // Allocate three blocks then free the middle one and check for correct state
        assert_eq!(alloc.allocate_range(3), Some(0..3));
        assert_eq!(alloc.allocate_range(3), Some(3..6));
        assert_eq!(alloc.allocate_range(3), Some(6..9));
        alloc.free_range(3..6);
        assert_eq!(alloc.free_ranges, vec![3..6, 9..10]);
        // Now request space that the middle block can fill, but the end one can't.
        assert_eq!(alloc.allocate_range(3), Some(3..6));
    }

    #[test]
    fn test_free_blocks_in_middle() {
        let mut alloc = RangeAllocator::new(0..100);
        // Allocate many blocks then free every other block.
        assert_eq!(alloc.allocate_range(10), Some(0..10));
        assert_eq!(alloc.allocate_range(10), Some(10..20));
        assert_eq!(alloc.allocate_range(10), Some(20..30));
        assert_eq!(alloc.allocate_range(10), Some(30..40));
        assert_eq!(alloc.allocate_range(10), Some(40..50));
        assert_eq!(alloc.allocate_range(10), Some(50..60));
        assert_eq!(alloc.allocate_range(10), Some(60..70));
        assert_eq!(alloc.allocate_range(10), Some(70..80));
        assert_eq!(alloc.allocate_range(10), Some(80..90));
        assert_eq!(alloc.allocate_range(10), Some(90..100));
        assert_eq!(alloc.free_ranges, vec![]);
        alloc.free_range(10..20);
        alloc.free_range(30..40);
        alloc.free_range(50..60);
        alloc.free_range(70..80);
        alloc.free_range(90..100);
        // Check that the right blocks were freed.
        assert_eq!(alloc.free_ranges, vec![10..20, 30..40, 50..60, 70..80, 90..100]);
        // Fragment the memory on purpose a bit.
        assert_eq!(alloc.allocate_range(6), Some(10..16));
        assert_eq!(alloc.allocate_range(6), Some(30..36));
        assert_eq!(alloc.allocate_range(6), Some(50..56));
        assert_eq!(alloc.allocate_range(6), Some(70..76));
        assert_eq!(alloc.allocate_range(6), Some(90..96));
        // Check for fragmentation.
        assert_eq!(alloc.free_ranges, vec![16..20, 36..40, 56..60, 76..80, 96..100]);
        // Fill up the fragmentation
        assert_eq!(alloc.allocate_range(4), Some(16..20));
        assert_eq!(alloc.allocate_range(4), Some(36..40));
        assert_eq!(alloc.allocate_range(4), Some(56..60));
        assert_eq!(alloc.allocate_range(4), Some(76..80));
        assert_eq!(alloc.allocate_range(4), Some(96..100));
        // Check that nothing is free.
        assert_eq!(alloc.free_ranges, vec![]);
    }

    #[test]
    fn test_ignore_block_if_another_fits_better() {
        let mut alloc = RangeAllocator::new(0..10);
        // Allocate blocks such that the only free spaces available are 3..6 and 9..10
        // in order to prepare for the next test.
        assert_eq!(alloc.allocate_range(3), Some(0..3));
        assert_eq!(alloc.allocate_range(3), Some(3..6));
        assert_eq!(alloc.allocate_range(3), Some(6..9));
        alloc.free_range(3..6);
        assert_eq!(alloc.free_ranges, vec![3..6, 9..10]);
        // Now request space that can be filled by 3..6 but should be filled by 9..10
        // because 9..10 is a perfect fit.
        assert_eq!(alloc.allocate_range(1), Some(9..10));
    }

    #[test]
    fn test_merge_neighbors() {
        let mut alloc = RangeAllocator::new(0..9);
        assert_eq!(alloc.allocate_range(3), Some(0..3));
        assert_eq!(alloc.allocate_range(3), Some(3..6));
        assert_eq!(alloc.allocate_range(3), Some(6..9));
        alloc.free_range(0..3);
        alloc.free_range(6..9);
        alloc.free_range(3..6);
        assert_eq!(alloc.free_ranges, vec![0..9]);
    }
}
<|endoftext|>


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

//! Helper functions for garbage collected doubly-linked trees.

// Macros to make add_child etc. less painful to write.
// Code outside this module should instead implement TreeNode
// and use its default methods.
macro_rules! get(
    ($node:expr, $fun:ident) => (
        {
            let val: Option<Self> = TreeNodeRef::<Node>::$fun($node);
            val
        }
    )
)

macro_rules! set(
    ($node:expr, $fun:ident, $val:expr) => (
        {
            let val: Option<Self> = $val;
            TreeNodeRef::<Node>::$fun($node, val)
        }
    )
)

pub struct ChildIterator<Ref> {
    priv current: Option<Ref>,
}

impl<Node, Ref: TreeNodeRef<Node>> Iterator<Ref> for ChildIterator<Ref> {
    fn next(&mut self) -> Option<Ref> {
        if self.current.is_none() {
            return None;
        }

        // FIXME: Do we need two clones here?
        let x = self.current.get_ref().clone();
        self.current = x.with_base(|n| TreeNodeRef::<Node>::next_sibling(n));
        Some(x.clone())
    }
}

// FIXME: Do this without precomputing a vector of refs.
// Easy for preorder; harder for postorder.
pub struct TreeIterator<Ref> {
    priv nodes: ~[Ref],
    priv index: uint,
}

impl<Ref> TreeIterator<Ref> {
    fn new(nodes: ~[Ref]) -> TreeIterator<Ref> {
        TreeIterator {
            nodes: nodes,
            index: 0,
        }
    }
}

impl<Ref: Clone> Iterator<Ref> for TreeIterator<Ref> {
    fn next(&mut self) -> Option<Ref> {
        if self.index >= self.nodes.len() {
            None
        } else {
            let v = self.nodes[self.index].clone();
            self.index += 1;
            Some(v)
        }
    }
}

/// A type implementing TreeNodeRef<Node> is a clonable reference to an underlying
/// node type Node.
///
/// We have to define both ref and node operations in the same trait, which makes
/// the latter more annoying to call (as static methods).  But we provide non-static
/// proxies in trait TreeNode below.
pub trait TreeNodeRef<Node>: Clone {

    // Fundamental operations on refs.

    /// Borrows this node as immutable.
    fn with_base<R>(&self, callback: &fn(&Node) -> R) -> R;

    /// Borrows this node as mutable.
    fn with_mut_base<R>(&self, callback: &fn(&mut Node) -> R) -> R;

    // Fundamental operations on nodes.

    /// Returns the parent of this node.
    fn parent_node(node: &Node) -> Option<Self>;

    /// Returns the first child of this node.
    fn first_child(node: &Node) -> Option<Self>;

    /// Returns the last child of this node.
    fn last_child(node: &Node) -> Option<Self>;

    /// Returns the previous sibling of this node.
    fn prev_sibling(node: &Node) -> Option<Self>;

    /// Returns the next sibling of this node.
    fn next_sibling(node: &Node) -> Option<Self>;

    /// Sets the parent of this node.
    fn set_parent_node(node: &mut Node, new_parent: Option<Self>);

    /// Sets the first child of this node.
    fn set_first_child(node: &mut Node, new_first_child: Option<Self>);

    /// Sets the last child of this node.
    fn set_last_child(node: &mut Node, new_last_child: Option<Self>);

    /// Sets the previous sibling of this node.
    fn set_prev_sibling(node: &mut Node, new_prev_sibling: Option<Self>);

    /// Sets the next sibling of this node.
    fn set_next_sibling(node: &mut Node, new_next_sibling: Option<Self>);

    // The tree utilities, operating on refs mostly.

    /// Returns true if this node is disconnected from the tree or has no children.
    fn is_leaf(&self) -> bool {
        do self.with_base |this_node| {
            (get!(this_node, first_child)).is_none()
        }
    }

    /// Adds a new child to the end of this node's list of children.
    ///
    /// Fails unless `new_child` is disconnected from the tree.
    fn add_child(&self, new_child: Self) {
        do self.with_mut_base |this_node| {
            do new_child.with_mut_base |new_child_node| {
                assert!((get!(new_child_node, parent_node)).is_none());
                assert!((get!(new_child_node, prev_sibling)).is_none());
                assert!((get!(new_child_node, next_sibling)).is_none());

                match get!(this_node, last_child) {
                    None => set!(this_node, set_first_child, Some(new_child.clone())),
                    Some(last_child) => {
                        do last_child.with_mut_base |last_child_node| {
                            assert!((get!(last_child_node, next_sibling)).is_none());
                            set!(last_child_node, set_next_sibling, Some(new_child.clone()));
                            set!(new_child_node, set_prev_sibling, Some(last_child.clone()));
                        }
                    }
                }

                set!(this_node, set_last_child, Some(new_child.clone()));
                set!(new_child_node, set_parent_node, Some((*self).clone()));
            }
        }
    }

    /// Removes the given child from this node's list of children.
    ///
    /// Fails unless `child` is a child of this node. (FIXME: This is not yet checked.)
    fn remove_child(&self, child: Self) {
        do self.with_mut_base |this_node| {
            do child.with_mut_base |child_node| {
                assert!((get!(child_node, parent_node)).is_some());

                match get!(child_node, prev_sibling) {
                    None => set!(this_node, set_first_child, get!(child_node, next_sibling)),
                    Some(prev_sibling) => {
                        do prev_sibling.with_mut_base |prev_sibling_node| {
                            set!(prev_sibling_node, set_next_sibling, get!(child_node, next_sibling));
                        }
                    }
                }

                match get!(child_node, next_sibling) {
                    None => set!(this_node, set_last_child, get!(child_node, prev_sibling)),
                    Some(next_sibling) => {
                        do next_sibling.with_mut_base |next_sibling_node| {
                            set!(next_sibling_node, set_prev_sibling, get!(child_node, prev_sibling));
                        }
                    }
                }

                set!(child_node, set_prev_sibling, None);
                set!(child_node, set_next_sibling, None);
                set!(child_node, set_parent_node,  None);
            }
        }
    }

    /// Iterates over all children of this node.
    fn children(&self) -> ChildIterator<Self> {
        ChildIterator {
            current: self.with_base(|n| get!(n, first_child)),
        }
    }

    /// Iterates over this node and all its descendants, in preorder.
    fn traverse_preorder(&self) -> TreeIterator<Self> {
        self.traverse_preorder_prune(|_| false)
    }

    /// Iterates over this node and all its descendants, in postorder.
    fn traverse_postorder(&self) -> TreeIterator<Self> {
        self.traverse_postorder_prune(|_| false)
    }

    /// Like traverse_preorder but calls 'prune' first on each node.  If it returns true then we
    /// skip the whole subtree but continue iterating.
    fn traverse_preorder_prune(&self, prune: &fn(&Self) -> bool) -> TreeIterator<Self> {
        let mut nodes = ~[];
        gather(self, &mut nodes, false, prune);
        TreeIterator::new(nodes)
    }

    /// Like traverse_postorder but calls 'prune' first on each node.  If it returns true then we
    /// skip the whole subtree but continue iterating.
    ///
    /// NB: 'prune' is called *before* traversing children, even though this is a
    /// postorder traversal.
    fn traverse_postorder_prune(&self, prune: &fn(&Self) -> bool) -> TreeIterator<Self> {
        let mut nodes = ~[];
        gather(self, &mut nodes, true, prune);
        TreeIterator::new(nodes)
    }
}

fn gather<Node, Ref: TreeNodeRef<Node>>(cur: &Ref, refs: &mut ~[Ref],
                                        postorder: bool, prune: &fn(&Ref) -> bool) {
    // prune shouldn't mutate, so don't clone
    if prune(cur) {
        return;
    }

    if !postorder {
        refs.push(cur.clone());
    }
    for kid in cur.children() {
        // FIXME: Work around rust#2202. We should be able to pass the callback directly.
        gather(&kid, refs, postorder, |a| prune(a))
    }
    if postorder {
        refs.push(cur.clone());
    }
}

/// Access the fields of a node without a static TreeNodeRef method call.
/// If you make an impl TreeNodeRef<Node> for Ref then you should also make
/// impl TreeNode<Ref> for Node with an empty body.
pub trait TreeNode<Ref: TreeNodeRef<Self>> {
    /// Returns the parent of this node.
    fn parent_node(&self) -> Option<Ref> {
        TreeNodeRef::<Self>::parent_node(self)
    }

    /// Returns the first child of this node.
    fn first_child(&self) -> Option<Ref> {
        TreeNodeRef::<Self>::first_child(self)
    }

    /// Returns the last child of this node.
    fn last_child(&self) -> Option<Ref> {
        TreeNodeRef::<Self>::last_child(self)
    }

    /// Returns the previous sibling of this node.
    fn prev_sibling(&self) -> Option<Ref> {
        TreeNodeRef::<Self>::prev_sibling(self)
    }

    /// Returns the next sibling of this node.
    fn next_sibling(&self) -> Option<Ref> {
        TreeNodeRef::<Self>::next_sibling(self)
    }

    /// Sets the parent of this node.
    fn set_parent_node(&mut self, new_parent: Option<Ref>) {
        TreeNodeRef::<Self>::set_parent_node(self, new_parent)
    }

    /// Sets the first child of this node.
    fn set_first_child(&mut self, new_first_child: Option<Ref>) {
        TreeNodeRef::<Self>::set_first_child(self, new_first_child)
    }

    /// Sets the last child of this node.
    fn set_last_child(&mut self, new_last_child: Option<Ref>) {
        TreeNodeRef::<Self>::set_last_child(self, new_last_child)
    }

    /// Sets the previous sibling of this node.
    fn set_prev_sibling(&mut self, new_prev_sibling: Option<Ref>) {
        TreeNodeRef::<Self>::set_prev_sibling(self, new_prev_sibling)
    }

    /// Sets the next sibling of this node.
    fn set_next_sibling(&mut self, new_next_sibling: Option<Ref>) {
        TreeNodeRef::<Self>::set_next_sibling(self, new_next_sibling)
    }
}
<commit_msg>Add AncestorIterator by jgraham<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Helper functions for garbage collected doubly-linked trees.

// Macros to make add_child etc. less painful to write.
// Code outside this module should instead implement TreeNode
// and use its default methods.
macro_rules! get(
    ($node:expr, $fun:ident) => (
        {
            let val: Option<Self> = TreeNodeRef::<Node>::$fun($node);
            val
        }
    )
)

macro_rules! set(
    ($node:expr, $fun:ident, $val:expr) => (
        {
            let val: Option<Self> = $val;
            TreeNodeRef::<Node>::$fun($node, val)
        }
    )
)

pub struct ChildIterator<Ref> {
    priv current: Option<Ref>,
}

impl<Node, Ref: TreeNodeRef<Node>> Iterator<Ref> for ChildIterator<Ref> {
    fn next(&mut self) -> Option<Ref> {
        if self.current.is_none() {
            return None;
        }

        // FIXME: Do we need two clones here?
        let x = self.current.get_ref().clone();
        self.current = x.with_base(|n| TreeNodeRef::<Node>::next_sibling(n));
        Some(x.clone())
    }
}

pub struct AncestorIterator<Ref> {
    priv current: Option<Ref>,
}

impl<Node, Ref: TreeNodeRef<Node>> Iterator<Ref> for AncestorIterator<Ref> {
    fn next(&mut self) -> Option<Ref> {
        if self.current.is_none() {
            return None;
        }

        // FIXME: Do we need two clones here?
        let x = self.current.get_ref().clone();
        self.current = x.with_base(|n| TreeNodeRef::<Node>::parent_node(n));
        Some(x.clone())
    }
}

// FIXME: Do this without precomputing a vector of refs.
// Easy for preorder; harder for postorder.
pub struct TreeIterator<Ref> {
    priv nodes: ~[Ref],
    priv index: uint,
}

impl<Ref> TreeIterator<Ref> {
    fn new(nodes: ~[Ref]) -> TreeIterator<Ref> {
        TreeIterator {
            nodes: nodes,
            index: 0,
        }
    }
}

impl<Ref: Clone> Iterator<Ref> for TreeIterator<Ref> {
    fn next(&mut self) -> Option<Ref> {
        if self.index >= self.nodes.len() {
            None
        } else {
            let v = self.nodes[self.index].clone();
            self.index += 1;
            Some(v)
        }
    }
}

/// A type implementing TreeNodeRef<Node> is a clonable reference to an underlying
/// node type Node.
///
/// We have to define both ref and node operations in the same trait, which makes
/// the latter more annoying to call (as static methods).  But we provide non-static
/// proxies in trait TreeNode below.
pub trait TreeNodeRef<Node>: Clone {

    // Fundamental operations on refs.

    /// Borrows this node as immutable.
    fn with_base<R>(&self, callback: &fn(&Node) -> R) -> R;

    /// Borrows this node as mutable.
    fn with_mut_base<R>(&self, callback: &fn(&mut Node) -> R) -> R;

    // Fundamental operations on nodes.

    /// Returns the parent of this node.
    fn parent_node(node: &Node) -> Option<Self>;

    /// Returns the first child of this node.
    fn first_child(node: &Node) -> Option<Self>;

    /// Returns the last child of this node.
    fn last_child(node: &Node) -> Option<Self>;

    /// Returns the previous sibling of this node.
    fn prev_sibling(node: &Node) -> Option<Self>;

    /// Returns the next sibling of this node.
    fn next_sibling(node: &Node) -> Option<Self>;

    /// Sets the parent of this node.
    fn set_parent_node(node: &mut Node, new_parent: Option<Self>);

    /// Sets the first child of this node.
    fn set_first_child(node: &mut Node, new_first_child: Option<Self>);

    /// Sets the last child of this node.
    fn set_last_child(node: &mut Node, new_last_child: Option<Self>);

    /// Sets the previous sibling of this node.
    fn set_prev_sibling(node: &mut Node, new_prev_sibling: Option<Self>);

    /// Sets the next sibling of this node.
    fn set_next_sibling(node: &mut Node, new_next_sibling: Option<Self>);

    // The tree utilities, operating on refs mostly.

    /// Returns true if this node is disconnected from the tree or has no children.
    fn is_leaf(&self) -> bool {
        do self.with_base |this_node| {
            (get!(this_node, first_child)).is_none()
        }
    }

    /// Adds a new child to the end of this node's list of children.
    ///
    /// Fails unless `new_child` is disconnected from the tree.
    fn add_child(&self, new_child: Self) {
        do self.with_mut_base |this_node| {
            do new_child.with_mut_base |new_child_node| {
                assert!((get!(new_child_node, parent_node)).is_none());
                assert!((get!(new_child_node, prev_sibling)).is_none());
                assert!((get!(new_child_node, next_sibling)).is_none());

                match get!(this_node, last_child) {
                    None => set!(this_node, set_first_child, Some(new_child.clone())),
                    Some(last_child) => {
                        do last_child.with_mut_base |last_child_node| {
                            assert!((get!(last_child_node, next_sibling)).is_none());
                            set!(last_child_node, set_next_sibling, Some(new_child.clone()));
                            set!(new_child_node, set_prev_sibling, Some(last_child.clone()));
                        }
                    }
                }

                set!(this_node, set_last_child, Some(new_child.clone()));
                set!(new_child_node, set_parent_node, Some((*self).clone()));
            }
        }
    }

    /// Removes the given child from this node's list of children.
    ///
    /// Fails unless `child` is a child of this node. (FIXME: This is not yet checked.)
    fn remove_child(&self, child: Self) {
        do self.with_mut_base |this_node| {
            do child.with_mut_base |child_node| {
                assert!((get!(child_node, parent_node)).is_some());

                match get!(child_node, prev_sibling) {
                    None => set!(this_node, set_first_child, get!(child_node, next_sibling)),
                    Some(prev_sibling) => {
                        do prev_sibling.with_mut_base |prev_sibling_node| {
                            set!(prev_sibling_node, set_next_sibling, get!(child_node, next_sibling));
                        }
                    }
                }

                match get!(child_node, next_sibling) {
                    None => set!(this_node, set_last_child, get!(child_node, prev_sibling)),
                    Some(next_sibling) => {
                        do next_sibling.with_mut_base |next_sibling_node| {
                            set!(next_sibling_node, set_prev_sibling, get!(child_node, prev_sibling));
                        }
                    }
                }

                set!(child_node, set_prev_sibling, None);
                set!(child_node, set_next_sibling, None);
                set!(child_node, set_parent_node,  None);
            }
        }
    }

    /// Iterates over all children of this node.
    fn children(&self) -> ChildIterator<Self> {
        ChildIterator {
            current: self.with_base(|n| get!(n, first_child)),
        }
    }

    /// Iterates over all ancestors of this node.
    fn ancestors(&self) -> AncestorIterator<Self> {
        AncestorIterator {
            current: self.with_base(|n| get!(n, parent_node)),
        }
    }

    /// Iterates over this node and all its descendants, in preorder.
    fn traverse_preorder(&self) -> TreeIterator<Self> {
        self.traverse_preorder_prune(|_| false)
    }

    /// Iterates over this node and all its descendants, in postorder.
    fn traverse_postorder(&self) -> TreeIterator<Self> {
        self.traverse_postorder_prune(|_| false)
    }

    /// Like traverse_preorder but calls 'prune' first on each node.  If it returns true then we
    /// skip the whole subtree but continue iterating.
    fn traverse_preorder_prune(&self, prune: &fn(&Self) -> bool) -> TreeIterator<Self> {
        let mut nodes = ~[];
        gather(self, &mut nodes, false, prune);
        TreeIterator::new(nodes)
    }

    /// Like traverse_postorder but calls 'prune' first on each node.  If it returns true then we
    /// skip the whole subtree but continue iterating.
    ///
    /// NB: 'prune' is called *before* traversing children, even though this is a
    /// postorder traversal.
    fn traverse_postorder_prune(&self, prune: &fn(&Self) -> bool) -> TreeIterator<Self> {
        let mut nodes = ~[];
        gather(self, &mut nodes, true, prune);
        TreeIterator::new(nodes)
    }
}

fn gather<Node, Ref: TreeNodeRef<Node>>(cur: &Ref, refs: &mut ~[Ref],
                                        postorder: bool, prune: &fn(&Ref) -> bool) {
    // prune shouldn't mutate, so don't clone
    if prune(cur) {
        return;
    }

    if !postorder {
        refs.push(cur.clone());
    }
    for kid in cur.children() {
        // FIXME: Work around rust#2202. We should be able to pass the callback directly.
        gather(&kid, refs, postorder, |a| prune(a))
    }
    if postorder {
        refs.push(cur.clone());
    }
}

/// Access the fields of a node without a static TreeNodeRef method call.
/// If you make an impl TreeNodeRef<Node> for Ref then you should also make
/// impl TreeNode<Ref> for Node with an empty body.
pub trait TreeNode<Ref: TreeNodeRef<Self>> {
    /// Returns the parent of this node.
    fn parent_node(&self) -> Option<Ref> {
        TreeNodeRef::<Self>::parent_node(self)
    }

    /// Returns the first child of this node.
    fn first_child(&self) -> Option<Ref> {
        TreeNodeRef::<Self>::first_child(self)
    }

    /// Returns the last child of this node.
    fn last_child(&self) -> Option<Ref> {
        TreeNodeRef::<Self>::last_child(self)
    }

    /// Returns the previous sibling of this node.
    fn prev_sibling(&self) -> Option<Ref> {
        TreeNodeRef::<Self>::prev_sibling(self)
    }

    /// Returns the next sibling of this node.
    fn next_sibling(&self) -> Option<Ref> {
        TreeNodeRef::<Self>::next_sibling(self)
    }

    /// Sets the parent of this node.
    fn set_parent_node(&mut self, new_parent: Option<Ref>) {
        TreeNodeRef::<Self>::set_parent_node(self, new_parent)
    }

    /// Sets the first child of this node.
    fn set_first_child(&mut self, new_first_child: Option<Ref>) {
        TreeNodeRef::<Self>::set_first_child(self, new_first_child)
    }

    /// Sets the last child of this node.
    fn set_last_child(&mut self, new_last_child: Option<Ref>) {
        TreeNodeRef::<Self>::set_last_child(self, new_last_child)
    }

    /// Sets the previous sibling of this node.
    fn set_prev_sibling(&mut self, new_prev_sibling: Option<Ref>) {
        TreeNodeRef::<Self>::set_prev_sibling(self, new_prev_sibling)
    }

    /// Sets the next sibling of this node.
    fn set_next_sibling(&mut self, new_next_sibling: Option<Ref>) {
        TreeNodeRef::<Self>::set_next_sibling(self, new_next_sibling)
    }
}
<|endoftext|>


<commit_before>//! Checks interface
// see: https://developer.github.com/v3/checks/suites/
use serde::{Deserialize, Serialize};

use self::super::{AuthenticationConstraint, Future, Github, MediaType};

pub struct CheckRuns {
    github: Github,
    owner: String,
    repo: String,
}

impl<'a> CheckRuns {
    #[doc(hidden)]
    pub(crate) fn new<O, R>(github: Github, owner: O, repo: R) -> Self
    where
        O: Into<String>,
        R: Into<String>,
    {
        CheckRuns {
            github,
            owner: owner.into(),
            repo: repo.into(),
        }
    }

    fn path(&self, more: &str) -> String {
        format!("/repos/{}/{}/check-runs{}", self.owner, self.repo, more)
    }

    pub fn create(&self, check_run_options: &CheckRunOptions) -> Future<CheckRun> {
        match serde_json::to_string(check_run_options) {
            Ok(data) => self.github.post_media::<CheckRun>(
                &self.path(""),
                data.into_bytes(),
                MediaType::Preview("antiope"),
                AuthenticationConstraint::Unconstrained,
            ),
            Err(e) => Box::pin(futures::future::err(e.into())),
        }
    }

    pub fn update(
        &self,
        check_run_id: &str,
        check_run_options: &CheckRunUpdateOptions,
    ) -> Future<CheckRun> {
        match serde_json::to_string(check_run_options) {
            Ok(data) => self.github.post_media::<CheckRun>(
                &self.path(&format!("/{}", check_run_id)),
                data.into_bytes(),
                MediaType::Preview("antiope"),
                AuthenticationConstraint::Unconstrained,
            ),
            Err(e) => Box::pin(futures::future::err(e.into())),
        }
    }

    pub fn list_for_suite(&self, suite_id: &str) -> Future<Vec<CheckRun>> {
        // !!! does this actually work?
        // https://developer.github.com/v3/checks/runs/#list-check-runs-in-a-check-suite
        self.github.get_media::<Vec<CheckRun>>(
            &self.path(&format!("/{}/check-runs", suite_id)),
            MediaType::Preview("antiope"),
        )
    }
}

// representations

#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum CheckRunState {
    Queued,
    InProgress,
    Completed,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum Conclusion {
    Success,
    Failure,
    Neutral,
    Cancelled,
    TimedOut,
    ActionRequired,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum AnnotationLevel {
    Notice,
    Warning,
    Failure,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct Output {
    pub title: String,
    pub summary: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub text: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub annotations: Option<Vec<Annotation>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub images: Option<Vec<Image>>,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct Action {
    pub label: String,
    pub description: String,
    pub identifier: String,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct Annotation {
    pub path: String,
    pub start_line: u32,
    pub end_line: u32,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub start_column: Option<u32>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub end_column: Option<u32>,
    pub annotation_level: AnnotationLevel,
    pub message: String,
    pub title: String,
    pub raw_details: String,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct Image {
    pub alt: String,
    pub image_url: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub caption: Option<String>,
}

#[derive(Debug, Serialize, PartialEq)]
pub struct CheckRunOptions {
    pub name: String,
    pub head_sha: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub details_url: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub external_id: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub status: Option<CheckRunState>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub started_at: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub conclusion: Option<Conclusion>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub completed_at: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub output: Option<Output>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub actions: Option<Vec<Action>>,
}

#[derive(Debug, Serialize, PartialEq)]
pub struct CheckRunUpdateOptions {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub name: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub details_url: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub external_id: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub status: Option<CheckRunState>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub started_at: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub conclusion: Option<Conclusion>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub completed_at: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub output: Option<Output>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub actions: Option<Vec<Action>>,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct CheckRun {
    pub id: i32,
    pub name: String,
    pub head_sha: String,
    pub url: String,
    pub check_suite: CheckSuite,
    pub details_url: Option<String>,
    pub external_id: Option<String>,
    pub status: Option<CheckRunState>,
    pub started_at: Option<String>,
    pub conclusion: Option<Conclusion>,
    pub completed_at: Option<String>,
    /*
    Deleted for now:

    GitHub's API returns:

      "output": {
        "title": null,
        "summary": null,
        "text": null,
        "annotations_count": 0,
        "annotations_url": "https://api.github.com/repos/grahamc/notpkgs/check-runs/30726963/annotations"
      },

    if there is no Output, which confuses serde.

    pub output: Option<Output>,
     */
    pub actions: Option<Vec<Action>>,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct CheckSuite {
    pub id: u32,
}
<commit_msg>checks.rs: add skipped conclusion<commit_after>//! Checks interface
// see: https://developer.github.com/v3/checks/suites/
use serde::{Deserialize, Serialize};

use self::super::{AuthenticationConstraint, Future, Github, MediaType};

pub struct CheckRuns {
    github: Github,
    owner: String,
    repo: String,
}

impl<'a> CheckRuns {
    #[doc(hidden)]
    pub(crate) fn new<O, R>(github: Github, owner: O, repo: R) -> Self
    where
        O: Into<String>,
        R: Into<String>,
    {
        CheckRuns {
            github,
            owner: owner.into(),
            repo: repo.into(),
        }
    }

    fn path(&self, more: &str) -> String {
        format!("/repos/{}/{}/check-runs{}", self.owner, self.repo, more)
    }

    pub fn create(&self, check_run_options: &CheckRunOptions) -> Future<CheckRun> {
        match serde_json::to_string(check_run_options) {
            Ok(data) => self.github.post_media::<CheckRun>(
                &self.path(""),
                data.into_bytes(),
                MediaType::Preview("antiope"),
                AuthenticationConstraint::Unconstrained,
            ),
            Err(e) => Box::pin(futures::future::err(e.into())),
        }
    }

    pub fn update(
        &self,
        check_run_id: &str,
        check_run_options: &CheckRunUpdateOptions,
    ) -> Future<CheckRun> {
        match serde_json::to_string(check_run_options) {
            Ok(data) => self.github.post_media::<CheckRun>(
                &self.path(&format!("/{}", check_run_id)),
                data.into_bytes(),
                MediaType::Preview("antiope"),
                AuthenticationConstraint::Unconstrained,
            ),
            Err(e) => Box::pin(futures::future::err(e.into())),
        }
    }

    pub fn list_for_suite(&self, suite_id: &str) -> Future<Vec<CheckRun>> {
        // !!! does this actually work?
        // https://developer.github.com/v3/checks/runs/#list-check-runs-in-a-check-suite
        self.github.get_media::<Vec<CheckRun>>(
            &self.path(&format!("/{}/check-runs", suite_id)),
            MediaType::Preview("antiope"),
        )
    }
}

// representations

#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum CheckRunState {
    Queued,
    InProgress,
    Completed,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum Conclusion {
    Skipped,
    Success,
    Failure,
    Neutral,
    Cancelled,
    TimedOut,
    ActionRequired,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum AnnotationLevel {
    Notice,
    Warning,
    Failure,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct Output {
    pub title: String,
    pub summary: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub text: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub annotations: Option<Vec<Annotation>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub images: Option<Vec<Image>>,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct Action {
    pub label: String,
    pub description: String,
    pub identifier: String,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct Annotation {
    pub path: String,
    pub start_line: u32,
    pub end_line: u32,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub start_column: Option<u32>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub end_column: Option<u32>,
    pub annotation_level: AnnotationLevel,
    pub message: String,
    pub title: String,
    pub raw_details: String,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct Image {
    pub alt: String,
    pub image_url: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub caption: Option<String>,
}

#[derive(Debug, Serialize, PartialEq)]
pub struct CheckRunOptions {
    pub name: String,
    pub head_sha: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub details_url: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub external_id: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub status: Option<CheckRunState>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub started_at: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub conclusion: Option<Conclusion>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub completed_at: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub output: Option<Output>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub actions: Option<Vec<Action>>,
}

#[derive(Debug, Serialize, PartialEq)]
pub struct CheckRunUpdateOptions {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub name: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub details_url: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub external_id: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub status: Option<CheckRunState>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub started_at: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub conclusion: Option<Conclusion>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub completed_at: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub output: Option<Output>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub actions: Option<Vec<Action>>,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct CheckRun {
    pub id: i32,
    pub name: String,
    pub head_sha: String,
    pub url: String,
    pub check_suite: CheckSuite,
    pub details_url: Option<String>,
    pub external_id: Option<String>,
    pub status: Option<CheckRunState>,
    pub started_at: Option<String>,
    pub conclusion: Option<Conclusion>,
    pub completed_at: Option<String>,
    /*
    Deleted for now:

    GitHub's API returns:

      "output": {
        "title": null,
        "summary": null,
        "text": null,
        "annotations_count": 0,
        "annotations_url": "https://api.github.com/repos/grahamc/notpkgs/check-runs/30726963/annotations"
      },

    if there is no Output, which confuses serde.

    pub output: Option<Output>,
     */
    pub actions: Option<Vec<Action>>,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct CheckSuite {
    pub id: u32,
}
<|endoftext|>