<commit_before>extern crate hyper;
extern crate clap;
#[macro_use]
extern crate log;
extern crate env_logger;
extern crate commercetools;
extern crate rustc_serialize;

use std::str::FromStr;
use clap::{App, Arg};
use commercetools::region::Region;
use commercetools::client::CtpClient;
use std::collections::HashMap;

#[allow(non_snake_case)]
#[derive(Debug, RustcDecodable)]
pub struct Reference {
    pub typeId: String,
    pub id: String,
}

#[allow(non_snake_case)]
#[derive(Debug, RustcDecodable)]
pub struct ProductVariant {
    pub id: u64,
    pub sku: Option<String>,
}

#[allow(non_snake_case)]
#[derive(Debug, RustcDecodable)]
pub struct ProductData {
    pub name: HashMap<String, String>,
    pub categories: Vec<Reference>,
    pub description: Option<HashMap<String, String>>,
    pub slug: HashMap<String, String>,
    pub metaTitle: Option<HashMap<String, String>>,
    pub metaDescription: Option<HashMap<String, String>>,
    pub metaKeywords: Option<HashMap<String, String>>,
    pub masterVariant: ProductVariant,
}

#[allow(non_snake_case)]
#[derive(Debug, RustcDecodable)]
pub struct ProductCatalogData {
    pub published: bool,
    pub hasStagedChanges: bool,
    pub current: ProductData,
    pub staged: ProductData,
}

#[allow(non_snake_case)]
#[derive(Debug, RustcDecodable)]
pub struct Product {
    pub id: String,
    pub version: u64,
    pub createdAt: String,
    pub lastModifiedAt: String,
    pub masterData: ProductCatalogData,
}

#[allow(non_snake_case)]
#[derive(Debug, RustcDecodable)]
pub struct Review {
    pub id: String,
    pub version: u64,
    pub createdAt: String,
    pub lastModifiedAt: String,
    pub text: Option<String>,
}

