<commit_before>use common::{ApiError, Body, Credentials, Query, discovery_api};
use hyper::method::Method::{Delete, Get, Post};
use serde_json::{Value, to_string};

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(deny_unknown_fields)]
pub struct NewCollection {
    pub name: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub configuration_id: Option<String>,
}

pub fn list(creds: &Credentials, env_id: &str) -> Result<Value, ApiError> {
    let path = "/v1/environments/".to_string() + env_id + "/collections";
    Ok(discovery_api(creds, Get, &path, Query::None, &Body::None)?)
}

pub fn detail(creds: &Credentials,
              env_id: &str,
              collection_id: &str)
              -> Result<Value, ApiError> {
    let path = "/v1/environments/".to_string() + env_id + "/collections/" +
               collection_id;
    Ok(discovery_api(creds, Get, &path, Query::None, &Body::None)?)
}

pub fn create(creds: &Credentials,
              env_id: &str,
              options: &NewCollection)
              -> Result<Value, ApiError> {
    let path = "/v1/environments/".to_string() + env_id + "/collections";
    let request_body = to_string(options)
        .expect("Internal error: failed to convert NewCollection into JSON");
    Ok(discovery_api(creds,
                     Post,
                     &path,
                     Query::None,
                     &Body::Json(&request_body))?)
}

pub fn delete(creds: &Credentials,
              env_id: &str,
              collection_id: &str)
              -> Result<Value, ApiError> {
    let path = "/v1/environments/".to_string() + env_id + "/collections/" +
               collection_id;
    Ok(discovery_api(creds, Delete, &path, Query::None, &Body::None)?)
}
<commit_msg>Add collection::fields<commit_after>use common::{ApiError, Body, Credentials, Query, discovery_api};
use hyper::method::Method::{Delete, Get, Post};
use serde_json::{Value, to_string};

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(deny_unknown_fields)]
pub struct NewCollection {
    pub name: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub configuration_id: Option<String>,
}

pub fn list(creds: &Credentials, env_id: &str) -> Result<Value, ApiError> {
    let path = "/v1/environments/".to_string() + env_id + "/collections";
    Ok(discovery_api(creds, Get, &path, Query::None, &Body::None)?)
}

pub fn detail(creds: &Credentials,
              env_id: &str,
              collection_id: &str)
              -> Result<Value, ApiError> {
    let path = "/v1/environments/".to_string() + env_id + "/collections/" +
               collection_id;
    Ok(discovery_api(creds, Get, &path, Query::None, &Body::None)?)
}

pub fn fields(creds: &Credentials,
              env_id: &str,
              collection_id: &str)
              -> Result<Value, ApiError> {
    let path = "/v1/environments/".to_string() + env_id + "/collections/" +
               collection_id + "/fields";
    Ok(discovery_api(creds, Get, &path, Query::None, &Body::None)?)
}

pub fn create(creds: &Credentials,
              env_id: &str,
              options: &NewCollection)
              -> Result<Value, ApiError> {
    let path = "/v1/environments/".to_string() + env_id + "/collections";
    let request_body = to_string(options)
        .expect("Internal error: failed to convert NewCollection into JSON");
    Ok(discovery_api(creds,
                     Post,
                     &path,
                     Query::None,
                     &Body::Json(&request_body))?)
}

pub fn delete(creds: &Credentials,
              env_id: &str,
              collection_id: &str)
              -> Result<Value, ApiError> {
    let path = "/v1/environments/".to_string() + env_id + "/collections/" +
               collection_id;
    Ok(discovery_api(creds, Delete, &path, Query::None, &Body::None)?)
}
<|endoftext|>


<commit_before>enum MyEnum {
    MyEmptyVariant,
    MyNewtypeVariant(i32),
    MyTupleVariant(i32, i32),
    MyStructVariant {
        my_first_field: i32,
        my_second_field: i32,
    }
}

fn test(me: MyEnum) {
    match me {
        MyEnum::MyEmptyVariant => {},
        MyEnum::MyNewtypeVariant(ref val) => assert_eq!(val, &42),
        MyEnum::MyTupleVariant(ref a, ref b) => {
            assert_eq!(a, &43);
            assert_eq!(b, &44);
        },
        MyEnum::MyStructVariant { ref my_first_field, ref my_second_field } => {
            assert_eq!(my_first_field, &45);
            assert_eq!(my_second_field, &46);
        },
    }
}

fn main() {
    test(MyEnum::MyEmptyVariant);
    test(MyEnum::MyNewtypeVariant(42));
    test(MyEnum::MyTupleVariant(43, 44));
    test(MyEnum::MyStructVariant{
        my_first_field: 45,
        my_second_field: 46,
    });
}
<commit_msg>test for niche enum discriminant computation that overflows<commit_after>enum MyEnum {
    MyEmptyVariant,
    MyNewtypeVariant(i32),
    MyTupleVariant(i32, i32),
    MyStructVariant {
        my_first_field: i32,
        my_second_field: i32,
    }
}

fn test(me: MyEnum) {
    match me {
        MyEnum::MyEmptyVariant => {},
        MyEnum::MyNewtypeVariant(ref val) => assert_eq!(val, &42),
        MyEnum::MyTupleVariant(ref a, ref b) => {
            assert_eq!(a, &43);
            assert_eq!(b, &44);
        },
        MyEnum::MyStructVariant { ref my_first_field, ref my_second_field } => {
            assert_eq!(my_first_field, &45);
            assert_eq!(my_second_field, &46);
        },
    }
}

fn discriminant_overflow() {
    // Tests for https://github.com/rust-lang/rust/issues/62138.
    #[repr(u8)]
    #[allow(dead_code)]
    enum WithWraparoundInvalidValues {
        X = 1,
        Y = 254,
    }

    #[allow(dead_code)]
    enum Foo {
        A,
        B,
        C(WithWraparoundInvalidValues),
    }

    let x = Foo::B;
    if let Foo::C(_) = x {
        panic!();
    }
}

fn main() {
    test(MyEnum::MyEmptyVariant);
    test(MyEnum::MyNewtypeVariant(42));
    test(MyEnum::MyTupleVariant(43, 44));
    test(MyEnum::MyStructVariant{
        my_first_field: 45,
        my_second_field: 46,
    });

    discriminant_overflow();
}
<|endoftext|>


<commit_before>extern crate herder;
extern crate hyper;
extern crate url;

use herder::Mastodon;
use herder::api::v1::methods::{
    AccountID,
    APIEndpoint,
    APIEndpointRequest,
    RelationshipsQuery,
    SearchAccountsQuery,
    UserFormData
};
use herder::mastodon::NodeInstance;
use hyper::Method::{Get, Patch, Post};

const BASE_URL: &str = "http://localhost:3000";
const MY_TOKEN: &str = "MY_TOKEN";
// Testing API Method Requests
// pub enum APIEndpoint {
//     // AccountsMethod: Fetch Account
//     FetchAccount(AccountID),
//     GetCurrentUser,
//     UpdateCurrentUser(UserFormData),
//     GetAccountFollowers(AccountID),
//     GetFollowing(AccountID),
//     GetAccountStatuses(AccountID),
//     FollowAccount(AccountID),
//     UnfollowAccount(AccountID),
//     BlockAccount(AccountID),
//     UnblockAccount(AccountID),
//     MuteAccount(AccountID),
//     UnmuteAccount(AccountID),
//     GetAccountRelationships(RelationshipsQuery),
//     SearchAccounts(SearchAccountsQuery)
// }

#[test]
fn api_request_fetch_account() {
    let client = Mastodon::new(BASE_URL).unwrap().client(MY_TOKEN).unwrap();
    let endpoint = APIEndpoint::FetchAccount(AccountID { id: 12345 });
    let request = client.build_request(endpoint).unwrap();
    assert_eq!(*request.method(), Get);
    assert_eq!(request.uri().path(), "/api/v1/accounts/12345")
}

#[test]
fn api_request_get_current_user() {
    let client = Mastodon::new(BASE_URL).unwrap().client(MY_TOKEN).unwrap();
    let endpoint = APIEndpoint::GetCurrentUser;
    let request = client.build_request(endpoint).unwrap();
    assert_eq!(*request.method(), Get);
    assert_eq!(request.uri().path(), "/api/v1/accounts/verify_credentials")
}

#[test]
fn api_request_update_current_user() {
    let client = Mastodon::new(BASE_URL).unwrap().client(MY_TOKEN).unwrap();
    let endpoint = APIEndpoint::UpdateCurrentUser(UserFormData::new(None, None, None, None));
    let request = client.build_request(endpoint).unwrap();
    assert_eq!(*request.method(), Patch);
    assert_eq!(request.uri().path(), "/api/v1/accounts/update_credentials")
}

#[test]
fn api_request_get_account_followers() {
    let client = Mastodon::new(BASE_URL).unwrap().client(MY_TOKEN).unwrap();
    let endpoint = APIEndpoint::GetAccountFollowers(AccountID { id: 12345 });
    let request = client.build_request(endpoint).unwrap();
    assert_eq!(*request.method(), Get);
    assert_eq!(request.uri().path(), "/api/v1/accounts/12345/followers")
}

#[test]
fn api_request_get_account_following() {
    let client = Mastodon::new(BASE_URL).unwrap().client(MY_TOKEN).unwrap();
    let endpoint = APIEndpoint::GetFollowing(AccountID { id: 12345 });
    let request = client.build_request(endpoint).unwrap();
    assert_eq!(*request.method(), Get);
    assert_eq!(request.uri().path(), "/api/v1/accounts/12345/following")
}

#[test]
fn api_request_get_account_statuses() {
    let client = Mastodon::new(BASE_URL).unwrap().client(MY_TOKEN).unwrap();
    let endpoint = APIEndpoint::GetAccountStatuses(AccountID { id: 12345 });
    let request = client.build_request(endpoint).unwrap();
    assert_eq!(*request.method(), Get);
    assert_eq!(request.uri().path(), "/api/v1/accounts/12345/statuses")
}

#[test]
fn api_request_following_an_account() {
    let client = Mastodon::new(BASE_URL).unwrap().client(MY_TOKEN).unwrap();
    let endpoint = APIEndpoint::FollowAccount(AccountID { id: 12345 });
    let request = client.build_request(endpoint).unwrap();
    assert_eq!(*request.method(), Post);
    assert_eq!(request.uri().path(), "/api/v1/accounts/12345/follow")
}

#[test]
fn api_request_unfollowing_an_account() {
    let client = Mastodon::new(BASE_URL).unwrap().client(MY_TOKEN).unwrap();
    let endpoint = APIEndpoint::UnfollowAccount(AccountID { id: 12345 });
    let request = client.build_request(endpoint).unwrap();
    assert_eq!(*request.method(), Post);
    assert_eq!(request.uri().path(), "/api/v1/accounts/12345/unfollow")
}

#[test]
fn api_request_block_an_account() {
    let client = Mastodon::new(BASE_URL).unwrap().client(MY_TOKEN).unwrap();
    let endpoint = APIEndpoint::BlockAccount(AccountID { id: 12345 });
    let request = client.build_request(endpoint).unwrap();
    assert_eq!(*request.method(), Post);
    assert_eq!(request.uri().path(), "/api/v1/accounts/12345/block")
}

#[test]
fn api_request_unblock_an_account() {
    let client = Mastodon::new(BASE_URL).unwrap().client(MY_TOKEN).unwrap();
    let endpoint = APIEndpoint::UnblockAccount(AccountID { id: 12345 });
    let request = client.build_request(endpoint).unwrap();
    assert_eq!(*request.method(), Post);
    assert_eq!(request.uri().path(), "/api/v1/accounts/12345/unblock")
}

#[test]
fn api_request_mute_an_account() {
    let client = Mastodon::new(BASE_URL).unwrap().client(MY_TOKEN).unwrap();
    let endpoint = APIEndpoint::MuteAccount(AccountID { id: 12345 });
    let request = client.build_request(endpoint).unwrap();
    assert_eq!(*request.method(), Post);
    assert_eq!(request.uri().path(), "/api/v1/accounts/12345/mute")
}

#[test]
fn api_request_unmute_an_account() {
    let client = Mastodon::new(BASE_URL).unwrap().client(MY_TOKEN).unwrap();
    let endpoint = APIEndpoint::UnmuteAccount(AccountID { id: 12345 });
    let request = client.build_request(endpoint).unwrap();
    assert_eq!(*request.method(), Post);
    assert_eq!(request.uri().path(), "/api/v1/accounts/12345/unmute")
}

#[test]
fn api_request_single_account_relationship() {
    let client = Mastodon::new(BASE_URL).unwrap().client(MY_TOKEN).unwrap();
    let query = RelationshipsQuery::SingleAccount(AccountID { id: 12345 });
    let endpoint = APIEndpoint::GetAccountRelationships(query);
    let request = client.build_request(endpoint).unwrap();
    assert_eq!(*request.method(), Get);
    assert_eq!(request.uri().path(), "/api/v1/accounts/relationships")
}

#[test]
fn api_request_many_accounts_relationship() {
    let client = Mastodon::new(BASE_URL).unwrap().client(MY_TOKEN).unwrap();
    let accounts = vec![AccountID { id: 12345 }, AccountID { id: 67890 }];
    let query = RelationshipsQuery::MultipleAccounts(accounts);
    let endpoint = APIEndpoint::GetAccountRelationships(query);
    let request = client.build_request(endpoint).unwrap();
    assert_eq!(*request.method(), Get);
    assert_eq!(request.uri().path(), "/api/v1/accounts/relationships")
}

#[test]
fn api_request_search_accounts() {
    let client = Mastodon::new(BASE_URL).unwrap().client(MY_TOKEN).unwrap();
    let query = SearchAccountsQuery { q: String::from("search text"), limit: None };
    let endpoint = APIEndpoint::SearchAccounts(query);
    let request = client.build_request(endpoint).unwrap();
    assert_eq!(*request.method(), Get);
    assert_eq!(request.uri().path(), "/api/v1/accounts/search")
}
<commit_msg>tests for all API v1 endpoint requests<commit_after>extern crate herder;
extern crate hyper;
extern crate url;

