<commit_before>use tournament;

#[test]
fn just_the_header_if_no_input() {
    let input = "";
    let expected = "Team                           | MP |  W |  D |  L |  P";

    assert_eq!(tournament::tally(&input), expected);
}

#[test]
#[ignore]
fn a_win_is_three_points_a_loss_is_zero_points() {
    let input = "Allegoric Alaskans;Blithering Badgers;win";
    let expected = "".to_string()
        + "Team                           | MP |  W |  D |  L |  P\n"
        + "Allegoric Alaskans             |  1 |  1 |  0 |  0 |  3\n"
        + "Blithering Badgers             |  1 |  0 |  0 |  1 |  0";

    assert_eq!(tournament::tally(&input), expected);
}

#[test]
#[ignore]
fn a_win_can_also_be_expressed_as_a_loss() {
    let input = "Blithering Badgers;Allegoric Alaskans;loss";
    let expected = "".to_string()
        + "Team                           | MP |  W |  D |  L |  P\n"
        + "Allegoric Alaskans             |  1 |  1 |  0 |  0 |  3\n"
        + "Blithering Badgers             |  1 |  0 |  0 |  1 |  0";

    assert_eq!(tournament::tally(&input), expected);
}

#[test]
#[ignore]
fn a_different_team_can_win() {
    let input = "Blithering Badgers;Allegoric Alaskans;win";
    let expected = "".to_string()
        + "Team                           | MP |  W |  D |  L |  P\n"
        + "Blithering Badgers             |  1 |  1 |  0 |  0 |  3\n"
        + "Allegoric Alaskans             |  1 |  0 |  0 |  1 |  0";

    assert_eq!(tournament::tally(&input), expected);
}

#[test]
#[ignore]
fn a_draw_is_one_point_each() {
    let input = "Allegoric Alaskans;Blithering Badgers;draw";
    let expected = "".to_string()
        + "Team                           | MP |  W |  D |  L |  P\n"
        + "Allegoric Alaskans             |  1 |  0 |  1 |  0 |  1\n"
        + "Blithering Badgers             |  1 |  0 |  1 |  0 |  1";

    assert_eq!(tournament::tally(&input), expected);
}

#[test]
#[ignore]
fn there_can_be_more_than_one_match() {
    let input = "Allegoric Alaskans;Blithering Badgers;win\n".to_string()
        + "Allegoric Alaskans;Blithering Badgers;win";
    let expected = "".to_string()
        + "Team                           | MP |  W |  D |  L |  P\n"
        + "Allegoric Alaskans             |  2 |  2 |  0 |  0 |  6\n"
        + "Blithering Badgers             |  2 |  0 |  0 |  2 |  0";

    assert_eq!(tournament::tally(&input), expected);
}

#[test]
#[ignore]
fn there_can_be_more_than_one_winner() {
    let input = "Allegoric Alaskans;Blithering Badgers;loss\n".to_string()
        + "Allegoric Alaskans;Blithering Badgers;win";
    let expected = "".to_string()
        + "Team                           | MP |  W |  D |  L |  P\n"
        + "Allegoric Alaskans             |  2 |  1 |  0 |  1 |  3\n"
        + "Blithering Badgers             |  2 |  1 |  0 |  1 |  3";

    assert_eq!(tournament::tally(&input), expected);
}

#[test]
#[ignore]
fn there_can_be_more_than_two_teams() {
    let input = "Allegoric Alaskans;Blithering Badgers;win\n".to_string()
        + "Blithering Badgers;Courageous Californians;win\n"
        + "Courageous Californians;Allegoric Alaskans;loss";
    let expected = "".to_string()
        + "Team                           | MP |  W |  D |  L |  P\n"
        + "Allegoric Alaskans             |  2 |  2 |  0 |  0 |  6\n"
        + "Blithering Badgers             |  2 |  1 |  0 |  1 |  3\n"
        + "Courageous Californians        |  2 |  0 |  0 |  2 |  0";

    assert_eq!(tournament::tally(&input), expected);
}

#[test]
#[ignore]
fn typical_input() {
    let input = "Allegoric Alaskans;Blithering Badgers;win\n".to_string()
        + "Devastating Donkeys;Courageous Californians;draw\n"
        + "Devastating Donkeys;Allegoric Alaskans;win\n"
        + "Courageous Californians;Blithering Badgers;loss\n"
        + "Blithering Badgers;Devastating Donkeys;loss\n"
        + "Allegoric Alaskans;Courageous Californians;win";
    let expected = "".to_string()
        + "Team                           | MP |  W |  D |  L |  P\n"
        + "Devastating Donkeys            |  3 |  2 |  1 |  0 |  7\n"
        + "Allegoric Alaskans             |  3 |  2 |  0 |  1 |  6\n"
        + "Blithering Badgers             |  3 |  1 |  0 |  2 |  3\n"
        + "Courageous Californians        |  3 |  0 |  1 |  2 |  1";

    assert_eq!(tournament::tally(&input), expected);
}

#[test]
#[ignore]
fn incomplete_competition_not_all_pairs_have_played() {
    let input = "Allegoric Alaskans;Blithering Badgers;loss\n".to_string()
        + "Devastating Donkeys;Allegoric Alaskans;loss\n"
        + "Courageous Californians;Blithering Badgers;draw\n"
        + "Allegoric Alaskans;Courageous Californians;win";
    let expected = "".to_string()
        + "Team                           | MP |  W |  D |  L |  P\n"
        + "Allegoric Alaskans             |  3 |  2 |  0 |  1 |  6\n"
        + "Blithering Badgers             |  2 |  1 |  1 |  0 |  4\n"
        + "Courageous Californians        |  2 |  0 |  1 |  1 |  1\n"
        + "Devastating Donkeys            |  1 |  0 |  0 |  1 |  0";

    assert_eq!(tournament::tally(&input), expected);
}

#[test]
#[ignore]
fn ties_broken_alphabetically() {
    let input = "Courageous Californians;Devastating Donkeys;win\n".to_string()
        + "Allegoric Alaskans;Blithering Badgers;win\n"
        + "Devastating Donkeys;Allegoric Alaskans;loss\n"
        + "Courageous Californians;Blithering Badgers;win\n"
        + "Blithering Badgers;Devastating Donkeys;draw\n"
        + "Allegoric Alaskans;Courageous Californians;draw";
    let expected = "".to_string()
        + "Team                           | MP |  W |  D |  L |  P\n"
        + "Allegoric Alaskans             |  3 |  2 |  1 |  0 |  7\n"
        + "Courageous Californians        |  3 |  2 |  1 |  0 |  7\n"
        + "Blithering Badgers             |  3 |  0 |  1 |  2 |  1\n"
        + "Devastating Donkeys            |  3 |  0 |  1 |  2 |  1";

    assert_eq!(tournament::tally(&input), expected);
}
<commit_msg>tournament: rework the 'a_draw_is_one_point_each' test to handle any ordering<commit_after>use tournament;

#[test]
fn just_the_header_if_no_input() {
    let input = "";
    let expected = "Team                           | MP |  W |  D |  L |  P";

    assert_eq!(tournament::tally(&input), expected);
}

#[test]
#[ignore]
fn a_win_is_three_points_a_loss_is_zero_points() {
    let input = "Allegoric Alaskans;Blithering Badgers;win";
    let expected = "".to_string()
        + "Team                           | MP |  W |  D |  L |  P\n"
        + "Allegoric Alaskans             |  1 |  1 |  0 |  0 |  3\n"
        + "Blithering Badgers             |  1 |  0 |  0 |  1 |  0";

    assert_eq!(tournament::tally(&input), expected);
}

#[test]
#[ignore]
fn a_win_can_also_be_expressed_as_a_loss() {
    let input = "Blithering Badgers;Allegoric Alaskans;loss";
    let expected = "".to_string()
        + "Team                           | MP |  W |  D |  L |  P\n"
        + "Allegoric Alaskans             |  1 |  1 |  0 |  0 |  3\n"
        + "Blithering Badgers             |  1 |  0 |  0 |  1 |  0";

    assert_eq!(tournament::tally(&input), expected);
}

#[test]
#[ignore]
fn a_different_team_can_win() {
    let input = "Blithering Badgers;Allegoric Alaskans;win";
    let expected = "".to_string()
        + "Team                           | MP |  W |  D |  L |  P\n"
        + "Blithering Badgers             |  1 |  1 |  0 |  0 |  3\n"
        + "Allegoric Alaskans             |  1 |  0 |  0 |  1 |  0";

    assert_eq!(tournament::tally(&input), expected);
}

#[test]
#[ignore]
fn there_can_be_more_than_one_match() {
    let input = "Allegoric Alaskans;Blithering Badgers;win\n".to_string()
        + "Allegoric Alaskans;Blithering Badgers;win";
    let expected = "".to_string()
        + "Team                           | MP |  W |  D |  L |  P\n"
        + "Allegoric Alaskans             |  2 |  2 |  0 |  0 |  6\n"
        + "Blithering Badgers             |  2 |  0 |  0 |  2 |  0";

    assert_eq!(tournament::tally(&input), expected);
}

#[test]
#[ignore]
fn a_draw_is_one_point_each() {
    let input = "Allegoric Alaskans;Blithering Badgers;draw\n".to_string()
        + "Allegoric Alaskans;Blithering Badgers;win";
    let expected = "".to_string()
        + "Team                           | MP |  W |  D |  L |  P\n"
        + "Allegoric Alaskans             |  2 |  1 |  1 |  0 |  4\n"
        + "Blithering Badgers             |  2 |  0 |  1 |  1 |  1";

    assert_eq!(tournament::tally(&input), expected);
}

#[test]
#[ignore]
fn there_can_be_more_than_one_winner() {
    let input = "Allegoric Alaskans;Blithering Badgers;loss\n".to_string()
        + "Allegoric Alaskans;Blithering Badgers;win";
    let expected = "".to_string()
        + "Team                           | MP |  W |  D |  L |  P\n"
        + "Allegoric Alaskans             |  2 |  1 |  0 |  1 |  3\n"
        + "Blithering Badgers             |  2 |  1 |  0 |  1 |  3";

    assert_eq!(tournament::tally(&input), expected);
}

#[test]
#[ignore]
fn there_can_be_more_than_two_teams() {
    let input = "Allegoric Alaskans;Blithering Badgers;win\n".to_string()
        + "Blithering Badgers;Courageous Californians;win\n"
        + "Courageous Californians;Allegoric Alaskans;loss";
    let expected = "".to_string()
        + "Team                           | MP |  W |  D |  L |  P\n"
        + "Allegoric Alaskans             |  2 |  2 |  0 |  0 |  6\n"
        + "Blithering Badgers             |  2 |  1 |  0 |  1 |  3\n"
        + "Courageous Californians        |  2 |  0 |  0 |  2 |  0";

    assert_eq!(tournament::tally(&input), expected);
}

#[test]
#[ignore]
fn typical_input() {
    let input = "Allegoric Alaskans;Blithering Badgers;win\n".to_string()
        + "Devastating Donkeys;Courageous Californians;draw\n"
        + "Devastating Donkeys;Allegoric Alaskans;win\n"
        + "Courageous Californians;Blithering Badgers;loss\n"
        + "Blithering Badgers;Devastating Donkeys;loss\n"
        + "Allegoric Alaskans;Courageous Californians;win";
    let expected = "".to_string()
        + "Team                           | MP |  W |  D |  L |  P\n"
        + "Devastating Donkeys            |  3 |  2 |  1 |  0 |  7\n"
        + "Allegoric Alaskans             |  3 |  2 |  0 |  1 |  6\n"
        + "Blithering Badgers             |  3 |  1 |  0 |  2 |  3\n"
        + "Courageous Californians        |  3 |  0 |  1 |  2 |  1";

    assert_eq!(tournament::tally(&input), expected);
}