fn main() {
    env_logger::init().unwrap();
    let matches = App::new("sphere")
        .version("1.0")
        .author("Yann Simon <yann.simon@commercetools.com>")
        .args_from_usage(
            "<PROJECT_KEY> 'project key'
             <CLIENT_ID> 'client ID'
             <CLIENT_SECRET> 'client secret'
             --region=[Europe|NorthAmerica] 'region to use (default to Europe)'")
        .arg(Arg::with_name("permissions")
            .short("p")
            .long("permission")
            .help("permissions (default to manage_project)")
            .multiple(true)
            .takes_value(true)
        )
        .get_matches();

    let project_key = matches.value_of("PROJECT_KEY").unwrap();
    let client_id = matches.value_of("CLIENT_ID").unwrap();
    let client_secret = matches.value_of("CLIENT_SECRET").unwrap();
    let region = matches.value_of("region").map(|s| Region::from_str(s).unwrap()).unwrap_or(Region::Europe);
    let permissions: Vec<&str> = if matches.is_present("permissions") {
        matches.values_of("permissions").unwrap().collect()
    } else {
        vec!("manage_project")
    };

    let ctp_client = CtpClient::new(&region, project_key, client_id, client_secret)
        .with_permissions(&permissions);

    // simple GET call
    let mut products = ctp_client.get("/products?limit=1").unwrap();
    println!("\nProducts: {}", products.body_as_string().unwrap());

    // paged result of products
    let products2 = ctp_client.list::<Product>("products").unwrap();
    println!("\nList of product ids: {:?}", products2.results.iter().map(|p| &p.id).collect::<Vec<&String>>());

    println!("\nFirst product: {:?}", &products2.results.first());

    // read reviews
    let mut reviews = ctp_client.get("/reviews?limit=1").unwrap();
    println!("\nReviews: {}", reviews.body_as_string().unwrap());

    let create = permissions.iter().any(|&p| p == "manage_project" || p == "manage_products");
    if create {
        // create and delete a review
        let create_review = r#"
        {
          "text": "my review"
        }
        "#;
        let mut review_call = ctp_client.post("/reviews", create_review).unwrap();
        let review = review_call.body_as::<Review>().unwrap();
        println!("\n[{}] New Review: {:?}", &review_call.status(), review);

        let url = format!("/reviews/{}", review.id);
        let mut deleted_review = ctp_client.delete(&url).unwrap();
        println!("\n[{}] Deleted Review: {:?}", &deleted_review.status(), deleted_review.body_as_string().unwrap());
    }

    // read products IDs with a Graph QL query
    let query = r#"
    {
      products {
        results {
          id
        }
      }
    }
    "#;
    let mut graphql = ctp_client.graphql(query).unwrap();
    println!("\nGraphQL: {}", graphql.body_as_string().unwrap());

}
<commit_msg>fix deletion<commit_after>extern crate hyper;
extern crate clap;
#[macro_use]
extern crate log;
extern crate env_logger;
extern crate commercetools;
extern crate rustc_serialize;

use std::str::FromStr;
use clap::{App, Arg};
use commercetools::region::Region;
use commercetools::client::CtpClient;
use std::collections::HashMap;

#[allow(non_snake_case)]
#[derive(Debug, RustcDecodable)]
pub struct Reference {
    pub typeId: String,
    pub id: String,
}

#[allow(non_snake_case)]
#[derive(Debug, RustcDecodable)]
pub struct ProductVariant {
    pub id: u64,
    pub sku: Option<String>,
}

#[allow(non_snake_case)]
#[derive(Debug, RustcDecodable)]
pub struct ProductData {
    pub name: HashMap<String, String>,
    pub categories: Vec<Reference>,
    pub description: Option<HashMap<String, String>>,
    pub slug: HashMap<String, String>,
    pub metaTitle: Option<HashMap<String, String>>,
    pub metaDescription: Option<HashMap<String, String>>,
    pub metaKeywords: Option<HashMap<String, String>>,
    pub masterVariant: ProductVariant,
}

#[allow(non_snake_case)]
#[derive(Debug, RustcDecodable)]
pub struct ProductCatalogData {
    pub published: bool,
    pub hasStagedChanges: bool,
    pub current: ProductData,
    pub staged: ProductData,
}

#[allow(non_snake_case)]
#[derive(Debug, RustcDecodable)]
pub struct Product {
    pub id: String,
    pub version: u64,
    pub createdAt: String,
    pub lastModifiedAt: String,
    pub masterData: ProductCatalogData,
}

#[allow(non_snake_case)]
#[derive(Debug, RustcDecodable)]
pub struct Review {
    pub id: String,
    pub version: u64,
    pub createdAt: String,
    pub lastModifiedAt: String,
    pub text: Option<String>,
}

fn main() {
    env_logger::init().unwrap();
    let matches = App::new("sphere")
        .version("1.0")
        .author("Yann Simon <yann.simon@commercetools.com>")
        .args_from_usage(
            "<PROJECT_KEY> 'project key'
             <CLIENT_ID> 'client ID'
             <CLIENT_SECRET> 'client secret'
             --region=[Europe|NorthAmerica] 'region to use (default to Europe)'")
        .arg(Arg::with_name("permissions")
            .short("p")
            .long("permission")
            .help("permissions (default to manage_project)")
            .multiple(true)
            .takes_value(true)
        )
        .get_matches();

    let project_key = matches.value_of("PROJECT_KEY").unwrap();
    let client_id = matches.value_of("CLIENT_ID").unwrap();
    let client_secret = matches.value_of("CLIENT_SECRET").unwrap();
    let region = matches.value_of("region").map(|s| Region::from_str(s).unwrap()).unwrap_or(Region::Europe);
    let permissions: Vec<&str> = if matches.is_present("permissions") {
        matches.values_of("permissions").unwrap().collect()
    } else {
        vec!("manage_project")
    };

    let ctp_client = CtpClient::new(&region, project_key, client_id, client_secret)
        .with_permissions(&permissions);

    // simple GET call
    let mut products = ctp_client.get("/products?limit=1").unwrap();
    println!("\nProducts: {}", products.body_as_string().unwrap());

    // paged result of products
    let products2 = ctp_client.list::<Product>("products").unwrap();
    println!("\nList of product ids: {:?}", products2.results.iter().map(|p| &p.id).collect::<Vec<&String>>());

    println!("\nFirst product: {:?}", &products2.results.first());

    // read reviews
    let mut reviews = ctp_client.get("/reviews?limit=1").unwrap();
    println!("\nReviews: {}", reviews.body_as_string().unwrap());

    let create = permissions.iter().any(|&p| p == "manage_project" || p == "manage_products");
    if create {
        // create and delete a review
        let create_review = r#"
        {
          "text": "my review"
        }
        "#;
        let mut review_call = ctp_client.post("/reviews", create_review).unwrap();
        let review = review_call.body_as::<Review>().unwrap();
        println!("\n[{}] New Review: {:?}", &review_call.status(), review);

        let url = format!("/reviews/{}?version={}", review.id, review.version);
        let mut deleted_review = ctp_client.delete(&url).unwrap();
        println!("\n[{}] Deleted Review: {:?}", &deleted_review.status(), deleted_review.body_as_string().unwrap());
    }

    // read products IDs with a Graph QL query
    let query = r#"
    {
      products {
        results {
          id
        }
      }
    }
    "#;
    let mut graphql = ctp_client.graphql(query).unwrap();
    println!("\nGraphQL: {}", graphql.body_as_string().unwrap());

}
<|endoftext|>


<commit_before>extern crate bit_vec;
extern crate ssz;

use bit_vec::BitVec;

use std::default;

/// A BooleanBitfield represents a set of booleans compactly stored as a vector of bits.
/// The BooleanBitfield is given a fixed size during construction. Reads outside of the current size return an out-of-bounds error. Writes outside of the current size expand the size of the set.
#[derive(Debug, Clone, PartialEq)]
pub struct BooleanBitfield(BitVec);

/// Error represents some reason a request against a bitfield was not satisfied
#[derive(Debug, PartialEq)]
pub enum Error {
    /// OutOfBounds refers to indexing into a bitfield where no bits exist; returns the illegal index and the current size of the bitfield, respectively
    OutOfBounds(usize, usize),
}

impl BooleanBitfield {
    /// Create a new bitfield.
    pub fn new() -> Self {
        Default::default()
    }

    /// Create a new bitfield with the given length `initial_len` and all values set to `bit`.
    pub fn from_elem(inital_len: usize, bit: bool) -> Self {
        Self {
            0: BitVec::from_elem(inital_len, bit),
        }
    }

    /// Create a new bitfield using the supplied `bytes` as input
    pub fn from_bytes(bytes: &[u8]) -> Self {
        Self {
            0: BitVec::from_bytes(bytes),
        }
    }

    /// Read the value of a bit.
    ///
    /// If the index is in bounds, then result is Ok(value) where value is `true` if the bit is 1 and `false` if the bit is 0.
    /// If the index is out of bounds, we return an error to that extent.
    pub fn get(&self, i: usize) -> Result<bool, Error> {
        match self.0.get(i) {
            Some(value) => Ok(value),
            None => Err(Error::OutOfBounds(i, self.0.len())),
        }
    }

    /// Set the value of a bit.
    ///
    /// If the index is out of bounds, we expand the size of the underlying set to include the new index.
    /// Returns the previous value if there was one.
    pub fn set(&mut self, i: usize, value: bool) -> Option<bool> {
        let previous = match self.get(i) {
            Ok(previous) => Some(previous),
            Err(Error::OutOfBounds(_, len)) => {
                let new_len = i - len + 1;
                self.0.grow(new_len, false);
                None
            }
        };
        self.0.set(i, value);
        previous
    }

    /// Returns the index of the highest set bit. Some(n) if some bit is set, None otherwise.
    pub fn highest_set_bit(&self) -> Option<usize> {
        self.0.iter().rposition(|bit| bit)
    }

    /// Returns the number of bits in this bitfield.
    pub fn len(&self) -> usize {
        self.0.len()
    }

    /// Returns the number of bytes required to represent this bitfield.
    pub fn num_bytes(&self) -> usize {
        self.to_bytes().len()
    }

    /// Returns the number of `1` bits in the bitfield
    pub fn num_set_bits(&self) -> usize {
        self.0.iter().filter(|&bit| bit).count()
    }

    /// Returns a vector of bytes representing the bitfield
    /// Note that this returns the bit layout of the underlying implementation in the `bit-vec` crate.
    pub fn to_bytes(&self) -> Vec<u8> {
        self.0.to_bytes()
    }
}

impl default::Default for BooleanBitfield {
    /// default provides the "empty" bitfield
    /// Note: the empty bitfield is set to the `0` byte.
    fn default() -> Self {
        Self::from_elem(8, false)
    }
}

// borrowed from bit_vec crate
fn reverse_bits(byte: u8) -> u8 {
    let mut result = 0;
    for i in 0..8 {
        result = result | ((byte >> i) & 1) << (7 - i);
    }
    result
}

impl ssz::Encodable for BooleanBitfield {
    // ssz_append encodes Self according to the `ssz` spec.
    // Note that we have to flip the endianness of the encoding with `reverse_bits` to account for an implementation detail of `bit-vec` crate.
    fn ssz_append(&self, s: &mut ssz::SszStream) {
        let bytes: Vec<u8> = self
            .to_bytes()
            .iter()
            .map(|&byte| reverse_bits(byte))
            .collect();
        s.append_vec(&bytes);
    }
}

impl ssz::Decodable for BooleanBitfield {
    fn ssz_decode(bytes: &[u8], index: usize) -> Result<(Self, usize), ssz::DecodeError> {
        let len = ssz::decode::decode_length(bytes, index, ssz::LENGTH_BYTES)?;
        if (ssz::LENGTH_BYTES + len) > bytes.len() {
            return Err(ssz::DecodeError::TooShort);
        }

        if len == 0 {
            Ok((BooleanBitfield::new(), index + ssz::LENGTH_BYTES))
        } else {
            let bytes = &bytes[(index + 4)..(index + len + 4)];

            let mut field = BooleanBitfield::from_elem(0, false);
            for (byte_index, byte) in bytes.iter().enumerate() {
                for i in 0..8 {
                    let bit = byte & (1 << i);
                    if bit != 0 {
                        field.set(8 * byte_index + i, true);
                    }
                }
            }

            let index = index + ssz::LENGTH_BYTES + len;
            Ok((field, index))
        }
    }
}

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

    #[test]
    fn test_new_bitfield() {
        let mut field = BooleanBitfield::new();
        let original_len = field.len();

        for i in 0..100 {
            if i < original_len {
                assert!(!field.get(i).unwrap());
            } else {
                assert!(field.get(i).is_err());
            }
            let previous = field.set(i, true);
            if i < original_len {
                assert!(!previous.unwrap());
            } else {
                assert!(previous.is_none());
            }
        }
    }

    #[test]
    fn test_empty_bitfield() {
        let mut field = BooleanBitfield::from_elem(0, false);
        let original_len = field.len();

        assert_eq!(original_len, 0);

        for i in 0..100 {
            if i < original_len {
                assert!(!field.get(i).unwrap());
            } else {
                assert!(field.get(i).is_err());
            }
            let previous = field.set(i, true);
            if i < original_len {
                assert!(!previous.unwrap());
            } else {
                assert!(previous.is_none());
            }
        }

        assert_eq!(field.len(), 100);
        assert_eq!(field.num_set_bits(), 100);
    }

    const INPUT: &[u8] = &[0b0000_0010, 0b0000_0010];

    #[test]
    fn test_get_from_bitfield() {
        let field = BooleanBitfield::from_bytes(INPUT);
        let unset = field.get(0).unwrap();
        assert!(!unset);
        let set = field.get(6).unwrap();
        assert!(set);
        let set = field.get(14).unwrap();
        assert!(set);
    }

    #[test]
    fn test_set_for_bitfield() {
        let mut field = BooleanBitfield::from_bytes(INPUT);
        let previous = field.set(10, true).unwrap();
        assert!(!previous);
        let previous = field.get(10).unwrap();
        assert!(previous);
        let previous = field.set(6, false).unwrap();
        assert!(previous);
        let previous = field.get(6).unwrap();
        assert!(!previous);
    }

    #[test]
    fn test_highest_set_bit() {
        let field = BooleanBitfield::from_bytes(INPUT);
        assert_eq!(field.highest_set_bit().unwrap(), 14);

        let field = BooleanBitfield::from_bytes(&[0b0000_0011]);
        assert_eq!(field.highest_set_bit().unwrap(), 7);

        let field = BooleanBitfield::new();
        assert_eq!(field.highest_set_bit(), None);
    }

    #[test]
    fn test_len() {
        let field = BooleanBitfield::from_bytes(INPUT);
        assert_eq!(field.len(), 16);

        let field = BooleanBitfield::new();
        assert_eq!(field.len(), 8);
    }

    #[test]
    fn test_num_set_bits() {
        let field = BooleanBitfield::from_bytes(INPUT);
        assert_eq!(field.num_set_bits(), 2);

        let field = BooleanBitfield::new();
        assert_eq!(field.num_set_bits(), 0);
    }

    #[test]
    fn test_to_bytes() {
        let field = BooleanBitfield::from_bytes(INPUT);
        assert_eq!(field.to_bytes(), INPUT);

        let field = BooleanBitfield::new();
        assert_eq!(field.to_bytes(), vec![0]);
    }

    #[test]
    fn test_out_of_bounds() {
        let mut field = BooleanBitfield::from_bytes(INPUT);

        let out_of_bounds_index = field.len();
        assert!(field.set(out_of_bounds_index, true).is_none());
        assert!(field.len() == out_of_bounds_index + 1);
        assert!(field.get(out_of_bounds_index).unwrap());

        for i in 0..100 {
            if i <= out_of_bounds_index {
                assert!(field.set(i, true).is_some());
            } else {
                assert!(field.set(i, true).is_none());
            }
        }
    }

    #[test]
    fn test_grows_with_false() {
        let input_all_set: &[u8] = &[0b1111_1111, 0b1111_1111];
        let mut field = BooleanBitfield::from_bytes(input_all_set);

        // Define `a` and `b`, where both are out of bounds and `b` is greater than `a`.
        let a = field.len();
        let b = a + 1;

        // Ensure `a` is out-of-bounds for test integrity.
        assert!(field.get(a).is_err());

        // Set `b` to `true`. Also, for test integrity, ensure it was previously out-of-bounds.
        assert!(field.set(b, true).is_none());

        // Ensure that `a` wasn't also set to `true` during the grow.
        assert_eq!(field.get(a), Ok(false));
        assert_eq!(field.get(b), Ok(true));
    }

    #[test]
    fn test_num_bytes() {
        let field = BooleanBitfield::from_bytes(INPUT);
        assert_eq!(field.num_bytes(), 2);

        let field = BooleanBitfield::from_elem(2, true);
        assert_eq!(field.num_bytes(), 1);

        let field = BooleanBitfield::from_elem(13, true);
        assert_eq!(field.num_bytes(), 2);
    }

    #[test]
    fn test_ssz_encode() {
        let field = BooleanBitfield::from_elem(5, true);

        let mut stream = SszStream::new();
        stream.append(&field);
        assert_eq!(stream.drain(), vec![0, 0, 0, 1, 31]);

        let field = BooleanBitfield::from_elem(18, true);
        let mut stream = SszStream::new();
        stream.append(&field);
        assert_eq!(stream.drain(), vec![0, 0, 0, 3, 255, 255, 3]);
    }

    #[test]
    fn test_ssz_decode() {
        let encoded = vec![0, 0, 0, 1, 31];
        let (field, _): (BooleanBitfield, usize) = ssz::decode_ssz(&encoded, 0).unwrap();
        let expected = BooleanBitfield::from_elem(5, true);
        assert_eq!(field, expected);

        let encoded = vec![0, 0, 0, 3, 255, 255, 3];
        let (field, _): (BooleanBitfield, usize) = ssz::decode_ssz(&encoded, 0).unwrap();
        let expected = BooleanBitfield::from_elem(18, true);
        assert_eq!(field, expected);
    }
}
<commit_msg>Add failing boolean bitfield test<commit_after>extern crate bit_vec;
extern crate ssz;

use bit_vec::BitVec;

use std::default;

/// A BooleanBitfield represents a set of booleans compactly stored as a vector of bits.
/// The BooleanBitfield is given a fixed size during construction. Reads outside of the current size return an out-of-bounds error. Writes outside of the current size expand the size of the set.
#[derive(Debug, Clone, PartialEq)]
pub struct BooleanBitfield(BitVec);

/// Error represents some reason a request against a bitfield was not satisfied
#[derive(Debug, PartialEq)]
pub enum Error {
    /// OutOfBounds refers to indexing into a bitfield where no bits exist; returns the illegal index and the current size of the bitfield, respectively
    OutOfBounds(usize, usize),
}

impl BooleanBitfield {
    /// Create a new bitfield.
    pub fn new() -> Self {
        Default::default()
    }

    /// Create a new bitfield with the given length `initial_len` and all values set to `bit`.
    pub fn from_elem(inital_len: usize, bit: bool) -> Self {
        Self {
            0: BitVec::from_elem(inital_len, bit),
        }
    }

    /// Create a new bitfield using the supplied `bytes` as input
    pub fn from_bytes(bytes: &[u8]) -> Self {
        Self {
            0: BitVec::from_bytes(bytes),
        }
    }

    /// Read the value of a bit.
    ///
    /// If the index is in bounds, then result is Ok(value) where value is `true` if the bit is 1 and `false` if the bit is 0.
    /// If the index is out of bounds, we return an error to that extent.
    pub fn get(&self, i: usize) -> Result<bool, Error> {
        match self.0.get(i) {
            Some(value) => Ok(value),
            None => Err(Error::OutOfBounds(i, self.0.len())),
        }
    }

    /// Set the value of a bit.
    ///
    /// If the index is out of bounds, we expand the size of the underlying set to include the new index.
    /// Returns the previous value if there was one.
    pub fn set(&mut self, i: usize, value: bool) -> Option<bool> {
        let previous = match self.get(i) {
            Ok(previous) => Some(previous),
            Err(Error::OutOfBounds(_, len)) => {
                let new_len = i - len + 1;
                self.0.grow(new_len, false);
                None
            }
        };
        self.0.set(i, value);
        previous
    }

    /// Returns the index of the highest set bit. Some(n) if some bit is set, None otherwise.
    pub fn highest_set_bit(&self) -> Option<usize> {
        self.0.iter().rposition(|bit| bit)
    }

    /// Returns the number of bits in this bitfield.
    pub fn len(&self) -> usize {
        self.0.len()
    }

    /// Returns the number of bytes required to represent this bitfield.
    pub fn num_bytes(&self) -> usize {
        self.to_bytes().len()
    }

    /// Returns the number of `1` bits in the bitfield
    pub fn num_set_bits(&self) -> usize {
        self.0.iter().filter(|&bit| bit).count()
    }

    /// Returns a vector of bytes representing the bitfield
    /// Note that this returns the bit layout of the underlying implementation in the `bit-vec` crate.
    pub fn to_bytes(&self) -> Vec<u8> {
        self.0.to_bytes()
    }
}

impl default::Default for BooleanBitfield {
    /// default provides the "empty" bitfield
    /// Note: the empty bitfield is set to the `0` byte.
    fn default() -> Self {
        Self::from_elem(8, false)
    }
}

// borrowed from bit_vec crate
fn reverse_bits(byte: u8) -> u8 {
    let mut result = 0;
    for i in 0..8 {
        result = result | ((byte >> i) & 1) << (7 - i);
    }
    result
}

impl ssz::Encodable for BooleanBitfield {
    // ssz_append encodes Self according to the `ssz` spec.
    // Note that we have to flip the endianness of the encoding with `reverse_bits` to account for an implementation detail of `bit-vec` crate.
    fn ssz_append(&self, s: &mut ssz::SszStream) {
        let bytes: Vec<u8> = self
            .to_bytes()
            .iter()
            .map(|&byte| reverse_bits(byte))
            .collect();
        s.append_vec(&bytes);
    }
}

impl ssz::Decodable for BooleanBitfield {
    fn ssz_decode(bytes: &[u8], index: usize) -> Result<(Self, usize), ssz::DecodeError> {
        let len = ssz::decode::decode_length(bytes, index, ssz::LENGTH_BYTES)?;
        if (ssz::LENGTH_BYTES + len) > bytes.len() {
            return Err(ssz::DecodeError::TooShort);
        }

        if len == 0 {
            Ok((BooleanBitfield::new(), index + ssz::LENGTH_BYTES))
        } else {
            let bytes = &bytes[(index + 4)..(index + len + 4)];

            let mut field = BooleanBitfield::from_elem(0, false);
            for (byte_index, byte) in bytes.iter().enumerate() {
                for i in 0..8 {
                    let bit = byte & (1 << i);
                    if bit != 0 {
                        field.set(8 * byte_index + i, true);
                    }
                }
            }

            let index = index + ssz::LENGTH_BYTES + len;
            Ok((field, index))
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use ssz::{ssz_encode, Decodable, SszStream};

    #[test]
    fn test_new_bitfield() {
        let mut field = BooleanBitfield::new();
        let original_len = field.len();

        for i in 0..100 {
            if i < original_len {
                assert!(!field.get(i).unwrap());
            } else {
                assert!(field.get(i).is_err());
            }
            let previous = field.set(i, true);
            if i < original_len {
                assert!(!previous.unwrap());
            } else {
                assert!(previous.is_none());
            }
        }
    }

    #[test]
    fn test_empty_bitfield() {
        let mut field = BooleanBitfield::from_elem(0, false);
        let original_len = field.len();

        assert_eq!(original_len, 0);

        for i in 0..100 {
            if i < original_len {
                assert!(!field.get(i).unwrap());
            } else {
                assert!(field.get(i).is_err());
            }
            let previous = field.set(i, true);
            if i < original_len {
                assert!(!previous.unwrap());
            } else {
                assert!(previous.is_none());
            }
        }

        assert_eq!(field.len(), 100);
        assert_eq!(field.num_set_bits(), 100);
    }

    const INPUT: &[u8] = &[0b0000_0010, 0b0000_0010];

    #[test]
    fn test_get_from_bitfield() {
        let field = BooleanBitfield::from_bytes(INPUT);
        let unset = field.get(0).unwrap();
        assert!(!unset);
        let set = field.get(6).unwrap();
        assert!(set);
        let set = field.get(14).unwrap();
        assert!(set);
    }

    #[test]
    fn test_set_for_bitfield() {
        let mut field = BooleanBitfield::from_bytes(INPUT);
        let previous = field.set(10, true).unwrap();
        assert!(!previous);
        let previous = field.get(10).unwrap();
        assert!(previous);
        let previous = field.set(6, false).unwrap();
        assert!(previous);
        let previous = field.get(6).unwrap();
        assert!(!previous);
    }

    #[test]
    fn test_highest_set_bit() {
        let field = BooleanBitfield::from_bytes(INPUT);
        assert_eq!(field.highest_set_bit().unwrap(), 14);

        let field = BooleanBitfield::from_bytes(&[0b0000_0011]);
        assert_eq!(field.highest_set_bit().unwrap(), 7);

        let field = BooleanBitfield::new();
        assert_eq!(field.highest_set_bit(), None);
    }

    #[test]
    fn test_len() {
        let field = BooleanBitfield::from_bytes(INPUT);
        assert_eq!(field.len(), 16);

        let field = BooleanBitfield::new();
        assert_eq!(field.len(), 8);
    }

    #[test]
    fn test_num_set_bits() {
        let field = BooleanBitfield::from_bytes(INPUT);
        assert_eq!(field.num_set_bits(), 2);

        let field = BooleanBitfield::new();
        assert_eq!(field.num_set_bits(), 0);
    }

    #[test]
    fn test_to_bytes() {
        let field = BooleanBitfield::from_bytes(INPUT);
        assert_eq!(field.to_bytes(), INPUT);

        let field = BooleanBitfield::new();
        assert_eq!(field.to_bytes(), vec![0]);
    }

    #[test]
    fn test_out_of_bounds() {
        let mut field = BooleanBitfield::from_bytes(INPUT);

        let out_of_bounds_index = field.len();
        assert!(field.set(out_of_bounds_index, true).is_none());
        assert!(field.len() == out_of_bounds_index + 1);
        assert!(field.get(out_of_bounds_index).unwrap());

        for i in 0..100 {
            if i <= out_of_bounds_index {
                assert!(field.set(i, true).is_some());
            } else {
                assert!(field.set(i, true).is_none());
            }
        }
    }

    #[test]
    fn test_grows_with_false() {
        let input_all_set: &[u8] = &[0b1111_1111, 0b1111_1111];
        let mut field = BooleanBitfield::from_bytes(input_all_set);

        // Define `a` and `b`, where both are out of bounds and `b` is greater than `a`.
        let a = field.len();
        let b = a + 1;

        // Ensure `a` is out-of-bounds for test integrity.
        assert!(field.get(a).is_err());

        // Set `b` to `true`. Also, for test integrity, ensure it was previously out-of-bounds.
        assert!(field.set(b, true).is_none());

        // Ensure that `a` wasn't also set to `true` during the grow.
        assert_eq!(field.get(a), Ok(false));
        assert_eq!(field.get(b), Ok(true));
    }

    #[test]
    fn test_num_bytes() {
        let field = BooleanBitfield::from_bytes(INPUT);
        assert_eq!(field.num_bytes(), 2);

        let field = BooleanBitfield::from_elem(2, true);
        assert_eq!(field.num_bytes(), 1);

        let field = BooleanBitfield::from_elem(13, true);
        assert_eq!(field.num_bytes(), 2);
    }

    #[test]
    fn test_ssz_encode() {
        let field = BooleanBitfield::from_elem(5, true);

        let mut stream = SszStream::new();
        stream.append(&field);
        assert_eq!(stream.drain(), vec![0, 0, 0, 1, 31]);

        let field = BooleanBitfield::from_elem(18, true);
        let mut stream = SszStream::new();
        stream.append(&field);
        assert_eq!(stream.drain(), vec![0, 0, 0, 3, 255, 255, 3]);
    }

    #[test]
    fn test_ssz_decode() {
        let encoded = vec![0, 0, 0, 1, 31];
        let (field, _): (BooleanBitfield, usize) = ssz::decode_ssz(&encoded, 0).unwrap();
        let expected = BooleanBitfield::from_elem(5, true);
        assert_eq!(field, expected);

        let encoded = vec![0, 0, 0, 3, 255, 255, 3];
        let (field, _): (BooleanBitfield, usize) = ssz::decode_ssz(&encoded, 0).unwrap();
        let expected = BooleanBitfield::from_elem(18, true);
        assert_eq!(field, expected);
    }

    #[test]
    fn test_ssz_round_trip() {
        let original = BooleanBitfield::from_bytes(&vec![18; 12][..]);
        let ssz = ssz_encode(&original);
        let (decoded, _) = BooleanBitfield::ssz_decode(&ssz, 0).unwrap();
        assert_eq!(original, decoded);
    }
}
<|endoftext|>


<commit_before>use std::net::{SocketAddr};
use std::str;
use std::collections::HashMap;

use futures::prelude::*;
use futures::{Future, Stream};

use hyper::Client;

use tokio::prelude::FutureExt;
use tokio::net::UdpSocket;

use bytes::Bytes;

use aio::Gateway;
use common::{messages, parsing, SearchOptions};
use errors::SearchError;

const MAX_RESPONSE_SIZE: usize = 1500;

/// Search for a gateway with the provided options
pub fn search_gateway(options: SearchOptions) -> impl Future<Item=Gateway, Error=SearchError> {
    use futures::future::{err, Either::A, Either::B};

    // Create socket for future calls
    let socket = match UdpSocket::bind(&options.bind_addr) {
        Ok(s) => s,
        Err(e) => return  A(err(SearchError::from(e))),
    };

    // Create future and issue request
    match options.timeout {
        Some(t) =>B(A(SearchFuture::search(socket, options.broadcast_address)
            .and_then(|search| search ).timeout(t).map_err(|e| SearchError::from(e) ))),
        _ =>B(B(SearchFuture::search(socket, options.broadcast_address).and_then(|search| search ))),
    }
}

pub struct SearchFuture {
    socket: UdpSocket,
    pending: HashMap<SocketAddr, SearchState>,
}

enum SearchState {
    Connecting(Box<Future<Item=Bytes, Error=SearchError> + Send>),
    Done(String),
    Error,
}

impl SearchFuture {
    // Create a new search
    fn search(socket: UdpSocket, addr: SocketAddr) -> impl Future<Item=SearchFuture, Error=SearchError> {
        debug!("sending broadcast request to: {} on interface: {:?}", addr, socket.local_addr());

        socket.send_dgram(messages::SEARCH_REQUEST.as_bytes(), &addr)
            .map(|(socket, _n)| SearchFuture{socket, pending: HashMap::new() })
            .map_err(|e| SearchError::from(e) )
    }

    // Handle a UDP response message
    fn handle_broadcast_resp(from: SocketAddr, data: &[u8]) -> Result<(SocketAddr, String), SearchError> {
        debug!("handling broadcast response from: {}", from);

        // Convert response to text
        let text = str::from_utf8(&data)
            .map_err(|e| SearchError::from(e))?;

        // Parse socket address and path
        let (addr, path) = parsing::parse_search_result(text)?;

        Ok((SocketAddr::V4(addr), path))
    }

    // Issue a control URL request over HTTP using the provided
    fn request_control_url(addr: SocketAddr, path: String) -> Result<Box<Future<Item=Bytes, Error=SearchError> + Send>, SearchError> {
        let client = Client::new();

        let uri = match format!("http://{}{}", addr, path).parse() {
            Ok(uri) => uri,
            Err(err) => return Err(SearchError::from(err)),
        };

        debug!("requesting control url from: {}", uri);

        Ok(Box::new(client.get(uri)
            .and_then(|resp| resp.into_body().concat2() )
            .map(|chunk| chunk.into_bytes() )
            .map_err(|e| SearchError::from(e) )
        ))
    }

    // Process a control response to extract the control URL
    fn handle_control_resp(addr: SocketAddr, resp: Bytes) -> Result<Vec<String>, SearchError> {
        debug!("handling control response from: {}", addr);

        // Create a cursor over the response data
        let c = std::io::Cursor::new(&resp);

        // Parse control URL out of body
        let url = parsing::parse_control_url(c)?;

        Ok(url)
    }
}

impl Future for SearchFuture {
    type Item=Gateway;
    type Error=SearchError;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {

        // Poll for (and handle) incoming messages
        let mut buff = [0u8; MAX_RESPONSE_SIZE];
        if let Async::Ready((n, from)) = self.socket.poll_recv_from(&mut buff)? {
            // Try handle response messages
            if let Ok((addr, path)) = Self::handle_broadcast_resp(from, &buff[0..n]) {
                if !self.pending.contains_key(&addr) {
                    debug!("received broadcast response from: {}", from);

                    // Issue control request
                    let req = Self::request_control_url(addr, path)?;
                    // Store pending requests
                    self.pending.insert(addr, SearchState::Connecting(req));
                } else {
                    debug!("received duplicate broadcast response from: {}, dropping", from);
                }
            }
        }

        // Poll on any outstanding control requests
        for (addr, state) in &mut self.pending {
            // Poll if we're in the connecting state
            let resp = {
                let c = match state {
                    SearchState::Connecting(c) => c,
                    _ => continue,
                };

                match c.poll()? {
                    Async::Ready(resp) => resp,
                    _ => continue,
                }
            };

            // Handle any responses
            if let Ok(url) = Self::handle_control_resp(*addr, resp) {
                debug!("received control url from: {} (url: {})", addr, url);
                *state = SearchState::Done(url.clone());

                match addr {
                    SocketAddr::V4(a) => {
                        let g = Gateway::new(*a, url);
                        return Ok(Async::Ready(g));
                    }
                    _ => warn!("unsupported IPv6 gateway response from addr: {}", addr),
                }

            } else {
                *state = SearchState::Error;
            }
        }

        Ok(Async::NotReady)
    }
}
<commit_msg>Update search.rs<commit_after>use std::net::{SocketAddr};
use std::str;
use std::collections::HashMap;

use futures::prelude::*;
use futures::{Future, Stream};

use hyper::Client;

use tokio::prelude::FutureExt;
use tokio::net::UdpSocket;

use bytes::Bytes;

use aio::Gateway;
use common::{messages, parsing, SearchOptions};
use errors::SearchError;

const MAX_RESPONSE_SIZE: usize = 1500;

/// Search for a gateway with the provided options
pub fn search_gateway(options: SearchOptions) -> impl Future<Item=Gateway, Error=SearchError> {
    use futures::future::{err, Either::A, Either::B};

    // Create socket for future calls
    let socket = match UdpSocket::bind(&options.bind_addr) {
        Ok(s) => s,
        Err(e) => return  A(err(SearchError::from(e))),
    };

    // Create future and issue request
    match options.timeout {
        Some(t) =>B(A(SearchFuture::search(socket, options.broadcast_address)
            .and_then(|search| search ).timeout(t).map_err(|e| SearchError::from(e) ))),
        _ =>B(B(SearchFuture::search(socket, options.broadcast_address).and_then(|search| search ))),
    }
}

pub struct SearchFuture {
    socket: UdpSocket,
    pending: HashMap<SocketAddr, SearchState>,
}

enum SearchState {
    Connecting(Box<Future<Item=Bytes, Error=SearchError> + Send>),
    Done(String),
    Error,
}

impl SearchFuture {
    // Create a new search
    fn search(socket: UdpSocket, addr: SocketAddr) -> impl Future<Item=SearchFuture, Error=SearchError> {
        debug!("sending broadcast request to: {} on interface: {:?}", addr, socket.local_addr());

        socket.send_dgram(messages::SEARCH_REQUEST.as_bytes(), &addr)
            .map(|(socket, _n)| SearchFuture{socket, pending: HashMap::new() })
            .map_err(|e| SearchError::from(e) )
    }

    // Handle a UDP response message
    fn handle_broadcast_resp(from: SocketAddr, data: &[u8]) -> Result<(SocketAddr, String), SearchError> {
        debug!("handling broadcast response from: {}", from);

        // Convert response to text
        let text = str::from_utf8(&data)
            .map_err(|e| SearchError::from(e))?;

        // Parse socket address and path
        let (addr, path) = parsing::parse_search_result(text)?;

        Ok((SocketAddr::V4(addr), path))
    }

    // Issue a control URL request over HTTP using the provided
    fn request_control_url(addr: SocketAddr, path: String) -> Result<Box<Future<Item=Bytes, Error=SearchError> + Send>, SearchError> {
        let client = Client::new();

        let uri = match format!("http://{}{}", addr, path).parse() {
            Ok(uri) => uri,
            Err(err) => return Err(SearchError::from(err)),
        };

        debug!("requesting control url from: {}", uri);

        Ok(Box::new(client.get(uri)
            .and_then(|resp| resp.into_body().concat2() )
            .map(|chunk| chunk.into_bytes() )
            .map_err(|e| SearchError::from(e) )
        ))
    }

    // Process a control response to extract the control URL
    fn handle_control_resp(addr: SocketAddr, resp: Bytes) -> Result<Vec<String>, SearchError> {
        debug!("handling control response from: {}", addr);

        // Create a cursor over the response data
        let c = std::io::Cursor::new(&resp);

        // Parse control URL out of body
        let url = parsing::parse_control_url(c)?;

        Ok(url)
    }
}

impl Future for SearchFuture {
    type Item=Gateway;
    type Error=SearchError;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {

        // Poll for (and handle) incoming messages
        let mut buff = [0u8; MAX_RESPONSE_SIZE];
        if let Async::Ready((n, from)) = self.socket.poll_recv_from(&mut buff)? {
            // Try handle response messages
            if let Ok((addr, path)) = Self::handle_broadcast_resp(from, &buff[0..n]) {
                if !self.pending.contains_key(&addr) {
                    debug!("received broadcast response from: {}", from);

                    // Issue control request
                    let req = Self::request_control_url(addr, path)?;
                    // Store pending requests
                    self.pending.insert(addr, SearchState::Connecting(req));
                } else {
                    debug!("received duplicate broadcast response from: {}, dropping", from);
                }
            }
        }

        // Poll on any outstanding control requests
        for (addr, state) in &mut self.pending {
            // Poll if we're in the connecting state
            let resp = {
                let c = match state {
                    SearchState::Connecting(c) => c,
                    _ => continue,
                };

                match c.poll()? {
                    Async::Ready(resp) => resp,
                    _ => continue,
                }
            };

            // Handle any responses
            if let Ok(url) = Self::handle_control_resp(*addr, resp) {
                debug!("received control url from: {} (url: {:?})", addr, url);
                *state = SearchState::Done(url[0].clone());

                match addr {
                    SocketAddr::V4(a) => {
                        let g = Gateway::new(*a, url[0]);
                        return Ok(Async::Ready(g));
                    }
                    _ => warn!("unsupported IPv6 gateway response from addr: {}", addr),
                }

            } else {
                *state = SearchState::Error;
            }
        }

        Ok(Async::NotReady)
    }
}
<|endoftext|>


<commit_before>use num::{Zero,One};
use num::Num;
use std::fmt;
use std::ops::{Index,IndexMut,Add,Mul,Div,Sub,Range};

use alg::Vector;

#[derive(Clone,PartialEq,Debug)]
pub struct Matrix<T> {
    /// Number of rows (max Y)
    pub m: usize,
    /// Number of columns (max X)
    pub n: usize,

    // Inner data. Cols concatenated.
    data: Vec<T>,
}

impl <T> Matrix<T> {
    /// Creates a new matrix with the given dimensions,
    /// initializing each cell with the given functor.
    ///
    /// * `m` is the number of lines (the Y size)
    /// * `n` is the number of columns (the X size)
    pub fn new<F>(n: usize, m: usize, f: F) -> Self
        where F: Fn(usize,usize) -> T
    {
        let data = (0..n*m).map(|i| (i/m,i%m)).map(|(x,y)| f(x,y)).collect();
        Matrix {
            m: m,
            n: n,
            data: data,
        }
    }

    pub fn keep_cols(&mut self, cols: Range<usize>) {
        let n_cols = cols.end - cols.start;
        let start = cols.start * self.m;
        let end = cols.end * self.m;

        self.data.truncate(end);

        if start > 0 {
            self.data = self.data.split_off(start);
        }

        self.n = n_cols;
    }

    pub fn append_cols(&mut self, mut other: Matrix<T>) {
        if self.m != other.m {
            panic!("Matrices don't have the same height.");
        }

        self.n += other.n;
        // append is currently unstable. See ../lib.rs
        self.data.append(&mut other.data);
    }

    fn get_index(&self, (x,y): (usize,usize)) -> usize {
        y + x * self.m
    }

    /// Creates a dummy empty matrix.
    pub fn dummy() -> Self {
        Matrix {
            m: 0,
            n: 0,
            data: Vec::new(),
        }
    }

    pub fn is_squared(&self) -> bool {
        return self.m == self.n
    }

    pub fn swap(&mut self, a: (usize,usize), b: (usize,usize)) {
        let ia = self.get_index(a);
        let ib = self.get_index(b);
        self.data.swap(ia, ib);
    }

    pub fn swap_cols(&mut self, xa: usize, xb: usize) {
        if xa == xb { return; }

        for y in 0..self.n {
            self.swap((xa,y), (xb,y));
        }
    }

    pub fn swap_rows(&mut self, ya: usize, yb: usize) {
        if ya == yb { return; }

        for x in 0..self.n {
            self.swap((x,ya),(x,yb));
        }
    }
}

impl <T: Zero> Matrix<T> {
    /// Creates a new matrix initialized to zero.
    pub fn zero(n: usize, m: usize) -> Self {
        Matrix::new(n,m, |_,_| T::zero())
    }
}

impl <T: Clone> Matrix<T> {

    /// Create a single-column matrix from the given Vector.
    pub fn from_col(v: &Vector<T>) -> Self {
        Matrix::new(1, v.dim(), |_,y| v[y].clone())
    }

    pub fn row(&self, y: usize) -> Vector<T> {
        Vector::new(self.n, |i| self[(i,y)].clone())
    }

    pub fn col(&self, x: usize) -> Vector<T> {
        Vector::new(self.m, |i| self[(x,i)].clone())
    }

    /// Make a matrix from the given vectors, to treat as columns.
    pub fn from_cols(cols: &[Vector<T>]) -> Self {
        if cols.is_empty() {
            Matrix::dummy()
        } else {
            let n = cols.len();
            let m = cols.first().unwrap().dim();
            Matrix::new(n, m, |x,y| cols[x][y].clone())
        }
    }

    /// Create a single-row matrix from the given Vector.
    pub fn from_row(v: &Vector<T>) -> Self {
        Matrix::new(v.dim(), 1, |x,_| v[x].clone())
    }

    /// Make a matrix from the given vectors, to treas as rows.
    pub fn from_rows(rows: &[Vector<T>]) -> Self {
        if rows.is_empty() {
            Matrix::dummy()
        } else {
            let m = rows.len();
            let n = rows.first().unwrap().dim();
            Matrix::new(n, m, |x,y| rows[y][x].clone())
        }
    }

    /// Returns the transposed matrix.
    pub fn transpose(&self) -> Matrix<T> {
        Matrix::new(self.m, self.n, |x,y| self[(y,x)].clone())
    }

    /// If this matrix is single-row or single-column,
    /// transforms this into a Vector.
    pub fn to_vector(self) -> Vector<T> {
        if self.n == 1 || self.m == 1 {
            Vector::from(self.data)
        } else {
            panic!("Matrix is not single-row or single-column.");
        }
    }
}

impl <T: Clone + Zero> Matrix<T> {
    /// Creates a new diagonal matrix, with the given vector serving as the diagonal.
    pub fn diagonal(vector: Vector<T>) -> Self {
        let n = vector.dim();
        let mut m = Matrix::zero(n,n);
        for (i,x) in vector.into_iter().enumerate() {
            m[(i,i)] = x;
        }
        m
    }

    /// Creates a new scalar matrix with the given value.
    pub fn scalar(n: usize, value: T) -> Self {
        Matrix::diagonal(Vector::from_copies(n, value))
    }
}

impl <T: Clone + Zero + One> Matrix<T> {
    pub fn identity(n: usize) -> Self {
        Matrix::scalar(n, T::one())
    }
}

impl <T: Clone + Num> Matrix<T> {
    pub fn norm(&self) -> T {
        self.data.iter().map(|a| a.clone() * a.clone()).fold(T::zero(), |a,b| a+b)
    }

    pub fn inverse(&self) -> Option<Self> {
        self.clone().invert_inplace()
    }

    pub fn invert_inplace(mut self) -> Option<Self> {
        if !self.is_squared() {
            panic!("Attempting to invert a non-square matrix.");
        }

        let n = self.n;

        // Waaa matrix inversion is a complex business.
        // Let's keep it `simple` with a Gauss-Jordan elimination...
        // The idea is: append an Identity matrix to the right (so we have a 2x1 aspect ratio)
        // Apply simple linear row operations (permutation, multiplication, addition) until the
        // first half is an identity matrix.
        // At this point, the second half should be the inverse matrix.
        // (Since we apply the inverse of the first half to an identity matrix.)

        self.append_cols(Matrix::scalar(n, T::one()));

        // For each (original) column...
        for k in 0..n {
            // Make sure the column is C[i] = i==k ? 1 : 0

            // Find the perfect candidate: a non-zero element
            let j = match (k..n).find(|&i| self[(k,i)] != T::zero()) {
                None => return None,
                Some(j) => j,
            };

            self.swap_rows(j, k);

            // Now divide the row by the diagonal value
            let pivot = self[(k,k)].clone();
            // No need to divide the first k values, they should be zeroes
            for x in k..self.n {
                self[(x,k)] = self[(x,k)].clone() / pivot.clone();
            }

            // Finally, zero all other rows
            for y in (0..n).filter(|&i| i != k) {
                let value = self[(k,y)].clone();
                for x in k..self.n {
                    self[(x,y)] = self[(x,y)].clone() - value.clone() * self[(x,k)].clone();
                }
            }
        }

        // And remove the first half
        self.keep_cols(n..2*n);

        Some(self)
    }
}

impl <'a, T: Add<Output=T> + Mul<Output=T> + Zero + Clone> Mul for &'a Matrix<T> {
    type Output = Matrix<T>;

    fn mul(self, other: &'a Matrix<T>) -> Matrix<T> {
        // TODO: might want to make this faster. Parallel? Skip zero values?
        Matrix::new(other.n, self.m, |x,y| (0..self.n).map(|i| self[(i,y)].clone() * other[(x,i)].clone()).fold(T::zero(), |a,b|a+b))
    }
}

impl <'a, T: Add<Output=T> + Mul<Output=T> + Zero + Clone> Mul<&'a Vector<T>> for &'a Matrix<T> {
    type Output = Vector<T>;

    fn mul(self, other: &'a Vector<T>) -> Vector<T> {
        Vector::new(self.m, |i| (0..self.n).map(|j| self[(j,i)].clone() * other[j].clone()).fold(T::zero(), |a,b| a+b))
    }
}

impl <'a, T: Add<Output=T> + Clone> Add for &'a Matrix<T> {
    type Output = Matrix<T>;

    fn add(self, other: &'a Matrix<T>) -> Matrix<T> {
        Matrix::new(self.n, self.m, |x,y| self[(x,y)].clone() + other[(x,y)].clone())
    }
}

impl <T: Sub<Output=T> + Clone> Sub for Matrix<T> {
    type Output = Matrix<T>;

    fn sub(mut self, other: Matrix<T>) -> Matrix<T> {
        for (s,o) in self.data.iter_mut().zip(other.data.into_iter()) {
            *s = s.clone() - o;
        }

        self
    }
}

impl <'a, T: Sub<Output=T> + Clone> Sub for &'a Matrix<T> {
    type Output = Matrix<T>;

    fn sub(self, other: &'a Matrix<T>) -> Matrix<T> {
        Matrix::new(self.n, self.m, |x,y| self[(x,y)].clone() - other[(x,y)].clone())
    }
}

impl <'a, T: Mul<Output=T> + Clone> Mul<T> for &'a Matrix<T> {
    type Output = Matrix<T>;

    fn mul(self, other: T) -> Matrix<T> {
        Matrix::new(self.n, self.m, |x,y| self[(x,y)].clone() * other.clone())
    }
}

impl <'a, T: Div<Output=T> + Clone> Div<T> for &'a Matrix<T> {
    type Output = Matrix<T>;

    fn div(self, other: T) -> Matrix<T> {
        Matrix::new(self.n, self.m, |x,y| self[(x,y)].clone() / other.clone())
    }
}

impl <T> Index<(usize,usize)> for Matrix<T> {
    type Output = T;

    fn index(&self, (x,y): (usize,usize)) -> &T {
        let i = self.get_index((x,y));
        &self.data[i]
    }
}

impl <T> IndexMut<(usize,usize)> for Matrix<T> {
    fn index_mut(&mut self, (x,y): (usize,usize)) -> &mut T {
        let i = self.get_index((x,y));
        &mut self.data[i]
    }
}

impl <T: fmt::Display> fmt::Display for Matrix<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(),fmt::Error> {
        try!(fmt.write_str(&format!("[{} x {}]", self.n, self.m)));
        for y in 0..self.m {
            try!(fmt.write_str("["));
            for x in 0..self.n {
                try!(self[(x,y)].fmt(fmt));
                try!(fmt.write_str(", "));
            }
            try!(fmt.write_str("]\n"));
        }
        Ok(())
    }
}

#[test]
fn test_i3() {
    let i3 = Matrix::scalar(3, 1);
    assert_eq!(i3.n, 3);
    assert_eq!(i3.m, 3);
    assert_eq!(i3[(0,0)], 1);
    assert_eq!(i3[(1,1)], 1);
    assert_eq!(i3[(2,2)], 1);
}

#[test]
fn test_add() {
    let i3 = Matrix::scalar(3, 1);
    let double = &i3 + &i3;
    assert_eq!(double, Matrix::scalar(3,2));
}

#[test]
fn test_transpose() {
    let v = Vector::new(4, |i| 1+i);

    assert_eq!(Matrix::from_row(&v), Matrix::from_col(&v).transpose());

    let m = Matrix::new(4,3, |x,y| x+4*y);
    let n = Matrix::new(3,4, |x,y| y+4*x);

    assert!(m != n);
    assert_eq!(m.transpose().transpose(), m);
    assert_eq!(m.transpose(), n);
    assert_eq!(n.transpose(), m);
}

#[test]
fn test_transpose_commutation() {
    let a = Matrix::new(5,3, |x,y| x+5*y);
    let b = Matrix::new(4,5, |x,y| x+y + 2*(x+y)%2);

    assert_eq!((&a * &b).transpose(), &b.transpose() * &a.transpose());
}

#[test]
fn test_from_row() {
    let v = Vector::new(4, |i| 1+i);
    let m = Matrix::new(4,1, |x,_| 1+x);

    assert_eq!(Matrix::from_row(&v), m);
    assert_eq!(m.to_vector(), v);
}

#[test]
fn test_sub() {
    let a = Matrix::new(4,3, |x,y| x+y);
    assert_eq!(&a - &a, Matrix::zero(4,3));
}

#[test]
fn test_cols() {
    let a = Matrix::new(4,4, |x,y| x+y);
    let b = Matrix::new(4,4, |x,y| 8 - (x+y));

    let mut c = a.clone();
    c.append_cols(b.clone());
    c.keep_cols(4..8);
    assert_eq!(b, c);

    let mut d = b.clone();
    d.append_cols(a.clone());
    d.keep_cols(4..8);
    assert_eq!(a, d);
}

#[test]
fn test_inverse() {
    let a = Matrix::new(2,2, |x,y| (x+y) as f64);
    let b = a.inverse().unwrap();

    assert_eq!((&a * &b), Matrix::identity(2));
}

#[test]
fn test_mul() {
    let m = Matrix::new(4,4, |x,y| x+y);
    let v = Vector::new(4, |i| i+1);

    assert_eq!(Matrix::from_col(&(&m * &v)), &m * &Matrix::from_col(&v));
}
<commit_msg>Add matrix determinant<commit_after>use num::{Zero,One};
use num::Num;
use std::fmt;
use std::ops::{Index,IndexMut,Add,Mul,Div,Sub,Range};

use alg::Vector;

#[derive(Clone,PartialEq,Debug)]
pub struct Matrix<T> {
    /// Number of rows (max Y)
    pub m: usize,
    /// Number of columns (max X)
    pub n: usize,

    // Inner data. Cols concatenated.
    data: Vec<T>,
}

impl <T> Matrix<T> {
    /// Creates a new matrix with the given dimensions,
    /// initializing each cell with the given functor.
    ///
    /// * `m` is the number of lines (the Y size)
    /// * `n` is the number of columns (the X size)
    pub fn new<F>(n: usize, m: usize, f: F) -> Self
        where F: Fn(usize,usize) -> T
    {
        let data = (0..n*m).map(|i| (i/m,i%m)).map(|(x,y)| f(x,y)).collect();
        Matrix {
            m: m,
            n: n,
            data: data,
        }
    }

    pub fn keep_cols(&mut self, cols: Range<usize>) {
        let n_cols = cols.end - cols.start;
        let start = cols.start * self.m;
        let end = cols.end * self.m;

        self.data.truncate(end);

        if start > 0 {
            self.data = self.data.split_off(start);
        }

        self.n = n_cols;
    }

    pub fn append_cols(&mut self, mut other: Matrix<T>) {
        if self.m != other.m {
            panic!("Matrices don't have the same height.");
        }

        self.n += other.n;
        // append is currently unstable. See ../lib.rs
        self.data.append(&mut other.data);
    }

    fn get_index(&self, (x,y): (usize,usize)) -> usize {
        y + x * self.m
    }

    /// Creates a dummy empty matrix.
    pub fn dummy() -> Self {
        Matrix {
            m: 0,
            n: 0,
            data: Vec::new(),
        }
    }

    pub fn is_squared(&self) -> bool {
        return self.m == self.n
    }

    pub fn swap(&mut self, a: (usize,usize), b: (usize,usize)) {
        let ia = self.get_index(a);
        let ib = self.get_index(b);
        self.data.swap(ia, ib);
    }

    pub fn swap_cols(&mut self, xa: usize, xb: usize) {
        if xa == xb { return; }

        for y in 0..self.n {
            self.swap((xa,y), (xb,y));
        }
    }

    pub fn swap_rows(&mut self, ya: usize, yb: usize) {
        if ya == yb { return; }

        for x in 0..self.n {
            self.swap((x,ya),(x,yb));
        }
    }
}

impl <T: Zero> Matrix<T> {
    /// Creates a new matrix initialized to zero.
    pub fn zero(n: usize, m: usize) -> Self {
        Matrix::new(n,m, |_,_| T::zero())
    }
}

impl <T: Clone> Matrix<T> {

    /// Create a single-column matrix from the given Vector.
    pub fn from_col(v: &Vector<T>) -> Self {
        Matrix::new(1, v.dim(), |_,y| v[y].clone())
    }

    pub fn row(&self, y: usize) -> Vector<T> {
        Vector::new(self.n, |i| self[(i,y)].clone())
    }

    pub fn col(&self, x: usize) -> Vector<T> {
        Vector::new(self.m, |i| self[(x,i)].clone())
    }

    /// Make a matrix from the given vectors, to treat as columns.
    pub fn from_cols(cols: &[Vector<T>]) -> Self {
        if cols.is_empty() {
            Matrix::dummy()
        } else {
            let n = cols.len();
            let m = cols.first().unwrap().dim();
            Matrix::new(n, m, |x,y| cols[x][y].clone())
        }
    }

    /// Create a single-row matrix from the given Vector.
    pub fn from_row(v: &Vector<T>) -> Self {
        Matrix::new(v.dim(), 1, |x,_| v[x].clone())
    }

    /// Make a matrix from the given vectors, to treas as rows.
    pub fn from_rows(rows: &[Vector<T>]) -> Self {
        if rows.is_empty() {
            Matrix::dummy()
        } else {
            let m = rows.len();
            let n = rows.first().unwrap().dim();
            Matrix::new(n, m, |x,y| rows[y][x].clone())
        }
    }

    /// Returns the transposed matrix.
    pub fn transpose(&self) -> Matrix<T> {
        Matrix::new(self.m, self.n, |x,y| self[(y,x)].clone())
    }

    /// If this matrix is single-row or single-column,
    /// transforms this into a Vector.
    pub fn to_vector(self) -> Vector<T> {
        if self.n == 1 || self.m == 1 {
            Vector::from(self.data)
        } else {
            panic!("Matrix is not single-row or single-column.");
        }
    }
}

impl <T: Clone + Zero> Matrix<T> {
    /// Creates a new diagonal matrix, with the given vector serving as the diagonal.
    pub fn diagonal(vector: Vector<T>) -> Self {
        let n = vector.dim();
        let mut m = Matrix::zero(n,n);
        for (i,x) in vector.into_iter().enumerate() {
            m[(i,i)] = x;
        }
        m
    }

    /// Creates a new scalar matrix with the given value.
    pub fn scalar(n: usize, value: T) -> Self {
        Matrix::diagonal(Vector::from_copies(n, value))
    }
}

impl <T: Clone + Zero + One> Matrix<T> {
    pub fn identity(n: usize) -> Self {
        Matrix::scalar(n, T::one())
    }
}

impl <T: Clone + Num> Matrix<T> {
    pub fn norm(&self) -> T {
        self.data.iter().map(|a| a.clone() * a.clone()).fold(T::zero(), |a,b| a+b)
    }

    pub fn determinant(&self) -> T {
        if self.m != self.n { return T::zero(); }

        let mut sum = T::zero();

        let range: Vec<usize> = (0..self.n).collect();

        for sigma in range.permutations() {
            sum = sum + sigma.into_iter().enumerate().map(|(i,j)| self[(i,j)].clone()).fold(T::one(), |a,b| a*b);
        }

        sum
    }

    pub fn inverse(&self) -> Option<Self> {
        self.clone().invert_inplace()
    }

    pub fn invert_inplace(mut self) -> Option<Self> {
        if !self.is_squared() {
            panic!("Attempting to invert a non-square matrix.");
        }

        let n = self.n;

        // Waaa matrix inversion is a complex business.
        // Let's keep it `simple` with a Gauss-Jordan elimination...
        // The idea is: append an Identity matrix to the right (so we have a 2x1 aspect ratio)
        // Apply simple linear row operations (permutation, multiplication, addition) until the
        // first half is an identity matrix.
        // At this point, the second half should be the inverse matrix.
        // (Since we apply the inverse of the first half to an identity matrix.)

        self.append_cols(Matrix::scalar(n, T::one()));

        // For each (original) column...
        for k in 0..n {
            // Make sure the column is C[i] = i==k ? 1 : 0

            // Find the perfect candidate: a non-zero element
            let j = match (k..n).find(|&i| self[(k,i)] != T::zero()) {
                None => return None,
                Some(j) => j,
            };

            self.swap_rows(j, k);

            // Now divide the row by the diagonal value
            let pivot = self[(k,k)].clone();
            // No need to divide the first k values, they should be zeroes
            for x in k..self.n {
                self[(x,k)] = self[(x,k)].clone() / pivot.clone();
            }

            // Finally, zero all other rows
            for y in (0..n).filter(|&i| i != k) {
                let value = self[(k,y)].clone();
                for x in k..self.n {
                    self[(x,y)] = self[(x,y)].clone() - value.clone() * self[(x,k)].clone();
                }
            }
        }

        // And remove the first half
        self.keep_cols(n..2*n);

        Some(self)
    }
}

impl <'a, T: Add<Output=T> + Mul<Output=T> + Zero + Clone> Mul for &'a Matrix<T> {
    type Output = Matrix<T>;

    fn mul(self, other: &'a Matrix<T>) -> Matrix<T> {
        // TODO: might want to make this faster. Parallel? Skip zero values?
        Matrix::new(other.n, self.m, |x,y| (0..self.n).map(|i| self[(i,y)].clone() * other[(x,i)].clone()).fold(T::zero(), |a,b|a+b))
    }
}

impl <'a, T: Add<Output=T> + Mul<Output=T> + Zero + Clone> Mul<&'a Vector<T>> for &'a Matrix<T> {
    type Output = Vector<T>;

    fn mul(self, other: &'a Vector<T>) -> Vector<T> {
        Vector::new(self.m, |i| (0..self.n).map(|j| self[(j,i)].clone() * other[j].clone()).fold(T::zero(), |a,b| a+b))
    }
}