use herder::Mastodon;
use herder::api::v1::methods::{
    AccountID,
    APIEndpoint,
    APIEndpointRequest,
    RelationshipsQuery,
    SearchAccountsQuery,
    UserFormData
};
use herder::mastodon::NodeInstance;
use hyper::Method::{Get, Patch, Post};

const BASE_URL: &str = "http://localhost:3000";
const MY_TOKEN: &str = "MY_TOKEN";

// APIEndpoint::FetchAccount(AccountID)
#[test]
fn api_request_fetch_account() {
    let client = Mastodon::new(BASE_URL).unwrap().client(MY_TOKEN).unwrap();
    let endpoint = APIEndpoint::FetchAccount(AccountID { id: 12345 });
    let request = client.build_request(endpoint).unwrap();
    assert_eq!(*request.method(), Get);
    assert_eq!(request.uri().path(), "/api/v1/accounts/12345")
}

// APIEndpoint::GetCurrentUser,
#[test]
fn api_request_get_current_user() {
    let client = Mastodon::new(BASE_URL).unwrap().client(MY_TOKEN).unwrap();
    let endpoint = APIEndpoint::GetCurrentUser;
    let request = client.build_request(endpoint).unwrap();
    assert_eq!(*request.method(), Get);
    assert_eq!(request.uri().path(), "/api/v1/accounts/verify_credentials")
}

// APIEndpoint::UpdateCurrentUser(UserFormData)
#[test]
fn api_request_update_current_user() {
    let client = Mastodon::new(BASE_URL).unwrap().client(MY_TOKEN).unwrap();
    let endpoint = APIEndpoint::UpdateCurrentUser(UserFormData::new(None, None, None, None));
    let request = client.build_request(endpoint).unwrap();
    assert_eq!(*request.method(), Patch);
    assert_eq!(request.uri().path(), "/api/v1/accounts/update_credentials")
}

// APIEndpoint::GetAccountFollowers(AccountID)
#[test]
fn api_request_get_account_followers() {
    let client = Mastodon::new(BASE_URL).unwrap().client(MY_TOKEN).unwrap();
    let endpoint = APIEndpoint::GetAccountFollowers(AccountID { id: 12345 });
    let request = client.build_request(endpoint).unwrap();
    assert_eq!(*request.method(), Get);
    assert_eq!(request.uri().path(), "/api/v1/accounts/12345/followers")
}

// APIEndpoint::GetFollowing(AccountID)
#[test]
fn api_request_get_account_following() {
    let client = Mastodon::new(BASE_URL).unwrap().client(MY_TOKEN).unwrap();
    let endpoint = APIEndpoint::GetFollowing(AccountID { id: 12345 });
    let request = client.build_request(endpoint).unwrap();
    assert_eq!(*request.method(), Get);
    assert_eq!(request.uri().path(), "/api/v1/accounts/12345/following")
}

// APIEndpoint::GetAccountStatuses(AccountID)
#[test]
fn api_request_get_account_statuses() {
    let client = Mastodon::new(BASE_URL).unwrap().client(MY_TOKEN).unwrap();
    let endpoint = APIEndpoint::GetAccountStatuses(AccountID { id: 12345 });
    let request = client.build_request(endpoint).unwrap();
    assert_eq!(*request.method(), Get);
    assert_eq!(request.uri().path(), "/api/v1/accounts/12345/statuses")
}

// APIEndpoint::FollowAccount(AccountID)
#[test]
fn api_request_following_an_account() {
    let client = Mastodon::new(BASE_URL).unwrap().client(MY_TOKEN).unwrap();
    let endpoint = APIEndpoint::FollowAccount(AccountID { id: 12345 });
    let request = client.build_request(endpoint).unwrap();
    assert_eq!(*request.method(), Post);
    assert_eq!(request.uri().path(), "/api/v1/accounts/12345/follow")
}

// APIEndpoint::UnfollowAccount(AccountID)
#[test]
fn api_request_unfollowing_an_account() {
    let client = Mastodon::new(BASE_URL).unwrap().client(MY_TOKEN).unwrap();
    let endpoint = APIEndpoint::UnfollowAccount(AccountID { id: 12345 });
    let request = client.build_request(endpoint).unwrap();
    assert_eq!(*request.method(), Post);
    assert_eq!(request.uri().path(), "/api/v1/accounts/12345/unfollow")
}

// APIEndpoint::BlockAccount(AccountID)
#[test]
fn api_request_block_an_account() {
    let client = Mastodon::new(BASE_URL).unwrap().client(MY_TOKEN).unwrap();
    let endpoint = APIEndpoint::BlockAccount(AccountID { id: 12345 });
    let request = client.build_request(endpoint).unwrap();
    assert_eq!(*request.method(), Post);
    assert_eq!(request.uri().path(), "/api/v1/accounts/12345/block")
}

// APIEndpoint::UnblockAccount(AccountID)
#[test]
fn api_request_unblock_an_account() {
    let client = Mastodon::new(BASE_URL).unwrap().client(MY_TOKEN).unwrap();
    let endpoint = APIEndpoint::UnblockAccount(AccountID { id: 12345 });
    let request = client.build_request(endpoint).unwrap();
    assert_eq!(*request.method(), Post);
    assert_eq!(request.uri().path(), "/api/v1/accounts/12345/unblock")
}

// APIEndpoint::MuteAccount(AccountID)
#[test]
fn api_request_mute_an_account() {
    let client = Mastodon::new(BASE_URL).unwrap().client(MY_TOKEN).unwrap();
    let endpoint = APIEndpoint::MuteAccount(AccountID { id: 12345 });
    let request = client.build_request(endpoint).unwrap();
    assert_eq!(*request.method(), Post);
    assert_eq!(request.uri().path(), "/api/v1/accounts/12345/mute")
}

// APIEndpoint::UnmuteAccount(AccountID)
#[test]
fn api_request_unmute_an_account() {
    let client = Mastodon::new(BASE_URL).unwrap().client(MY_TOKEN).unwrap();
    let endpoint = APIEndpoint::UnmuteAccount(AccountID { id: 12345 });
    let request = client.build_request(endpoint).unwrap();
    assert_eq!(*request.method(), Post);
    assert_eq!(request.uri().path(), "/api/v1/accounts/12345/unmute")
}

// APIEndpoint::GetAccountRelationships(RelationshipsQuery::Single)
#[test]
fn api_request_single_account_relationship() {
    let client = Mastodon::new(BASE_URL).unwrap().client(MY_TOKEN).unwrap();
    let query = RelationshipsQuery::Single(AccountID { id: 12345 });
    let endpoint = APIEndpoint::GetAccountRelationships(query);
    let request = client.build_request(endpoint).unwrap();
    assert_eq!(*request.method(), Get);
    assert_eq!(request.uri().path(), "/api/v1/accounts/relationships")
}

// APIEndpoint::GetAccountRelationships(RelationshipsQuery::Many)
#[test]
fn api_request_many_accounts_relationship() {
    let client = Mastodon::new(BASE_URL).unwrap().client(MY_TOKEN).unwrap();
    let accounts = vec![AccountID { id: 12345 }, AccountID { id: 67890 }];
    let query = RelationshipsQuery::Many(accounts);
    let endpoint = APIEndpoint::GetAccountRelationships(query);
    let request = client.build_request(endpoint).unwrap();
    assert_eq!(*request.method(), Get);
    assert_eq!(request.uri().path(), "/api/v1/accounts/relationships")
}

// APIEndpoint::SearchAccounts(SearchAccountsQuery)
#[test]
fn api_request_search_accounts() {
    let client = Mastodon::new(BASE_URL).unwrap().client(MY_TOKEN).unwrap();
    let query = SearchAccountsQuery { q: String::from("search text"), limit: None };
    let endpoint = APIEndpoint::SearchAccounts(query);
    let request = client.build_request(endpoint).unwrap();
    assert_eq!(*request.method(), Get);
    assert_eq!(request.uri().path(), "/api/v1/accounts/search")
}
#[test]
// APIEndpoint::FetchBlocks(AccountID)
fn api_request_fetch_blocks() {
    let client = Mastodon::new(BASE_URL).unwrap().client(MY_TOKEN).unwrap();
    let endpoint = APIEndpoint::FetchBlocks(AccountID { id: 12345 });
    let request = client.build_request(endpoint).unwrap();
    assert_eq!(*request.method(), Post);
    assert_eq!(request.uri().path(), "/api/v1/accounts/12345/mute")
}
// APIEndpoint::FetchFollowRequests(AccountID)
#[test]
fn api_request_fetch_favourites() {
    unimplemented!()
}
// APIEndpoint::FetchFollowRequests(Query)
#[test]
fn api_request_fetch_follow_requests() {
    unimplemented!()
}
// APIEndpoint::AuthorizeFollowRequest(FormData)
#[test]
fn api_request_authorize_follow_request(){
}
// APIEndpoint::RejectFollowRequest(FormData)
#[test]
fn api_request_reject_follow_request() {
    unimplemented!()
}
// APIEndpoint::FollowRemoteUser(FormData)
#[test]
fn api_request_follow_remote_user() {
    unimplemented!()
}
// APIEndpoint::GetInstance
#[test]
fn api_request_get_instance() {
    unimplemented!()
}
// APIEndpoint::UploadMedia
#[test]
fn api_request_upload_media() {
    unimplemented!()
}
// APIEndpoint::FetchMutes(Query)
#[test]
fn api_request_fetch_mutes() {
    unimplemented!()
}
// APIEndpoint::FetchNotifications(Query)
#[test]
fn api_request_fetch_notifications() {
    unimplemented!()
}
// APIEndpoint::GetNotification(NotificationID)
#[test]
fn api_request_get_notification() {
    unimplemented!()
}
// APIEndpoint::ClearNotifications
#[test]
fn api_request_clear_notifications() {
    unimplemented!()
}
// APIEndpoint::FetchingReports
#[test]
fn api_request_fetching_reports() {
    unimplemented!()
}
// APIEndpoint::ReportingUser(UserReport)
#[test]
fn api_request_reporting_user() {
    unimplemented!()
}
// APIEndpoint::SearchContent(ContentQuery)
#[test]
fn api_request_search_content() {
    unimplemented!()
}
// APIEndpoint::FetchStatus(StatusID)
#[test]
fn api_request_fetch_status() {
    unimplemented!()
}
// APIEndpoint::GetStatusContext(StatusID)
#[test]
fn api_request_get_status_context() {
    unimplemented!()
}
// APIEndpoint::GetStatusCard(StatusID)
#[test]
fn api_request_get_status_card() {
    unimplemented!()
}
// APIEndpoint::RebloggedBy(StatusID)
#[test]
fn api_request_reblogged_by() {
    unimplemented!()
}
// APIEndpoint::FavouritedBy(StatusID)
#[test]
fn api_request_favourited_by() {
    unimplemented!()
}
// APIEndpoint::PostStatus(PostFormData)
#[test]
fn api_request_post_status() {
    unimplemented!()
}
// APIEndpoint::DeleteStatus(StatusID)
#[test]
fn api_request_delete_status() {
    unimplemented!()
}
// APIEndpoint::ReblogStatus(StatusID)
#[test]
fn api_request_reblog_status() {
    unimplemented!()
}
// APIEndpoint::UnreblogStatus(StatusID)
#[test]
fn api_request_unreblog_status() {
    unimplemented!()
}
// APIEndpoint::FavouriteStatus(StatusID)
#[test]
fn api_request_favourite_status() {
    unimplemented!()
}
// APIEndpoint::UnfavouriteStatus(StatusID)
#[test]
fn api_request_unfavourite_status() {
    unimplemented!()
}
// APIEndpoint::PublicTimeLine(PublicQuery)
#[test]
fn api_request_home_timeline() {
    unimplemented!()
}
// APIEndpoint::PublicTimeLine(PublicQuery)
#[test]
fn api_request_public_timeline() {
    unimplemented!()
}
// APIEndpoint::TagTimeLine(Tag, TagQuery)
#[test]
fn api_request_tag_timeline() {
    unimplemented!()
}
<|endoftext|>


<commit_before>use ffmpeg_sys;
use libc::*;
use std::cmp;
use std::ffi::{ CStr, CString };
use std::ops::Deref;
use std::ptr;

use errors::*;

#[derive(Debug, Clone, Copy)]
pub struct Rational {
    pub numerator: i32,
    pub denominator: i32,
}

#[derive(Clone, Copy)]
pub struct Codec {
    ptr: *mut ffmpeg_sys::AVCodec,
}

unsafe impl Send for Codec {}
unsafe impl Sync for Codec {}

pub struct PixelFormats {
    codec: Codec,
    index: isize,
}

pub struct Context {
    // The Codec which was used to initialize this Context.
    codec: Codec,
    ptr: *mut ffmpeg_sys::AVCodecContext,
}

pub struct OpenContext {
    context: Context,
}

pub struct Frame {
    ptr: *mut ffmpeg_sys::AVFrame,
}

impl From<(i32, i32)> for Rational {
    fn from((numerator, denominator): (i32, i32)) -> Self {
        Self {
            numerator,
            denominator,
        }
    }
}

impl From<ffmpeg_sys::AVRational> for Rational {
    fn from(rational: ffmpeg_sys::AVRational) -> Self {
        Self {
            numerator: rational.num,
            denominator: rational.den,
        }
    }
}

impl From<Rational> for ffmpeg_sys::AVRational {
    fn from(rational: Rational) -> Self {
        Self {
            num: rational.numerator,
            den: rational.denominator,
        }
    }
}

impl Codec {
    pub fn description(self) -> String {
        unsafe {
            CStr::from_ptr((*self.ptr).long_name).to_string_lossy().into_owned()
        }
    }