#[test]
#[ignore]
fn incomplete_competition_not_all_pairs_have_played() {
    let input = "Allegoric Alaskans;Blithering Badgers;loss\n".to_string()
        + "Devastating Donkeys;Allegoric Alaskans;loss\n"
        + "Courageous Californians;Blithering Badgers;draw\n"
        + "Allegoric Alaskans;Courageous Californians;win";
    let expected = "".to_string()
        + "Team                           | MP |  W |  D |  L |  P\n"
        + "Allegoric Alaskans             |  3 |  2 |  0 |  1 |  6\n"
        + "Blithering Badgers             |  2 |  1 |  1 |  0 |  4\n"
        + "Courageous Californians        |  2 |  0 |  1 |  1 |  1\n"
        + "Devastating Donkeys            |  1 |  0 |  0 |  1 |  0";

    assert_eq!(tournament::tally(&input), expected);
}

#[test]
#[ignore]
fn ties_broken_alphabetically() {
    let input = "Courageous Californians;Devastating Donkeys;win\n".to_string()
        + "Allegoric Alaskans;Blithering Badgers;win\n"
        + "Devastating Donkeys;Allegoric Alaskans;loss\n"
        + "Courageous Californians;Blithering Badgers;win\n"
        + "Blithering Badgers;Devastating Donkeys;draw\n"
        + "Allegoric Alaskans;Courageous Californians;draw";
    let expected = "".to_string()
        + "Team                           | MP |  W |  D |  L |  P\n"
        + "Allegoric Alaskans             |  3 |  2 |  1 |  0 |  7\n"
        + "Courageous Californians        |  3 |  2 |  1 |  0 |  7\n"
        + "Blithering Badgers             |  3 |  0 |  1 |  2 |  1\n"
        + "Devastating Donkeys            |  3 |  0 |  1 |  2 |  1";

    assert_eq!(tournament::tally(&input), expected);
}
<|endoftext|>


<commit_before>use std::option::Option;

// use resources::Club;
// use resources::Gear;
use resources::enums::ResourceState;

use http;
use accesstoken::AccessToken;

use error::Result;
use api;

/// Athletes are Strava users, Strava users are athletes.
///
/// The object is returned in detailed, summary or meta representations.
///
/// See: http://strava.github.io/api/v3/athlete/
#[derive(RustcDecodable, Debug)]
pub struct Athlete {
    pub id: i32,
    pub resource_state: ResourceState,
    pub firstname: Option<String>,
    pub lastname: Option<String>,
    pub profile_medium: Option<String>,
    pub profile: Option<String>,
    pub city: Option<String>,
    pub state: Option<String>,
    pub country: Option<String>,
    pub sex: Option<String>,
    pub friend: Option<String>,
    pub follower: Option<String>,
    pub premium: Option<bool>,
    pub created_at: Option<String>,
    pub updated_at: Option<String>,
    pub approve_followers: Option<bool>,
    pub follower_count: Option<i32>,
    pub friend_count: Option<i32>,
    pub mutual_friend_count: Option<i32>,
    pub date_preference: Option<String>,
    pub measurement_preference: Option<String>,
    pub email: Option<String>,
    pub ftp: Option<i32>,
    pub weight: Option<f32>
    // pub clubs: Vec<Club>,
    // pub shoes: Vec<Gear>,
    // pub bikes: Vec<Gear>
}

/// Statistics for an athlete
///
/// This data is only retrieveable for the currently authenticated athlete. Values are in seconds
/// and meters.
///
/// http://strava.github.io/api/v3/athlete/#stats
#[derive(Debug, RustcDecodable)]
pub struct Stats {
    biggest_ride_distance: f32,
    biggest_climb_elevation_gain: f32,
    recent_ride_totals: RecentTotals,
    recent_run_totals: RecentTotals,
    ytd_ride_totals: Totals,
    ytd_run_totals: Totals,
    all_ride_totals: Totals,
    all_run_totals: Totals,
}

#[derive(Debug, RustcDecodable)]
pub struct RecentTotals {
    count: i32,
    distance: f32,
    moving_time: i32,
    elapsed_time: i32,
    elevation_gain: f32,
    achievement_count: i32
}

#[derive(Debug, RustcDecodable)]
pub struct Totals {
    count: i32,
    distance: i32,
    moving_time: i32,
    elapsed_time: i32,
    elevation_gain: i32
}

impl Athlete {
    pub fn get_current(token: &AccessToken) -> Result<Athlete> {
        let url = api::v3(token, "athlete".to_string());
        http::get::<Athlete>(&url[..])
    }

    pub fn get(token: &AccessToken, id: i32) -> Result<Athlete> {
        let url = api::v3(token, format!("athletes/{}", id));
        http::get::<Athlete>(&url[..])
    }

    pub fn stats(&self, token: &AccessToken) -> Result<Stats> {
        let url = api::v3(token, format!("athletes/{}/stats", self.id));
        http::get::<Stats>(&url[..])
    }
}

#[cfg(feature = "api_test")]
#[cfg(test)]
mod api_tests {
    use accesstoken::AccessToken;
    use super::Athlete;
    use resources::enums::ResourceState;
    use error::ApiError;

    #[test]
    fn get_current_athlete() {
        let token = AccessToken::new_from_env().unwrap();
        let athlete = Athlete::get_current(&token).unwrap();
        assert_eq!(athlete.resource_state, ResourceState::Detailed);
    }

    #[test]
    fn get_athlete_by_id() {
        let id = 1712082;
        let token = AccessToken::new_from_env().unwrap();
        let athlete = Athlete::get(&token, id).unwrap();
        println!("{:?}", athlete);
        assert_eq!(athlete.id, id);
    }

    #[test]
    #[allow(dead_code)]
    fn get_athlete_stats() {
        let token = AccessToken::new_from_env().unwrap();
        let athlete = Athlete::get_current(&token).unwrap();
        let stats = athlete.stats(&token).unwrap();

        println!("{:?}", stats);
    }

    #[test]
    fn get_other_athlete_stats() {
        let id = 1712082;
        let token = AccessToken::new_from_env().unwrap();
        let athlete = Athlete::get(&token, id).unwrap();
        match athlete.stats(&token) {
            Ok(_) => panic!("somehow got stats for other athlete"),
            Err(ApiError::InvalidAccessToken) => (),
            Err(e) => panic!("unexpected error type {:?}", e)
        }
    }
}
<commit_msg>Add support for getting current athlete koms<commit_after>use std::option::Option;

// use resources::Club;
// use resources::Gear;
use resources::enums::ResourceState;

use http;
use accesstoken::AccessToken;

use error::Result;
use api;
use segment;
use paginate::Paginated;

/// Athletes are Strava users, Strava users are athletes.
///
/// The object is returned in detailed, summary or meta representations.
///
/// See: http://strava.github.io/api/v3/athlete/
#[derive(RustcDecodable, Debug)]
pub struct Athlete {
    pub id: i32,
    pub resource_state: ResourceState,
    pub firstname: Option<String>,
    pub lastname: Option<String>,
    pub profile_medium: Option<String>,
    pub profile: Option<String>,
    pub city: Option<String>,
    pub state: Option<String>,
    pub country: Option<String>,
    pub sex: Option<String>,
    pub friend: Option<String>,
    pub follower: Option<String>,
    pub premium: Option<bool>,
    pub created_at: Option<String>,
    pub updated_at: Option<String>,
    pub approve_followers: Option<bool>,
    pub follower_count: Option<i32>,
    pub friend_count: Option<i32>,
    pub mutual_friend_count: Option<i32>,
    pub date_preference: Option<String>,
    pub measurement_preference: Option<String>,
    pub email: Option<String>,
    pub ftp: Option<i32>,
    pub weight: Option<f32>
    // pub clubs: Vec<Club>,
    // pub shoes: Vec<Gear>,
    // pub bikes: Vec<Gear>
}

/// Statistics for an athlete
///
/// This data is only retrieveable for the currently authenticated athlete. Values are in seconds
/// and meters.
///
/// http://strava.github.io/api/v3/athlete/#stats
#[derive(Debug, RustcDecodable)]
pub struct Stats {
    biggest_ride_distance: f32,
    biggest_climb_elevation_gain: f32,
    recent_ride_totals: RecentTotals,
    recent_run_totals: RecentTotals,
    ytd_ride_totals: Totals,
    ytd_run_totals: Totals,
    all_ride_totals: Totals,
    all_run_totals: Totals,
}

#[derive(Debug, RustcDecodable)]
pub struct RecentTotals {
    count: i32,
    distance: f32,
    moving_time: i32,
    elapsed_time: i32,
    elevation_gain: f32,
    achievement_count: i32
}

#[derive(Debug, RustcDecodable)]
pub struct Totals {
    count: i32,
    distance: i32,
    moving_time: i32,
    elapsed_time: i32,
    elevation_gain: i32
}

impl Athlete {
    pub fn get_current(token: &AccessToken) -> Result<Athlete> {
        let url = api::v3(token, "athlete".to_string());
        http::get::<Athlete>(&url[..])
    }

    pub fn get(token: &AccessToken, id: i32) -> Result<Athlete> {
        let url = api::v3(token, format!("athletes/{}", id));
        http::get::<Athlete>(&url[..])
    }

    pub fn stats(&self, token: &AccessToken) -> Result<Stats> {
        let url = api::v3(token, format!("athletes/{}/stats", self.id));
        http::get::<Stats>(&url[..])
    }

    pub fn koms(&self, token: &AccessToken) -> Result<Paginated<segment::Effort>> {
        let url = api::v3(token, format!("athletes/{}/koms", self.id));
        let efforts = try!(http::get::<Vec<segment::Effort>>(&url[..]));
        Ok(Paginated::new(url, efforts))
    }
}

#[cfg(feature = "api_test")]
#[cfg(test)]
mod api_tests {
    use accesstoken::AccessToken;
    use super::Athlete;
    use resources::enums::ResourceState;
    use error::ApiError;

    #[test]
    fn get_current_athlete() {
        let token = AccessToken::new_from_env().unwrap();
        let athlete = Athlete::get_current(&token).unwrap();
        assert_eq!(athlete.resource_state, ResourceState::Detailed);
    }

    #[test]
    fn get_athlete_by_id() {
        let id = 1712082;
        let token = AccessToken::new_from_env().unwrap();
        let athlete = Athlete::get(&token, id).unwrap();
        println!("{:?}", athlete);
        assert_eq!(athlete.id, id);
    }

    #[test]
    #[allow(dead_code)]
    fn get_athlete_stats() {
        let token = AccessToken::new_from_env().unwrap();
        let athlete = Athlete::get_current(&token).unwrap();
        let stats = athlete.stats(&token).unwrap();

        println!("{:?}", stats);
    }

    #[test]
    fn get_other_athlete_stats() {
        let id = 1712082;
        let token = AccessToken::new_from_env().unwrap();
        let athlete = Athlete::get(&token, id).unwrap();
        match athlete.stats(&token) {
            Ok(_) => panic!("somehow got stats for other athlete"),
            Err(ApiError::InvalidAccessToken) => (),
            Err(e) => panic!("unexpected error type {:?}", e)
        }
    }

    #[test]
    fn get_koms() {
        let token = AccessToken::new_from_env().unwrap();
        let athlete = Athlete::get_current(&token).unwrap();
        let koms = athlete.koms(&token).unwrap();
        println!("{:?}", koms);
    }
}
<|endoftext|>


<commit_before>use crate::{message::BasicReturnMessage, pinky_swear::Pinky, BasicProperties, Result};
use log::error;
use parking_lot::Mutex;
use std::{collections::VecDeque, sync::Arc};

#[derive(Clone, Debug, Default)]
pub(crate) struct ReturnedMessages {
    inner: Arc<Mutex<Inner>>,
}

impl ReturnedMessages {
    pub(crate) fn start_new_delivery(&self, message: BasicReturnMessage) {
        self.inner.lock().current_message = Some(message);
    }

    pub(crate) fn set_delivery_properties(&self, properties: BasicProperties) {
        if let Some(message) = self.inner.lock().current_message.as_mut() {
            message.delivery.properties = properties;
        }
    }