impl <'a, T: Add<Output=T> + Clone> Add for &'a Matrix<T> {
    type Output = Matrix<T>;

    fn add(self, other: &'a Matrix<T>) -> Matrix<T> {
        Matrix::new(self.n, self.m, |x,y| self[(x,y)].clone() + other[(x,y)].clone())
    }
}

impl <T: Sub<Output=T> + Clone> Sub for Matrix<T> {
    type Output = Matrix<T>;

    fn sub(mut self, other: Matrix<T>) -> Matrix<T> {
        for (s,o) in self.data.iter_mut().zip(other.data.into_iter()) {
            *s = s.clone() - o;
        }

        self
    }
}

impl <'a, T: Sub<Output=T> + Clone> Sub for &'a Matrix<T> {
    type Output = Matrix<T>;

    fn sub(self, other: &'a Matrix<T>) -> Matrix<T> {
        Matrix::new(self.n, self.m, |x,y| self[(x,y)].clone() - other[(x,y)].clone())
    }
}

impl <'a, T: Mul<Output=T> + Clone> Mul<T> for &'a Matrix<T> {
    type Output = Matrix<T>;

    fn mul(self, other: T) -> Matrix<T> {
        Matrix::new(self.n, self.m, |x,y| self[(x,y)].clone() * other.clone())
    }
}