    #[inline]
    pub fn kind(self) -> ffmpeg_sys::AVMediaType {
        unsafe {
            (*self.ptr).kind
        }
    }

    #[inline]
    pub fn is_video(self) -> bool {
        self.kind() == ffmpeg_sys::AVMediaType::AVMEDIA_TYPE_VIDEO
    }

    pub fn pixel_formats(self) -> Option<PixelFormats> {
        unsafe {
            if (*self.ptr).pix_fmts.is_null() {
                None
            } else {
                Some(PixelFormats::new(self))
            }
        }
    }

    pub fn context(self) -> Result<Context> {
        let ptr = unsafe {
            ffmpeg_sys::avcodec_alloc_context3(self.ptr)
        };

        ensure!(!ptr.is_null(), "unable to allocate the codec context");

        Ok(Context {
            codec: self,
            ptr,
        })
    }
}

impl PixelFormats {
    fn new(codec: Codec) -> Self {
        Self {
            codec,
            index: 0,
        }
    }
}

impl Iterator for PixelFormats {
    type Item = ffmpeg_sys::AVPixelFormat;

    fn next(&mut self) -> Option<Self::Item> {
        let format = unsafe {
            *(*self.codec.ptr).pix_fmts.offset(self.index)
        };

        if format == ffmpeg_sys::AVPixelFormat::AV_PIX_FMT_NONE {
            None
        } else {
            self.index += 1;
            Some(format)
        }
    }
}

impl Context {
    #[inline]
    pub fn width(&self) -> u32 {
        unsafe {
            cmp::max(0, (*self.ptr).width) as u32
        }
    }

    #[inline]
    pub fn set_width(&mut self, width: u32) {
        unsafe {
            (*self.ptr).width = cmp::min(width, c_int::max_value() as u32) as c_int;
        }
    }

    #[inline]
    pub fn height(&self) -> u32 {
        unsafe {
            cmp::max(0, (*self.ptr).height) as u32
        }
    }

    #[inline]
    pub fn set_height(&mut self, height: u32) {
        unsafe {
            (*self.ptr).height = cmp::min(height, c_int::max_value() as u32) as c_int;
        }
    }

    #[inline]
    pub fn time_base(&self) -> Rational {
        unsafe {
            (*self.ptr).time_base.into()
        }
    }

    #[inline]
    pub fn set_time_base(&mut self, time_base: &Rational) {
        unsafe {
            (*self.ptr).time_base = (*time_base).into();
        }
    }

    #[inline]
    pub fn pixel_format(&self) -> ffmpeg_sys::AVPixelFormat {
        unsafe {
            (*self.ptr).pix_fmt
        }
    }

    #[inline]
    pub fn set_pixel_format(&mut self, pixel_format: ffmpeg_sys::AVPixelFormat) {
        unsafe {
            (*self.ptr).pix_fmt = pixel_format;
        }
    }

    pub fn open(self) -> Result<OpenContext> {
        let rv = unsafe {
            ffmpeg_sys::avcodec_open2(self.ptr, self.codec.ptr, ptr::null_mut())
        };

        ensure!(rv == 0, "error opening context");

        Ok(OpenContext { context: self })
    }
}

impl Drop for Context {
    fn drop(&mut self) {
        unsafe {
            ffmpeg_sys::avcodec_free_context(&mut self.ptr);
        }
    }
}

impl Drop for Frame {
    fn drop(&mut self) {
        unsafe {
            ffmpeg_sys::av_frame_free(&mut self.ptr);
        }
    }
}

pub fn initialize() {
    unsafe {
        ffmpeg_sys::av_register_all();
        ffmpeg_sys::avcodec_register_all();
    }
}

pub fn find_encoder_by_name(name: &str) -> Result<Option<Codec>> {
    let name = CString::new(name).chain_err(|| "could not convert name to CString")?;

    let codec = unsafe {
        ffmpeg_sys::avcodec_find_encoder_by_name(name.as_ptr())
    };

    if codec.is_null() {
        Ok(None)
    } else {
        Ok(Some(Codec { ptr: codec }))
    }
}
<commit_msg>Add Frame::new()<commit_after>use ffmpeg_sys;
use libc::*;
use std::cmp;
use std::ffi::{ CStr, CString };
use std::ops::Deref;
use std::ptr;

use errors::*;

#[derive(Debug, Clone, Copy)]
pub struct Rational {
    pub numerator: i32,
    pub denominator: i32,
}

#[derive(Clone, Copy)]
pub struct Codec {
    ptr: *mut ffmpeg_sys::AVCodec,
}

unsafe impl Send for Codec {}
unsafe impl Sync for Codec {}

pub struct PixelFormats {
    codec: Codec,
    index: isize,
}

pub struct Context {
    // The Codec which was used to initialize this Context.
    codec: Codec,
    ptr: *mut ffmpeg_sys::AVCodecContext,
}

pub struct OpenContext {
    context: Context,
}

pub struct Frame {
    ptr: *mut ffmpeg_sys::AVFrame,
}

impl From<(i32, i32)> for Rational {
    fn from((numerator, denominator): (i32, i32)) -> Self {
        Self {
            numerator,
            denominator,
        }
    }
}

impl From<ffmpeg_sys::AVRational> for Rational {
    fn from(rational: ffmpeg_sys::AVRational) -> Self {
        Self {
            numerator: rational.num,
            denominator: rational.den,
        }
    }
}

impl From<Rational> for ffmpeg_sys::AVRational {
    fn from(rational: Rational) -> Self {
        Self {
            num: rational.numerator,
            den: rational.denominator,
        }
    }
}

impl Codec {
    pub fn description(self) -> String {
        unsafe {
            CStr::from_ptr((*self.ptr).long_name).to_string_lossy().into_owned()
        }
    }

    #[inline]
    pub fn kind(self) -> ffmpeg_sys::AVMediaType {
        unsafe {
            (*self.ptr).kind
        }
    }

    #[inline]
    pub fn is_video(self) -> bool {
        self.kind() == ffmpeg_sys::AVMediaType::AVMEDIA_TYPE_VIDEO
    }

    pub fn pixel_formats(self) -> Option<PixelFormats> {
        unsafe {
            if (*self.ptr).pix_fmts.is_null() {
                None
            } else {
                Some(PixelFormats::new(self))
            }
        }
    }

    pub fn context(self) -> Result<Context> {
        let ptr = unsafe {
            ffmpeg_sys::avcodec_alloc_context3(self.ptr)
        };

        ensure!(!ptr.is_null(), "unable to allocate the codec context");

        Ok(Context {
            codec: self,
            ptr,
        })
    }
}

impl PixelFormats {
    fn new(codec: Codec) -> Self {
        Self {
            codec,
            index: 0,
        }
    }
}

impl Iterator for PixelFormats {
    type Item = ffmpeg_sys::AVPixelFormat;

    fn next(&mut self) -> Option<Self::Item> {
        let format = unsafe {
            *(*self.codec.ptr).pix_fmts.offset(self.index)
        };

        if format == ffmpeg_sys::AVPixelFormat::AV_PIX_FMT_NONE {
            None
        } else {
            self.index += 1;
            Some(format)
        }
    }
}

impl Context {
    #[inline]
    pub fn width(&self) -> u32 {
        unsafe {
            cmp::max(0, (*self.ptr).width) as u32
        }
    }

    #[inline]
    pub fn set_width(&mut self, width: u32) {
        unsafe {
            (*self.ptr).width = cmp::min(width, c_int::max_value() as u32) as c_int;
        }
    }

    #[inline]
    pub fn height(&self) -> u32 {
        unsafe {
            cmp::max(0, (*self.ptr).height) as u32
        }
    }

    #[inline]
    pub fn set_height(&mut self, height: u32) {
        unsafe {
            (*self.ptr).height = cmp::min(height, c_int::max_value() as u32) as c_int;
        }
    }

    #[inline]
    pub fn time_base(&self) -> Rational {
        unsafe {
            (*self.ptr).time_base.into()
        }
    }

    #[inline]
    pub fn set_time_base(&mut self, time_base: &Rational) {
        unsafe {
            (*self.ptr).time_base = (*time_base).into();
        }
    }

    #[inline]
    pub fn pixel_format(&self) -> ffmpeg_sys::AVPixelFormat {
        unsafe {
            (*self.ptr).pix_fmt
        }
    }

    #[inline]
    pub fn set_pixel_format(&mut self, pixel_format: ffmpeg_sys::AVPixelFormat) {
        unsafe {
            (*self.ptr).pix_fmt = pixel_format;
        }
    }

    pub fn open(self) -> Result<OpenContext> {
        let rv = unsafe {
            ffmpeg_sys::avcodec_open2(self.ptr, self.codec.ptr, ptr::null_mut())
        };

        ensure!(rv == 0, "error opening context");

        Ok(OpenContext { context: self })
    }
}

impl Drop for Context {
    fn drop(&mut self) {
        unsafe {
            ffmpeg_sys::avcodec_free_context(&mut self.ptr);
        }
    }
}

impl Frame {
    pub fn new() -> Result<Self> {
        let ptr = unsafe {
            ffmpeg_sys::av_frame_alloc()
        };

        ensure!(!ptr.is_null(), "unable to allocate a frame");

        Ok(Self { ptr })
    }
}

impl Drop for Frame {
    fn drop(&mut self) {
        unsafe {
            ffmpeg_sys::av_frame_free(&mut self.ptr);
        }
    }
}

pub fn initialize() {
    unsafe {
        ffmpeg_sys::av_register_all();
        ffmpeg_sys::avcodec_register_all();
    }
}

pub fn find_encoder_by_name(name: &str) -> Result<Option<Codec>> {
    let name = CString::new(name).chain_err(|| "could not convert name to CString")?;

    let codec = unsafe {
        ffmpeg_sys::avcodec_find_encoder_by_name(name.as_ptr())
    };

    if codec.is_null() {
        Ok(None)
    } else {
        Ok(Some(Codec { ptr: codec }))
    }
}
<|endoftext|>


<commit_before>// Allow unstable items until Rust hits 1.0
#![feature(core)]
#![feature(io)]
#![feature(env)]
#![feature(path)]
#![feature(fs)]

extern crate yaml;

use yaml::constructor::YamlStandardData;
use yaml::ffi::YamlEncoding;
use std::env;
use std::path;
use std::io::BufReader;
use std::fs::File;

fn match_utf8(filename: &str, expected: YamlStandardData) {
    match_file(YamlEncoding::YamlUtf8Encoding, filename, expected);
}

fn match_file(encoding: yaml::ffi::YamlEncoding, filename: &str, expected: YamlStandardData) {
    let mut args = env::args();
    let this_path = args.next().unwrap();
    let dir_path = path::Path::new(this_path.as_slice()).parent().unwrap();
    let file_path = dir_path.join("../tests/source").join(filename);
    println!("{}", file_path.display());
    let file = match File::open(&file_path) {
        Ok(f) => f,
        Err(e) => panic!("Failed to open file {}: {}", file_path.to_str().unwrap(), e)
    };
    let mut reader = BufReader::new(file);
    match yaml::parse_io(&mut reader, encoding) {
        Ok(docs) => if docs.len() == 1 {
            assert_eq!(docs.as_slice().first().unwrap(), &expected)
        } else {
            panic!("too many number of documents: {:?}", docs)
        },
        Err(e) => panic!("parse failure: {:?}", e)
    }
}

macro_rules! ystr{
    ($e: expr) => (
        YamlStandardData::YamlString($e.to_string())
    )
}

macro_rules! yint{
    ($e: expr) => (
        YamlStandardData::YamlInteger($e)
    )
}

macro_rules! yfloat{
    ($e: expr) => (
        YamlStandardData::YamlFloat($e)
    )
}

macro_rules! yseq{
    ($($e:expr),*) => (
        YamlStandardData::YamlSequence(vec![$(($e),)*])
    )
}

macro_rules! ymap{
    ($($k:expr => $v:expr),*) => (
        YamlStandardData::YamlMapping(vec![$((ystr!($k), $v),)*])
    )
}

macro_rules! y_cmp_map{
    ($($k:expr => $v:expr),*) => (
        YamlStandardData::YamlMapping(vec![$(($k, $v),)*])
    )
}

#[test]
fn sequence_of_scalars() {
    match_utf8("ball_players.yml", yseq![ystr!("Mark McGwire"), ystr!("Sammy Sosa"), ystr!("Ken Griffey")]);
}

#[test]
fn scalar_mappings() {
    match_utf8("player_stat.yml", ymap!{
                                    "hr" => yint!(65),
                                    "avg" => yfloat!(0.278),
                                    "rbi" => yint!(147)
                                })
}

#[test]
fn maps_of_sequences() {
    match_utf8("ball_clubs.yml", ymap!{
                                    "american" => yseq![ystr!("Boston Red Sox"), ystr!("Detroit Tigers"), ystr!("New York Yankees")],
                                    "national" => yseq![ystr!("New York Mets"), ystr!("Chicago Cubs"), ystr!("Atlanta Braves")]
                                })
}

#[test]
fn sequence_of_maps() {
    match_utf8("multiple_player_stat.yml",
    yseq![
        ymap!{
            "name" => ystr!("Mark McGwire"),
            "hr" => yint!(65)
        },
        ymap!{
            "name" => ystr!("Sammy Sosa"),
            "hr" => yint!(63)
        }
    ])
}

#[test]
fn sequence_of_sequences() {
    match_utf8("csv.yml",
    yseq![
        yseq![ystr!("name"), ystr!("hr")],
        yseq![ystr!("Mark McGwire"), yint!(65)],
        yseq![ystr!("Sammy Sosa"), yint!(63)]
    ])
}

#[test]
fn mapping_of_mappings() {
    match_utf8("map_map.yml",
    ymap!{
        "Mark McGwire" => ymap!{ "hr" => yint!(65) },
        "Sammy Sosa" => ymap!{ "hr" => yint!(63) }
    })
}