    pub(crate) fn new_delivery_complete(&self) {
        self.inner.lock().new_delivery_complete();
    }

    pub(crate) fn receive_delivery_content(&self, data: Vec<u8>) {
        if let Some(message) = self.inner.lock().current_message.as_mut() {
            message.delivery.data.extend(data);
        }
    }

    pub(crate) fn drain(&self) -> Vec<BasicReturnMessage> {
        self.inner.lock().messages.drain(..).collect()
    }

    pub(crate) fn register_pinky(&self, pinky: Pinky<Result<()>>) {
        self.inner.lock().pinkies.push_back(pinky);
    }
}

#[derive(Debug, Default)]
pub struct Inner {
    current_message: Option<BasicReturnMessage>,
    messages: Vec<BasicReturnMessage>,
    pinkies: VecDeque<Pinky<Result<()>>>,
}

impl Inner {
    fn new_delivery_complete(&mut self) {
        if let Some(message) = self.current_message.take() {
            error!("Server returned us a message: {:?}", message);
            self.messages.push(message);
            if let Some(pinky) = self.pinkies.pop_front() {
                pinky.swear(Ok(()));
            }
        }
    }
}
<commit_msg>fix basic-nack vs basic-return order handling<commit_after>use crate::{message::BasicReturnMessage, pinky_swear::Pinky, BasicProperties, Result};
use log::error;
use parking_lot::Mutex;
use std::{collections::VecDeque, sync::Arc};

#[derive(Clone, Debug, Default)]
pub(crate) struct ReturnedMessages {
    inner: Arc<Mutex<Inner>>,
}

impl ReturnedMessages {
    pub(crate) fn start_new_delivery(&self, message: BasicReturnMessage) {
        self.inner.lock().current_message = Some(message);
    }

    pub(crate) fn set_delivery_properties(&self, properties: BasicProperties) {
        if let Some(message) = self.inner.lock().current_message.as_mut() {
            message.delivery.properties = properties;
        }
    }

    pub(crate) fn new_delivery_complete(&self) {
        self.inner.lock().new_delivery_complete();
    }

    pub(crate) fn receive_delivery_content(&self, data: Vec<u8>) {
        if let Some(message) = self.inner.lock().current_message.as_mut() {
            message.delivery.data.extend(data);
        }
    }

    pub(crate) fn drain(&self) -> Vec<BasicReturnMessage> {
        self.inner.lock().messages.drain(..).collect()
    }

    pub(crate) fn register_pinky(&self, pinky: Pinky<Result<()>>) {
        self.inner.lock().register_pinky(pinky);
    }
}

#[derive(Debug, Default)]
pub struct Inner {
    current_message: Option<BasicReturnMessage>,
    waiting_messages: VecDeque<BasicReturnMessage>,
    messages: Vec<BasicReturnMessage>,
    pinkies: VecDeque<Pinky<Result<()>>>,
}

impl Inner {
    fn new_delivery_complete(&mut self) {
        if let Some(message) = self.current_message.take() {
            error!("Server returned us a message: {:?}", message);
            if let Some(pinky) = self.pinkies.pop_front() {
                self.notify(pinky, message);
            } else {
                self.waiting_messages.push_back(message);
            }
        }
    }

    fn register_pinky(&mut self, pinky: Pinky<Result<()>>) {
        if let Some(message) = self.waiting_messages.pop_front() {
            self.notify(pinky, message);
        } else {
            self.pinkies.push_back(pinky);
        }
    }

    fn notify(&mut self, pinky: Pinky<Result<()>>, message: BasicReturnMessage) {
        self.messages.push(message);
        pinky.swear(Ok(()));
    }
}
<|endoftext|>


<commit_before>use std::rc::Rc;
use parsers::{Parser, ParserCombinator, ParseResult};

pub type SliceParser<I,O> = Parser<I=[I], O=O>;

/// Create a parser that only recognizes the given literal value
pub fn lit<T: Eq + Clone>(l: T) -> LiteralParser<T> {
  LiteralParser{literal: l}
}

pub fn matcher<T: Clone, U, F: 'static + Fn(T) -> Option<U>>(f: F) -> MatchParser<T, U> {
  MatchParser{matcher: Rc::new(Box::new(f))}
}

//////////////////////// STRUCTS /////////////////////////////////////////////

/// A LiteralParser looks for an exact match of the given item at the beginning
// of the slice
#[derive(Clone)]
pub struct LiteralParser< T: Eq + Clone> {
  pub literal: T,
}

impl<T: Eq + Clone> Parser for LiteralParser< T> {
  type I = [T];
  type O = T;

  fn parse<'a>(&self, data: &'a [T]) -> ParseResult<&'a [T], T> {
    if data.len() < 1 {
      return Err(format!("ran out of data"))
    }
    if data[0] == self.literal {
      Ok((data[0].clone(), &data[1..]))
    } else {
      Err(format!("Literal mismatch"))
    }
  }
}

impl<T: Eq + Clone> ParserCombinator for LiteralParser<T>{}

pub struct MatchParser<T: Clone, U> {
  matcher: Rc<Box<Fn(T) -> Option<U>>>
}

impl<T: Clone, U> Parser for MatchParser<T,U> {
  type I = [T];
  type O = U;

  fn parse<'a>(&self, data: &'a [T]) -> ParseResult<&'a [T], Self::O> {
    if data.len() < 1 {
      return Err(format!("ran out of data"))
    }
    match (self.matcher)(data[0].clone()) {
      Some(u) => Ok((u, &data[1..])),
      None    => Err(format!("Match failed"))
    }
  }
}

impl<T: Clone, U> ParserCombinator for MatchParser<T,U> {}

impl<T: Clone, U> Clone for MatchParser<T,U> {

  fn clone(&self) -> Self {
    MatchParser{matcher: self.matcher.clone()}
  }

}

<commit_msg>unboxing matcher closure<commit_after>use std::rc::Rc;
use std::marker::PhantomData;
use parsers::{Parser, ParserCombinator, ParseResult};

pub type SliceParser<I,O> = Parser<I=[I], O=O>;

/// Create a parser that only recognizes the given literal value
pub fn lit<T: Eq + Clone>(l: T) -> LiteralParser<T> {
  LiteralParser{literal: l}
}

pub fn matcher<T: Clone, U, F: 'static + Fn(T) -> Option<U>>(f: F) -> MatchParser<T, U, F> {
  MatchParser{matcher: Rc::new(f), _marker: PhantomData}
}

//////////////////////// STRUCTS /////////////////////////////////////////////

/// A LiteralParser looks for an exact match of the given item at the beginning
// of the slice
#[derive(Clone)]
pub struct LiteralParser< T: Eq + Clone> {
  pub literal: T,
}

impl<T: Eq + Clone> Parser for LiteralParser< T> {
  type I = [T];
  type O = T;

  fn parse<'a>(&self, data: &'a [T]) -> ParseResult<&'a [T], T> {
    if data.len() < 1 {
      return Err(format!("ran out of data"))
    }
    if data[0] == self.literal {
      Ok((data[0].clone(), &data[1..]))
    } else {
      Err(format!("Literal mismatch"))
    }
  }
}

impl<T: Eq + Clone> ParserCombinator for LiteralParser<T>{}

pub struct MatchParser<T: Clone, U, F: Fn(T) -> Option<U>> {
  matcher: Rc<F>,
  _marker: PhantomData<T>
}

impl<T: Clone, U, F: Fn(T) -> Option<U>> Parser for MatchParser<T,U, F> {
  type I = [T];
  type O = U;

  fn parse<'a>(&self, data: &'a [T]) -> ParseResult<&'a [T], Self::O> {
    if data.len() < 1 {
      return Err(format!("ran out of data"))
    }
    match (self.matcher)(data[0].clone()) {
      Some(u) => Ok((u, &data[1..])),
      None    => Err(format!("Match failed"))
    }
  }
}

impl<T: Clone, U, F: Fn(T) -> Option<U>> ParserCombinator for MatchParser<T,U, F> {}

impl<T: Clone, U, F: Fn(T) -> Option<U>> Clone for MatchParser<T,U, F> {

  fn clone(&self) -> Self {
    MatchParser{matcher: self.matcher.clone(), _marker: PhantomData}
  }

}

<|endoftext|>


<commit_before>use std::ptr;
use libc::{c_int};
use glib::Error;
use glib::ffi::{GObject};
use glib::object::{Wrapper, Ref};
use glib::types::{StaticType, Type};
use glib::translate::*;
use glib::glib_container::GlibContainer;
use secret_service::SecretService;
use secret_item::SecretItem;
use SecretResult;
use ffi;

pub struct SecretCollection(Ref);

impl SecretCollection {

    /// Lookup which collection is assigned to this alias.
    /// Aliases help determine well known collections, such as 'default'.
    /// Returns the collection, or NULL if none assigned to the alias.
    pub fn for_alias(alias: &str) -> SecretResult<SecretCollection>{
        let mut err = ptr::null_mut();
        let ptr = unsafe{ffi::secret_collection_for_alias_sync(ptr::null_mut(), alias.to_glib_none().0, SECRET_COLLECTION_LOAD_ITEMS, ptr::null_mut(), &mut err)};
        if err.is_null(){
            Ok(SecretCollection(Ref::from_glib_none(ptr as *mut GObject)))
        } else {
            Err(Error::wrap(err))
        }
    }

    /// Create a new collection in the secret service.
    /// If you specify an alias and a collection with that alias already exists, then a new collection will not be created. The previous one will be returned instead.
    /// Returns the created Collection.
    pub fn create(label: &str, alias: Option<&str>) -> SecretResult<SecretCollection> {
        let mut err = ptr::null_mut();
        let ptr = unsafe{ffi::secret_collection_create_sync(ptr::null_mut(), label.to_glib_none().0, alias.to_glib_none().0, 0 as c_int, ptr::null_mut(), &mut err)};
        if err.is_null(){
            Ok(SecretCollection(Ref::from_glib_none(ptr as *mut GObject)))
        } else {
            Err(Error::wrap(err))
        }
    }

    /// Get the created date and time of the collection.
    /// The return value is the number of seconds since the unix epoch, January 1st 1970.
    pub fn get_created(&self) -> u64 {
        unsafe {ffi::secret_collection_get_created(self.raw())}
    }

    /// Get the modified date and time of the collection.
    /// The return value is the number of seconds since the unix epoch, January 1st 1970.
    pub fn get_modified(&self) -> u64 {
        unsafe {ffi::secret_collection_get_modified(self.raw())}
    }

    /// Get the Secret Service object that this collection was created with.
    pub fn get_service(&self) -> SecretService { //TODO find out if this can return null
        unsafe {
            let ptr = ffi::secret_collection_get_service(self.raw());
            SecretService::wrap(Ref::from_glib_none(ptr as *mut GObject))
        }
    }

    pub fn are_items_loaded(&self) -> bool {
        let flags = unsafe {ffi::secret_collection_get_flags(self.raw())};
        flags & SECRET_COLLECTION_LOAD_ITEMS != 0
    }

    /// Get the label of this collection.
    pub fn get_label(&self) -> String {
        unsafe{
            let ptr = ffi::secret_collection_get_label(self.raw());
            FromGlibPtr::from_glib_none(ptr)
        }
    }

    /// Get whether the collection is locked or not.
    pub fn get_locked(&self) -> bool {
        let gbool = unsafe{ffi::secret_collection_get_locked(self.raw())};
        FromGlib::from_glib(gbool)
    }

    /// Returns None, if the items have not yet been loaded.
    pub fn get_items(&self) -> Option<Vec<SecretItem>> {
        unsafe {
            let glist = ffi::secret_collection_get_items(self.raw());
            if glist.is_null(){
                None
            } else {
                Some(FromGlibPtrContainer::from_glib_none(glist))
            }
        }

    }