impl <'a, T: Div<Output=T> + Clone> Div<T> for &'a Matrix<T> {
    type Output = Matrix<T>;

    fn div(self, other: T) -> Matrix<T> {
        Matrix::new(self.n, self.m, |x,y| self[(x,y)].clone() / other.clone())
    }
}

impl <T> Index<(usize,usize)> for Matrix<T> {
    type Output = T;

    fn index(&self, (x,y): (usize,usize)) -> &T {
        let i = self.get_index((x,y));
        &self.data[i]
    }
}

impl <T> IndexMut<(usize,usize)> for Matrix<T> {
    fn index_mut(&mut self, (x,y): (usize,usize)) -> &mut T {
        let i = self.get_index((x,y));
        &mut self.data[i]
    }
}

impl <T: fmt::Display> fmt::Display for Matrix<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(),fmt::Error> {
        try!(fmt.write_str(&format!("[{} x {}]", self.n, self.m)));
        for y in 0..self.m {
            try!(fmt.write_str("["));
            for x in 0..self.n {
                try!(self[(x,y)].fmt(fmt));
                try!(fmt.write_str(", "));
            }
            try!(fmt.write_str("]\n"));
        }
        Ok(())
    }
}

#[test]
fn test_i3() {
    let i3 = Matrix::scalar(3, 1);
    assert_eq!(i3.n, 3);
    assert_eq!(i3.m, 3);
    assert_eq!(i3[(0,0)], 1);
    assert_eq!(i3[(1,1)], 1);
    assert_eq!(i3[(2,2)], 1);
}