#[test]
fn alias() {
    match_utf8("alias.yml",
    ymap!{
        "hr" => yseq![ystr!("Mark McGwire"), ystr!("Sammy Sosa")],
        "rbi" => yseq![ystr!("Sammy Sosa"), ystr!("Ken Griffey")]
    })
}

#[test]
fn complex_keys() {
    match_utf8("complex_key.yml",
    y_cmp_map!{
        yseq![ystr!("Detroit Tigers"), ystr!("Chicago Cubs")] => yseq![ystr!("2001-07-23")],
        yseq![ystr!("New York Yankees"), ystr!("Atlanta Braves")] => yseq![ystr!("2001-07-02"), ystr!("2001-08-12"), ystr!("2001-08-14")]
    })
}

#[test]
fn block_literal() {
    match_utf8("block_literal.yml", ystr!("\\//||\\/||\n// ||  ||__\n"))
}

#[test]
fn plain_scalar() {
    match_utf8("plain_scalar.yml", ystr!("Mark McGwire's year was crippled by a knee injury."))
}

#[test]
fn quoted_scalar() {
    match_utf8("quoted_scalar.yml",
    ymap!{
        "unicode" => ystr!("Sosa did fine.\u{263A}"),
        "control" => ystr!("\x081998\t1999\t2000\n"),
        "hexesc" =>  ystr!("\x13\x10 is \r\n"),
        "single" => ystr!(r#""Howdy!" he cried."#),
        "quoted" => ystr!(" # not a 'comment'."),
        "tie-fighter" => ystr!(r"|\-*-/|")
    })
}

#[test]
fn multi_line_scalar() {
    match_utf8("multi_line_scalar.yml",
    ymap!{
        "plain" => ystr!("This unquoted scalar spans many lines."),
        "quoted" => ystr!("So does this quoted scalar.\n")
    })
}

#[test]
fn utf16le() {
    match_file(YamlEncoding::YamlUtf16LeEncoding, "utf16le.yml",
               yseq![ystr!("Hello"), ystr!("世界")]
    )
}

#[test]
fn utf16be() {
    match_file(YamlEncoding::YamlUtf16BeEncoding, "utf16be.yml",
               yseq![ystr!("Hello"), ystr!("世界")]
    )
}
<commit_msg>Use include_bytes! compiler feature for the test<commit_after>// Allow unstable items until Rust hits 1.0

extern crate yaml;

use yaml::constructor::YamlStandardData;
use yaml::ffi::YamlEncoding;
use std::io::Cursor;

macro_rules! test_utf8{
    ($filename: expr, $expected: expr) => (
        test_file!(yaml::ffi::YamlEncoding::YamlUtf8Encoding, $filename, $expected)
    )
}

macro_rules! test_file{
    ($encoding: expr, $filename: expr, $expected: expr) => (
        {
            let data = include_bytes!($filename);
            let mut reader = Cursor::new(data);
            match yaml::parse_io(&mut reader, $encoding) {
                Ok(docs) => if docs.len() == 1 {
                    assert_eq!(docs[..].first().unwrap(), &$expected)
                } else {
                    panic!("too many number of documents: {:?}", docs)
                },
                Err(e) => panic!("parse failure: {:?}", e)
            }
        }
    )
}

macro_rules! ystr{
    ($e: expr) => (
        YamlStandardData::YamlString($e.to_string())
    )
}

macro_rules! yint{
    ($e: expr) => (
        YamlStandardData::YamlInteger($e)
    )
}

macro_rules! yfloat{
    ($e: expr) => (
        YamlStandardData::YamlFloat($e)
    )
}

macro_rules! yseq{
    ($($e:expr),*) => (
        YamlStandardData::YamlSequence(vec![$(($e),)*])
    )
}

macro_rules! ymap{
    ($($k:expr => $v:expr),*) => (
        YamlStandardData::YamlMapping(vec![$((ystr!($k), $v),)*])
    )
}

macro_rules! y_cmp_map{
    ($($k:expr => $v:expr),*) => (
        YamlStandardData::YamlMapping(vec![$(($k, $v),)*])
    )
}

#[test]
fn sequence_of_scalars() {
    test_utf8!("source/ball_players.yml", yseq![ystr!("Mark McGwire"), ystr!("Sammy Sosa"), ystr!("Ken Griffey")]);
}

#[test]
fn scalar_mappings() {
    test_utf8!("source/player_stat.yml", ymap!{
                                    "hr" => yint!(65),
                                    "avg" => yfloat!(0.278),
                                    "rbi" => yint!(147)
                                })
}

#[test]
fn maps_of_sequences() {
    test_utf8!("source/ball_clubs.yml", ymap!{
                                    "american" => yseq![ystr!("Boston Red Sox"), ystr!("Detroit Tigers"), ystr!("New York Yankees")],
                                    "national" => yseq![ystr!("New York Mets"), ystr!("Chicago Cubs"), ystr!("Atlanta Braves")]
                                })
}

#[test]
fn sequence_of_maps() {
    test_utf8!("source/multiple_player_stat.yml",
    yseq![
        ymap!{
            "name" => ystr!("Mark McGwire"),
            "hr" => yint!(65)
        },
        ymap!{
            "name" => ystr!("Sammy Sosa"),
            "hr" => yint!(63)
        }
    ])
}

#[test]
fn sequence_of_sequences() {
    test_utf8!("source/csv.yml",
    yseq![
        yseq![ystr!("name"), ystr!("hr")],
        yseq![ystr!("Mark McGwire"), yint!(65)],
        yseq![ystr!("Sammy Sosa"), yint!(63)]
    ])
}

#[test]
fn mapping_of_mappings() {
    test_utf8!("source/map_map.yml",
    ymap!{
        "Mark McGwire" => ymap!{ "hr" => yint!(65) },
        "Sammy Sosa" => ymap!{ "hr" => yint!(63) }
    })
}

#[test]
fn alias() {
    test_utf8!("source/alias.yml",
    ymap!{
        "hr" => yseq![ystr!("Mark McGwire"), ystr!("Sammy Sosa")],
        "rbi" => yseq![ystr!("Sammy Sosa"), ystr!("Ken Griffey")]
    })
}

#[test]
fn complex_keys() {
    test_utf8!("source/complex_key.yml",
    y_cmp_map!{
        yseq![ystr!("Detroit Tigers"), ystr!("Chicago Cubs")] => yseq![ystr!("2001-07-23")],
        yseq![ystr!("New York Yankees"), ystr!("Atlanta Braves")] => yseq![ystr!("2001-07-02"), ystr!("2001-08-12"), ystr!("2001-08-14")]
    })
}

#[test]
fn block_literal() {
    test_utf8!("source/block_literal.yml", ystr!("\\//||\\/||\n// ||  ||__\n"))
}

#[test]
fn plain_scalar() {
    test_utf8!("source/plain_scalar.yml", ystr!("Mark McGwire's year was crippled by a knee injury."))
}

#[test]
fn quoted_scalar() {
    test_utf8!("source/quoted_scalar.yml",
    ymap!{
        "unicode" => ystr!("Sosa did fine.\u{263A}"),
        "control" => ystr!("\x081998\t1999\t2000\n"),
        "hexesc" =>  ystr!("\x13\x10 is \r\n"),
        "single" => ystr!(r#""Howdy!" he cried."#),
        "quoted" => ystr!(" # not a 'comment'."),
        "tie-fighter" => ystr!(r"|\-*-/|")
    })
}

#[test]
fn multi_line_scalar() {
    test_utf8!("source/multi_line_scalar.yml",
    ymap!{
        "plain" => ystr!("This unquoted scalar spans many lines."),
        "quoted" => ystr!("So does this quoted scalar.\n")
    })
}

#[test]
fn utf16le() {
    test_file!(YamlEncoding::YamlUtf16LeEncoding, "source/utf16le.yml",
               yseq![ystr!("Hello"), ystr!("世界")]
    )
}

#[test]
fn utf16be() {
    test_file!(YamlEncoding::YamlUtf16BeEncoding, "source/utf16be.yml",
               yseq![ystr!("Hello"), ystr!("世界")]
    )
}
<|endoftext|>


<commit_before>// Copyright 2013-2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

#![cfg_attr(not(feature = "v3_10"), allow(unused_imports))]

use libc::{c_char, ssize_t};

use glib::Object;
use glib::object::{Downcast, IsA};
use glib::translate::*;
use ffi;

glib_wrapper! {
    pub struct Buildable(Object<ffi::GtkBuildable>);

    match fn {
        get_type => || ffi::gtk_buildable_get_type(),
    }
}

glib_wrapper! {
    pub struct Builder(Object<ffi::GtkBuilder>);

    match fn {
        get_type => || ffi::gtk_builder_get_type(),
    }
}

impl Builder {
    pub fn new() -> Builder {
        assert_initialized_main_thread!();
        unsafe { from_glib_full(ffi::gtk_builder_new()) }
    }

    #[cfg(feature = "v3_10")]
    pub fn new_from_file(file_name: &str) -> Builder {
        assert_initialized_main_thread!();
        unsafe { from_glib_full(ffi::gtk_builder_new_from_file(file_name.to_glib_none().0)) }
    }

    #[cfg(feature = "v3_10")]
    pub fn new_from_resource(resource_path: &str) -> Builder {
        assert_initialized_main_thread!();
        unsafe {
            from_glib_full(ffi::gtk_builder_new_from_resource(resource_path.to_glib_none().0))
        }
    }

    #[cfg(feature = "v3_10")]
    pub fn new_from_string(string: &str) -> Builder {
        assert_initialized_main_thread!();
        unsafe {
            // Don't need a null-terminated string here
            from_glib_full(
                ffi::gtk_builder_new_from_string(string.as_ptr() as *const c_char,
                    string.len() as ssize_t))
        }
    }

    pub fn get_object<T>(&self, name: &str) -> Option<T>
    where T: IsA<Buildable> + IsA<Object> {
        unsafe {
            Option::<Object>::from_glib_none(
                ffi::gtk_builder_get_object(self.to_glib_none().0, name.to_glib_none().0))
                .and_then(|obj| obj.downcast().ok())
        }
    }
}
<commit_msg>Remove the IsA<Buildable> bound on Builder::get_object<commit_after>// Copyright 2013-2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

#![cfg_attr(not(feature = "v3_10"), allow(unused_imports))]

use libc::{c_char, ssize_t};

use glib::Object;
use glib::object::{Downcast, IsA};
use glib::translate::*;
use ffi;

glib_wrapper! {
    pub struct Buildable(Object<ffi::GtkBuildable>);

    match fn {
        get_type => || ffi::gtk_buildable_get_type(),
    }
}

glib_wrapper! {
    pub struct Builder(Object<ffi::GtkBuilder>);

    match fn {
        get_type => || ffi::gtk_builder_get_type(),
    }
}

impl Builder {
    pub fn new() -> Builder {
        assert_initialized_main_thread!();
        unsafe { from_glib_full(ffi::gtk_builder_new()) }
    }

    #[cfg(feature = "v3_10")]
    pub fn new_from_file(file_name: &str) -> Builder {
        assert_initialized_main_thread!();
        unsafe { from_glib_full(ffi::gtk_builder_new_from_file(file_name.to_glib_none().0)) }
    }

    #[cfg(feature = "v3_10")]
    pub fn new_from_resource(resource_path: &str) -> Builder {
        assert_initialized_main_thread!();
        unsafe {
            from_glib_full(ffi::gtk_builder_new_from_resource(resource_path.to_glib_none().0))
        }
    }

    #[cfg(feature = "v3_10")]
    pub fn new_from_string(string: &str) -> Builder {
        assert_initialized_main_thread!();
        unsafe {
            // Don't need a null-terminated string here
            from_glib_full(
                ffi::gtk_builder_new_from_string(string.as_ptr() as *const c_char,
                    string.len() as ssize_t))
        }
    }

    pub fn get_object<T: IsA<Object>>(&self, name: &str) -> Option<T> {
        unsafe {
            Option::<Object>::from_glib_none(
                ffi::gtk_builder_get_object(self.to_glib_none().0, name.to_glib_none().0))
                .and_then(|obj| obj.downcast().ok())
        }
    }
}
<|endoftext|>


<commit_before>use {Action, InputTranslator, InputRebind, MouseTranslationData};
use input::Button;
use window::Size;
use std::convert::Into;
use std::default::Default;

/// Convenience object for constructing an InputMap
pub struct RebindBuilder<A: Action> {
    input_remappings: Vec<(Button, A)>,
    mouse_data: MouseTranslationData
}

impl<A: Action> RebindBuilder<A> {
    #[allow(missing_docs)]
    pub fn new(size: Size) -> Self {
        RebindBuilder {
            input_remappings: vec![],
            mouse_data: MouseTranslationData::new(size)
        }
    }

    #[allow(missing_docs)]
    pub fn x_scroll_inverted(mut self, invert: bool) -> Self {
        self.mouse_data.x_axis_scroll_inverted = invert;
        self
    }

    #[allow(missing_docs)]
    pub fn get_x_scroll_inverted(&self) -> &bool {
        &self.mouse_data.x_axis_scroll_inverted
    }

    #[allow(missing_docs)]
    pub fn y_scroll_inverted(mut self, invert: bool) -> Self {
        self.mouse_data.y_axis_scroll_inverted = invert;
        self
    }

    #[allow(missing_docs)]
    pub fn get_y_scroll_inverted(&self) -> &bool {
        &self.mouse_data.y_axis_scroll_inverted
    }

    #[allow(missing_docs)]
    pub fn x_motion_inverted(mut self, invert: bool) -> Self {
        self.mouse_data.x_axis_motion_inverted = invert;
        self
    }

    #[allow(missing_docs)]
    pub fn get_x_motion_inverted(&self) -> &bool {
        &self.mouse_data.x_axis_motion_inverted
    }

    #[allow(missing_docs)]
    pub fn y_motion_inverted(mut self, invert: bool) -> Self {
        self.mouse_data.y_axis_motion_inverted = invert;
        self
    }

    #[allow(missing_docs)]
    pub fn get_y_motion_inverted(&self) -> &bool {
        &self.mouse_data.y_axis_motion_inverted
    }

    #[allow(missing_docs)]
    pub fn viewport_size(mut self, sz: Size) -> Self {
        self.mouse_data.viewport_size = sz;
        self
    }

    #[allow(missing_docs)]
    pub fn get_viewport_size(&self) -> &Size {
        &self.mouse_data.viewport_size
    }

    #[allow(missing_docs)]
    pub fn with_action_mapping(mut self, but: Button, act: A) -> Self {
        self.input_remappings.push((but, act));
        self
    }

    #[allow(missing_docs)]
    pub fn build_translator(self) -> InputTranslator<A> { self.into() }

    #[allow(missing_docs)]
    pub fn build_rebind(self) -> InputRebind<A> { self.into() }
}

impl<A: Action> Default for RebindBuilder<A> {
    #[allow(missing_docs)]
    fn default() -> Self {
        Self::new((800, 600).into())
    }
}

impl<A: Action> Into<InputTranslator<A>> for RebindBuilder<A> {
    #[allow(missing_docs)]
    fn into(self) -> InputTranslator<A> {
        let mut input_map = InputTranslator::new(self.mouse_data.viewport_size);

        input_map.mouse_translator.data = self.mouse_data;
        input_map.keymap = self.input_remappings.iter().cloned().collect();

        input_map
    }
}

impl<A: Action> Into<InputRebind<A>> for RebindBuilder<A> {
    #[allow(missing_docs, dead_code, unused_variables, unreachable_code)]
    fn into(self) -> InputRebind<A> {
        unimplemented!();

        let mut input_rebind = InputRebind::new(self.mouse_data.viewport_size);

        input_rebind.mouse_data = self.mouse_data;
        //input_rebind.keymap.btn_map = self.input_remappings.iter().map(|x| x.clone()).collect();

        input_rebind
    }
}

<commit_msg>Remove unnecessary allow(missing_docs) annotations<commit_after>use {Action, InputTranslator, InputRebind, MouseTranslationData};
use input::Button;
use window::Size;
use std::convert::Into;
use std::default::Default;

/// Convenience object for constructing an InputMap
pub struct RebindBuilder<A: Action> {
    input_remappings: Vec<(Button, A)>,
    mouse_data: MouseTranslationData
}

impl<A: Action> RebindBuilder<A> {
    #[allow(missing_docs)]
    pub fn new(size: Size) -> Self {
        RebindBuilder {
            input_remappings: vec![],
            mouse_data: MouseTranslationData::new(size)
        }
    }

    #[allow(missing_docs)]
    pub fn x_scroll_inverted(mut self, invert: bool) -> Self {
        self.mouse_data.x_axis_scroll_inverted = invert;
        self
    }

    #[allow(missing_docs)]
    pub fn get_x_scroll_inverted(&self) -> &bool {
        &self.mouse_data.x_axis_scroll_inverted
    }

    #[allow(missing_docs)]
    pub fn y_scroll_inverted(mut self, invert: bool) -> Self {
        self.mouse_data.y_axis_scroll_inverted = invert;
        self
    }

    #[allow(missing_docs)]
    pub fn get_y_scroll_inverted(&self) -> &bool {
        &self.mouse_data.y_axis_scroll_inverted
    }

    #[allow(missing_docs)]
    pub fn x_motion_inverted(mut self, invert: bool) -> Self {
        self.mouse_data.x_axis_motion_inverted = invert;
        self
    }

    #[allow(missing_docs)]
    pub fn get_x_motion_inverted(&self) -> &bool {
        &self.mouse_data.x_axis_motion_inverted
    }

    #[allow(missing_docs)]
    pub fn y_motion_inverted(mut self, invert: bool) -> Self {
        self.mouse_data.y_axis_motion_inverted = invert;
        self
    }

    #[allow(missing_docs)]
    pub fn get_y_motion_inverted(&self) -> &bool {
        &self.mouse_data.y_axis_motion_inverted
    }

    #[allow(missing_docs)]
    pub fn viewport_size(mut self, sz: Size) -> Self {
        self.mouse_data.viewport_size = sz;
        self
    }

    #[allow(missing_docs)]
    pub fn get_viewport_size(&self) -> &Size {
        &self.mouse_data.viewport_size
    }

    #[allow(missing_docs)]
    pub fn with_action_mapping(mut self, but: Button, act: A) -> Self {
        self.input_remappings.push((but, act));
        self
    }

    #[allow(missing_docs)]
    pub fn build_translator(self) -> InputTranslator<A> { self.into() }

    #[allow(missing_docs)]
    pub fn build_rebind(self) -> InputRebind<A> { self.into() }
}

impl<A: Action> Default for RebindBuilder<A> {
    fn default() -> Self {
        Self::new((800, 600).into())
    }
}

impl<A: Action> Into<InputTranslator<A>> for RebindBuilder<A> {
    fn into(self) -> InputTranslator<A> {
        let mut input_map = InputTranslator::new(self.mouse_data.viewport_size);

        input_map.mouse_translator.data = self.mouse_data;
        input_map.keymap = self.input_remappings.iter().cloned().collect();

        input_map
    }
}

impl<A: Action> Into<InputRebind<A>> for RebindBuilder<A> {
    #[allow(dead_code, unused_variables, unreachable_code)]
    fn into(self) -> InputRebind<A> {
        unimplemented!();

        let mut input_rebind = InputRebind::new(self.mouse_data.viewport_size);

        input_rebind.mouse_data = self.mouse_data;
        //input_rebind.keymap.btn_map = self.input_remappings.iter().map(|x| x.clone()).collect();

        input_rebind
    }
}

<|endoftext|>


<commit_before>use error_chain::ChainedError;
use ffmpeg;
use std::ptr;
use std::sync::mpsc::{channel, Receiver, Sender};
use std::sync::{Mutex, RwLock, Once, ONCE_INIT};
use std::thread;

use encode;
use errors::*;

lazy_static! {
    static ref CAPTURING: RwLock<bool> = RwLock::new(false);

    static ref ENCODER: Mutex<Option<encode::Encoder>> = Mutex::new(None);

    /// Receives buffers to write pixels to.
    static ref BUF_RECEIVER: Mutex<Option<Receiver<Buffer>>> = Mutex::new(None);

    /// Sends events and frames to encode to the capture thread.
    static ref SEND_TO_CAPTURE_THREAD: Mutex<Option<Sender<CaptureThreadEvent>>> = Mutex::new(None);
}

enum CaptureThreadEvent {
    CaptureStart,
    CaptureStop,
    Frame(Buffer),
}

pub struct Buffer {
    pub data: Vec<u8>,
    width: u32,
    height: u32,
}

fn capture_thread(buf_sender: Sender<Buffer>, event_receiver: Receiver<CaptureThreadEvent>) {
    // Send the buffer to the game thread right away.
    buf_sender.send(Buffer {
        data: Vec::new(),
        width: 0,
        height: 0,
    }).unwrap();

    // This is our frame which will only be reallocated on resolution changes.
    let mut frame = ffmpeg::frame::Video::empty();

    // This is set to true on encoding error or cap_stop and reset on cap_start.
    // When this is true, ignore any received frames.
    let mut drop_frames = true;

    // Event loop for the capture thread.
    loop {
        match event_receiver.recv().unwrap() {
            CaptureThreadEvent::CaptureStart => {
                drop_frames = false;
            },

            CaptureThreadEvent::CaptureStop => {
                *ENCODER.lock().unwrap() = None;
                drop_frames = true;
            },

            CaptureThreadEvent::Frame(buffer) => {
                if drop_frames {
                    continue;
                }

                if let Err(ref e) = encode(buffer, &buf_sender, &mut frame) {
                    *CAPTURING.write().unwrap() = false;
                    drop_frames = true;
                    println!("Encoding error: {}", e.display());
                }
            },
        }
    }
}

fn start_encoder((width, height): (u32, u32)) -> Result<encode::Encoder> {
    encode::Encoder::start("/home/yalter/test.mp4", (width, height), (1, 60).into())
}

fn encode(buf: Buffer, buf_sender: &Sender<Buffer>, frame: &mut ffmpeg::frame::Video) -> Result<()> {
    // Make sure frame is of correct size.
    if buf.width != frame.width() || buf.height != frame.height() {
        *frame = ffmpeg::frame::Video::new(ffmpeg::format::Pixel::RGB24, buf.width, buf.height);
    }

    // Copy the pixel data into the frame.
    {
        let linesize = unsafe { ((*frame.as_ptr()).linesize[0]) as u32 };
        let mut data = frame.data_mut(0);

        for y in 0..buf.height {
            unsafe {
                ptr::copy_nonoverlapping(buf.data.as_ptr().offset((y * buf.width * 3) as isize),
                data.as_mut_ptr().offset(((buf.height - y - 1) * linesize) as isize),
                (buf.width * 3) as usize);
            }
        }
    }

    // We're done with buf, now it can receive the next pack of pixels.
    buf_sender.send(buf).unwrap();

    // Let's encode the frame we just received.
    let mut encoder = ENCODER.lock().unwrap();

    // If the encoder wasn't initialized or if the frame size changed, initialize it.
    if encoder.as_ref().map_or(true, |enc| {
        enc.width() != frame.width() || enc.height() != frame.height()
    }) {
        *encoder = Some(start_encoder((frame.width(), frame.height()))
            .chain_err(|| "could not start the video encoder")?);
    }

    // Encode the frame.
    encoder.as_mut().unwrap().encode(&frame)
        .chain_err(|| "could not encode the frame")?;

    Ok(())
}

pub fn initialize() {
    static INIT: Once = ONCE_INIT;
    INIT.call_once(|| {
        let (tx, rx) = channel::<Buffer>();
        let (tx2, rx2) = channel::<CaptureThreadEvent>();

        *BUF_RECEIVER.lock().unwrap() = Some(rx);
        *SEND_TO_CAPTURE_THREAD.lock().unwrap() = Some(tx2);

        thread::spawn(move || capture_thread(tx, rx2));
    });
}

pub fn get_buffer((width, height): (u32, u32)) -> Buffer {
    let mut buf = BUF_RECEIVER.lock().unwrap().as_ref().unwrap().recv().unwrap();

    if buf.width != width || buf.height != height {
        println!("Changing resolution from {:?} to {:?}.",
                 (buf.width, buf.height),
                 (width, height));

        buf.data.resize((width * height * 3) as usize, 0);
        buf.width = width;
        buf.height = height;
    }

    buf
}

pub fn capture(buf: Buffer) {
    SEND_TO_CAPTURE_THREAD.lock().unwrap()
        .as_ref().unwrap()
        .send(CaptureThreadEvent::Frame(buf)).unwrap();
}

pub fn is_capturing() -> bool {
    *CAPTURING.read().unwrap()
}

command!(cap_start, |_engine| {
    *CAPTURING.write().unwrap() = true;

    SEND_TO_CAPTURE_THREAD.lock().unwrap()
        .as_ref().unwrap()
        .send(CaptureThreadEvent::CaptureStart).unwrap();
});

command!(cap_stop, |_engine| {
    *CAPTURING.write().unwrap() = false;

    SEND_TO_CAPTURE_THREAD.lock().unwrap()
        .as_ref().unwrap()
        .send(CaptureThreadEvent::CaptureStop).unwrap();
});
<commit_msg>Format code<commit_after>use error_chain::ChainedError;
use ffmpeg;
use std::ptr;
use std::sync::mpsc::{channel, Receiver, Sender};
use std::sync::{Mutex, RwLock, Once, ONCE_INIT};
use std::thread;

use encode;
use errors::*;

lazy_static! {
    static ref CAPTURING: RwLock<bool> = RwLock::new(false);

    static ref ENCODER: Mutex<Option<encode::Encoder>> = Mutex::new(None);

    /// Receives buffers to write pixels to.
    static ref BUF_RECEIVER: Mutex<Option<Receiver<Buffer>>> = Mutex::new(None);

    /// Sends events and frames to encode to the capture thread.
    static ref SEND_TO_CAPTURE_THREAD: Mutex<Option<Sender<CaptureThreadEvent>>> = Mutex::new(None);
}

enum CaptureThreadEvent {
    CaptureStart,
    CaptureStop,
    Frame(Buffer),
}

pub struct Buffer {
    pub data: Vec<u8>,
    width: u32,
    height: u32,
}

fn capture_thread(buf_sender: Sender<Buffer>, event_receiver: Receiver<CaptureThreadEvent>) {
    // Send the buffer to the game thread right away.
    buf_sender.send(Buffer {
                        data: Vec::new(),
                        width: 0,
                        height: 0,
                    })
              .unwrap();

    // This is our frame which will only be reallocated on resolution changes.
    let mut frame = ffmpeg::frame::Video::empty();

    // This is set to true on encoding error or cap_stop and reset on cap_start.
    // When this is true, ignore any received frames.
    let mut drop_frames = true;

    // Event loop for the capture thread.
    loop {
        match event_receiver.recv().unwrap() {
            CaptureThreadEvent::CaptureStart => {
                drop_frames = false;
            }

            CaptureThreadEvent::CaptureStop => {
                *ENCODER.lock().unwrap() = None;
                drop_frames = true;
            }

            CaptureThreadEvent::Frame(buffer) => {
                if drop_frames {
                    continue;
                }

                if let Err(ref e) = encode(buffer, &buf_sender, &mut frame) {
                    *CAPTURING.write().unwrap() = false;
                    drop_frames = true;
                    println!("Encoding error: {}", e.display());
                }
            }
        }
    }
}

fn start_encoder((width, height): (u32, u32)) -> Result<encode::Encoder> {
    encode::Encoder::start("/home/yalter/test.mp4", (width, height), (1, 60).into())
}

fn encode(buf: Buffer,
          buf_sender: &Sender<Buffer>,
          frame: &mut ffmpeg::frame::Video)
          -> Result<()> {
    // Make sure frame is of correct size.
    if buf.width != frame.width() || buf.height != frame.height() {
        *frame = ffmpeg::frame::Video::new(ffmpeg::format::Pixel::RGB24, buf.width, buf.height);
    }

    // Copy the pixel data into the frame.
    {
        let linesize = unsafe { ((*frame.as_ptr()).linesize[0]) as u32 };
        let mut data = frame.data_mut(0);

        for y in 0..buf.height {
            unsafe {
                ptr::copy_nonoverlapping(buf.data.as_ptr().offset((y * buf.width * 3) as isize),
                                         data.as_mut_ptr()
                                             .offset(((buf.height - y - 1) * linesize) as
                                                     isize),
                                         (buf.width * 3) as usize);
            }
        }
    }

    // We're done with buf, now it can receive the next pack of pixels.
    buf_sender.send(buf).unwrap();

    // Let's encode the frame we just received.
    let mut encoder = ENCODER.lock().unwrap();

    // If the encoder wasn't initialized or if the frame size changed, initialize it.
    if encoder.as_ref()
              .map_or(true,
                      |enc| enc.width() != frame.width() || enc.height() != frame.height()) {
        *encoder = Some(start_encoder((frame.width(), frame.height()))
                            .chain_err(|| "could not start the video encoder")?);
    }

    // Encode the frame.
    encoder.as_mut().unwrap().encode(&frame)
        .chain_err(|| "could not encode the frame")?;

    Ok(())
}

pub fn initialize() {
    static INIT: Once = ONCE_INIT;
    INIT.call_once(|| {
        let (tx, rx) = channel::<Buffer>();
        let (tx2, rx2) = channel::<CaptureThreadEvent>();

        *BUF_RECEIVER.lock().unwrap() = Some(rx);
        *SEND_TO_CAPTURE_THREAD.lock().unwrap() = Some(tx2);

        thread::spawn(move || capture_thread(tx, rx2));
    });
}

pub fn get_buffer((width, height): (u32, u32)) -> Buffer {
    let mut buf = BUF_RECEIVER.lock().unwrap()
        .as_ref().unwrap()
        .recv().unwrap();

    if buf.width != width || buf.height != height {
        println!("Changing resolution from {:?} to {:?}.",
                 (buf.width, buf.height),
                 (width, height));

        buf.data.resize((width * height * 3) as usize, 0);
        buf.width = width;
        buf.height = height;
    }

    buf
}

pub fn capture(buf: Buffer) {
    SEND_TO_CAPTURE_THREAD.lock().unwrap()
        .as_ref().unwrap()
        .send(CaptureThreadEvent::Frame(buf)).unwrap();
}

pub fn is_capturing() -> bool {
    *CAPTURING.read().unwrap()
}

command!(cap_start, |_engine| {
    *CAPTURING.write().unwrap() = true;

    SEND_TO_CAPTURE_THREAD.lock().unwrap()
        .as_ref().unwrap()
        .send(CaptureThreadEvent::CaptureStart).unwrap();
});

command!(cap_stop, |_engine| {
    *CAPTURING.write().unwrap() = false;

    SEND_TO_CAPTURE_THREAD.lock().unwrap()
        .as_ref().unwrap()
        .send(CaptureThreadEvent::CaptureStop).unwrap();
});
<|endoftext|>


<commit_before>use crate::{Command, Merge};
use std::fmt::{self, Debug, Formatter};

/// Creates a command from the provided function.
///
/// The undo functionality is provided by cloning the original data before editing it.
///
/// # Examples
/// ```
/// # use undo::*;
/// # fn main() -> undo::Result {
/// let mut record = Record::default();
/// record.apply(undo::from_fn(|s: &mut String| s.push('a')))?;
/// record.apply(undo::from_fn(|s: &mut String| s.push('b')))?;
/// record.apply(undo::from_fn(|s: &mut String| s.push('c')))?;
/// assert_eq!(record.target(), "abc");
/// record.undo()?;
/// record.undo()?;
/// record.undo()?;
/// assert_eq!(record.target(), "");
/// record.redo()?;
/// record.redo()?;
/// record.redo()?;
/// assert_eq!(record.target(), "abc");
/// # Ok(())
/// # }
/// ```
pub fn from_fn<T, F>(f: F) -> FromFn<T, F> {
    FromFn { f, target: None }
}

/// A command wrapper created from a function.
///
/// Created by the [`from_fn`](fn.from_fn.html) function.
pub struct FromFn<T: 'static, F: 'static> {
    f: F,
    target: Option<T>,
}

impl<T, F> FromFn<T, F> {
    /// Returns a new command with the provided text.
    pub fn with_text(self, text: impl Into<String>) -> WithText<FromFn<T, F>> {
        with_text(self, text)
    }

    /// Returns a new command with the provided merge behavior.
    pub fn with_merge(self, merge: Merge) -> WithMerge<FromFn<T, F>> {
        with_merge(self, merge)
    }
}

impl<T: Debug + Clone, F: FnMut(&mut T)> Command<T> for FromFn<T, F> {
    fn apply(&mut self, target: &mut T) -> crate::Result {
        self.target = Some(target.clone());
        (self.f)(target);
        Ok(())
    }

    fn undo(&mut self, target: &mut T) -> crate::Result {
        *target = self.target.take().unwrap();
        Ok(())
    }
}

impl<T: Debug, F> Debug for FromFn<T, F> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        f.debug_struct("Fn").field("target", &self.target).finish()
    }
}