    #[inline]
    fn raw(&self) -> *mut ffi::SecretCollectionFFI {
        self.0.to_glib_none() as *mut ffi::SecretCollectionFFI
    }

    /// Ensure that the SecretCollection proxy has loaded all the items present in the Secret Service.
    pub fn load_items(&self) -> SecretResult<()>{
        unsafe {
            let mut err = ptr::null_mut();
            ffi::secret_collection_load_items_sync(self.raw(), ptr::null_mut(), &mut err);
            if err.is_null() {
                Ok(())
            } else {
                Err(Error::wrap(err))
            }
        }
    }

    //TODO set_alias from ss
}

impl StaticType for SecretCollection {
    fn static_type() -> Type{
        unsafe { from_glib(ffi::secret_collection_get_type()) }
    }
}

impl Wrapper for SecretCollection {
    type GlibType = ffi::SecretCollectionFFI;
    unsafe fn wrap(r: Ref) -> Self{
        SecretCollection(r)
    }

    fn as_ref(&self) -> &Ref{
        &self.0
    }

    fn unwrap(self) -> Ref{
        self.0
    }
}

#[allow(dead_code)]
const SECRET_COLLECTION_NONE: i32        = 0;
const SECRET_COLLECTION_LOAD_ITEMS: i32  = 1 << 1;
<commit_msg>Remove the raw method and use ToGlibPtr directly<commit_after>use std::ptr;
use libc::{c_int};
use glib::Error;
use glib::ffi::{GObject};
use glib::object::{Wrapper, Ref};
use glib::types::{StaticType, Type};
use glib::translate::*;
use glib::glib_container::GlibContainer;
use secret_service::SecretService;
use secret_item::SecretItem;
use SecretResult;
use ffi;

pub struct SecretCollection(Ref);

impl SecretCollection {

    /// Lookup which collection is assigned to this alias.
    /// Aliases help determine well known collections, such as 'default'.
    /// Returns the collection, or NULL if none assigned to the alias.
    pub fn for_alias(alias: &str) -> SecretResult<SecretCollection>{
        let mut err = ptr::null_mut();
        let ptr = unsafe{ffi::secret_collection_for_alias_sync(ptr::null_mut(), alias.to_glib_none().0, SECRET_COLLECTION_LOAD_ITEMS, ptr::null_mut(), &mut err)};
        if err.is_null(){
            Ok(SecretCollection(Ref::from_glib_none(ptr as *mut GObject)))
        } else {
            Err(Error::wrap(err))
        }
    }

    /// Create a new collection in the secret service.
    /// If you specify an alias and a collection with that alias already exists, then a new collection will not be created. The previous one will be returned instead.
    /// Returns the created Collection.
    pub fn create(label: &str, alias: Option<&str>) -> SecretResult<SecretCollection> {
        let mut err = ptr::null_mut();
        let ptr = unsafe{ffi::secret_collection_create_sync(ptr::null_mut(), label.to_glib_none().0, alias.to_glib_none().0, 0 as c_int, ptr::null_mut(), &mut err)};
        if err.is_null(){
            Ok(SecretCollection(Ref::from_glib_none(ptr as *mut GObject)))
        } else {
            Err(Error::wrap(err))
        }
    }

    /// Get the created date and time of the collection.
    /// The return value is the number of seconds since the unix epoch, January 1st 1970.
    pub fn get_created(&self) -> u64 {
        unsafe {ffi::secret_collection_get_created(self.to_glib_none().0)}
    }

    /// Get the modified date and time of the collection.
    /// The return value is the number of seconds since the unix epoch, January 1st 1970.
    pub fn get_modified(&self) -> u64 {
        unsafe {ffi::secret_collection_get_modified(self.to_glib_none().0)}
    }

    /// Get the Secret Service object that this collection was created with.
    pub fn get_service(&self) -> SecretService { //TODO find out if this can return null
        unsafe {
            let ptr = ffi::secret_collection_get_service(self.to_glib_none().0);
            SecretService::wrap(Ref::from_glib_none(ptr as *mut GObject))
        }
    }

    pub fn are_items_loaded(&self) -> bool {
        let flags = unsafe {ffi::secret_collection_get_flags(self.to_glib_none().0)};
        flags & SECRET_COLLECTION_LOAD_ITEMS != 0
    }

    /// Get the label of this collection.
    pub fn get_label(&self) -> String {
        unsafe{
            let ptr = ffi::secret_collection_get_label(self.to_glib_none().0);
            FromGlibPtr::from_glib_none(ptr)
        }
    }

    /// Get whether the collection is locked or not.
    pub fn get_locked(&self) -> bool {
        let gbool = unsafe{ffi::secret_collection_get_locked(self.to_glib_none().0)};
        FromGlib::from_glib(gbool)
    }

    /// Returns None, if the items have not yet been loaded.
    pub fn get_items(&self) -> Option<Vec<SecretItem>> {
        unsafe {
            let glist = ffi::secret_collection_get_items(self.to_glib_none().0);
            if glist.is_null(){
                None
            } else {
                Some(FromGlibPtrContainer::from_glib_none(glist))
            }
        }

    }

    /// Ensure that the SecretCollection proxy has loaded all the items present in the Secret Service.
    pub fn load_items(&self) -> SecretResult<()>{
        unsafe {
            let mut err = ptr::null_mut();
            ffi::secret_collection_load_items_sync(self.to_glib_none().0, ptr::null_mut(), &mut err);
            if err.is_null() {
                Ok(())
            } else {
                Err(Error::wrap(err))
            }
        }
    }

    //TODO set_alias from ss
}

impl StaticType for SecretCollection {
    fn static_type() -> Type{
        unsafe { from_glib(ffi::secret_collection_get_type()) }
    }
}

impl Wrapper for SecretCollection {
    type GlibType = ffi::SecretCollectionFFI;
    unsafe fn wrap(r: Ref) -> Self{
        SecretCollection(r)
    }

    fn as_ref(&self) -> &Ref{
        &self.0
    }

    fn unwrap(self) -> Ref{
        self.0
    }
}

#[allow(dead_code)]
const SECRET_COLLECTION_NONE: i32        = 0;
const SECRET_COLLECTION_LOAD_ITEMS: i32  = 1 << 1;
<|endoftext|>


<commit_before>// run-rustfix

#![warn(clippy::toplevel_ref_arg)]
#![allow(unused)]

fn main() {
    // Closures should not warn
    let y = |ref x| println!("{:?}", x);
    y(1u8);

    let ref x = 1;

    let ref y: (&_, u8) = (&1, 2);

    let ref z = 1 + 2;

    let ref mut z = 1 + 2;

    let (ref x, _) = (1, 2); // ok, not top level
    println!("The answer is {}.", x);

    // Make sure that allowing the lint works
    #[allow(clippy::toplevel_ref_arg)]
    let ref mut x = 1_234_543;
}
<commit_msg>Add regression test for macro expansion<commit_after>// run-rustfix

#![warn(clippy::toplevel_ref_arg)]
#![allow(unused)]

fn main() {
    // Closures should not warn
    let y = |ref x| println!("{:?}", x);
    y(1u8);

    let ref x = 1;

    let ref y: (&_, u8) = (&1, 2);

    let ref z = 1 + 2;

    let ref mut z = 1 + 2;

    let (ref x, _) = (1, 2); // ok, not top level
    println!("The answer is {}.", x);

    let ref x = vec![1, 2, 3];

    // Make sure that allowing the lint works
    #[allow(clippy::toplevel_ref_arg)]
    let ref mut x = 1_234_543;
}
<|endoftext|>


<commit_before>// Edge Operation Genome

use evo::prob::{Probability, ProbabilityValue};
use evo::crossover::linear_2point_crossover_random;
use evo::nsga2::Mate;
use rand::Rng;
use rand::distributions::{IndependentSample, Weighted};
use petgraph::{Directed, Graph};
use petgraph::graph::NodeIndex;
use graph_edge_evolution::{EdgeOperation, GraphBuilder};
use owned_weighted_choice::OwnedWeightedChoice;
use std::str::FromStr;

#[derive(Clone, Debug)]
pub struct EdgeOpsGenome {
    edge_ops: Vec<EdgeOperation<f32, ()>>,
}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Op {
    Dup,
    Split,
    Loop,
    Merge,
    Next,
    Parent,
    Reverse,
    Save,
    Restore,
}

impl FromStr for Op {
   type Err = String;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "Dup" => Ok(Op::Dup),
            "Split" => Ok(Op::Split),
            "Loop" => Ok(Op::Loop),
            "Merge" => Ok(Op::Merge),
            "Next" => Ok(Op::Next),
            "Parent" => Ok(Op::Parent),
            "Reverse" => Ok(Op::Reverse),
            "Save" => Ok(Op::Save),
            "Restore" => Ok(Op::Restore),
            _ => Err(format!("Invalid opcode: {}", s)),
        }
    }
}

pub struct Toolbox {
    weighted_op_choice: OwnedWeightedChoice<Op>,
    prob_mutate_elem: Probability,
}

impl Mate<EdgeOpsGenome> for Toolbox {
    fn mate<R: Rng>(&mut self,
                    rng: &mut R,
                    p1: &EdgeOpsGenome,
                    p2: &EdgeOpsGenome)
                    -> EdgeOpsGenome {

        let mut child = EdgeOpsGenome {
            edge_ops: linear_2point_crossover_random(rng, &p1.edge_ops[..], &p2.edge_ops[..]),
        };
        self.mutate(rng, &mut child);
        child
    }
}

#[test]
fn test_parse_weighted_op_choice_list() {
    assert_eq!(Ok(vec![]), Toolbox::parse_weighted_op_choice_list(""));
    assert_eq!(Ok(vec![(Op::Dup, 1)]),
               Toolbox::parse_weighted_op_choice_list("Dup"));
    assert_eq!(Ok(vec![(Op::Dup, 1)]),
               Toolbox::parse_weighted_op_choice_list("Dup:1"));
    assert_eq!(Ok(vec![(Op::Dup, 2)]),
               Toolbox::parse_weighted_op_choice_list("Dup:2"));
    assert_eq!(Ok(vec![(Op::Dup, 2), (Op::Split, 1)]),
               Toolbox::parse_weighted_op_choice_list("Dup:2,Split"));
    assert_eq!(Err("Invalid weight: ".to_string()),
               Toolbox::parse_weighted_op_choice_list("Dup:2,Split:"));
    assert_eq!(Err("Invalid weight: a".to_string()),
               Toolbox::parse_weighted_op_choice_list("Dup:2,Split:a"));
    assert_eq!(Err("Invalid opcode: dup".to_string()),
               Toolbox::parse_weighted_op_choice_list("dup:2,Split:a"));
}

impl Toolbox {
    pub fn mutate<R: Rng>(&self, rng: &mut R, ind: &mut EdgeOpsGenome) {
        for edge_op in ind.edge_ops.iter_mut() {
            if rng.gen::<ProbabilityValue>().is_probable_with(self.prob_mutate_elem) {
                let new_edge_op = match edge_op {
                    &mut EdgeOperation::Merge{..} => {
                        EdgeOperation::Merge { n: rng.gen::<u32>() }
                    }
                    &mut EdgeOperation::Next{..} => {
                        EdgeOperation::Next { n: rng.gen::<u32>() }
                    }
                    &mut EdgeOperation::Parent{..} => {
                        EdgeOperation::Parent { n: rng.gen::<u32>() }
                    }
                    ref op => {
                        (*op).clone()
                    }
                };

                *edge_op = new_edge_op;
            }
        }
    }

    pub fn parse_weighted_op_choice_list(s: &str) -> Result<Vec<(Op, u32)>, String> {
        let mut v = Vec::new();
        for opstr in s.split(",") {
            if opstr.is_empty() {
                continue;
            }
            let mut i = opstr.splitn(2, ":");
            if let Some(ops) = i.next() {
                match Op::from_str(ops) {
                    Ok(op) => {
                        let ws = i.next().unwrap_or("1");
                        if let Ok(weight) = u32::from_str(ws) {
                            v.push((op, weight));
                        } else {
                            return Err(format!("Invalid weight: {}", ws));
                        }
                    }
                    Err(s) => {
                        return Err(s);
                    }
                }
            } else {
                return Err("missing op".to_string());
            }
        }
        return Ok(v);
    }