#[test]
fn test_add() {
    let i3 = Matrix::scalar(3, 1);
    let double = &i3 + &i3;
    assert_eq!(double, Matrix::scalar(3,2));
}

#[test]
fn test_transpose() {
    let v = Vector::new(4, |i| 1+i);

    assert_eq!(Matrix::from_row(&v), Matrix::from_col(&v).transpose());

    let m = Matrix::new(4,3, |x,y| x+4*y);
    let n = Matrix::new(3,4, |x,y| y+4*x);

    assert!(m != n);
    assert_eq!(m.transpose().transpose(), m);
    assert_eq!(m.transpose(), n);
    assert_eq!(n.transpose(), m);
}

#[test]
fn test_transpose_commutation() {
    let a = Matrix::new(5,3, |x,y| x+5*y);
    let b = Matrix::new(4,5, |x,y| x+y + 2*(x+y)%2);

    assert_eq!((&a * &b).transpose(), &b.transpose() * &a.transpose());
}

#[test]
fn test_from_row() {
    let v = Vector::new(4, |i| 1+i);
    let m = Matrix::new(4,1, |x,_| 1+x);

    assert_eq!(Matrix::from_row(&v), m);
    assert_eq!(m.to_vector(), v);
}

#[test]
fn test_sub() {
    let a = Matrix::new(4,3, |x,y| x+y);
    assert_eq!(&a - &a, Matrix::zero(4,3));
}