/// Joins the `a` and `b` command.
///
/// The commands are executed in the order they were merged in.
pub fn join<A, B>(a: A, b: B) -> Join<A, B> {
    Join(a, b)
}

/// A command wrapper used for joining commands.
///
/// Created by the [`join`](fn.join.html) function.
#[derive(Debug)]
pub struct Join<A, B>(A, B);

impl<A, B> Join<A, B> {
    /// Joins the two commands.
    pub fn join<C>(self, command: C) -> Join<Join<A, B>, C> {
        Join(self, command)
    }

    /// Returns a new command with the provided text.
    pub fn with_text(self, text: impl Into<String>) -> WithText<Join<A, B>> {
        with_text(self, text)
    }

    /// Returns a new command with the provided merge behavior.
    pub fn with_merge(self, merge: Merge) -> WithMerge<Join<A, B>> {
        with_merge(self, merge)
    }
}

impl<T, A: Command<T>, B: Command<T>> Command<T> for Join<A, B> {
    fn apply(&mut self, target: &mut T) -> crate::Result {
        self.0.apply(target)?;
        self.1.apply(target)
    }

    fn undo(&mut self, target: &mut T) -> crate::Result {
        self.1.undo(target)?;
        self.0.undo(target)
    }

    fn redo(&mut self, target: &mut T) -> crate::Result {
        self.0.redo(target)?;
        self.1.redo(target)
    }