    pub fn new(prob_mutate_elem: Probability, weighted_op_choices: &[(Op, u32)]) -> Toolbox {
        let mut w = Vec::new();
        for &(op, weight) in weighted_op_choices {
            if weight > 0 {
                // an operation with weight=0 cannot be selected
                w.push(Weighted {
                    weight: weight,
                    item: op,
                });
            }
        }
        Toolbox {
            prob_mutate_elem: prob_mutate_elem,
            weighted_op_choice: OwnedWeightedChoice::new(w),
        }
    }

    fn generate_random_edge_operation<R: Rng>(&self, rng: &mut R) -> EdgeOperation<f32, ()> {
        match self.weighted_op_choice.ind_sample(rng) {
            Op::Dup => {
                EdgeOperation::Duplicate { weight: 0.0 }
            }
            Op::Split => {
                EdgeOperation::Split { weight: 0.0 }
            }
            Op::Loop => {
                EdgeOperation::Loop { weight: 0.0 }
            }
            Op::Merge => {
                EdgeOperation::Merge { n: rng.gen::<u32>() }
            }
            Op::Next => {
                EdgeOperation::Next { n: rng.gen::<u32>() }
            }
            Op::Parent => {
                EdgeOperation::Parent { n: rng.gen::<u32>() }
            }
            Op::Reverse => {
                EdgeOperation::Reverse
            }
            Op::Save => {
                EdgeOperation::Save
            }
            Op::Restore => {
                EdgeOperation::Restore
            }
        }
    }

    pub fn random_genome<R: Rng>(&self, rng: &mut R, len: usize) -> EdgeOpsGenome {
        let edge_ops: Vec<_> = (0..len)
                                   .map(|_| self.generate_random_edge_operation(rng))
                                   .collect();

        EdgeOpsGenome { edge_ops: edge_ops }
    }
}

impl EdgeOpsGenome {
    pub fn len(&self) -> usize {
        self.edge_ops.len()
    }

    pub fn to_graph(&self) -> Graph<(), (), Directed, u32> {
        let mut builder = GraphBuilder::new();
        for op in self.edge_ops.iter() {
            builder.apply_operation(op.clone());
        }
        let edge_list = builder.to_edge_list();

        let mut g: Graph<(), (), Directed, u32> = Graph::new();
        let n = edge_list.len();
        for _ in 0..n {
            let _ = g.add_node(());
        }

        for (i, node) in edge_list.iter().enumerate() {
            for &(j, _weight) in node.iter() {
                g.add_edge(NodeIndex::new(i), NodeIndex::new(j), ());
            }
        }

        return g;
    }
}
<commit_msg>Reorder code<commit_after>// Edge Operation Genome

use evo::prob::{Probability, ProbabilityValue};
use evo::crossover::linear_2point_crossover_random;
use evo::nsga2::Mate;
use rand::Rng;
use rand::distributions::{IndependentSample, Weighted};
use petgraph::{Directed, Graph};
use petgraph::graph::NodeIndex;
use graph_edge_evolution::{EdgeOperation, GraphBuilder};
use owned_weighted_choice::OwnedWeightedChoice;
use std::str::FromStr;

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Op {
    Dup,
    Split,
    Loop,
    Merge,
    Next,
    Parent,
    Reverse,
    Save,
    Restore,
}

impl FromStr for Op {
   type Err = String;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "Dup" => Ok(Op::Dup),
            "Split" => Ok(Op::Split),
            "Loop" => Ok(Op::Loop),
            "Merge" => Ok(Op::Merge),
            "Next" => Ok(Op::Next),
            "Parent" => Ok(Op::Parent),
            "Reverse" => Ok(Op::Reverse),
            "Save" => Ok(Op::Save),
            "Restore" => Ok(Op::Restore),
            _ => Err(format!("Invalid opcode: {}", s)),
        }
    }
}

#[derive(Clone, Debug)]
pub struct EdgeOpsGenome {
    edge_ops: Vec<EdgeOperation<f32, ()>>,
}

pub struct Toolbox {
    weighted_op_choice: OwnedWeightedChoice<Op>,
    prob_mutate_elem: Probability,
}

impl Mate<EdgeOpsGenome> for Toolbox {
    fn mate<R: Rng>(&mut self,
                    rng: &mut R,
                    p1: &EdgeOpsGenome,
                    p2: &EdgeOpsGenome)
                    -> EdgeOpsGenome {

        let mut child = EdgeOpsGenome {
            edge_ops: linear_2point_crossover_random(rng, &p1.edge_ops[..], &p2.edge_ops[..]),
        };
        self.mutate(rng, &mut child);
        child
    }
}

impl Toolbox {
    pub fn mutate<R: Rng>(&self, rng: &mut R, ind: &mut EdgeOpsGenome) {
        for edge_op in ind.edge_ops.iter_mut() {
            if rng.gen::<ProbabilityValue>().is_probable_with(self.prob_mutate_elem) {
                let new_edge_op = match edge_op {
                    &mut EdgeOperation::Merge{..} => {
                        EdgeOperation::Merge { n: rng.gen::<u32>() }
                    }
                    &mut EdgeOperation::Next{..} => {
                        EdgeOperation::Next { n: rng.gen::<u32>() }
                    }
                    &mut EdgeOperation::Parent{..} => {
                        EdgeOperation::Parent { n: rng.gen::<u32>() }
                    }
                    ref op => {
                        (*op).clone()
                    }
                };

                *edge_op = new_edge_op;
            }
        }
    }

    pub fn parse_weighted_op_choice_list(s: &str) -> Result<Vec<(Op, u32)>, String> {
        let mut v = Vec::new();
        for opstr in s.split(",") {
            if opstr.is_empty() {
                continue;
            }
            let mut i = opstr.splitn(2, ":");
            if let Some(ops) = i.next() {
                match Op::from_str(ops) {
                    Ok(op) => {
                        let ws = i.next().unwrap_or("1");
                        if let Ok(weight) = u32::from_str(ws) {
                            v.push((op, weight));
                        } else {
                            return Err(format!("Invalid weight: {}", ws));
                        }
                    }
                    Err(s) => {
                        return Err(s);
                    }
                }
            } else {
                return Err("missing op".to_string());
            }
        }
        return Ok(v);
    }

    pub fn new(prob_mutate_elem: Probability, weighted_op_choices: &[(Op, u32)]) -> Toolbox {
        let mut w = Vec::new();
        for &(op, weight) in weighted_op_choices {
            if weight > 0 {
                // an operation with weight=0 cannot be selected
                w.push(Weighted {
                    weight: weight,
                    item: op,
                });
            }
        }
        Toolbox {
            prob_mutate_elem: prob_mutate_elem,
            weighted_op_choice: OwnedWeightedChoice::new(w),
        }
    }

    fn generate_random_edge_operation<R: Rng>(&self, rng: &mut R) -> EdgeOperation<f32, ()> {
        match self.weighted_op_choice.ind_sample(rng) {
            Op::Dup => {
                EdgeOperation::Duplicate { weight: 0.0 }
            }
            Op::Split => {
                EdgeOperation::Split { weight: 0.0 }
            }
            Op::Loop => {
                EdgeOperation::Loop { weight: 0.0 }
            }
            Op::Merge => {
                EdgeOperation::Merge { n: rng.gen::<u32>() }
            }
            Op::Next => {
                EdgeOperation::Next { n: rng.gen::<u32>() }
            }
            Op::Parent => {
                EdgeOperation::Parent { n: rng.gen::<u32>() }
            }
            Op::Reverse => {
                EdgeOperation::Reverse
            }
            Op::Save => {
                EdgeOperation::Save
            }
            Op::Restore => {
                EdgeOperation::Restore
            }
        }
    }

    pub fn random_genome<R: Rng>(&self, rng: &mut R, len: usize) -> EdgeOpsGenome {
        let edge_ops: Vec<_> = (0..len)
                                   .map(|_| self.generate_random_edge_operation(rng))
                                   .collect();

        EdgeOpsGenome { edge_ops: edge_ops }
    }
}

impl EdgeOpsGenome {
    pub fn len(&self) -> usize {
        self.edge_ops.len()
    }

    pub fn to_graph(&self) -> Graph<(), (), Directed, u32> {
        let mut builder = GraphBuilder::new();
        for op in self.edge_ops.iter() {
            builder.apply_operation(op.clone());
        }
        let edge_list = builder.to_edge_list();

        let mut g: Graph<(), (), Directed, u32> = Graph::new();
        let n = edge_list.len();
        for _ in 0..n {
            let _ = g.add_node(());
        }

        for (i, node) in edge_list.iter().enumerate() {
            for &(j, _weight) in node.iter() {
                g.add_edge(NodeIndex::new(i), NodeIndex::new(j), ());
            }
        }

        return g;
    }
}