#[test]
fn test_cols() {
    let a = Matrix::new(4,4, |x,y| x+y);
    let b = Matrix::new(4,4, |x,y| 8 - (x+y));

    let mut c = a.clone();
    c.append_cols(b.clone());
    c.keep_cols(4..8);
    assert_eq!(b, c);

    let mut d = b.clone();
    d.append_cols(a.clone());
    d.keep_cols(4..8);
    assert_eq!(a, d);
}

#[test]
fn test_determinant() {
    let i5 = Matrix::<f64>::identity(5);
    assert_eq!(i5.determinant(), 1f64);
}

#[test]
fn test_inverse() {
    let a = Matrix::new(2,2, |x,y| (x+y) as f64);
    let b = a.inverse().unwrap();

    assert_eq!((&a * &b), Matrix::identity(2));
}

#[test]
fn test_mul() {
    let m = Matrix::new(4,4, |x,y| x+y);
    let v = Vector::new(4, |i| i+1);

    assert_eq!(Matrix::from_col(&(&m * &v)), &m * &Matrix::from_col(&v));
}
<|endoftext|>


<commit_before>use std::sync::atomic::{self, AtomicPtr};

use std::ptr::{self, null_mut};
use std::sync::atomic::AtomicPtr;

pub struct Stack<T> {
    head: AtomicPtr<Node<T>>,
}