    fn merge(&self) -> Merge {
        Merge::No
    }

    fn text(&self) -> String {
        format!("{} & {}", self.0.text(), self.1.text())
    }
}

/// Creates a command wrapper with the specified text.
pub fn with_text<A>(command: A, text: impl Into<String>) -> WithText<A> {
    WithText {
        command,
        text: text.into(),
    }
}

/// A command wrapper with a specified text.
///
/// Created by the [`with_text`](fn.with_text.html) function.
#[derive(Debug)]
pub struct WithText<A> {
    command: A,
    text: String,
}

impl<A> WithText<A> {
    /// Returns a new command with the provided merge behavior.
    pub fn with_merge(self, merge: Merge) -> WithMerge<WithText<A>> {
        with_merge(self, merge)
    }
}

impl<T, C: Command<T>> Command<T> for WithText<C> {
    fn apply(&mut self, target: &mut T) -> crate::Result {
        self.command.apply(target)
    }

    fn undo(&mut self, target: &mut T) -> crate::Result {
        self.command.undo(target)
    }

    fn redo(&mut self, target: &mut T) -> crate::Result {
        self.command.redo(target)
    }

    fn merge(&self) -> Merge {
        self.command.merge()
    }

    fn text(&self) -> String {
        self.text.clone()
    }
}

/// Creates a command wrapper with the specified merge behavior.
pub fn with_merge<A>(command: A, merge: Merge) -> WithMerge<A> {
    WithMerge { command, merge }
}

/// A command wrapper with a specified merge behavior.
///
/// Created by the [`with_merge`](fn.with_merge.html) function.
#[derive(Debug)]
pub struct WithMerge<A> {
    command: A,
    merge: Merge,
}

impl<A> WithMerge<A> {
    /// Returns a new command with the provided text.
    pub fn with_text(self, text: impl Into<String>) -> WithText<WithMerge<A>> {
        with_text(self, text)
    }
}

impl<T, C: Command<T>> Command<T> for WithMerge<C> {
    fn apply(&mut self, target: &mut T) -> crate::Result {
        self.command.apply(target)
    }

    fn undo(&mut self, target: &mut T) -> crate::Result {
        self.command.undo(target)
    }

    fn redo(&mut self, target: &mut T) -> crate::Result {
        self.command.redo(target)
    }

    fn merge(&self) -> Merge {
        self.merge
    }

    fn text(&self) -> String {
        self.command.text()
    }
}
<commit_msg>Add examples to command wrappers<commit_after>use crate::{Command, Merge};
use std::fmt::{self, Debug, Formatter};

/// Creates a command from the provided function.
///
/// The undo functionality is provided by cloning the original data before editing it.
///
/// # Examples
/// ```
/// # use undo::*;
/// # fn main() -> undo::Result {
/// let mut record = Record::default();
/// record.apply(from_fn(|s: &mut String| s.push('a')))?;
/// record.apply(from_fn(|s: &mut String| s.push('b')))?;
/// record.apply(from_fn(|s: &mut String| s.push('c')))?;
/// assert_eq!(record.target(), "abc");
/// record.undo()?;
/// record.undo()?;
/// record.undo()?;
/// assert_eq!(record.target(), "");
/// record.redo()?;
/// record.redo()?;
/// record.redo()?;
/// assert_eq!(record.target(), "abc");
/// # Ok(())
/// # }
/// ```
pub fn from_fn<T, F>(f: F) -> FromFn<T, F> {
    FromFn { f, target: None }
}

/// A command wrapper created from a function.
///
/// Created by the [`from_fn`](fn.from_fn.html) function.
pub struct FromFn<T: 'static, F: 'static> {
    f: F,
    target: Option<T>,
}

impl<T, F> FromFn<T, F> {
    /// Returns a new command with the provided text.
    pub fn with_text(self, text: impl Into<String>) -> WithText<FromFn<T, F>> {
        with_text(self, text)
    }

    /// Returns a new command with the provided merge behavior.
    pub fn with_merge(self, merge: Merge) -> WithMerge<FromFn<T, F>> {
        with_merge(self, merge)
    }
}

impl<T: Debug + Clone, F: FnMut(&mut T)> Command<T> for FromFn<T, F> {
    fn apply(&mut self, target: &mut T) -> crate::Result {
        self.target = Some(target.clone());
        (self.f)(target);
        Ok(())
    }

    fn undo(&mut self, target: &mut T) -> crate::Result {
        *target = self.target.take().unwrap();
        Ok(())
    }
}

impl<T: Debug, F> Debug for FromFn<T, F> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        f.debug_struct("Fn").field("target", &self.target).finish()
    }
}

/// Joins the `a` and `b` command.
///
/// The commands are executed in the order they were merged in.
///
/// # Examples
/// ```
/// # use undo::*;
/// # fn main() -> undo::Result {
/// let mut record = Record::default();
/// let a = from_fn(|s: &mut String| s.push('a'));
/// let b = from_fn(|s: &mut String| s.push('b'));
/// let c = from_fn(|s: &mut String| s.push('c'));
/// let abc = join(a, b).join(c);
/// record.apply(abc)?;
/// assert_eq!(record.target(), "abc");
/// record.undo()?;
/// assert_eq!(record.target(), "");
/// record.redo()?;
/// assert_eq!(record.target(), "abc");
/// # Ok(())
/// # }
/// ```
pub fn join<A, B>(a: A, b: B) -> Join<A, B> {
    Join(a, b)
}

/// A command wrapper used for joining commands.
///
/// Created by the [`join`](fn.join.html) function.
#[derive(Debug)]
pub struct Join<A, B>(A, B);

impl<A, B> Join<A, B> {
    /// Joins the two commands.
    pub fn join<C>(self, command: C) -> Join<Join<A, B>, C> {
        Join(self, command)
    }

    /// Returns a new command with the provided text.
    pub fn with_text(self, text: impl Into<String>) -> WithText<Join<A, B>> {
        with_text(self, text)
    }

    /// Returns a new command with the provided merge behavior.
    pub fn with_merge(self, merge: Merge) -> WithMerge<Join<A, B>> {
        with_merge(self, merge)
    }
}

impl<T, A: Command<T>, B: Command<T>> Command<T> for Join<A, B> {
    fn apply(&mut self, target: &mut T) -> crate::Result {
        self.0.apply(target)?;
        self.1.apply(target)
    }

    fn undo(&mut self, target: &mut T) -> crate::Result {
        self.1.undo(target)?;
        self.0.undo(target)
    }

    fn redo(&mut self, target: &mut T) -> crate::Result {
        self.0.redo(target)?;
        self.1.redo(target)
    }

    fn merge(&self) -> Merge {
        Merge::No
    }

    fn text(&self) -> String {
        format!("{} & {}", self.0.text(), self.1.text())
    }
}