#[test]
fn test_parse_weighted_op_choice_list() {
    assert_eq!(Ok(vec![]), Toolbox::parse_weighted_op_choice_list(""));
    assert_eq!(Ok(vec![(Op::Dup, 1)]),
               Toolbox::parse_weighted_op_choice_list("Dup"));
    assert_eq!(Ok(vec![(Op::Dup, 1)]),
               Toolbox::parse_weighted_op_choice_list("Dup:1"));
    assert_eq!(Ok(vec![(Op::Dup, 2)]),
               Toolbox::parse_weighted_op_choice_list("Dup:2"));
    assert_eq!(Ok(vec![(Op::Dup, 2), (Op::Split, 1)]),
               Toolbox::parse_weighted_op_choice_list("Dup:2,Split"));
    assert_eq!(Err("Invalid weight: ".to_string()),
               Toolbox::parse_weighted_op_choice_list("Dup:2,Split:"));
    assert_eq!(Err("Invalid weight: a".to_string()),
               Toolbox::parse_weighted_op_choice_list("Dup:2,Split:a"));
    assert_eq!(Err("Invalid opcode: dup".to_string()),
               Toolbox::parse_weighted_op_choice_list("dup:2,Split:a"));
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate bit_field;

use bit_field::*;

pub trait BitOper {
    const BIT_LEN: usize;
    fn get_b(&self, idx: usize) -> bool;
    fn set_b(&mut self, idx: usize, val: bool);
    fn toggle(&mut self, idx: usize);
}

pub trait BitArrayOper<T: BitOper> {
    fn get_blen(&self)->usize;
    fn get_b(&self, idx: usize) -> bool;
    fn set_b(&mut self, idx: usize, val: bool);
    fn toggle(&mut self, idx: usize);
}

impl BitOper for u8 {
    const BIT_LEN: usize = std::mem::size_of::<Self>() as usize * 8;

    fn set_b(&mut self, idx: usize, val: bool) {
        assert!(idx < Self::BIT_LEN);
        if val {
            *self |= 1 << idx;
        } else {
            *self &= !(1 << idx);
        }
    }

    fn get_b(&self, idx: usize) -> bool {
        assert!(idx < Self::BIT_LEN);
        (self & 1 << idx) != 0
    }

    fn toggle(&mut self, idx: usize) {
        assert!(idx <  Self::BIT_LEN);
        *self ^= 1 << idx;
    }
}

impl BitOper for u32 {
  const BIT_LEN: usize = std::mem::size_of::<Self>() as usize * 8;
    fn set_b(&mut self, idx: usize, val: bool) {
        assert!(idx < Self::BIT_LEN);
        if val {
            *self |= 1 << idx;
        } else {
            *self &= !(1 << idx);
        }
    }

    fn get_b(&self, idx: usize) -> bool {
        assert!(idx < Self::BIT_LEN);
        (self & 1 << idx) != 0
    }

    fn toggle(&mut self, idx: usize) {
        assert!(idx <  Self::BIT_LEN);
        *self ^= 1 << idx;
    }
}

impl BitOper for u64 {
  const BIT_LEN: usize = std::mem::size_of::<Self>() as usize * 8;
    fn set_b(&mut self, idx: usize, val: bool) {
        assert!(idx < Self::BIT_LEN);
        if val {
            *self |= 1 << idx;
        } else {
            *self &= !(1 << idx);
        }
    }

    fn get_b(&self, idx: usize) -> bool {
        assert!(idx < Self::BIT_LEN);
        (self & 1 << idx) != 0
    }

    fn toggle(&mut self, idx: usize) {
        assert!(idx <  Self::BIT_LEN);
        *self ^= 1 << idx;
    }
}

impl <T:BitOper> BitArrayOper<T> for [T] {
    fn get_blen(&self) -> usize {
        self.len() * T::BIT_LEN
    }

    fn get_b(&self, idx: usize) -> bool {
        self[idx / T::BIT_LEN].get_b(idx % T::BIT_LEN)
    }

    fn set_b(&mut self, idx: usize, val: bool) {
        self[idx / T::BIT_LEN].set_b(idx % T::BIT_LEN, val);
    }

    fn toggle(&mut self, idx: usize) {
        self[idx / T::BIT_LEN].toggle(idx % T::BIT_LEN);
    }
}

extern crate test;

use test::Bencher;

const LEN: usize = 256;

fn set_bitfield<T:BitField>(v: &mut Vec<T>) {
        for i in 0..v.len() * T::BIT_LENGTH {
            v.as_mut_slice().set_bit(i, true);;
        }
 }

fn get_bitfield<T:BitField>(v: &Vec<T>) {
        for i in 0..v.len() * T::BIT_LENGTH {
            let _b = v.as_slice().get_bit(i);
        }
 }

 fn set_trivial<T:BitOper>(v: &mut Vec<T>) {
        for i in 0..v.len() * T::BIT_LEN {
            v.set_b(i, true);
        }
}

 fn toggle<T:BitOper>(v: &mut Vec<T>) {
        for i in 0..v.len() * T::BIT_LEN {
            v.toggle(i);
        }
}

 fn get_trivial<T:BitOper>(v: &Vec<T>) {
        for i in 0..v.len() * T::BIT_LEN {
            let _b = v.get_b(i);
        }
}

#[bench]
fn u8_set_bitfield(b: &mut Bencher) {
    let mut v = vec![0u8; LEN];
    b.iter(|| {
        set_bitfield(&mut v);
    });
}

#[bench]
fn u8_set_trivial(b: &mut Bencher) {
    let mut v = vec![0u8; LEN];

    b.iter(|| {
       set_trivial(&mut v);
    });
}

#[bench]
fn u8_get_bitfield(b: &mut Bencher) {
    let v = vec![1u8; LEN];
    b.iter(|| {
       get_bitfield(&v);
    });
}

#[bench]
fn u8_get_trivial(b: &mut Bencher) {
    let v = vec![1u8; LEN];
    b.iter(|| {
        get_trivial(&v);
    });
}

#[bench]
fn u32_set_bitfield(b: &mut Bencher) {
    let mut v = vec![0u32; LEN];
    b.iter(|| {
        set_bitfield(&mut v);
    });
}

#[bench]
fn u32_set_trivial(b: &mut Bencher) {
    let mut v = vec![0u32; LEN];

    b.iter(|| {
       set_trivial(&mut v);
    });
}

#[bench]
fn u32_get_bitfield(b: &mut Bencher) {
    let v = vec![1u32; LEN];
    b.iter(|| {
       get_bitfield(&v);
    });
}

#[bench]
fn u32_get_trivial(b: &mut Bencher) {
    let v = vec![1u32; LEN];
    b.iter(|| {
        get_trivial(&v);
    });
}

#[bench]
fn u64_set_bitfield(b: &mut Bencher) {
    let mut v = vec![0u64; LEN];
    b.iter(|| {
        set_bitfield(&mut v);
    });
}

#[bench]
fn u64_set_trivial(b: &mut Bencher) {
    let mut v = vec![0u64; LEN];

    b.iter(|| {
       set_trivial(&mut v);
    });
}

#[bench]
fn u64_get_bitfield(b: &mut Bencher) {
    let v = vec![1u64; LEN];
    b.iter(|| {
       get_bitfield(&v);
    });
}

#[bench]
fn u64_get_trivial(b: &mut Bencher) {
    let v = vec![1u64; LEN];
    b.iter(|| {
        get_trivial(&v);
    });
}
<commit_msg>Remove unused toggle function<commit_after>#![feature(test)]

extern crate bit_field;

use bit_field::*;

pub trait BitOper {
    const BIT_LEN: usize;
    fn get_b(&self, idx: usize) -> bool;
    fn set_b(&mut self, idx: usize, val: bool);
    fn toggle(&mut self, idx: usize);
}

pub trait BitArrayOper<T: BitOper> {
    fn get_blen(&self)->usize;
    fn get_b(&self, idx: usize) -> bool;
    fn set_b(&mut self, idx: usize, val: bool);
    fn toggle(&mut self, idx: usize);
}

impl BitOper for u8 {
    const BIT_LEN: usize = std::mem::size_of::<Self>() as usize * 8;

    fn set_b(&mut self, idx: usize, val: bool) {
        assert!(idx < Self::BIT_LEN);
        if val {
            *self |= 1 << idx;
        } else {
            *self &= !(1 << idx);
        }
    }

    fn get_b(&self, idx: usize) -> bool {
        assert!(idx < Self::BIT_LEN);
        (self & 1 << idx) != 0
    }

    fn toggle(&mut self, idx: usize) {
        assert!(idx <  Self::BIT_LEN);
        *self ^= 1 << idx;
    }
}

impl BitOper for u32 {
  const BIT_LEN: usize = std::mem::size_of::<Self>() as usize * 8;
    fn set_b(&mut self, idx: usize, val: bool) {
        assert!(idx < Self::BIT_LEN);
        if val {
            *self |= 1 << idx;
        } else {
            *self &= !(1 << idx);
        }
    }

    fn get_b(&self, idx: usize) -> bool {
        assert!(idx < Self::BIT_LEN);
        (self & 1 << idx) != 0
    }

    fn toggle(&mut self, idx: usize) {
        assert!(idx <  Self::BIT_LEN);
        *self ^= 1 << idx;
    }
}

impl BitOper for u64 {
  const BIT_LEN: usize = std::mem::size_of::<Self>() as usize * 8;
    fn set_b(&mut self, idx: usize, val: bool) {
        assert!(idx < Self::BIT_LEN);
        if val {
            *self |= 1 << idx;
        } else {
            *self &= !(1 << idx);
        }
    }

    fn get_b(&self, idx: usize) -> bool {
        assert!(idx < Self::BIT_LEN);
        (self & 1 << idx) != 0
    }

    fn toggle(&mut self, idx: usize) {
        assert!(idx <  Self::BIT_LEN);
        *self ^= 1 << idx;
    }
}

impl <T:BitOper> BitArrayOper<T> for [T] {
    fn get_blen(&self) -> usize {
        self.len() * T::BIT_LEN
    }

    fn get_b(&self, idx: usize) -> bool {
        self[idx / T::BIT_LEN].get_b(idx % T::BIT_LEN)
    }

    fn set_b(&mut self, idx: usize, val: bool) {
        self[idx / T::BIT_LEN].set_b(idx % T::BIT_LEN, val);
    }

    fn toggle(&mut self, idx: usize) {
        self[idx / T::BIT_LEN].toggle(idx % T::BIT_LEN);
    }
}

extern crate test;

use test::Bencher;

const LEN: usize = 256;

fn set_bitfield<T:BitField>(v: &mut Vec<T>) {
        for i in 0..v.len() * T::BIT_LENGTH {
            v.as_mut_slice().set_bit(i, true);;
        }
 }

fn get_bitfield<T:BitField>(v: &Vec<T>) {
        for i in 0..v.len() * T::BIT_LENGTH {
            let _b = v.as_slice().get_bit(i);
        }
 }

 fn set_trivial<T:BitOper>(v: &mut Vec<T>) {
        for i in 0..v.len() * T::BIT_LEN {
            v.set_b(i, true);
        }
}

 fn get_trivial<T:BitOper>(v: &Vec<T>) {
        for i in 0..v.len() * T::BIT_LEN {
            let _b = v.get_b(i);
        }
}

#[bench]
fn u8_set_bitfield(b: &mut Bencher) {
    let mut v = vec![0u8; LEN];
    b.iter(|| {
        set_bitfield(&mut v);
    });
}

#[bench]
fn u8_set_trivial(b: &mut Bencher) {
    let mut v = vec![0u8; LEN];

    b.iter(|| {
       set_trivial(&mut v);
    });
}

#[bench]
fn u8_get_bitfield(b: &mut Bencher) {
    let v = vec![1u8; LEN];
    b.iter(|| {
       get_bitfield(&v);
    });
}

#[bench]
fn u8_get_trivial(b: &mut Bencher) {
    let v = vec![1u8; LEN];
    b.iter(|| {
        get_trivial(&v);
    });
}

#[bench]
fn u32_set_bitfield(b: &mut Bencher) {
    let mut v = vec![0u32; LEN];
    b.iter(|| {
        set_bitfield(&mut v);
    });
}

#[bench]
fn u32_set_trivial(b: &mut Bencher) {
    let mut v = vec![0u32; LEN];

    b.iter(|| {
       set_trivial(&mut v);
    });
}

#[bench]
fn u32_get_bitfield(b: &mut Bencher) {
    let v = vec![1u32; LEN];
    b.iter(|| {
       get_bitfield(&v);
    });
}

#[bench]
fn u32_get_trivial(b: &mut Bencher) {
    let v = vec![1u32; LEN];
    b.iter(|| {
        get_trivial(&v);
    });
}

#[bench]
fn u64_set_bitfield(b: &mut Bencher) {
    let mut v = vec![0u64; LEN];
    b.iter(|| {
        set_bitfield(&mut v);
    });
}

#[bench]
fn u64_set_trivial(b: &mut Bencher) {
    let mut v = vec![0u64; LEN];

    b.iter(|| {
       set_trivial(&mut v);
    });
}

#[bench]
fn u64_get_bitfield(b: &mut Bencher) {
    let v = vec![1u64; LEN];
    b.iter(|| {
       get_bitfield(&v);
    });
}

#[bench]
fn u64_get_trivial(b: &mut Bencher) {
    let v = vec![1u64; LEN];
    b.iter(|| {
        get_trivial(&v);
    });
}
<|endoftext|>


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

use std::str::CharIndices;

// support arguments like '4', 'ab', '4.0'
fn acceptable_arg_character(c: char) -> bool {
    c.is_alphanumeric() || c == '.'
}

// A crapy parser for parsing strings like "translate(1, 3)"
pub fn parse_function(s: &str) -> (&str, Vec<&str>) {
    // XXX: This it not particular easy to read. Sorry.
    struct Parser<'a> {
        itr: CharIndices<'a>,
        start: usize,
        o: Option<(usize, char)>,
    }
    impl<'a> Parser<'a> {
        fn skip_whitespace(&mut self) {
            while let Some(k) = self.o {
                if !k.1.is_whitespace() {
                    break;
                }
                self.start = k.0 + k.1.len_utf8();
                self.o = self.itr.next();
            }

        }
    }
    let mut c = s.char_indices();
    let o = c.next();
    let mut p = Parser { itr: c, start: 0, o: o };

    p.skip_whitespace();

    let mut end = p.start;
    while let Some(k) = p.o {
        if !k.1.is_alphabetic() && k.1 != '_' {
            break;
        }
        end = k.0 + k.1.len_utf8();
        p.o = p.itr.next();
    }

    let name = &s[p.start..end];
    let mut args = Vec::new();

    p.skip_whitespace();

    if let Some(k) = p.o {
        if !(k.1 == '(') {
            return (name, args);
        }
        p.start = k.0 + k.1.len_utf8();
        p.o = p.itr.next();
    }

    loop {
        p.skip_whitespace();

        let mut end = p.start;
        while let Some(k) = p.o {
            if !acceptable_arg_character(k.1) {
                break;
            }
            end = k.0 + k.1.len_utf8();
            p.o = p.itr.next();
        }

        args.push(&s[p.start..end]);

        p.skip_whitespace();

        if let Some(k) = p.o {
            // unless we find a comma we're done
            if k.1 != ',' {
                break;
            }
            p.start = k.0 + k.1.len_utf8();
            p.o = p.itr.next();
        }

    }
    (name, args)
}