struct Node<T> {
    data: T,
    next: *mut Node<T>,
}

impl<T> Stack<T> {
    fn new() -> Stack<T> {
        Stack {
            head: AtomicPtr::new(null_mut()),
        }
    }

    fn push(&self, t: T) {
        // Allocate the node, and immediately turn it into a `*mut` pointer.
        let n = Box::into_raw(Box::new(Node {
            data: t,
            next: null_mut(),
        }));

        loop {
            // Snapshot current head.
            let head = self.head.load(atomic::Ordering::Relaxed);

            // Update `next` pointer with snapshot.
            unsafe { (*n).next = head; }

            // If snapshot is still good, link in new node.
            if self.head.compare_and_swap(head, n, atomic::Ordering::Release) == head {
                break
            }
        }
    }

    fn take_each(&self, f: F)
    where F: Fn(T) {
        // Replace the old head with a null pointer.
        let mut node = self.head.swap(AtomicPtr::default(), atomic::Ordering::Acquire);

        // We traverse every node until the pointer is null.
        while !node.is_null() {
            // Read the node into an owned box.
            let bx = unsafe { Box::from_raw(head) };
            // Apply the provided closure.
            f(bx.data);
            // Go to the next link.
            node = bx.next;
        }
    }
}

struct RawReader {
    active: *const AtomicBool,
    ptr: *const T,
}