/// Creates a command wrapper with the specified text.
///
/// # Examples
/// ```
/// # use undo::*;
/// # fn main() -> undo::Result {
/// let mut record = Record::default();
/// let a = from_fn(|s: &mut String| s.push('a'));
/// let a = a.with_text("add 'a' to the string");
/// record.apply(a)?;
/// assert_eq!(record.undo_text(), Some(String::from("add 'a' to the string")));
/// # Ok(())
/// # }
/// ```
pub fn with_text<A>(command: A, text: impl Into<String>) -> WithText<A> {
    WithText {
        command,
        text: text.into(),
    }
}

/// A command wrapper with a specified text.
///
/// Created by the [`with_text`](fn.with_text.html) function.
#[derive(Debug)]
pub struct WithText<A> {
    command: A,
    text: String,
}

impl<A> WithText<A> {
    /// Returns a new command with the provided merge behavior.
    pub fn with_merge(self, merge: Merge) -> WithMerge<WithText<A>> {
        with_merge(self, merge)
    }
}

impl<T, C: Command<T>> Command<T> for WithText<C> {
    fn apply(&mut self, target: &mut T) -> crate::Result {
        self.command.apply(target)
    }

    fn undo(&mut self, target: &mut T) -> crate::Result {
        self.command.undo(target)
    }

    fn redo(&mut self, target: &mut T) -> crate::Result {
        self.command.redo(target)
    }

    fn merge(&self) -> Merge {
        self.command.merge()
    }

    fn text(&self) -> String {
        self.text.clone()
    }
}

/// Creates a command wrapper with the specified merge behavior.
///
/// # Examples
/// ```
/// # use undo::*;
/// # fn main() -> undo::Result {
/// let mut record = Record::default();
/// let a = from_fn(|s: &mut String| s.push('a'));
/// let b = from_fn(|s: &mut String| s.push('b'));
/// let a = a.with_merge(Merge::If(0));
/// let b = b.with_merge(Merge::If(0));
/// record.apply(a)?;
/// record.apply(b)?;
/// assert_eq!(record.target(), "ab");
/// record.undo()?;
/// assert_eq!(record.target(), "");
/// record.redo()?;
/// assert_eq!(record.target(), "ab");
/// # Ok(())
/// # }
/// ```
pub fn with_merge<A>(command: A, merge: Merge) -> WithMerge<A> {
    WithMerge { command, merge }
}

/// A command wrapper with a specified merge behavior.
///
/// Created by the [`with_merge`](fn.with_merge.html) function.
#[derive(Debug)]
pub struct WithMerge<A> {
    command: A,
    merge: Merge,
}

impl<A> WithMerge<A> {
    /// Returns a new command with the provided text.
    pub fn with_text(self, text: impl Into<String>) -> WithText<WithMerge<A>> {
        with_text(self, text)
    }
}

impl<T, C: Command<T>> Command<T> for WithMerge<C> {
    fn apply(&mut self, target: &mut T) -> crate::Result {
        self.command.apply(target)
    }

    fn undo(&mut self, target: &mut T) -> crate::Result {
        self.command.undo(target)
    }

    fn redo(&mut self, target: &mut T) -> crate::Result {
        self.command.redo(target)
    }

    fn merge(&self) -> Merge {
        self.merge
    }

    fn text(&self) -> String {
        self.command.text()
    }
}
<|endoftext|>


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

//! Complex numbers.

use std::fmt;
use std::num::{Zero, One, ToStrRadix};

// FIXME #1284: handle complex NaN & infinity etc. This
// probably doesn't map to C's _Complex correctly.

/// A complex number in Cartesian form.
#[deriving(PartialEq, Clone, Hash)]
pub struct Complex<T> {
    /// Real portion of the complex number
    pub re: T,
    /// Imaginary portion of the complex number
    pub im: T
}

pub type Complex32 = Complex<f32>;
pub type Complex64 = Complex<f64>;

impl<T: Clone + Num> Complex<T> {
    /// Create a new Complex
    #[inline]
    pub fn new(re: T, im: T) -> Complex<T> {
        Complex { re: re, im: im }
    }

    /// Returns the square of the norm (since `T` doesn't necessarily
    /// have a sqrt function), i.e. `re^2 + im^2`.
    #[inline]
    pub fn norm_sqr(&self) -> T {
        self.re * self.re + self.im * self.im
    }

    /// Returns the complex conjugate. i.e. `re - i im`
    #[inline]
    pub fn conj(&self) -> Complex<T> {
        Complex::new(self.re.clone(), -self.im)
    }

    /// Multiplies `self` by the scalar `t`.
    #[inline]
    pub fn scale(&self, t: T) -> Complex<T> {
        Complex::new(self.re * t, self.im * t)
    }

    /// Divides `self` by the scalar `t`.
    #[inline]
    pub fn unscale(&self, t: T) -> Complex<T> {
        Complex::new(self.re / t, self.im / t)
    }

    /// Returns `1/self`
    #[inline]
    pub fn inv(&self) -> Complex<T> {
        let norm_sqr = self.norm_sqr();
        Complex::new(self.re / norm_sqr,
                    -self.im / norm_sqr)
    }
}

impl<T: Clone + FloatMath> Complex<T> {
    /// Calculate |self|
    #[inline]
    pub fn norm(&self) -> T {
        self.re.hypot(self.im)
    }
}

impl<T: Clone + FloatMath> Complex<T> {
    /// Calculate the principal Arg of self.
    #[inline]
    pub fn arg(&self) -> T {
        self.im.atan2(self.re)
    }
    /// Convert to polar form (r, theta), such that `self = r * exp(i
    /// * theta)`
    #[inline]
    pub fn to_polar(&self) -> (T, T) {
        (self.norm(), self.arg())
    }
    /// Convert a polar representation into a complex number.
    #[inline]
    pub fn from_polar(r: &T, theta: &T) -> Complex<T> {
        Complex::new(*r * theta.cos(), *r * theta.sin())
    }
}

/* arithmetic */
// (a + i b) + (c + i d) == (a + c) + i (b + d)
impl<T: Clone + Num> Add<Complex<T>, Complex<T>> for Complex<T> {
    #[inline]
    fn add(&self, other: &Complex<T>) -> Complex<T> {
        Complex::new(self.re + other.re, self.im + other.im)
    }
}
// (a + i b) - (c + i d) == (a - c) + i (b - d)
impl<T: Clone + Num> Sub<Complex<T>, Complex<T>> for Complex<T> {
    #[inline]
    fn sub(&self, other: &Complex<T>) -> Complex<T> {
        Complex::new(self.re - other.re, self.im - other.im)
    }
}
// (a + i b) * (c + i d) == (a*c - b*d) + i (a*d + b*c)
impl<T: Clone + Num> Mul<Complex<T>, Complex<T>> for Complex<T> {
    #[inline]
    fn mul(&self, other: &Complex<T>) -> Complex<T> {
        Complex::new(self.re*other.re - self.im*other.im,
                   self.re*other.im + self.im*other.re)
    }
}

// (a + i b) / (c + i d) == [(a + i b) * (c - i d)] / (c*c + d*d)
//   == [(a*c + b*d) / (c*c + d*d)] + i [(b*c - a*d) / (c*c + d*d)]
impl<T: Clone + Num> Div<Complex<T>, Complex<T>> for Complex<T> {
    #[inline]
    fn div(&self, other: &Complex<T>) -> Complex<T> {
        let norm_sqr = other.norm_sqr();
        Complex::new((self.re*other.re + self.im*other.im) / norm_sqr,
                   (self.im*other.re - self.re*other.im) / norm_sqr)
    }
}

impl<T: Clone + Num> Neg<Complex<T>> for Complex<T> {
    #[inline]
    fn neg(&self) -> Complex<T> {
        Complex::new(-self.re, -self.im)
    }
}

/* constants */
impl<T: Clone + Num> Zero for Complex<T> {
    #[inline]
    fn zero() -> Complex<T> {
        Complex::new(Zero::zero(), Zero::zero())
    }

    #[inline]
    fn is_zero(&self) -> bool {
        self.re.is_zero() && self.im.is_zero()
    }
}

impl<T: Clone + Num> One for Complex<T> {
    #[inline]
    fn one() -> Complex<T> {
        Complex::new(One::one(), Zero::zero())
    }
}

/* string conversions */
impl<T: fmt::Show + Num + PartialOrd> fmt::Show for Complex<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.im < Zero::zero() {
            write!(f, "{}-{}i", self.re, -self.im)
        } else {
            write!(f, "{}+{}i", self.re, self.im)
        }
    }
}

impl<T: ToStrRadix + Num + PartialOrd> ToStrRadix for Complex<T> {
    fn to_str_radix(&self, radix: uint) -> String {
        if self.im < Zero::zero() {
            format!("{}-{}i",
                    self.re.to_str_radix(radix),
                    (-self.im).to_str_radix(radix))
        } else {
            format!("{}+{}i",
                    self.re.to_str_radix(radix),
                    self.im.to_str_radix(radix))
        }
    }
}

#[cfg(test)]
mod test {
    #![allow(non_uppercase_statics)]

    use super::{Complex64, Complex};
    use std::num::{Zero, One, Float};
    use std::hash::hash;

    pub const _0_0i : Complex64 = Complex { re: 0.0, im: 0.0 };
    pub const _1_0i : Complex64 = Complex { re: 1.0, im: 0.0 };
    pub const _1_1i : Complex64 = Complex { re: 1.0, im: 1.0 };
    pub const _0_1i : Complex64 = Complex { re: 0.0, im: 1.0 };
    pub const _neg1_1i : Complex64 = Complex { re: -1.0, im: 1.0 };
    pub const _05_05i : Complex64 = Complex { re: 0.5, im: 0.5 };
    pub const all_consts : [Complex64, .. 5] = [_0_0i, _1_0i, _1_1i, _neg1_1i, _05_05i];

    #[test]
    fn test_consts() {
        // check our constants are what Complex::new creates
        fn test(c : Complex64, r : f64, i: f64) {
            assert_eq!(c, Complex::new(r,i));
        }
        test(_0_0i, 0.0, 0.0);
        test(_1_0i, 1.0, 0.0);
        test(_1_1i, 1.0, 1.0);
        test(_neg1_1i, -1.0, 1.0);
        test(_05_05i, 0.5, 0.5);

        assert_eq!(_0_0i, Zero::zero());
        assert_eq!(_1_0i, One::one());
    }

    #[test]
    #[ignore(cfg(target_arch = "x86"))]
    // FIXME #7158: (maybe?) currently failing on x86.
    fn test_norm() {
        fn test(c: Complex64, ns: f64) {
            assert_eq!(c.norm_sqr(), ns);
            assert_eq!(c.norm(), ns.sqrt())
        }
        test(_0_0i, 0.0);
        test(_1_0i, 1.0);
        test(_1_1i, 2.0);
        test(_neg1_1i, 2.0);
        test(_05_05i, 0.5);
    }

    #[test]
    fn test_scale_unscale() {
        assert_eq!(_05_05i.scale(2.0), _1_1i);
        assert_eq!(_1_1i.unscale(2.0), _05_05i);
        for &c in all_consts.iter() {
            assert_eq!(c.scale(2.0).unscale(2.0), c);
        }
    }

    #[test]
    fn test_conj() {
        for &c in all_consts.iter() {
            assert_eq!(c.conj(), Complex::new(c.re, -c.im));
            assert_eq!(c.conj().conj(), c);
        }
    }

    #[test]
    fn test_inv() {
        assert_eq!(_1_1i.inv(), _05_05i.conj());
        assert_eq!(_1_0i.inv(), _1_0i.inv());
    }

    #[test]
    #[should_fail]
    fn test_divide_by_zero_natural() {
        let n = Complex::new(2i, 3i);
        let d = Complex::new(0, 0);
        let _x = n / d;
    }

    #[test]
    #[should_fail]
    #[ignore]
    fn test_inv_zero() {
        // FIXME #5736: should this really fail, or just NaN?
        _0_0i.inv();
    }

    #[test]
    fn test_arg() {
        fn test(c: Complex64, arg: f64) {
            assert!((c.arg() - arg).abs() < 1.0e-6)
        }
        test(_1_0i, 0.0);
        test(_1_1i, 0.25 * Float::pi());
        test(_neg1_1i, 0.75 * Float::pi());
        test(_05_05i, 0.25 * Float::pi());
    }

    #[test]
    fn test_polar_conv() {
        fn test(c: Complex64) {
            let (r, theta) = c.to_polar();
            assert!((c - Complex::from_polar(&r, &theta)).norm() < 1e-6);
        }
        for &c in all_consts.iter() { test(c); }
    }

    mod arith {
        use super::{_0_0i, _1_0i, _1_1i, _0_1i, _neg1_1i, _05_05i, all_consts};
        use std::num::Zero;

        #[test]
        fn test_add() {
            assert_eq!(_05_05i + _05_05i, _1_1i);
            assert_eq!(_0_1i + _1_0i, _1_1i);
            assert_eq!(_1_0i + _neg1_1i, _0_1i);

            for &c in all_consts.iter() {
                assert_eq!(_0_0i + c, c);
                assert_eq!(c + _0_0i, c);
            }
        }

        #[test]
        fn test_sub() {
            assert_eq!(_05_05i - _05_05i, _0_0i);
            assert_eq!(_0_1i - _1_0i, _neg1_1i);
            assert_eq!(_0_1i - _neg1_1i, _1_0i);

            for &c in all_consts.iter() {
                assert_eq!(c - _0_0i, c);
                assert_eq!(c - c, _0_0i);
            }
        }