#[test]
fn test() {
    assert!(parse_function("rotate(40)").0 == "rotate");
    assert!(parse_function("  rotate(40)").0 == "rotate");
    assert!(parse_function("  rotate  (40)").0 == "rotate");
    assert!(parse_function("  rotate  (  40 )").1[0] == "40");
}
<commit_msg>Modify parse_function to accept hyphens<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::str::CharIndices;

// support arguments like '4', 'ab', '4.0'
fn acceptable_arg_character(c: char) -> bool {
    c.is_alphanumeric() || c == '.'
}

// A crapy parser for parsing strings like "translate(1, 3)"
pub fn parse_function(s: &str) -> (&str, Vec<&str>) {
    // XXX: This it not particular easy to read. Sorry.
    struct Parser<'a> {
        itr: CharIndices<'a>,
        start: usize,
        o: Option<(usize, char)>,
    }
    impl<'a> Parser<'a> {
        fn skip_whitespace(&mut self) {
            while let Some(k) = self.o {
                if !k.1.is_whitespace() {
                    break;
                }
                self.start = k.0 + k.1.len_utf8();
                self.o = self.itr.next();
            }

        }
    }
    let mut c = s.char_indices();
    let o = c.next();
    let mut p = Parser { itr: c, start: 0, o: o };

    p.skip_whitespace();

    let mut end = p.start;
    while let Some(k) = p.o {
        if !k.1.is_alphabetic() && k.1 != '_' && k.1 != '-' {
            break;
        }
        end = k.0 + k.1.len_utf8();
        p.o = p.itr.next();
    }

    let name = &s[p.start..end];
    let mut args = Vec::new();

    p.skip_whitespace();

    if let Some(k) = p.o {
        if !(k.1 == '(') {
            return (name, args);
        }
        p.start = k.0 + k.1.len_utf8();
        p.o = p.itr.next();
    }

    loop {
        p.skip_whitespace();

        let mut end = p.start;
        while let Some(k) = p.o {
            if !acceptable_arg_character(k.1) {
                break;
            }
            end = k.0 + k.1.len_utf8();
            p.o = p.itr.next();
        }

        args.push(&s[p.start..end]);

        p.skip_whitespace();

        if let Some(k) = p.o {
            // unless we find a comma we're done
            if k.1 != ',' {
                break;
            }
            p.start = k.0 + k.1.len_utf8();
            p.o = p.itr.next();
        }

    }
    (name, args)
}

#[test]
fn test() {
    assert!(parse_function("rotate(40)").0 == "rotate");
    assert!(parse_function("  rotate(40)").0 == "rotate");
    assert!(parse_function("  rotate  (40)").0 == "rotate");
    assert!(parse_function("  rotate  (  40 )").1[0] == "40");
}
<|endoftext|>


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

use std::ptr::{self, null_mut};
use std::sync::atomic::AtomicPtr;
use std::sync::atomic::Ordering::{Relaxed, Release, Acquire};

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

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

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

    pub 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(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, Release) == head {
                break
            }
        }
    }
}

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>Implement the take_each method for traversing Treiber stack.<commit_after>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));
    }
}
<|endoftext|>


<commit_before>
extern crate rustc_serialize;
extern crate amqp;

use amqp::{ConsumerCallBackFn, Session, Table, Basic, Channel, Options, Consumer};
use amqp::protocol;
use std::default::Default;
use rustc_serialize::json;
use std::slice;

// for debugging
fn listen_discovery(channel: &mut Channel) {
    fn participant_discovered(channel: &mut Channel, deliver: protocol::basic::Deliver,
                            headers: protocol::basic::BasicProperties, body: Vec<u8>){
        let s = std::str::from_utf8(&body).unwrap();
        let info: ParticipantInfo = json::decode(s).unwrap();
        println!("MsgFlo participant discovered: {:?}", info);
        //println!("Deliver info: {:?}", deliver);
        //println!("Content headers: {:?}", headers);
        //println!("Content body: ", );
        channel.basic_ack(deliver.delivery_tag, false);
    }

    let queue_name = "fbp";
    let consumer_name = channel.basic_consume(participant_discovered as ConsumerCallBackFn, queue_name,
                                                "", false, false, false, false, Table::new());
    println!("listening for discovery messages");
}

#[derive(Debug, Default, RustcDecodable, RustcEncodable)]
struct ParticipantPort {
    id: String, // port name
    queue: String, // the associated message queue
    // FIXME: support. Is a keyword so needs some special handling   type: String, // datatype, ex: "boolean"
    // options: queue options as specified by the message queue implementation
    // description?? TODO: standardize
}

#[derive(Debug, Default, RustcDecodable, RustcEncodable)]
struct ParticipantInfo {
    id: String, // unique name
    role: String ,// role participant has
    component: String, // component the participant is instance of
//   label: Option<String>, // (optional) short human-readable description
//    icon: Option<String>, // (optional)
    inports: Vec<ParticipantPort>,
    outports: Vec<ParticipantPort>,
}

type ProcessFunction = fn(Vec<u8>) -> Result<Vec<u8>, Vec<u8>>;
struct Participant {
    info: ParticipantInfo,
    process: ProcessFunction,
}

struct Connection {
    session: Session,
    channel: Channel,
}

// FIXME: wrap in protocol/command/payload envelope
fn create_queue_and_send(channel: &mut Channel, queue_name: &str, payload: String) {

    let queue_declare = channel.queue_declare(queue_name, false, true, false, false, false, Table::new());
    queue_declare.expect("queue creation failed");
    let content_type = Some("application/json".to_string());
    let props = protocol::basic::BasicProperties { content_type: content_type, ..Default::default() };
    println!("sending on {}: {}", queue_name, payload);
    let res = channel.basic_publish("", queue_name, true, false, props, payload.into_bytes());
    res.expect("send on new queue failed");
}

fn send_discovery(channel: &mut Channel, info: &ParticipantInfo) {
    let queue_name = "fbp"; // TODO: use an exchange istead, requires protocol change in msgflo

    let payload = json::encode(&info).unwrap();
    create_queue_and_send(channel, queue_name, payload);
}

struct PortConsumer {
    process: ProcessFunction,
    portname: String,
}

impl Consumer for PortConsumer {
    fn handle_delivery(&mut self,
                       channel: &mut Channel,
                       deliver: protocol::basic::Deliver,
                       headers: protocol::basic::BasicProperties,
                       body: Vec<u8>) {

        println!("delivery");

        let f = self.process;
        let res = f(body);

        if res.is_ok() {
            let r = channel.basic_ack(deliver.delivery_tag, false);
        } else {
            let r = channel.basic_nack(deliver.delivery_tag, true, true);
        }
    }
}

// FIXME: actually call ProcessFunction
fn setup_inport(participant: &Participant, port: &ParticipantPort, connection: &mut Connection) {
    println!("setup inport: {}", port.queue.to_string());

    let consumer = PortConsumer { process: participant.process, portname: port.id.to_string() };

    // create
    let declare = connection.channel.queue_declare(port.queue.to_string(), false, true, false, false, false, Table::new());
    declare.expect("inport queue creation failed");

    // subscribe
    let q = port.queue.to_string();
    let cons = connection.channel.basic_consume(consumer, q,
                                                "".to_string(), false, false, false, false, Table::new());

    cons.expect("iport setup failed");

    println!("setup inport done: {:?}, {:?}", port.id.to_string(), port.queue.to_string());
}

fn setup_outport(participant: &Participant, port: &ParticipantPort, connection: &mut Connection) {

    let queue_declare = connection.channel.queue_declare(port.queue.to_string(), false, true, false, false, false, Table::new());
    let content_type = Some("application/json".to_string());
}

// FIXME: actually send
fn send_output(participant: &Participant) {

    let queue_name = participant.info.outports[0].queue.to_string();
//    let payload = json::encode(&info).unwrap();
//    println!("sending: {}", payload);
//    let props = protocol::basic::BasicProperties { content_type: content_type, ..Default::default() };
//    let res = channel.basic_publish("", port.queue.to_string(), true, false, props, payload.into_bytes());
}

fn start_participant(participant: &Participant) -> Connection {
    let mut session = Session::new(Options{vhost: "/", .. Default::default()}).ok().expect("Can't create session");
    let mut channel = session.open_channel(1).expect("channel");

    send_discovery(&mut channel, &participant.info);

    let mut conn = Connection { session: session, channel: channel };

    // XXX: seems like can only connect to one queue?? or rather, seems program hangs forever if channel is borked
    listen_discovery(&mut conn.channel); // TESTING

    setup_inport(&participant, &participant.info.inports[0], &mut conn);

    return conn;
}

// for debugging
fn stop_participant(participant: &Participant, connection: &mut Connection) {

    let closed = connection.channel.close(200, "Bye".to_string());
    connection.session.close(200, "Good Bye".to_string());
}

// TODO: wire up input/output to the process() function
// TODO: respect MSGFLO_BROKER envvar
// TODO: setup the msgflo hetro automated test
// TODO: nicer way to declare ports
fn main() {
    let info = ParticipantInfo {
        id: "part11".to_string(),
        role: "myrole".to_string(),
        component: "rust/First".to_string(),
        inports: vec! [ ParticipantPort { id: "in".to_string(), queue: "rustparty.IN".to_string() } ],
        outports: vec! [ ParticipantPort { id: "out".to_string(), queue: "rustparty.OUT".to_string() } ],
    };

        //let s = std::str::from_utf8(&body).unwrap();
        //let json_obj: json::Object = json::decode(s).expect("json parse error");

    fn process_repeat(input: Vec<u8>) -> Result<Vec<u8>, Vec<u8>> {
        println!("process_repeat:");
        return Ok(input);
    }

    let p = Participant { info: info, process: process_repeat };

    let mut c = start_participant(&p);

    create_queue_and_send(&mut c.channel, "rustparty.IN", "{ \"data\": 300 }".to_string());

    c.channel.start_consuming();
    stop_participant(&p, &mut c);
}
<commit_msg>Sends output on exchange<commit_after>
extern crate rustc_serialize;
extern crate amqp;

use amqp::{ConsumerCallBackFn, Session, Table, Basic, Channel, Options, Consumer};
use amqp::protocol;
use std::default::Default;
use rustc_serialize::json;
use std::slice;

// for debugging
fn listen_discovery(channel: &mut Channel) {
    fn participant_discovered(channel: &mut Channel, deliver: protocol::basic::Deliver,
                            headers: protocol::basic::BasicProperties, body: Vec<u8>){
        let s = std::str::from_utf8(&body).unwrap();
        let info: ParticipantInfo = json::decode(s).unwrap();
        println!("MsgFlo participant discovered: {:?}", info);
        //println!("Deliver info: {:?}", deliver);
        //println!("Content headers: {:?}", headers);
        //println!("Content body: ", );
        channel.basic_ack(deliver.delivery_tag, false);
    }

    let queue_name = "fbp";
    let consumer_name = channel.basic_consume(participant_discovered as ConsumerCallBackFn, queue_name,
                                                "", false, false, false, false, Table::new());
    println!("listening for discovery messages");
}

#[derive(Debug, Default, RustcDecodable, RustcEncodable)]
struct ParticipantPort {
    id: String, // port name
    queue: String, // the associated message queue
    // FIXME: support. Is a keyword so needs some special handling   type: String, // datatype, ex: "boolean"
    // options: queue options as specified by the message queue implementation
    // description?? TODO: standardize
}