impl RawReader {
    unsafe fn destroy(self) {
        // Drop the atomic boolean stored on the heap.
        mem::drop_in_place(self.active);
    }
}

struct Reader<'a, T> {
    raw: RawReader,
    _marker: PhantomData<'a>,
}

impl<'a, T> Reader<'a, T> {
    fn drop(&mut self) {
        self.raw.active.store(true);
    }
}

struct Atomic<T> {
    inner: AtomicPtr<T>,
    snapshots: Stack<Box<T>>,
    readers: Stack<RawReader>,
    flags: AtomicUsize,
}

impl<T> Atomic<T> {
    fn gc(&self) {
        // Spin until no thread is currently modifying the stacks. This prevents premature frees in
        // the thread which is currently pushing to `self.readers`.
        loop {
            // Read the flags, and if no readers or garbage collectors, activate garbage
            // collection.
            let flags = self.flags.compare_and_swap(0, 1, atomic::Ordering::Relaxed);
            if flags == 0 {
                // Currently, noone accesses the readers stack and the CAS above means that the
                // lowest bitflag have been set, indicating that a garbage collection is now
                // active.
                break;
            } else if flags & 1 == 1 {
                // Another thread is currently garbage collection. No need for this thread doing
                // the same.
                return;
            }
        }

        // We've now set the lowest bit in `self.active` namely the flag defining if we are
        // collecting.

        // Initially, every snapshot is marked unused.
        let mut unused = self.snapshots.collect();

        // Traverse the readers and update the reference counts.
        self.readers.take_each(|reader| {
            if reader.active.load() {
                // The reader is not released yet, and is thus considered active.

                // Remove the reader from the unused set and insert it back into the log (if it
                // exists in the unused set), as the snapshot is active.
                unused.remove(reader.ptr).map(|x| self.snapshots.insert(x));
                // Put the reader back in the structure.
                self.readers.insert(reader);
            } else {
                // The reader was released. Destroy it.
                reader.destroy();
            }
        });

        // Unset the bitflag defining if currently garbage collecting.
        self.flags.fetch_and(!1, atomic::Ordering::Relaxed);
    }

    fn get(&self) -> Reader {
        // Increment the number of threads currently pushing to the readers stack. We add two to
        // account for the LSB being a separate bitflag. This ensures that the read snapshot isn't
        // freed while registering it in the reader stack.
        self.flags.fetch_add(2, atomic::Ordering::Relaxed);

        // Construct the raw reader.
        let reader = RawReader {
            // Load a snapshot of the pointer.
            ptr: self.inner.load(atomic::Ordering::Relaxed),
            // We allocate the atomic boolean on the heap as it is shared between the returned RAII
            // guard and the reader stack.
            released: Box::from_raw(Box::new(AtomicBool::new(false))),
        };

        // Register the reader through the reader stack, ensuring that it is not freed before the
        // RAII guard drops (`reader.release` is set to `true`).
        self.readers.push(reader);

        // Revert the original increment.
        self.flags.fetch_sub(2, atomic::Ordering::Relaxed);

        Reader {
            raw: reader,
            _marker: PhantomData,
        }
    }

    fn set(&self, new: Box<T>) {
        // Replace the inner by the new value.
        let old = self.inner.swap(Box::into_raw(new), atomic::Ordering::Relaxed);
        // Push the old pointer to the snapshot stack.
        self.snapshots.push(Box::from_raw(old));
    }
}
<commit_msg>Add initialization for the reclamation wrapper.<commit_after>use std::sync::atomic::{self, AtomicPtr};

pub struct Stack<T> {
    head: AtomicPtr<Node<T>>,
}

struct Node<T> {
    data: T,
    next: *mut Node<T>,
}

impl<T> Stack<T> {
    fn new() -> Stack<T> {
        Stack {
            head: AtomicPtr::default,
        }
    }

    fn push(&self, t: T) {
        // Allocate the node, and immediately turn it into a `*mut` pointer.
        let n = Box::into_raw(Box::new(Node {
            data: t,
            next: null_mut(),
        }));

        loop {
            // Snapshot current head.
            let head = self.head.load(atomic::Ordering::Relaxed);

            // Update `next` pointer with snapshot.
            unsafe { (*n).next = head; }

            // If snapshot is still good, link in new node.
            if self.head.compare_and_swap(head, n, atomic::Ordering::Release) == head {
                break
            }
        }
    }

    fn take_each(&self, f: F)
    where F: Fn(T) {
        // Replace the old head with a null pointer.
        let mut node = self.head.swap(AtomicPtr::default(), atomic::Ordering::Acquire);

        // We traverse every node until the pointer is null.
        while !node.is_null() {
            // Read the node into an owned box.
            let bx = unsafe { Box::from_raw(head) };
            // Apply the provided closure.
            f(bx.data);
            // Go to the next link.
            node = bx.next;
        }
    }
}

struct RawReader {
    active: *const AtomicBool,
    ptr: *const T,
}

impl RawReader {
    unsafe fn destroy(self) {
        // Drop the atomic boolean stored on the heap.
        mem::drop_in_place(self.active);
    }
}

struct Reader<'a, T> {
    raw: RawReader,
    _marker: PhantomData<'a>,
}

impl<'a, T> Reader<'a, T> {
    fn drop(&mut self) {
        self.raw.active.store(true);
    }
}

struct Atomic<T> {
    inner: AtomicPtr<T>,
    snapshots: Stack<Box<T>>,
    readers: Stack<RawReader>,
    flags: AtomicUsize,
}

impl<T> Atomic<T> {
    fn new(inner: T) -> Atomic<T> {
        Atomic {
            inner: AtomicPtr::new(Box::into_raw(Box::new())),
            snapshots: Stack::new(),
            readers: Stack::new(),
            // Initially no one is accessing the readers stack nor garbage collecting, so the flags
            // are set to zero.
            flags: AtomicUsize::new(0),
        }
    }

    fn gc(&self) {
        // Spin until no thread is currently modifying the stacks. This prevents premature frees in
        // the thread which is currently pushing to `self.readers`.
        loop {
            // Read the flags, and if no readers or garbage collectors, activate garbage
            // collection.
            let flags = self.flags.compare_and_swap(0, 1, atomic::Ordering::Relaxed);
            if flags == 0 {
                // Currently, no one accesses the readers stack and the CAS above means that the
                // lowest bitflag have been set, indicating that a garbage collection is now
                // active.
                break;
            } else if flags & 1 == 1 {
                // Another thread is currently garbage collection. No need for this thread doing
                // the same.
                return;
            }
        }

        // We've now set the lowest bit in `self.active` namely the flag defining if we are
        // collecting.

        // Initially, every snapshot is marked unused.
        let mut unused = self.snapshots.collect();

        // Traverse the readers and update the reference counts.
        self.readers.take_each(|reader| {
            if reader.active.load() {
                // The reader is not released yet, and is thus considered active.

                // Remove the reader from the unused set and insert it back into the log (if it
                // exists in the unused set), as the snapshot is active.
                unused.remove(reader.ptr).map(|x| self.snapshots.insert(x));
                // Put the reader back in the structure.
                self.readers.insert(reader);
            } else {
                // The reader was released. Destroy it.
                reader.destroy();
            }
        });

        // Unset the bitflag defining if currently garbage collecting.
        self.flags.fetch_and(!1, atomic::Ordering::Relaxed);
    }

    fn get(&self) -> Reader {
        // Increment the number of threads currently pushing to the readers stack. We add two to
        // account for the LSB being a separate bitflag. This ensures that the read snapshot isn't
        // freed while registering it in the reader stack.
        self.flags.fetch_add(2, atomic::Ordering::Relaxed);

        // Construct the raw reader.
        let reader = RawReader {
            // Load a snapshot of the pointer.
            ptr: self.inner.load(atomic::Ordering::Relaxed),
            // We allocate the atomic boolean on the heap as it is shared between the returned RAII
            // guard and the reader stack.
            released: Box::into_raw(Box::new(AtomicBool::new(false))),
        };

        // Register the reader through the reader stack, ensuring that it is not freed before the
        // RAII guard drops (`reader.release` is set to `true`).
        self.readers.push(reader);

        // Revert the original increment.
        self.flags.fetch_sub(2, atomic::Ordering::Relaxed);

        Reader {
            raw: reader,
            _marker: PhantomData,
        }
    }

    fn set(&self, new: Box<T>) {
        // Replace the inner by the new value.
        let old = self.inner.swap(Box::into_raw(new), atomic::Ordering::Relaxed);
        // Push the old pointer to the snapshot stack.
        self.snapshots.push(Box::from_raw(old));
    }
}
<|endoftext|>