        #[test]
        fn test_mul() {
            assert_eq!(_05_05i * _05_05i, _0_1i.unscale(2.0));
            assert_eq!(_1_1i * _0_1i, _neg1_1i);

            // i^2 & i^4
            assert_eq!(_0_1i * _0_1i, -_1_0i);
            assert_eq!(_0_1i * _0_1i * _0_1i * _0_1i, _1_0i);

            for &c in all_consts.iter() {
                assert_eq!(c * _1_0i, c);
                assert_eq!(_1_0i * c, c);
            }
        }
        #[test]
        fn test_div() {
            assert_eq!(_neg1_1i / _0_1i, _1_1i);
            for &c in all_consts.iter() {
                if c != Zero::zero() {
                    assert_eq!(c / c, _1_0i);
                }
            }
        }
        #[test]
        fn test_neg() {
            assert_eq!(-_1_0i + _0_1i, _neg1_1i);
            assert_eq!((-_0_1i) * _0_1i, _1_0i);
            for &c in all_consts.iter() {
                assert_eq!(-(-c), c);
            }
        }
    }

    #[test]
    fn test_to_string() {
        fn test(c : Complex64, s: String) {
            assert_eq!(c.to_string(), s);
        }
        test(_0_0i, "0+0i".to_string());
        test(_1_0i, "1+0i".to_string());
        test(_0_1i, "0+1i".to_string());
        test(_1_1i, "1+1i".to_string());
        test(_neg1_1i, "-1+1i".to_string());
        test(-_neg1_1i, "1-1i".to_string());
        test(_05_05i, "0.5+0.5i".to_string());
    }

    #[test]
    fn test_hash() {
        let a = Complex::new(0i32, 0i32);
        let b = Complex::new(1i32, 0i32);
        let c = Complex::new(0i32, 1i32);
        assert!(hash(&a) != hash(&b));
        assert!(hash(&b) != hash(&c));
        assert!(hash(&c) != hash(&a));
    }
}
<commit_msg>Migrate to new `cfg` attribute syntax`<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Complex numbers.

use std::fmt;
use std::num::{Zero, One, ToStrRadix};

// FIXME #1284: handle complex NaN & infinity etc. This
// probably doesn't map to C's _Complex correctly.

/// A complex number in Cartesian form.
#[deriving(PartialEq, Clone, Hash)]
pub struct Complex<T> {
    /// Real portion of the complex number
    pub re: T,
    /// Imaginary portion of the complex number
    pub im: T
}

pub type Complex32 = Complex<f32>;
pub type Complex64 = Complex<f64>;

impl<T: Clone + Num> Complex<T> {
    /// Create a new Complex
    #[inline]
    pub fn new(re: T, im: T) -> Complex<T> {
        Complex { re: re, im: im }
    }

    /// Returns the square of the norm (since `T` doesn't necessarily
    /// have a sqrt function), i.e. `re^2 + im^2`.
    #[inline]
    pub fn norm_sqr(&self) -> T {
        self.re * self.re + self.im * self.im
    }

    /// Returns the complex conjugate. i.e. `re - i im`
    #[inline]
    pub fn conj(&self) -> Complex<T> {
        Complex::new(self.re.clone(), -self.im)
    }

    /// Multiplies `self` by the scalar `t`.
    #[inline]
    pub fn scale(&self, t: T) -> Complex<T> {
        Complex::new(self.re * t, self.im * t)
    }

    /// Divides `self` by the scalar `t`.
    #[inline]
    pub fn unscale(&self, t: T) -> Complex<T> {
        Complex::new(self.re / t, self.im / t)
    }

    /// Returns `1/self`
    #[inline]
    pub fn inv(&self) -> Complex<T> {
        let norm_sqr = self.norm_sqr();
        Complex::new(self.re / norm_sqr,
                    -self.im / norm_sqr)
    }
}

impl<T: Clone + FloatMath> Complex<T> {
    /// Calculate |self|
    #[inline]
    pub fn norm(&self) -> T {
        self.re.hypot(self.im)
    }
}

impl<T: Clone + FloatMath> Complex<T> {
    /// Calculate the principal Arg of self.
    #[inline]
    pub fn arg(&self) -> T {
        self.im.atan2(self.re)
    }
    /// Convert to polar form (r, theta), such that `self = r * exp(i
    /// * theta)`
    #[inline]
    pub fn to_polar(&self) -> (T, T) {
        (self.norm(), self.arg())
    }
    /// Convert a polar representation into a complex number.
    #[inline]
    pub fn from_polar(r: &T, theta: &T) -> Complex<T> {
        Complex::new(*r * theta.cos(), *r * theta.sin())
    }
}

/* arithmetic */
// (a + i b) + (c + i d) == (a + c) + i (b + d)
impl<T: Clone + Num> Add<Complex<T>, Complex<T>> for Complex<T> {
    #[inline]
    fn add(&self, other: &Complex<T>) -> Complex<T> {
        Complex::new(self.re + other.re, self.im + other.im)
    }
}
// (a + i b) - (c + i d) == (a - c) + i (b - d)
impl<T: Clone + Num> Sub<Complex<T>, Complex<T>> for Complex<T> {
    #[inline]
    fn sub(&self, other: &Complex<T>) -> Complex<T> {
        Complex::new(self.re - other.re, self.im - other.im)
    }
}
// (a + i b) * (c + i d) == (a*c - b*d) + i (a*d + b*c)
impl<T: Clone + Num> Mul<Complex<T>, Complex<T>> for Complex<T> {
    #[inline]
    fn mul(&self, other: &Complex<T>) -> Complex<T> {
        Complex::new(self.re*other.re - self.im*other.im,
                   self.re*other.im + self.im*other.re)
    }
}

// (a + i b) / (c + i d) == [(a + i b) * (c - i d)] / (c*c + d*d)
//   == [(a*c + b*d) / (c*c + d*d)] + i [(b*c - a*d) / (c*c + d*d)]
impl<T: Clone + Num> Div<Complex<T>, Complex<T>> for Complex<T> {
    #[inline]
    fn div(&self, other: &Complex<T>) -> Complex<T> {
        let norm_sqr = other.norm_sqr();
        Complex::new((self.re*other.re + self.im*other.im) / norm_sqr,
                   (self.im*other.re - self.re*other.im) / norm_sqr)
    }
}

impl<T: Clone + Num> Neg<Complex<T>> for Complex<T> {
    #[inline]
    fn neg(&self) -> Complex<T> {
        Complex::new(-self.re, -self.im)
    }
}

/* constants */
impl<T: Clone + Num> Zero for Complex<T> {
    #[inline]
    fn zero() -> Complex<T> {
        Complex::new(Zero::zero(), Zero::zero())
    }

    #[inline]
    fn is_zero(&self) -> bool {
        self.re.is_zero() && self.im.is_zero()
    }
}

impl<T: Clone + Num> One for Complex<T> {
    #[inline]
    fn one() -> Complex<T> {
        Complex::new(One::one(), Zero::zero())
    }
}

/* string conversions */
impl<T: fmt::Show + Num + PartialOrd> fmt::Show for Complex<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.im < Zero::zero() {
            write!(f, "{}-{}i", self.re, -self.im)
        } else {
            write!(f, "{}+{}i", self.re, self.im)
        }
    }
}

impl<T: ToStrRadix + Num + PartialOrd> ToStrRadix for Complex<T> {
    fn to_str_radix(&self, radix: uint) -> String {
        if self.im < Zero::zero() {
            format!("{}-{}i",
                    self.re.to_str_radix(radix),
                    (-self.im).to_str_radix(radix))
        } else {
            format!("{}+{}i",
                    self.re.to_str_radix(radix),
                    self.im.to_str_radix(radix))
        }
    }
}

#[cfg(test)]
mod test {
    #![allow(non_uppercase_statics)]

    use super::{Complex64, Complex};
    use std::num::{Zero, One, Float};
    use std::hash::hash;

    pub const _0_0i : Complex64 = Complex { re: 0.0, im: 0.0 };
    pub const _1_0i : Complex64 = Complex { re: 1.0, im: 0.0 };
    pub const _1_1i : Complex64 = Complex { re: 1.0, im: 1.0 };
    pub const _0_1i : Complex64 = Complex { re: 0.0, im: 1.0 };
    pub const _neg1_1i : Complex64 = Complex { re: -1.0, im: 1.0 };
    pub const _05_05i : Complex64 = Complex { re: 0.5, im: 0.5 };
    pub const all_consts : [Complex64, .. 5] = [_0_0i, _1_0i, _1_1i, _neg1_1i, _05_05i];

    #[test]
    fn test_consts() {
        // check our constants are what Complex::new creates
        fn test(c : Complex64, r : f64, i: f64) {
            assert_eq!(c, Complex::new(r,i));
        }
        test(_0_0i, 0.0, 0.0);
        test(_1_0i, 1.0, 0.0);
        test(_1_1i, 1.0, 1.0);
        test(_neg1_1i, -1.0, 1.0);
        test(_05_05i, 0.5, 0.5);

        assert_eq!(_0_0i, Zero::zero());
        assert_eq!(_1_0i, One::one());
    }

    #[test]
    #[cfg_attr(target_arch = "x86", ignore)]
    // FIXME #7158: (maybe?) currently failing on x86.
    fn test_norm() {
        fn test(c: Complex64, ns: f64) {
            assert_eq!(c.norm_sqr(), ns);
            assert_eq!(c.norm(), ns.sqrt())
        }
        test(_0_0i, 0.0);
        test(_1_0i, 1.0);
        test(_1_1i, 2.0);
        test(_neg1_1i, 2.0);
        test(_05_05i, 0.5);
    }

    #[test]
    fn test_scale_unscale() {
        assert_eq!(_05_05i.scale(2.0), _1_1i);
        assert_eq!(_1_1i.unscale(2.0), _05_05i);
        for &c in all_consts.iter() {
            assert_eq!(c.scale(2.0).unscale(2.0), c);
        }
    }

    #[test]
    fn test_conj() {
        for &c in all_consts.iter() {
            assert_eq!(c.conj(), Complex::new(c.re, -c.im));
            assert_eq!(c.conj().conj(), c);
        }
    }

    #[test]
    fn test_inv() {
        assert_eq!(_1_1i.inv(), _05_05i.conj());
        assert_eq!(_1_0i.inv(), _1_0i.inv());
    }

    #[test]
    #[should_fail]
    fn test_divide_by_zero_natural() {
        let n = Complex::new(2i, 3i);
        let d = Complex::new(0, 0);
        let _x = n / d;
    }

    #[test]
    #[should_fail]
    #[ignore]
    fn test_inv_zero() {
        // FIXME #5736: should this really fail, or just NaN?
        _0_0i.inv();
    }

    #[test]
    fn test_arg() {
        fn test(c: Complex64, arg: f64) {
            assert!((c.arg() - arg).abs() < 1.0e-6)
        }
        test(_1_0i, 0.0);
        test(_1_1i, 0.25 * Float::pi());
        test(_neg1_1i, 0.75 * Float::pi());
        test(_05_05i, 0.25 * Float::pi());
    }

    #[test]
    fn test_polar_conv() {
        fn test(c: Complex64) {
            let (r, theta) = c.to_polar();
            assert!((c - Complex::from_polar(&r, &theta)).norm() < 1e-6);
        }
        for &c in all_consts.iter() { test(c); }
    }

    mod arith {
        use super::{_0_0i, _1_0i, _1_1i, _0_1i, _neg1_1i, _05_05i, all_consts};
        use std::num::Zero;

        #[test]
        fn test_add() {
            assert_eq!(_05_05i + _05_05i, _1_1i);
            assert_eq!(_0_1i + _1_0i, _1_1i);
            assert_eq!(_1_0i + _neg1_1i, _0_1i);

            for &c in all_consts.iter() {
                assert_eq!(_0_0i + c, c);
                assert_eq!(c + _0_0i, c);
            }
        }

        #[test]
        fn test_sub() {
            assert_eq!(_05_05i - _05_05i, _0_0i);
            assert_eq!(_0_1i - _1_0i, _neg1_1i);
            assert_eq!(_0_1i - _neg1_1i, _1_0i);

            for &c in all_consts.iter() {
                assert_eq!(c - _0_0i, c);
                assert_eq!(c - c, _0_0i);
            }
        }

        #[test]
        fn test_mul() {
            assert_eq!(_05_05i * _05_05i, _0_1i.unscale(2.0));
            assert_eq!(_1_1i * _0_1i, _neg1_1i);

            // i^2 & i^4
            assert_eq!(_0_1i * _0_1i, -_1_0i);
            assert_eq!(_0_1i * _0_1i * _0_1i * _0_1i, _1_0i);

            for &c in all_consts.iter() {
                assert_eq!(c * _1_0i, c);
                assert_eq!(_1_0i * c, c);
            }
        }
        #[test]
        fn test_div() {
            assert_eq!(_neg1_1i / _0_1i, _1_1i);
            for &c in all_consts.iter() {
                if c != Zero::zero() {
                    assert_eq!(c / c, _1_0i);
                }
            }
        }
        #[test]
        fn test_neg() {
            assert_eq!(-_1_0i + _0_1i, _neg1_1i);
            assert_eq!((-_0_1i) * _0_1i, _1_0i);
            for &c in all_consts.iter() {
                assert_eq!(-(-c), c);
            }
        }
    }

    #[test]
    fn test_to_string() {
        fn test(c : Complex64, s: String) {
            assert_eq!(c.to_string(), s);
        }
        test(_0_0i, "0+0i".to_string());
        test(_1_0i, "1+0i".to_string());
        test(_0_1i, "0+1i".to_string());
        test(_1_1i, "1+1i".to_string());
        test(_neg1_1i, "-1+1i".to_string());
        test(-_neg1_1i, "1-1i".to_string());
        test(_05_05i, "0.5+0.5i".to_string());
    }

    #[test]
    fn test_hash() {
        let a = Complex::new(0i32, 0i32);
        let b = Complex::new(1i32, 0i32);
        let c = Complex::new(0i32, 1i32);
        assert!(hash(&a) != hash(&b));
        assert!(hash(&b) != hash(&c));
        assert!(hash(&c) != hash(&a));
    }
}
<|endoftext|>