#[derive(Debug, Default, RustcDecodable, RustcEncodable)]
struct ParticipantInfo {
    id: String, // unique name
    role: String ,// role participant has
    component: String, // component the participant is instance of
//   label: Option<String>, // (optional) short human-readable description
//    icon: Option<String>, // (optional)
    inports: Vec<ParticipantPort>,
    outports: Vec<ParticipantPort>,
}

type SendFunction = fn(String, Vec<u8>);
type ProcessFunction = fn(Vec<u8>) -> Result<Vec<u8>, Vec<u8>>;
struct Participant {
    info: ParticipantInfo,
    process: ProcessFunction,
}

struct Connection {
    session: Session,
    channel: Channel,
}

// FIXME: wrap in protocol/command/payload envelope
fn create_queue_and_send(channel: &mut Channel, queue_name: &str, payload: String) {

    let queue_declare = channel.queue_declare(queue_name, false, true, false, false, false, Table::new());
    queue_declare.expect("queue creation failed");
    let content_type = Some("application/json".to_string());
    let props = protocol::basic::BasicProperties { content_type: content_type, ..Default::default() };
    println!("sending on {}: {}", queue_name, payload);
    let res = channel.basic_publish("", queue_name, true, false, props, payload.into_bytes());
    res.expect("send on new queue failed");
}

fn send_discovery(channel: &mut Channel, info: &ParticipantInfo) {
    let queue_name = "fbp"; // TODO: use an exchange istead, requires protocol change in msgflo

    let payload = json::encode(&info).unwrap();
    create_queue_and_send(channel, queue_name, payload);
}

struct PortConsumer {
    process: ProcessFunction,
    portname: String,
    outqueue: String, // FIXME: allow sending on any port, also multiple times
}

fn send_out(channel: &mut Channel, exchange: String, data: Vec<u8>) {

    let routing_key = "".to_string();
    let content_type = Some("application/json".to_string()); // TODO: should be parameter
    let props = protocol::basic::BasicProperties { content_type: content_type, ..Default::default() };
    let s = channel.basic_publish(exchange, routing_key, true, false, props, data);
    s.expect("failed to send");
    println!("sent output");
}

impl Consumer for PortConsumer {
    fn handle_delivery(&mut self,
                       channel: &mut Channel,
                       deliver: protocol::basic::Deliver,
                       headers: protocol::basic::BasicProperties,
                       body: Vec<u8>) {

        println!("calling process()");
        let f = self.process;
        let res = f(body);
        println!("process() returned");

        if res.is_ok() {
            println!("ACKing and sending");
            send_out(channel, self.outqueue.to_string(), res.unwrap());
            let r = channel.basic_ack(deliver.delivery_tag, false);
        } else {
            let r = channel.basic_nack(deliver.delivery_tag, true, true);
        }
        // FIXME: send error data
    }
}

// FIXME: actually call ProcessFunction
fn setup_inport(participant: &Participant, port: &ParticipantPort, connection: &mut Connection) {
    println!("setup inport: {}", port.queue.to_string());

    let consumer = PortConsumer {
        process: participant.process,
        portname: port.id.to_string(),
        outqueue: participant.info.outports[0].queue.to_string(),
    };

    // create
    let declare = connection.channel.queue_declare(port.queue.to_string(), false, true, false, false, false, Table::new());
    declare.expect("inport queue creation failed");

    // subscribe
    let q = port.queue.to_string();
    let cons = connection.channel.basic_consume(consumer, q,
                                                "".to_string(), false, false, false, false, Table::new());

    cons.expect("iport setup failed");

    println!("setup inport done: {:?}, {:?}", port.id.to_string(), port.queue.to_string());
}

fn setup_outport(participant: &Participant, port: &ParticipantPort, connection: &mut Connection) {

    let exchange_type = "direct".to_string();
    let queue_declare = connection.channel.exchange_declare(port.queue.to_string(), exchange_type, true, false, false, false, false, Table::new());
    let content_type = Some("application/json".to_string());
}

fn start_participant(participant: &Participant) -> Connection {
    let mut session = Session::new(Options{vhost: "/", .. Default::default()}).ok().expect("Can't create session");
    let mut channel = session.open_channel(1).expect("channel");

    send_discovery(&mut channel, &participant.info);

    let mut conn = Connection { session: session, channel: channel };

    // XXX: seems like can only connect to one queue?? or rather, seems program hangs forever if channel is borked
    listen_discovery(&mut conn.channel); // TESTING

    setup_inport(&participant, &participant.info.inports[0], &mut conn);

    return conn;
}

// for debugging
fn stop_participant(participant: &Participant, connection: &mut Connection) {

    let closed = connection.channel.close(200, "Bye".to_string());
    connection.session.close(200, "Good Bye".to_string());
}

// TODO: pass port info in/out of process()
// TODO: respect MSGFLO_BROKER envvar
// TODO: setup the msgflo hetro automated test
// TODO: move into library, have entrypoint(s) usable from outside
// TODO: nicer way to declare ports? ideally they are enums not stringly typed?
fn main() {
    let info = ParticipantInfo {
        id: "part11".to_string(),
        role: "myrole".to_string(),
        component: "rust/First".to_string(),
        inports: vec! [ ParticipantPort { id: "in".to_string(), queue: "rustparty.IN".to_string() } ],
        outports: vec! [ ParticipantPort { id: "out".to_string(), queue: "rustparty.OUT".to_string() } ],
    };

        //let s = std::str::from_utf8(&body).unwrap();
        //let json_obj: json::Object = json::decode(s).expect("json parse error");

    fn process_repeat(input: Vec<u8>) -> Result<Vec<u8>, Vec<u8>> {
        println!("process_repeat:");
        return Ok(input);
    }

    let p = Participant { info: info, process: process_repeat };

    let mut c = start_participant(&p);

    create_queue_and_send(&mut c.channel, "rustparty.IN", "{ \"data\": 300 }".to_string());

    c.channel.start_consuming();
    stop_participant(&p, &mut c);
}
<|endoftext|>


<commit_before>use std;
use std::fmt;
use util::u128;
use byteorder::{BigEndian, ByteOrder};
use std::ascii::AsciiExt;

#[derive(Debug,Copy,Clone,PartialEq,Eq,Hash)]
pub struct SpotifyId(u128);

const BASE62_DIGITS: &'static [u8] =
    b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
const BASE16_DIGITS: &'static [u8] = b"0123456789abcdef";

impl SpotifyId {
    pub fn from_base16(id: &str) -> SpotifyId {
        assert!(id.is_ascii());
        let data = id.as_bytes();

        let mut n: u128 = u128::zero();
        for c in data {
            let d = BASE16_DIGITS.iter().position(|e| e == c).unwrap() as u8;
            n = n * u128::from(16);
            n = n + u128::from(d);
        }

        SpotifyId(n)
    }

    pub fn from_base62(id: &str) -> SpotifyId {
        assert!(id.is_ascii());
        let data = id.as_bytes();

        let mut n: u128 = u128::zero();
        for c in data {
            let d = BASE62_DIGITS.iter().position(|e| e == c).unwrap() as u8;
            n = n * u128::from(62);
            n = n + u128::from(d);
        }

        SpotifyId(n)
    }

    pub fn from_raw(data: &[u8]) -> SpotifyId {
        assert_eq!(data.len(), 16);

        let high = BigEndian::read_u64(&data[0..8]);
        let low = BigEndian::read_u64(&data[8..16]);

        SpotifyId(u128::from_parts(high, low))
    }

    pub fn to_base16(&self) -> String {
        let &SpotifyId(ref n) = self;
        let (high, low) = n.parts();

        let mut data = [0u8; 32];
        for i in 0..16 {
            data[31 - i] = BASE16_DIGITS[(low.wrapping_shr(4 * i as u32) & 0xF) as usize];
        }
        for i in 0..16 {
            data[15 - i] = BASE16_DIGITS[(high.wrapping_shr(4 * i as u32) & 0xF) as usize];
        }

        std::str::from_utf8(&data).unwrap().to_owned()
    }

    pub fn to_raw(&self) -> [u8; 16] {
        let &SpotifyId(ref n) = self;
        let (high, low) = n.parts();

        let mut data = [0u8; 16];

        BigEndian::write_u64(&mut data[0..8], high);
        BigEndian::write_u64(&mut data[8..16], low);

        data
    }
}

#[derive(Copy,Clone,PartialEq,Eq,PartialOrd,Ord,Hash)]
pub struct FileId(pub [u8; 20]);

impl FileId {
    pub fn to_base16(&self) -> String {
        self.0
            .iter()
            .map(|b| format!("{:02x}", b))
            .collect::<Vec<String>>()
            .concat()
    }
}

impl fmt::Debug for FileId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_tuple("FileId").field(&self.to_base16()).finish()
    }
}

impl fmt::Display for FileId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&self.to_base16())
    }
}
<commit_msg>core: Remove an unneeded use warning<commit_after>use std;
use std::fmt;
use util::u128;
use byteorder::{BigEndian, ByteOrder};
// Unneeded since 1.21
#[allow(unused_imports)]
use std::ascii::AsciiExt;

#[derive(Debug,Copy,Clone,PartialEq,Eq,Hash)]
pub struct SpotifyId(u128);

const BASE62_DIGITS: &'static [u8] =
    b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
const BASE16_DIGITS: &'static [u8] = b"0123456789abcdef";

impl SpotifyId {
    pub fn from_base16(id: &str) -> SpotifyId {
        assert!(id.is_ascii());
        let data = id.as_bytes();

        let mut n: u128 = u128::zero();
        for c in data {
            let d = BASE16_DIGITS.iter().position(|e| e == c).unwrap() as u8;
            n = n * u128::from(16);
            n = n + u128::from(d);
        }

        SpotifyId(n)
    }

    pub fn from_base62(id: &str) -> SpotifyId {
        assert!(id.is_ascii());
        let data = id.as_bytes();

        let mut n: u128 = u128::zero();
        for c in data {
            let d = BASE62_DIGITS.iter().position(|e| e == c).unwrap() as u8;
            n = n * u128::from(62);
            n = n + u128::from(d);
        }

        SpotifyId(n)
    }

    pub fn from_raw(data: &[u8]) -> SpotifyId {
        assert_eq!(data.len(), 16);

        let high = BigEndian::read_u64(&data[0..8]);
        let low = BigEndian::read_u64(&data[8..16]);

        SpotifyId(u128::from_parts(high, low))
    }

    pub fn to_base16(&self) -> String {
        let &SpotifyId(ref n) = self;
        let (high, low) = n.parts();

        let mut data = [0u8; 32];
        for i in 0..16 {
            data[31 - i] = BASE16_DIGITS[(low.wrapping_shr(4 * i as u32) & 0xF) as usize];
        }
        for i in 0..16 {
            data[15 - i] = BASE16_DIGITS[(high.wrapping_shr(4 * i as u32) & 0xF) as usize];
        }

        std::str::from_utf8(&data).unwrap().to_owned()
    }

    pub fn to_raw(&self) -> [u8; 16] {
        let &SpotifyId(ref n) = self;
        let (high, low) = n.parts();

        let mut data = [0u8; 16];

        BigEndian::write_u64(&mut data[0..8], high);
        BigEndian::write_u64(&mut data[8..16], low);

        data
    }
}

#[derive(Copy,Clone,PartialEq,Eq,PartialOrd,Ord,Hash)]
pub struct FileId(pub [u8; 20]);

impl FileId {
    pub fn to_base16(&self) -> String {
        self.0
            .iter()
            .map(|b| format!("{:02x}", b))
            .collect::<Vec<String>>()
            .concat()
    }
}

impl fmt::Debug for FileId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_tuple("FileId").field(&self.to_base16()).finish()
    }
}

impl fmt::Display for FileId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&self.to_base16())
    }
}
<|endoftext|>