<commit_before>#![deny(deprecated, drop_with_repr_extern, improper_ctypes,
        non_shorthand_field_patterns, overflowing_literals, plugin_as_library,
        private_no_mangle_fns, private_no_mangle_statics, stable_features, unconditional_recursion,
        unknown_lints, unused, unused_allocation, unused_attributes,
        unused_comparisons, unused_features, unused_parens, while_true)]
#![warn(trivial_casts, trivial_numeric_casts, unused, unused_extern_crates,
        unused_import_braces, unused_qualifications, unused_results, variant_size_differences)]
#![allow(missing_docs)]

extern crate rand;
extern crate fractal_utils;

use std::str::FromStr;
use std::u64;

use rand::{Rng, thread_rng};

use fractal_utils::{WalletAddress, Amount, WALLET_ADDRESS_LEN};

#[cfg(test)]
#[test]
fn it_fromstr_walletaddress() {
    for _ in 0..50 {
        let mut random_addr = [0u8; WALLET_ADDRESS_LEN];
        thread_rng().fill_bytes(&mut random_addr[1..]);
        assert_eq!(WalletAddress::from_str(&format!("{}", WalletAddress::from_data(random_addr)))
            .unwrap().get_raw(), &random_addr);
    }
}

#[test]
#[should_panic]
fn it_invalid_wallet_address() {
    let _ = WalletAddress::from_data([1u8; WALLET_ADDRESS_LEN]);
}

#[test]
fn it_amount_parse() {
    let amount: Amount = "175.646".parse().unwrap();
    assert_eq!(amount, Amount::from_repr(175_646));
    assert_eq!(format!("{}", amount), "175.646");

    let amount: Amount = "175.64".parse().unwrap();
    assert_eq!(amount, Amount::from_repr(175_640));
    assert_eq!(format!("{}", amount), "175.64");

    let amount: Amount = "175.6".parse().unwrap();
    assert_eq!(amount, Amount::from_repr(175_600));
    assert_eq!(format!("{}", amount), "175.6");

    let amount: Amount = "175.000".parse().unwrap();
    assert_eq!(amount, Amount::from_repr(175_000));
    assert_eq!(format!("{}", amount), "175");

    let amount: Amount = "175.00".parse().unwrap();
    assert_eq!(amount, Amount::from_repr(175_000));
    assert_eq!(format!("{}", amount), "175");

    let amount: Amount = "175.0".parse().unwrap();
    assert_eq!(amount, Amount::from_repr(175_000));
    assert_eq!(format!("{}", amount), "175");

    let amount: Amount = "175".parse().unwrap();
    assert_eq!(amount, Amount::from_repr(175_000));
    assert_eq!(format!("{}", amount), "175");

    let amount = Amount::max_value();
    assert_eq!(format!("{}", amount),
               format!("{}.{}", u64::MAX / 1_000, u64::MAX % 1_000));

    let amount: Amount = format!("{}", amount).parse().unwrap();
    assert_eq!(amount, Amount::max_value());

    let amount = Amount::min_value();
    assert_eq!(format!("{}", amount), "0");

    let amount: Amount = "0".parse().unwrap();
    assert_eq!(amount, Amount::min_value());

    let amount: Amount = "0.00012".parse().unwrap();
    assert_eq!(amount, Amount::from_repr(0));
    assert_eq!(format!("{}", amount), "0");

    let amount: Amount = "175.6469".parse().unwrap();
    assert_eq!(amount, Amount::from_repr(175_647));
    assert_eq!(format!("{}", amount), "175.647");

    let amount: Amount = "175.6465".parse().unwrap();
    assert_eq!(amount, Amount::from_repr(175_647));
    assert_eq!(format!("{}", amount), "175.647");

    let amount: Amount = "175.6464".parse().unwrap();
    assert_eq!(amount, Amount::from_repr(175_646));
    assert_eq!(format!("{}", amount), "175.646");

    let amount: Amount = ".6465".parse().unwrap();
    assert_eq!(amount, Amount::from_repr(647));
    assert_eq!(format!("{}", amount), "0.647");
}

#[test]
fn it_amount_other_format() {
    let amount = Amount::from_repr(56_000); // 56.000
    assert_eq!(format!("{}", amount), "56");
    assert_eq!(format!("{:.2}", amount), "56.00");
    assert_eq!(format!("{:.5}", amount), "56.00000");
    assert_eq!(format!("{:05}", amount), "00056");
    assert_eq!(format!("{:05.2}", amount), "56.00");
    assert_eq!(format!("{:05.1}", amount), "056.0");

    let amount = Amount::from_repr(56); // 0.056
    assert_eq!(format!("{:.0}", amount), "0");
    assert_eq!(format!("{:.2}", amount), "0.06");

    let amount = Amount::from_repr(1500); // 1.500
    assert_eq!(format!("{:.0}", amount), "2");
}

#[test]
fn it_amount_bad_format() {
    let amount: Result<Amount, _> = "175.".parse();
    assert!(amount.is_err());

    let amount: Result<Amount, _> = "175.837.9239".parse();
    assert!(amount.is_err());

    let amount: Result<Amount, _> = ".098320.2930".parse();
    assert!(amount.is_err());
}

#[test]
fn it_amount_ops() {
    let mut amount = Amount::min_value();
    let amount_10 = Amount::from_repr(10_000);
    assert_eq!(amount + amount_10, Amount::from_repr(10_000));
    amount += amount_10;
    assert_eq!(amount, Amount::from_repr(10_000));

    assert_eq!(amount - amount_10, Amount::min_value());
    amount -= amount_10;
    assert_eq!(amount, Amount::min_value());

    amount += amount_10;
    assert_eq!(amount * 10u32, Amount::from_repr(100_000));
    amount *= 10u32;
    assert_eq!(amount, Amount::from_repr(100_000));

    assert_eq!(amount / 10u32, Amount::from_repr(10_000));
    amount /= 10u32;
    assert_eq!(amount, Amount::from_repr(10_000));

    let mut amount = Amount::from_repr(12_345);
    assert_eq!(amount % 10u32, Amount::from_repr(2_345));
    amount %= 10u32;
    assert_eq!(amount, Amount::from_repr(2_345));
    assert_eq!(amount % 1u32, Amount::from_repr(345));
}
<commit_msg>Trying to improve coverage report<commit_after>#![deny(deprecated, drop_with_repr_extern, improper_ctypes,
        non_shorthand_field_patterns, overflowing_literals, plugin_as_library,
        private_no_mangle_fns, private_no_mangle_statics, stable_features, unconditional_recursion,
        unknown_lints, unused, unused_allocation, unused_attributes,
        unused_comparisons, unused_features, unused_parens, while_true)]
#![warn(trivial_casts, trivial_numeric_casts, unused, unused_extern_crates,
        unused_import_braces, unused_qualifications, unused_results, variant_size_differences)]
#![allow(missing_docs)]

extern crate rand;
extern crate fractal_utils;

use std::str::FromStr;
use std::u64;

use rand::{Rng, thread_rng};

use fractal_utils::wallet_address::{WalletAddress, WALLET_ADDRESS_LEN};
use fractal_utils::amount::Amount;

#[cfg(test)]
#[test]
fn it_fromstr_walletaddress() {
    for _ in 0..50 {
        let mut random_addr = [0u8; WALLET_ADDRESS_LEN];
        thread_rng().fill_bytes(&mut random_addr[1..]);
        assert_eq!(WalletAddress::from_str(&format!("{}", WalletAddress::from_data(random_addr)))
            .unwrap().get_raw(), &random_addr);
    }
}

#[test]
#[should_panic]
fn it_invalid_wallet_address() {
    let _ = WalletAddress::from_data([1u8; WALLET_ADDRESS_LEN]);
}

#[test]
fn it_amount_parse() {
    let amount: Amount = "175.646".parse().unwrap();
    assert_eq!(amount, Amount::from_repr(175_646));
    assert_eq!(format!("{}", amount), "175.646");

    let amount: Amount = "175.64".parse().unwrap();
    assert_eq!(amount, Amount::from_repr(175_640));
    assert_eq!(format!("{}", amount), "175.64");

    let amount: Amount = "175.6".parse().unwrap();
    assert_eq!(amount, Amount::from_repr(175_600));
    assert_eq!(format!("{}", amount), "175.6");

    let amount: Amount = "175.000".parse().unwrap();
    assert_eq!(amount, Amount::from_repr(175_000));
    assert_eq!(format!("{}", amount), "175");

    let amount: Amount = "175.00".parse().unwrap();
    assert_eq!(amount, Amount::from_repr(175_000));
    assert_eq!(format!("{}", amount), "175");

    let amount: Amount = "175.0".parse().unwrap();
    assert_eq!(amount, Amount::from_repr(175_000));
    assert_eq!(format!("{}", amount), "175");

    let amount: Amount = "175".parse().unwrap();
    assert_eq!(amount, Amount::from_repr(175_000));
    assert_eq!(format!("{}", amount), "175");

    let amount = Amount::max_value();
    assert_eq!(format!("{}", amount),
               format!("{}.{}", u64::MAX / 1_000, u64::MAX % 1_000));

    let amount: Amount = format!("{}", amount).parse().unwrap();
    assert_eq!(amount, Amount::max_value());

    let amount = Amount::min_value();
    assert_eq!(format!("{}", amount), "0");

    let amount: Amount = "0".parse().unwrap();
    assert_eq!(amount, Amount::min_value());

    let amount: Amount = "0.00012".parse().unwrap();
    assert_eq!(amount, Amount::from_repr(0));
    assert_eq!(format!("{}", amount), "0");

    let amount: Amount = "175.6469".parse().unwrap();
    assert_eq!(amount, Amount::from_repr(175_647));
    assert_eq!(format!("{}", amount), "175.647");

    let amount: Amount = "175.6465".parse().unwrap();
    assert_eq!(amount, Amount::from_repr(175_647));
    assert_eq!(format!("{}", amount), "175.647");

    let amount: Amount = "175.6464".parse().unwrap();
    assert_eq!(amount, Amount::from_repr(175_646));
    assert_eq!(format!("{}", amount), "175.646");

    let amount: Amount = ".6465".parse().unwrap();
    assert_eq!(amount, Amount::from_repr(647));
    assert_eq!(format!("{}", amount), "0.647");
}

#[test]
fn it_amount_other_format() {
    let amount = Amount::from_repr(56_000); // 56.000
    assert_eq!(format!("{}", amount), "56");
    assert_eq!(format!("{:.2}", amount), "56.00");
    assert_eq!(format!("{:.5}", amount), "56.00000");
    assert_eq!(format!("{:05}", amount), "00056");
    assert_eq!(format!("{:05.2}", amount), "56.00");
    assert_eq!(format!("{:05.1}", amount), "056.0");

    let amount = Amount::from_repr(56); // 0.056
    assert_eq!(format!("{:.0}", amount), "0");
    assert_eq!(format!("{:.2}", amount), "0.06");

    let amount = Amount::from_repr(1500); // 1.500
    assert_eq!(format!("{:.0}", amount), "2");
}

#[test]
fn it_amount_bad_format() {
    let amount: Result<Amount, _> = "175.".parse();
    assert!(amount.is_err());

    let amount: Result<Amount, _> = "175.837.9239".parse();
    assert!(amount.is_err());

    let amount: Result<Amount, _> = ".098320.2930".parse();
    assert!(amount.is_err());
}

#[test]
fn it_amount_ops() {
    let mut amount = Amount::min_value();
    let amount_10 = Amount::from_repr(10_000);
    assert_eq!(amount + amount_10, Amount::from_repr(10_000));
    amount += amount_10;
    assert_eq!(amount, Amount::from_repr(10_000));

    assert_eq!(amount - amount_10, Amount::min_value());
    amount -= amount_10;
    assert_eq!(amount, Amount::min_value());

    amount += amount_10;
    assert_eq!(amount * 10u32, Amount::from_repr(100_000));
    amount *= 10u32;
    assert_eq!(amount, Amount::from_repr(100_000));

    assert_eq!(amount / 10u32, Amount::from_repr(10_000));
    amount /= 10u32;
    assert_eq!(amount, Amount::from_repr(10_000));

    let mut amount = Amount::from_repr(12_345);
    assert_eq!(amount % 10u32, Amount::from_repr(2_345));
    amount %= 10u32;
    assert_eq!(amount, Amount::from_repr(2_345));
    assert_eq!(amount % 1u32, Amount::from_repr(345));
}
<|endoftext|>


<commit_before>extern crate backblaze_b2;
extern crate hyper;
extern crate hyper_native_tls;
extern crate serde;
#[macro_use]
extern crate serde_json;
extern crate rand;
extern crate sha1;

use std::io::Read;
use std::fs::File;

use hyper::Client;
use hyper::net::HttpsConnector;
use hyper_native_tls::NativeTlsClient;

use rand::Rng;

use backblaze_b2::raw::authorize::*;
use backblaze_b2::raw::buckets::*;
use backblaze_b2::raw::files::*;

use serde_json::value::Value;

fn make_client() -> Client {
    let ssl = NativeTlsClient::new().unwrap();
    let connector = HttpsConnector::new(ssl);
    Client::with_connector(connector)
}

fn rand_string(len: usize) -> String {
    let mut rng = rand::thread_rng();
    rng.gen_ascii_chars().take(len).collect()
}

#[test]
fn main_test() {
    let client = make_client();
    let cred_file = File::open("credentials.txt") match {
        Ok(f) => f,
        Err(e) =>
            panic!("The test requires the credentials for b2 to be placed in the file \'credentials.txt\' which contains a json object with the properties \"id\" and \"key\".")
    };
    let cred: B2Credentials = serde_json::from_reader(cred_file).unwrap();
    let auth: B2Authorization = cred.authorize(&client).unwrap();

    let buckets_before: Vec<Bucket> = auth.list_buckets(&client).unwrap();

    let new_bucket_name = format!("rust-b2-test-{}", rand_string(16));

    {
        let bucket_info = json!({"abc": "test", "json": "data"});
        let bucket = auth.create_bucket(&new_bucket_name, BucketType::Private,
                                        bucket_info.clone(), Vec::new(), &client).unwrap();
        assert_eq!(bucket.bucket_name, new_bucket_name);
        assert_eq!(bucket.bucket_type, BucketType::Private);
        assert_eq!(bucket.bucket_info, bucket_info);
        assert_eq!(bucket.account_id, auth.credentials.id);
        auth.delete_bucket_id::<Value>(&bucket.bucket_id, &client).unwrap();
    }
    let bucket = auth.create_bucket_no_info(&new_bucket_name, BucketType::Private,
                                            Vec::new(), &client).unwrap();
    assert_eq!(bucket.bucket_name, new_bucket_name);
    assert_eq!(bucket.bucket_type, BucketType::Private);
    assert_eq!(bucket.bucket_info, json!({}));
    assert_eq!(bucket.account_id, auth.credentials.id);

    let buckets_after: Vec<Bucket> = auth.list_buckets(&client).unwrap();
    assert_eq!(buckets_after.len() - buckets_before.len(), 1);

    if let Ok((fnl, None)) =
        auth.list_file_names::<Value>(&bucket.bucket_id, None, 10, None, None, &client) {
        assert_eq!(fnl.files.len(), 0);
        assert_eq!(fnl.folders.len(), 0);
    } else {
        panic!();
    }

    let file_data: [u8; 9] = [23, 10, 43, 94, 23, 0, 18, 34, 244];
    let mut m = sha1::Sha1::new();
    m.update(&file_data);
    let sha1 = m.digest().to_string();
    let file = {
        let upload_auth = auth.get_upload_url(&bucket.bucket_id, &client).unwrap();

        let file: MoreFileInfo = upload_auth.upload_file(&file_data[..], "test_file.png".to_owned(), None, 9,
        sha1.clone(), &client).unwrap();
        assert_eq!(&file.file_name, "test_file.png");
        assert_eq!(file.account_id, auth.credentials.id);
        assert_eq!(file.content_sha1, sha1);
        assert_eq!(file.bucket_id, bucket.bucket_id);
        assert_eq!(file.content_length, 9);
        assert_eq!(file.content_type, "image/png");
        assert_eq!(file.action, FileType::File);
        file
    };

    {
        let file2: MoreFileInfo = auth.get_file_info(&file.file_id, &client).unwrap();
        assert_eq!(&file2.file_name, "test_file.png");
        assert_eq!(file2.account_id, auth.credentials.id);
        assert_eq!(file2.content_sha1, sha1);
        assert_eq!(file2.bucket_id, bucket.bucket_id);
        assert_eq!(file2.content_length, 9);
        assert_eq!(file2.content_type, "image/png");
        assert_eq!(file2.action, FileType::File);
    }
    if let Ok((fnl, None)) =
        auth.list_file_names::<Value>(&bucket.bucket_id, None, 10, None, None, &client) {
        assert_eq!(fnl.files.len(), 1);
        assert_eq!(fnl.folders.len(), 0);
        let file2 = &fnl.files[0];
        assert_eq!(&file2.file_name, "test_file.png");
        assert_eq!(file2.content_sha1, sha1);
        assert_eq!(file2.content_length, 9);
        assert_eq!(file2.content_type, "image/png");
    } else {
        panic!();
    }
    if let Ok((fvl, None, None)) =
        auth.list_file_versions::<Value>(&bucket.bucket_id, None, None, 10, None, None, &client) {
        assert_eq!(fvl.files.len(), 1);
        assert_eq!(fvl.folders.len(), 0);
        assert_eq!(fvl.hide_markers.len(), 0);
        assert_eq!(fvl.unfinished_large_files.len(), 0);
        let file2 = &fvl.files[0];
        assert_eq!(&file2.file_name, "test_file.png");
        assert_eq!(file2.content_sha1, sha1);
        assert_eq!(file2.content_length, 9);
        assert_eq!(file2.content_type, "image/png");
    } else {
        panic!();
    }

    {
        let (mut data, file2): (_, Option<FileInfo>) = auth.to_download_authorization()
                            .download_file_by_id(&file.file_id, &client).unwrap();
        let mut buf = Vec::new();
        data.read_to_end(&mut buf).unwrap();
        assert_eq!(buf, Vec::from(&file_data[..]));
        let file2 = file2.unwrap();
        assert_eq!(&file2.file_name, "test_file.png");
        assert_eq!(file2.content_sha1, sha1);
        assert_eq!(file2.content_length, 9);
        assert_eq!(file2.content_type, "image/png");
    }
    {
        let (mut data, file2): (_, Option<FileInfo>) = auth.to_download_authorization()
                            .download_file_by_name(&bucket.bucket_name, &file.file_name, &client).unwrap();
        let mut buf = Vec::new();
        data.read_to_end(&mut buf).unwrap();
        assert_eq!(buf, Vec::from(&file_data[..]));
        let file2 = file2.unwrap();
        assert_eq!(&file2.file_name, "test_file.png");
        assert_eq!(file2.content_sha1, sha1);
        assert_eq!(file2.content_length, 9);
        assert_eq!(file2.content_type, "image/png");
    }
    {
        let (mut data, file2): (_, Option<FileInfo>) = auth.to_download_authorization()
                            .download_range_by_id(&file.file_id, 1, 3, &client).unwrap();
        let mut buf = Vec::new();
        data.read_to_end(&mut buf).unwrap();
        assert_eq!(buf, Vec::from(&file_data[1..4]));
        let file2 = file2.unwrap();
        assert_eq!(&file2.file_name, "test_file.png");
        assert_eq!(file2.content_sha1, sha1);
        assert_eq!(file2.content_length, 3);
        assert_eq!(file2.content_type, "image/png");
    }
    {
        let (mut data, file2): (_, Option<FileInfo>) = auth.to_download_authorization()
                            .download_range_by_name(&bucket.bucket_name, &file.file_name, 1, 3, &client).unwrap();
        let mut buf = Vec::new();
        data.read_to_end(&mut buf).unwrap();
        assert_eq!(buf, Vec::from(&file_data[1..4]));
        let file2 = file2.unwrap();
        assert_eq!(&file2.file_name, "test_file.png");
        assert_eq!(file2.content_sha1, sha1);
        assert_eq!(file2.content_length, 3);
        assert_eq!(file2.content_type, "image/png");
    }

    auth.hide_file(&file.file_name, &bucket.bucket_id, &client).unwrap();
    if let Ok((fvl, None, None)) =
        auth.list_file_versions::<Value>(&bucket.bucket_id, None, None, 10, None, None, &client) {
        for file in fvl.files {
            auth.delete_file_version(&file.file_name, &file.file_id, &client).unwrap();
        }
        for file in fvl.hide_markers {
            auth.delete_file_version(&file.file_name, &file.file_id, &client).unwrap();
        }
        for file in fvl.unfinished_large_files {
            auth.delete_file_version(&file.file_name, &file.file_id, &client).unwrap();
        }
    } else {
        panic!();
    }
    auth.delete_bucket(&bucket, &client).unwrap();

    /*  comment in to clean up buckets
    for buck in buckets_before {
        if buck.bucket_name.starts_with("rust-b2-test-") {
            match auth.list_file_versions::<Value>(&buck.bucket_id, None, None, 10, None, None, &client) {
                Ok((fvl, None, None)) => {
                    for f in fvl.files {
                        auth.delete_file_version(&f.file_name, &f.file_id, &client).unwrap();
                    }
                    for f in fvl.hide_markers {
                        auth.delete_file_version(&f.file_name, &f.file_id, &client).unwrap();
                    }
                    for f in fvl.unfinished_large_files {
                        auth.delete_file_version(&f.file_name, &f.file_id, &client).unwrap();
                    }
                },
                Ok(x) => panic!("{:?}", x),
                Err(e) => panic!("{:?}", e)
            }
            auth.delete_bucket(&buck, &client).unwrap();
        }
    }
    */

}

<commit_msg>fix match<commit_after>extern crate backblaze_b2;
extern crate hyper;
extern crate hyper_native_tls;
extern crate serde;
#[macro_use]
extern crate serde_json;
extern crate rand;
extern crate sha1;

use std::io::Read;
use std::fs::File;

use hyper::Client;
use hyper::net::HttpsConnector;
use hyper_native_tls::NativeTlsClient;

use rand::Rng;

use backblaze_b2::raw::authorize::*;
use backblaze_b2::raw::buckets::*;
use backblaze_b2::raw::files::*;

use serde_json::value::Value;

fn make_client() -> Client {
    let ssl = NativeTlsClient::new().unwrap();
    let connector = HttpsConnector::new(ssl);
    Client::with_connector(connector)
}

fn rand_string(len: usize) -> String {
    let mut rng = rand::thread_rng();
    rng.gen_ascii_chars().take(len).collect()
}

#[test]
fn main_test() {
    let client = make_client();
    let cred_file = match File::open("credentials.txt") {
        Ok(f) => f,
        Err(_) =>
            panic!("The test requires the credentials for b2 to be placed in the file \'credentials.txt\' which contains a json object with the properties \"id\" and \"key\".")
    };
    let cred: B2Credentials = serde_json::from_reader(cred_file).unwrap();
    let auth: B2Authorization = cred.authorize(&client).unwrap();

    let buckets_before: Vec<Bucket> = auth.list_buckets(&client).unwrap();

    let new_bucket_name = format!("rust-b2-test-{}", rand_string(16));

    {
        let bucket_info = json!({"abc": "test", "json": "data"});
        let bucket = auth.create_bucket(&new_bucket_name, BucketType::Private,
                                        bucket_info.clone(), Vec::new(), &client).unwrap();
        assert_eq!(bucket.bucket_name, new_bucket_name);
        assert_eq!(bucket.bucket_type, BucketType::Private);
        assert_eq!(bucket.bucket_info, bucket_info);
        assert_eq!(bucket.account_id, auth.credentials.id);
        auth.delete_bucket_id::<Value>(&bucket.bucket_id, &client).unwrap();
    }
    let bucket = auth.create_bucket_no_info(&new_bucket_name, BucketType::Private,
                                            Vec::new(), &client).unwrap();
    assert_eq!(bucket.bucket_name, new_bucket_name);
    assert_eq!(bucket.bucket_type, BucketType::Private);
    assert_eq!(bucket.bucket_info, json!({}));
    assert_eq!(bucket.account_id, auth.credentials.id);

    let buckets_after: Vec<Bucket> = auth.list_buckets(&client).unwrap();
    assert_eq!(buckets_after.len() - buckets_before.len(), 1);

    if let Ok((fnl, None)) =
        auth.list_file_names::<Value>(&bucket.bucket_id, None, 10, None, None, &client) {
        assert_eq!(fnl.files.len(), 0);
        assert_eq!(fnl.folders.len(), 0);
    } else {
        panic!();
    }

    let file_data: [u8; 9] = [23, 10, 43, 94, 23, 0, 18, 34, 244];
    let mut m = sha1::Sha1::new();
    m.update(&file_data);
    let sha1 = m.digest().to_string();
    let file = {
        let upload_auth = auth.get_upload_url(&bucket.bucket_id, &client).unwrap();

        let file: MoreFileInfo = upload_auth.upload_file(&file_data[..], "test_file.png".to_owned(), None, 9,
        sha1.clone(), &client).unwrap();
        assert_eq!(&file.file_name, "test_file.png");
        assert_eq!(file.account_id, auth.credentials.id);
        assert_eq!(file.content_sha1, sha1);
        assert_eq!(file.bucket_id, bucket.bucket_id);
        assert_eq!(file.content_length, 9);
        assert_eq!(file.content_type, "image/png");
        assert_eq!(file.action, FileType::File);
        file
    };

    {
        let file2: MoreFileInfo = auth.get_file_info(&file.file_id, &client).unwrap();
        assert_eq!(&file2.file_name, "test_file.png");
        assert_eq!(file2.account_id, auth.credentials.id);
        assert_eq!(file2.content_sha1, sha1);
        assert_eq!(file2.bucket_id, bucket.bucket_id);
        assert_eq!(file2.content_length, 9);
        assert_eq!(file2.content_type, "image/png");
        assert_eq!(file2.action, FileType::File);
    }
    if let Ok((fnl, None)) =
        auth.list_file_names::<Value>(&bucket.bucket_id, None, 10, None, None, &client) {
        assert_eq!(fnl.files.len(), 1);
        assert_eq!(fnl.folders.len(), 0);
        let file2 = &fnl.files[0];
        assert_eq!(&file2.file_name, "test_file.png");
        assert_eq!(file2.content_sha1, sha1);
        assert_eq!(file2.content_length, 9);
        assert_eq!(file2.content_type, "image/png");
    } else {
        panic!();
    }
    if let Ok((fvl, None, None)) =
        auth.list_file_versions::<Value>(&bucket.bucket_id, None, None, 10, None, None, &client) {
        assert_eq!(fvl.files.len(), 1);
        assert_eq!(fvl.folders.len(), 0);
        assert_eq!(fvl.hide_markers.len(), 0);
        assert_eq!(fvl.unfinished_large_files.len(), 0);
        let file2 = &fvl.files[0];
        assert_eq!(&file2.file_name, "test_file.png");
        assert_eq!(file2.content_sha1, sha1);
        assert_eq!(file2.content_length, 9);
        assert_eq!(file2.content_type, "image/png");
    } else {
        panic!();
    }

    {
        let (mut data, file2): (_, Option<FileInfo>) = auth.to_download_authorization()
                            .download_file_by_id(&file.file_id, &client).unwrap();
        let mut buf = Vec::new();
        data.read_to_end(&mut buf).unwrap();
        assert_eq!(buf, Vec::from(&file_data[..]));
        let file2 = file2.unwrap();
        assert_eq!(&file2.file_name, "test_file.png");
        assert_eq!(file2.content_sha1, sha1);
        assert_eq!(file2.content_length, 9);
        assert_eq!(file2.content_type, "image/png");
    }
    {
        let (mut data, file2): (_, Option<FileInfo>) = auth.to_download_authorization()
                            .download_file_by_name(&bucket.bucket_name, &file.file_name, &client).unwrap();
        let mut buf = Vec::new();
        data.read_to_end(&mut buf).unwrap();
        assert_eq!(buf, Vec::from(&file_data[..]));
        let file2 = file2.unwrap();
        assert_eq!(&file2.file_name, "test_file.png");
        assert_eq!(file2.content_sha1, sha1);
        assert_eq!(file2.content_length, 9);
        assert_eq!(file2.content_type, "image/png");
    }
    {
        let (mut data, file2): (_, Option<FileInfo>) = auth.to_download_authorization()
                            .download_range_by_id(&file.file_id, 1, 3, &client).unwrap();
        let mut buf = Vec::new();
        data.read_to_end(&mut buf).unwrap();
        assert_eq!(buf, Vec::from(&file_data[1..4]));
        let file2 = file2.unwrap();
        assert_eq!(&file2.file_name, "test_file.png");
        assert_eq!(file2.content_sha1, sha1);
        assert_eq!(file2.content_length, 3);
        assert_eq!(file2.content_type, "image/png");
    }
    {
        let (mut data, file2): (_, Option<FileInfo>) = auth.to_download_authorization()
                            .download_range_by_name(&bucket.bucket_name, &file.file_name, 1, 3, &client).unwrap();
        let mut buf = Vec::new();
        data.read_to_end(&mut buf).unwrap();
        assert_eq!(buf, Vec::from(&file_data[1..4]));
        let file2 = file2.unwrap();
        assert_eq!(&file2.file_name, "test_file.png");
        assert_eq!(file2.content_sha1, sha1);
        assert_eq!(file2.content_length, 3);
        assert_eq!(file2.content_type, "image/png");
    }

    auth.hide_file(&file.file_name, &bucket.bucket_id, &client).unwrap();
    if let Ok((fvl, None, None)) =
        auth.list_file_versions::<Value>(&bucket.bucket_id, None, None, 10, None, None, &client) {
        for file in fvl.files {
            auth.delete_file_version(&file.file_name, &file.file_id, &client).unwrap();
        }
        for file in fvl.hide_markers {
            auth.delete_file_version(&file.file_name, &file.file_id, &client).unwrap();
        }
        for file in fvl.unfinished_large_files {
            auth.delete_file_version(&file.file_name, &file.file_id, &client).unwrap();
        }
    } else {
        panic!();
    }
    auth.delete_bucket(&bucket, &client).unwrap();

    /*  comment in to clean up buckets
    for buck in buckets_before {
        if buck.bucket_name.starts_with("rust-b2-test-") {
            match auth.list_file_versions::<Value>(&buck.bucket_id, None, None, 10, None, None, &client) {
                Ok((fvl, None, None)) => {
                    for f in fvl.files {
                        auth.delete_file_version(&f.file_name, &f.file_id, &client).unwrap();
                    }
                    for f in fvl.hide_markers {
                        auth.delete_file_version(&f.file_name, &f.file_id, &client).unwrap();
                    }
                    for f in fvl.unfinished_large_files {
                        auth.delete_file_version(&f.file_name, &f.file_id, &client).unwrap();
                    }
                },
                Ok(x) => panic!("{:?}", x),
                Err(e) => panic!("{:?}", e)
            }
            auth.delete_bucket(&buck, &client).unwrap();
        }
    }
    */

}

<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::mem;

use vertex::{RawVertex,Vertex};
use traversal::GraphQuery;
use path::{Path, Element};
use edge::Edge;
use parser::parse;

#[derive(Debug)]
pub struct Graph {
    elements: i64,
    // we transmute our Boxed vertex into a pointer later
    vertices: HashMap<i64, *mut RawVertex>,
    queue: Vec<String>,
}

// graph is not thread safe - needs to be wrapped in an Arc<Mutex> when running as server
impl Graph {
    pub fn new() -> Box<Graph> {
        let vertices: HashMap<i64, *mut RawVertex> = HashMap::new();
        Box::new(Graph{elements:0, vertices:vertices, queue:Vec::with_capacity(100)})
    }

    // todo actually return a result DERP DERP DERP
    pub fn execute(&self, query: &str) {
        // parse the graph query

        // let mut steps_table : HashMap<&'static str, FnMut() -> Result<&'static str, &'static str> > = HashMap::new();
        // steps_table.insert("outV", traverse_out);
        // steps_table.insert("inV", traverse_in);

        // todo - validate query is using legit steps

        match parse(query) {
            Ok(query) => {
                // execute each of the steps sequentially
                for step in query.steps.iter() {
                    // lookup step in hash table
                    println!("{}", step);

                    let name : &str = &step.name;
                    let step_result = match name {
                        "outV" => self.traverse_out_vertex(),
                        "inV" => self.traverse_in_vertex(),
                        "outE" => self.traverse_out_edge(),
                        "inE" => self.traverse_in_edge(),
                        "v" => self.vertex_query(),
                        "V" => self.global_query(),
                        _ => Err("no thingy found")
                    };
                    // execute function, passing step args
                }
            },
            Err(x) => {
                println!("SUCH FAIL!!!!")
            }
                // Result::Err("meh")
        }
        println!("query finished");
        ()
    }

    fn vertex_query(&self) -> Result<&'static str, &'static str>  {
        Ok("cool")
    }

    fn global_query(&self) -> Result<&'static str, &'static str>  {
        Ok("cool")
    }

    fn traverse_out_vertex(&self) -> Result<&'static str, &'static str>  {
        Ok("cool")
    }

    fn traverse_in_vertex(&self) -> Result<&'static str, &'static str>  {
        Ok("cool")
    }

    fn traverse_out_edge(&self) -> Result<&'static str, &'static str>  {
        Ok("cool")
    }

    fn traverse_in_edge(&self) -> Result<&'static str, &'static str>  {
        Ok("cool")
    }
    pub fn add_vertex(&mut self) -> Vertex {
        let new_id = self.elements + 1;
        self.elements += 1;
        let v = RawVertex::new(new_id);
        let ptr: *mut RawVertex = unsafe { mem::transmute(v) };

        self.vertices.insert(new_id, ptr);

        // return the proxy which knows it's own id
        Vertex{id:new_id, v: ptr}
    }

    pub fn get(&self, vertex_id:i64) -> Option<Vertex>  {
        let vertex_pointer = self.vertices.get(&vertex_id);
        // return a proxy
        match vertex_pointer {
            Some(ptr) =>
                Some(Vertex{id:vertex_id, v:*ptr}),
            None =>
                None
        }
    }

    // this will be used to start a graph query
    pub fn v(&self, vertex_id:i64) -> GraphQuery {
        // grab the original vertex
        let vertex = self.get(vertex_id);
        let mut v = Vec::new();
        match vertex {
            Some(result) => {
                v.push(result);
                GraphQuery::new(v)
            }
            None => GraphQuery::empty()
        }
    }
}

pub trait TraversableToVertex {
	fn inV(&self) -> Vec<Vertex>;
	fn outV(&self, &[&str]) -> Vec<Vertex>;
//	fn inE(&self) -> Vec<Edge>;

}
<commit_msg>passing args<commit_after>use std::collections::HashMap;
use std::mem;

use vertex::{RawVertex,Vertex};
use traversal::GraphQuery;
use path::{Path, Element};
use edge::Edge;
use parser::{parse, Arg};

#[derive(Debug)]
pub struct Graph {
    elements: i64,
    // we transmute our Boxed vertex into a pointer later
    vertices: HashMap<i64, *mut RawVertex>,
    queue: Vec<String>,
}

// graph is not thread safe - needs to be wrapped in an Arc<Mutex> when running as server
impl Graph {
    pub fn new() -> Box<Graph> {
        let vertices: HashMap<i64, *mut RawVertex> = HashMap::new();
        Box::new(Graph{elements:0, vertices:vertices, queue:Vec::with_capacity(100)})
    }

    // todo actually return a result DERP DERP DERP
    pub fn execute(&self, query: &str) {
        // parse the graph query

        // let mut steps_table : HashMap<&'static str, FnMut() -> Result<&'static str, &'static str> > = HashMap::new();
        // steps_table.insert("outV", traverse_out);
        // steps_table.insert("inV", traverse_in);

        // todo - validate query is using legit steps

        match parse(query) {
            Ok(query) => {
                // execute each of the steps sequentially
                for step in query.steps.iter() {
                    // lookup step in hash table
                    println!("{}", step);

                    let name : &str = &step.name;
                    let step_result = match name {
                        "outV" => self.traverse_out_vertex(&step.args),
                        "inV" => self.traverse_in_vertex(&step.args),
                        "outE" => self.traverse_out_edge(&step.args),
                        "inE" => self.traverse_in_edge(&step.args),
                        "v" => self.vertex_query(&step.args),
                        "V" => self.global_query(&step.args),
                        _ => Err("no thingy found")
                    };
                    // execute function, passing step args
                }
            },
            Err(x) => {
                println!("SUCH FAIL!!!!")
            }
                // Result::Err("meh")
        }
        println!("query finished");
        ()
    }

    fn vertex_query(&self, args: &Vec<Arg>) -> Result<&'static str, &'static str>  {
        println!("vertex query");
        Ok("cool")
    }

    fn global_query(&self, args: &Vec<Arg>) -> Result<&'static str, &'static str>  {
        println!("global query");
        Ok("cool")
    }

    fn traverse_out_vertex(&self, args: &Vec<Arg>) -> Result<&'static str, &'static str>  {
        println!("outV traversal");

        Ok("cool")
    }

    fn traverse_in_vertex(&self, args: &Vec<Arg>) -> Result<&'static str, &'static str>  {
        println!("inV traversal");

        Ok("cool")
    }

    fn traverse_out_edge(&self, args: &Vec<Arg>) -> Result<&'static str, &'static str>  {
        println!("outE traversal");
        Ok("cool")
    }

    fn traverse_in_edge(&self, args: &Vec<Arg>) -> Result<&'static str, &'static str>  {
        println!("inE traversal");
        Ok("cool")
    }
    pub fn add_vertex(&mut self) -> Vertex {
        let new_id = self.elements + 1;
        self.elements += 1;
        let v = RawVertex::new(new_id);
        let ptr: *mut RawVertex = unsafe { mem::transmute(v) };

        self.vertices.insert(new_id, ptr);

        // return the proxy which knows it's own id
        Vertex{id:new_id, v: ptr}
    }

    pub fn get(&self, vertex_id:i64) -> Option<Vertex>  {
        let vertex_pointer = self.vertices.get(&vertex_id);
        // return a proxy
        match vertex_pointer {
            Some(ptr) =>
                Some(Vertex{id:vertex_id, v:*ptr}),
            None =>
                None
        }
    }

    // this will be used to start a graph query
    pub fn v(&self, vertex_id:i64) -> GraphQuery {
        // grab the original vertex
        let vertex = self.get(vertex_id);
        let mut v = Vec::new();
        match vertex {
            Some(result) => {
                v.push(result);
                GraphQuery::new(v)
            }
            None => GraphQuery::empty()
        }
    }
}

pub trait TraversableToVertex {
	fn inV(&self) -> Vec<Vertex>;
	fn outV(&self, &[&str]) -> Vec<Vertex>;
//	fn inE(&self) -> Vec<Edge>;

}
<|endoftext|>


<commit_before>use std::collections::{HashMap, HashSet, VecDeque};
use std::hash::Hash;

use crate::colour::Colour;
use crate::grid::Grid;

// Represent the state of the game as a graph.  One node for each cell.  There is an edge between
// two cells if and only if they are the same colour and have a distance of 1 according to the
// Manhattan metric.
//
// The game has only one real operation (i.e. not counting level generation): Switching the colour
// of the connected component containing the top left cell to whichever colour the clicked cell
// has.  This results in said component growing by every component it neighbours which has its new
// colour.  In essence, the aim of the gaim is to join connected components until only one is
// left.  Fewer clicks is better.
//
// So, we represent the game state as a collection of connected components, each of which has a
// colour, a list of coordinates of the constituent cells, and a list of it s neighbours.  As we
// do all our operations on connected components, we actually work not with the graph of
// neighbouring cells but with a graph of connected components.  The graph of connected components
// is made up of one node representing each connected component and an edge between any two
// connected components that have cells which share an edge, i.e. two cells which would have been
// connected by an edge in the original graph if they had had the same colour (which they did
// not).

#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct Position {
    pub row: usize,
    pub column: usize,
}

#[derive(Debug, Clone)]
pub struct ConnectedComponent {
    id: usize,
    pub colour: Colour,
    pub cells: HashSet<Position>,
}

impl PartialEq for ConnectedComponent {
    fn eq(&self, other: &Self) -> bool {
        self.id == other.id
    }
}

impl Eq for ConnectedComponent {}

impl Hash for ConnectedComponent {
    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
        self.id.hash(state);
    }
}

#[derive(Debug)]
pub struct Graph {
    pub components: HashMap<usize, ConnectedComponent>,
    pub neighbours: HashMap<usize, HashSet<usize>>,
}

fn find_connected_components(grid: &Grid) -> Vec<(ConnectedComponent, HashSet<usize>)> {
    let rows = grid.number_of_rows;
    let columns = grid.number_of_columns;

    let mut remaining_cells: HashSet<usize> = (0..grid.cells.len()).into_iter().collect();

    let mut components = vec![];
    let mut counter = 0;

    // Take any element to land in any component.
    while let Some(&start_cell_index) = remaining_cells.iter().next() {
        let mut visited = HashSet::new();
        let mut neighbours = HashSet::new();
        let mut queue = VecDeque::new();

        queue.push_back(start_cell_index);

        // Gather all cells in the connected component of start_cell_index.
        while let Some(i) = queue.pop_front() {
            visited.insert(i);
            remaining_cells.remove(&i);

            let mut neighbouring_cells = vec![];
            if i % columns > 0 {
                neighbouring_cells.push(i - 1);
            }
            if i % columns < columns - 1 {
                neighbouring_cells.push(i + 1);
            }
            if i >= columns {
                neighbouring_cells.push(i - columns)
            }
            if i < (rows - 1) * columns {
                neighbouring_cells.push(i + columns)
            }

            for neighbour in neighbouring_cells {
                if visited.contains(&neighbour) {
                    continue;
                }

                if grid.cells[i] == grid.cells[neighbour] {
                    queue.push_back(neighbour);
                } else {
                    neighbours.insert(neighbour);
                }
            }
        }

        let cells = visited
            .iter()
            .map(|&i| Position {
                column: i % columns,
                row: i / columns,
            })
            .collect();

        let component = ConnectedComponent {
            id: counter,
            colour: grid.cells[*visited.iter().next().unwrap()],
            cells,
        };
        counter += 1;

        components.push((component, neighbours));
    }

    return components;
}

impl Graph {
    pub fn create(grid: &Grid) -> Self {
        let components_and_neighbours = find_connected_components(&grid);

        let map_cell_to_component: HashMap<Position, ConnectedComponent> =
            components_and_neighbours
                .iter()
                .flat_map(|(component, _)| {
                    component
                        .cells
                        .iter()
                        .map(|cell| (cell.clone(), component.clone()))
                        .collect::<Vec<(Position, ConnectedComponent)>>()
                })
                .collect();

        let mut neighbours: HashMap<usize, HashSet<usize>> = HashMap::new();

        for (component, neighbour_cells) in &components_and_neighbours {
            let mut neighbour_components = HashSet::new();

            for cell in neighbour_cells {
                let position = Position {
                    column: cell % grid.number_of_columns,
                    row: cell / grid.number_of_columns,
                };
                neighbour_components.insert(map_cell_to_component[&position].id);
            }
            neighbours.insert(component.id, neighbour_components);
        }

        let mut components = HashMap::with_capacity(components_and_neighbours.len());

        for (c, n) in components_and_neighbours.into_iter() {
            components.insert(c.id, c);
        }

        Self {
            components,
            neighbours
        }
    }

    fn to_grid(&self, rows: usize, columns: usize) -> Grid {
        let mut cells = vec![Colour::Red; rows * columns];

        for component in self.neighbours.keys() {
            for position in &self.components[component].cells {
                cells[position.column + position.row * columns] = self.components[component].colour;
            }
        }

        Grid {
            number_of_rows: rows,
            number_of_columns: columns,
            cells,
        }
    }

    pub fn find_component(&self, position: &Position) -> &ConnectedComponent {
        for component in self.neighbours.keys() {
            if self.components[component].cells.contains(&position) {
                return &self.components[component];
            }
        }

        unreachable!()
    }

    pub fn change_colour_of_component_at(&mut self, position: &Position, colour: Colour) {
        let component_id = self.find_component(position).id;

        // Remove the component which is to change colour
        let mut component = self.components.remove(&component_id).unwrap();
        let mut neighbours = self.neighbours.remove(&component_id).unwrap();

        // Gather new cells for that component by combinging the cells of all
        // its neighbours which already have the new colour.
        let mut new_cells = HashSet::new();
        // Gather the set of its new neighbours which is just the union of the
        // sets of neighbours its neighbours with the new colour have.
        let mut new_neighbours = HashSet::new();
        let mut removed_neighbours = HashSet::new();

        for id in &neighbours {
            if *id != component_id && self.components[id].colour == colour {
                let neighbour_component = self.components.remove(id).unwrap();
                new_cells.extend(neighbour_component.cells.into_iter());
                let set_of_neighbour_ids = self.neighbours.remove(&neighbour_component.id).unwrap();
                new_neighbours.extend(set_of_neighbour_ids.into_iter());
                removed_neighbours.insert(*id);
            }
        }

        // Add new neighbours
        neighbours.extend(new_neighbours.clone().into_iter());
        // Remove the ID of the component itself
        neighbours.remove(&component_id);
        // and the IDs of the neighbours that were merged into the component
        neighbours = neighbours.difference(&removed_neighbours).map(|&x| x).collect();

        // Add the cells from the neighbours which now have the new colour
        component.cells.extend(new_cells.into_iter());
        // and update the colour.  With this, the component itself is done.
        component.colour = colour;

        // Fix the neighbour sets for all the remaining components
        // All we have to do here is replace any of the indices in new_neighbours with component_id.
        for (_, n) in self.neighbours.iter_mut() {
            for incorporated_neighbour_id in &removed_neighbours {
                n.remove(incorporated_neighbour_id);
            }
            n.insert(component_id);
        }

        // Put the component and neighbours back into the Graph
        self.components.entry(component_id).or_insert(component);
        self.neighbours.entry(component_id).or_insert(neighbours);
    }
}

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

    #[test]
    fn should_return_same_grid_as_input() {
        let size = 4;
        let grid = Grid::generate(size);

        let graph = Graph::create(&grid);
        let reconstituted_grid = graph.to_grid(size, size);

        assert_eq!(reconstituted_grid, grid);
    }

    #[test]
    fn should_have_one_component() {
        let grid = Grid {
            number_of_columns: 2,
            number_of_rows: 2,
            cells: vec![Colour::Red; 4],
        };

        let graph = Graph::create(&grid);

        assert_eq!(graph.neighbours.len(), 1);
    }

    #[test]
    fn should_have_four_component() {
        let grid = Grid {
            number_of_columns: 2,
            number_of_rows: 2,
            cells: vec![Colour::Red, Colour::Yellow, Colour::Yellow, Colour::Red],
        };

        let graph = Graph::create(&grid);

        assert_eq!(graph.neighbours.len(), 4);
    }

    #[test]
    fn should_have_two_component() {
        let grid = Grid {
            number_of_columns: 2,
            number_of_rows: 2,
            cells: vec![Colour::Red, Colour::Red, Colour::Yellow, Colour::Yellow],
        };

        let graph = Graph::create(&grid);

        assert_eq!(graph.neighbours.len(), 2);
    }

    #[test]
    fn should_have_same_keys_for_components_and_neighbours_maps() {
        let size = 4;
        let grid = Grid::generate(size);

        let graph = Graph::create(&grid);

        let components_keys: HashSet<_> = graph.components.keys().collect();
        let neighbours_keys: HashSet<_> = graph.neighbours.keys().collect();
        assert_eq!(components_keys, neighbours_keys);
    }

    #[test]
    fn should_contain_exactly_the_component_ids_as_keys() {
        let size = 4;
        let grid = Grid::generate(size);

        let graph = Graph::create(&grid);

        let component_keys: HashSet<_> = graph.components.keys().collect();
        let component_ids: HashSet<_> = graph.components.values().map(|x| &x.id).collect();
        assert_eq!(component_keys, component_ids);

        for (id, component) in graph.components {
            assert_eq!(id, component.id);
        }
    }

    #[test]
    fn should_contain_only_component_ids_as_values_in_neighbours_map() {
        let size = 4;
        let grid = Grid::generate(size);

        let graph = Graph::create(&grid);

        let component_ids: HashSet<_> = graph.components.keys().map(|&x| x).collect();

        for (_, neighbours) in graph.neighbours {
            assert_eq!(neighbours.difference(&component_ids).collect::<HashSet<_>>().len(), 0);
        }
    }
}
<commit_msg>Replace variable with _<commit_after>use std::collections::{HashMap, HashSet, VecDeque};
use std::hash::Hash;

use crate::colour::Colour;
use crate::grid::Grid;

// Represent the state of the game as a graph.  One node for each cell.  There is an edge between
// two cells if and only if they are the same colour and have a distance of 1 according to the
// Manhattan metric.
//
// The game has only one real operation (i.e. not counting level generation): Switching the colour
// of the connected component containing the top left cell to whichever colour the clicked cell
// has.  This results in said component growing by every component it neighbours which has its new
// colour.  In essence, the aim of the gaim is to join connected components until only one is
// left.  Fewer clicks is better.
//
// So, we represent the game state as a collection of connected components, each of which has a
// colour, a list of coordinates of the constituent cells, and a list of it s neighbours.  As we
// do all our operations on connected components, we actually work not with the graph of
// neighbouring cells but with a graph of connected components.  The graph of connected components
// is made up of one node representing each connected component and an edge between any two
// connected components that have cells which share an edge, i.e. two cells which would have been
// connected by an edge in the original graph if they had had the same colour (which they did
// not).

#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct Position {
    pub row: usize,
    pub column: usize,
}

#[derive(Debug, Clone)]
pub struct ConnectedComponent {
    id: usize,
    pub colour: Colour,
    pub cells: HashSet<Position>,
}

impl PartialEq for ConnectedComponent {
    fn eq(&self, other: &Self) -> bool {
        self.id == other.id
    }
}

impl Eq for ConnectedComponent {}

impl Hash for ConnectedComponent {
    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
        self.id.hash(state);
    }
}

#[derive(Debug)]
pub struct Graph {
    pub components: HashMap<usize, ConnectedComponent>,
    pub neighbours: HashMap<usize, HashSet<usize>>,
}

fn find_connected_components(grid: &Grid) -> Vec<(ConnectedComponent, HashSet<usize>)> {
    let rows = grid.number_of_rows;
    let columns = grid.number_of_columns;

    let mut remaining_cells: HashSet<usize> = (0..grid.cells.len()).into_iter().collect();

    let mut components = vec![];
    let mut counter = 0;

    // Take any element to land in any component.
    while let Some(&start_cell_index) = remaining_cells.iter().next() {
        let mut visited = HashSet::new();
        let mut neighbours = HashSet::new();
        let mut queue = VecDeque::new();

        queue.push_back(start_cell_index);

        // Gather all cells in the connected component of start_cell_index.
        while let Some(i) = queue.pop_front() {
            visited.insert(i);
            remaining_cells.remove(&i);

            let mut neighbouring_cells = vec![];
            if i % columns > 0 {
                neighbouring_cells.push(i - 1);
            }
            if i % columns < columns - 1 {
                neighbouring_cells.push(i + 1);
            }
            if i >= columns {
                neighbouring_cells.push(i - columns)
            }
            if i < (rows - 1) * columns {
                neighbouring_cells.push(i + columns)
            }

            for neighbour in neighbouring_cells {
                if visited.contains(&neighbour) {
                    continue;
                }

                if grid.cells[i] == grid.cells[neighbour] {
                    queue.push_back(neighbour);
                } else {
                    neighbours.insert(neighbour);
                }
            }
        }

        let cells = visited
            .iter()
            .map(|&i| Position {
                column: i % columns,
                row: i / columns,
            })
            .collect();

        let component = ConnectedComponent {
            id: counter,
            colour: grid.cells[*visited.iter().next().unwrap()],
            cells,
        };
        counter += 1;

        components.push((component, neighbours));
    }

    return components;
}

impl Graph {
    pub fn create(grid: &Grid) -> Self {
        let components_and_neighbours = find_connected_components(&grid);

        let map_cell_to_component: HashMap<Position, ConnectedComponent> =
            components_and_neighbours
                .iter()
                .flat_map(|(component, _)| {
                    component
                        .cells
                        .iter()
                        .map(|cell| (cell.clone(), component.clone()))
                        .collect::<Vec<(Position, ConnectedComponent)>>()
                })
                .collect();

        let mut neighbours: HashMap<usize, HashSet<usize>> = HashMap::new();

        for (component, neighbour_cells) in &components_and_neighbours {
            let mut neighbour_components = HashSet::new();

            for cell in neighbour_cells {
                let position = Position {
                    column: cell % grid.number_of_columns,
                    row: cell / grid.number_of_columns,
                };
                neighbour_components.insert(map_cell_to_component[&position].id);
            }
            neighbours.insert(component.id, neighbour_components);
        }

        let mut components = HashMap::with_capacity(components_and_neighbours.len());

        for (c, _) in components_and_neighbours.into_iter() {
            components.insert(c.id, c);
        }

        Self {
            components,
            neighbours
        }
    }

    fn to_grid(&self, rows: usize, columns: usize) -> Grid {
        let mut cells = vec![Colour::Red; rows * columns];

        for component in self.neighbours.keys() {
            for position in &self.components[component].cells {
                cells[position.column + position.row * columns] = self.components[component].colour;
            }
        }

        Grid {
            number_of_rows: rows,
            number_of_columns: columns,
            cells,
        }
    }

    pub fn find_component(&self, position: &Position) -> &ConnectedComponent {
        for component in self.neighbours.keys() {
            if self.components[component].cells.contains(&position) {
                return &self.components[component];
            }
        }

        unreachable!()
    }

    pub fn change_colour_of_component_at(&mut self, position: &Position, colour: Colour) {
        let component_id = self.find_component(position).id;

        // Remove the component which is to change colour
        let mut component = self.components.remove(&component_id).unwrap();
        let mut neighbours = self.neighbours.remove(&component_id).unwrap();

        // Gather new cells for that component by combinging the cells of all
        // its neighbours which already have the new colour.
        let mut new_cells = HashSet::new();
        // Gather the set of its new neighbours which is just the union of the
        // sets of neighbours its neighbours with the new colour have.
        let mut new_neighbours = HashSet::new();
        let mut removed_neighbours = HashSet::new();

        for id in &neighbours {
            if *id != component_id && self.components[id].colour == colour {
                let neighbour_component = self.components.remove(id).unwrap();
                new_cells.extend(neighbour_component.cells.into_iter());
                let set_of_neighbour_ids = self.neighbours.remove(&neighbour_component.id).unwrap();
                new_neighbours.extend(set_of_neighbour_ids.into_iter());
                removed_neighbours.insert(*id);
            }
        }

        // Add new neighbours
        neighbours.extend(new_neighbours.clone().into_iter());
        // Remove the ID of the component itself
        neighbours.remove(&component_id);
        // and the IDs of the neighbours that were merged into the component
        neighbours = neighbours.difference(&removed_neighbours).map(|&x| x).collect();

        // Add the cells from the neighbours which now have the new colour
        component.cells.extend(new_cells.into_iter());
        // and update the colour.  With this, the component itself is done.
        component.colour = colour;

        // Fix the neighbour sets for all the remaining components
        // All we have to do here is replace any of the indices in new_neighbours with component_id.
        for (_, n) in self.neighbours.iter_mut() {
            for incorporated_neighbour_id in &removed_neighbours {
                n.remove(incorporated_neighbour_id);
            }
            n.insert(component_id);
        }

        // Put the component and neighbours back into the Graph
        self.components.entry(component_id).or_insert(component);
        self.neighbours.entry(component_id).or_insert(neighbours);
    }
}

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

    #[test]
    fn should_return_same_grid_as_input() {
        let size = 4;
        let grid = Grid::generate(size);

        let graph = Graph::create(&grid);
        let reconstituted_grid = graph.to_grid(size, size);

        assert_eq!(reconstituted_grid, grid);
    }

    #[test]
    fn should_have_one_component() {
        let grid = Grid {
            number_of_columns: 2,
            number_of_rows: 2,
            cells: vec![Colour::Red; 4],
        };

        let graph = Graph::create(&grid);

        assert_eq!(graph.neighbours.len(), 1);
    }

    #[test]
    fn should_have_four_component() {
        let grid = Grid {
            number_of_columns: 2,
            number_of_rows: 2,
            cells: vec![Colour::Red, Colour::Yellow, Colour::Yellow, Colour::Red],
        };

        let graph = Graph::create(&grid);

        assert_eq!(graph.neighbours.len(), 4);
    }

    #[test]
    fn should_have_two_component() {
        let grid = Grid {
            number_of_columns: 2,
            number_of_rows: 2,
            cells: vec![Colour::Red, Colour::Red, Colour::Yellow, Colour::Yellow],
        };

        let graph = Graph::create(&grid);

        assert_eq!(graph.neighbours.len(), 2);
    }

    #[test]
    fn should_have_same_keys_for_components_and_neighbours_maps() {
        let size = 4;
        let grid = Grid::generate(size);

        let graph = Graph::create(&grid);

        let components_keys: HashSet<_> = graph.components.keys().collect();
        let neighbours_keys: HashSet<_> = graph.neighbours.keys().collect();
        assert_eq!(components_keys, neighbours_keys);
    }

    #[test]
    fn should_contain_exactly_the_component_ids_as_keys() {
        let size = 4;
        let grid = Grid::generate(size);

        let graph = Graph::create(&grid);

        let component_keys: HashSet<_> = graph.components.keys().collect();
        let component_ids: HashSet<_> = graph.components.values().map(|x| &x.id).collect();
        assert_eq!(component_keys, component_ids);

        for (id, component) in graph.components {
            assert_eq!(id, component.id);
        }
    }

    #[test]
    fn should_contain_only_component_ids_as_values_in_neighbours_map() {
        let size = 4;
        let grid = Grid::generate(size);

        let graph = Graph::create(&grid);

        let component_ids: HashSet<_> = graph.components.keys().map(|&x| x).collect();

        for (_, neighbours) in graph.neighbours {
            assert_eq!(neighbours.difference(&component_ids).collect::<HashSet<_>>().len(), 0);
        }
    }
}
<|endoftext|>


<commit_before>
use std::cmp;

type Rgba = [u8; 4];

fn minf(a: f32, b: f32) -> f32 { if a < b { a } else { b } }
fn maxf(a: f32, b: f32) -> f32 { if a > b { a } else { b } }
fn saturate(a: f32) -> f32 { maxf(minf(a, 1.0), 0.0) }
fn fnorm(a: u8) -> f32 { a as f32 / 255.0 }
fn bnorm(a: f32) -> u8 { (saturate(a) * 255.0) as u8 }

/*type Hsva = [u8; 4];

fn to_hsva(rgba: &Rgba) -> Hsva {
	let (r, g, b) = (fnorm(rgba[0]), fnorm(rgba[1]), fnorm(rgba[2]));
	let max = maxf(maxf(r , g), b);
	let min = minf(minf(r , g), b);
	let c = max - min;
	let h =
		if c == 0.0 {
			0.0
		} else {
			(if max == r {
				(g - b) / c
			} else if max == g {
				(b - r) / c + 2.0
			} else {
				(r - g) / c + 4.0
			}) / 6.0
		};

	let s = if max == 0.0 { 0.0 } else { c / max };
	[bnorm(h), bnorm(s), bnorm(max), rgba[3]]
}

fn to_rgba(hsva: &Hsva) -> Rgba {
	let v = fnorm(hsva[2]);
	let c = v * fnorm(hsva[3]);
	let h = fnorm(hsva[0]) * 6.0;
	let x = c * (1.0 - (h % 2.0 - 1.0).abs());
	let rgb1 =
		if h < 1.0 {
			(c, x, 0.0)
		} else if h < 2.0 {
			(x, c, 0.0)
		} else if h < 3.0 {
			(0.0, c, x)
		} else if h < 4.0 {
			(0.0, x, c)
		} else if h < 5.0 {
			(x, 0.0, c)
		} else {
			(c, 0.0, x)
		};
	let m = v - c;
	[bnorm(rgb1.0 + m),
	bnorm(rgb1.1 + m),
	bnorm(rgb1.2 + m),
	hsva[3]]
}*/

fn bc1_dist(a: &Rgba, b: &Rgba) -> u32 {
	fn bc1_dist_one(a: u8, b: u8) -> u32 {
		let x = a as i32 - b as i32;
		(x * x) as u32
	}
	bc1_dist_one(a[0], b[0]) +
	bc1_dist_one(a[1], b[1]) +
	bc1_dist_one(a[2], b[2])
}

fn bc1_total_dist(table: &[Rgba; 4], pixels: &[Rgba; 16]) -> u32 {
	let mut sum = 0u32;
	let mut max = 0u32;
	for pix in pixels.into_iter().rev() {
		let e = (0..4).into_iter().map(|x| bc1_dist(&table[x], pix)).min().unwrap();
		sum += e;
		max = cmp::max(max, e);
	}
	sum + max * 16
}

fn bc1_build_entry(min: &Rgba, max: &Rgba, index: usize) -> Rgba {
	let coefs = match index {
		0x0 => (3, 0),
		0x1 => (0, 3),
		0x2 => (2 ,1),
		_ => (1, 2)
	};
	[((coefs.1 * min[0] as u16 + coefs.0 * max[0] as u16) / 3) as u8,
	 ((coefs.1 * min[1] as u16 + coefs.0 * max[1] as u16) / 3) as u8,
	 ((coefs.1 * min[2] as u16 + coefs.0 * max[2] as u16) / 3) as u8,
	 ((coefs.1 * min[3] as u16 + coefs.0 * max[3] as u16) / 3) as u8]
}

fn bc1_build_table(min: &Rgba, max: &Rgba) -> [Rgba; 4] {
	let mut interps = [[0u8; 4]; 4];
	for i in 0..4 {
		interps[i] = bc1_build_entry(&min, &max, i);
	}
	interps
}

fn bc1_minmax(pixels: &[Rgba; 16]) -> (Rgba, Rgba) {
	let mut min = [u8::max_value(); 4];
	let mut max = [0u8; 4];
	for p in pixels.into_iter() {
		for i in 0..4 {
			min[i] = cmp::min(min[i], p[i]);
			max[i] = cmp::max(max[i], p[i]);
		}
	}
	(min, max)
}

fn bc1_extrapolate_endpoint(a: &Rgba, b: &Rgba) -> [u8; 4] {
	let mut diff = *a;
	for i in 0..3 {
		let f = fnorm(diff[i]) - ((fnorm(a[i]) - fnorm(b[i])) * 1.5);
		diff[i] = bnorm(f);
	}
	diff
}

fn bc1_sort_endpoints(e: (Rgba, Rgba)) -> (Rgba, Rgba) {
	if bc1_encode_endpoint(&e.0) > bc1_encode_endpoint(&e.1) {
		(e.1, e.0)
	} else {
		(e.0, e.1)
	}
}

/*fn bc1_average(pixels: &[Rgba; 16]) -> Rgba {
	let mut avg = [0u16; 4];
	for i in 1..16 {
		for c in 0..4 {
			avg[c] += pixels[i][c] as u16;
		}
	}
	[(avg[0] / 16) as u8, (avg[1] / 16) as u8, (avg[2] / 16) as u8, (avg[3] / 16) as u8]
}*/

fn bc1_build_endpoints(pixels: &[Rgba; 16], quality: u8) -> Vec<(Rgba, Rgba)> {
	let (min, max) = bc1_minmax(pixels);

	let mut out = Vec::new();
	out.push((min, max));

	if quality > 0 && min != max {
		for i in 0..16 {
			for j in i..16 {
				if i != j {
					let a = pixels[i];
					let b = pixels[j];
					out.push(bc1_sort_endpoints((a, b)));
					if quality > 1 {
						let endpoints = (bc1_extrapolate_endpoint(&a, &b), bc1_extrapolate_endpoint(&b, &a));
						out.push(bc1_sort_endpoints(endpoints));
					}

				}
			}
		}
	}
	out
}

fn bc1_encode_endpoint(pix: &Rgba) -> u16 {
	((pix[0] as u16 >> 3) << 11) |
	((pix[1] as u16 >> 2) << 5) |
	(pix[2] as u16 >> 3)
}

fn bc1_encode_pixel(table: &[Rgba; 4], pixels: &[Rgba; 16]) -> u32 {
	let mut mask = 0u32;
	for pix in pixels.into_iter().rev() {
		let best = (0..4).into_iter().min_by_key(|x| bc1_dist(&table[*x], pix)).unwrap() as u32;
		mask = (mask << 2) | (best & 0x03);
	}
	mask
}

fn bc1_encode_block(pixels: &[Rgba; 16], quality: u8) -> (u64, u32) {
	/*let (min, max) = bc1_build_endpoints(&pixels)[0];
	let table = bc1_build_table(&min, &max);*/

	let ((min, max), table) = bc1_build_endpoints(pixels, quality).iter()
		.map(|pts| (*pts, bc1_build_table(&pts.0, &pts.1)))
		.min_by_key(|tbl| bc1_total_dist(&tbl.1, pixels)).unwrap();

	let dist = bc1_total_dist(&table, pixels);

	let min = bc1_encode_endpoint(&min) as u64;
	let max = bc1_encode_endpoint(&max) as u64;

	let encoded = bc1_encode_pixel(&table, &pixels) as u64;

	((encoded << 32) | (min << 16) | max, dist)
}

pub fn bc1(image: &Vec<u8>, size: (usize, usize), quality: u8) -> Result<Vec<u8>, ()> {
	if !(size.0 % 4 == 0 && size.1 % 4 == 0) {
		return Err(());
	}

    let mut out = Vec::with_capacity(image.len() / 8);
    let mut total_dist = 0u32;

    let block_size = 4;
    let blk_count = (size.0 / block_size, size.1 / block_size);

   	for x in 0..blk_count.0 {
   		for y in 0..blk_count.1 {

   			let mut pixels = [[0u8; 4]; 16]; // No compile time constants
   			for px in 0..block_size {
   				for py in 0..block_size {
   					let x = x * block_size + px;
   					let y = y * block_size + py;

   					let pi = (x * size.0 + y) * 4; // in bytes
   					let pix = [image[pi], image[pi + 1], image[pi + 2], image[pi + 3]];

   					pixels[px * block_size + py] = pix;
   				}
   			}

   			let (mut encoded, dist) = bc1_encode_block(&pixels, quality);
   			total_dist += dist;

   			for _ in 0..8 {
   				out.push((encoded & 0xFF) as u8);
   				encoded >>= 8;
   			}
		}
	}
	//println!("per-pixel dist = {:?}", total_dist / (size.0 * size.1) as u32);
	Ok(out)
}
<commit_msg>Tiny bit faster.<commit_after>
use std::cmp;

type Rgba = [u8; 4];

fn minf(a: f32, b: f32) -> f32 { if a < b { a } else { b } }
fn maxf(a: f32, b: f32) -> f32 { if a > b { a } else { b } }
fn saturate(a: f32) -> f32 { maxf(minf(a, 1.0), 0.0) }
fn fnorm(a: u8) -> f32 { a as f32 / 255.0 }
fn bnorm(a: f32) -> u8 { (saturate(a) * 255.0) as u8 }

/*type Hsva = [u8; 4];

fn to_hsva(rgba: &Rgba) -> Hsva {
	let (r, g, b) = (fnorm(rgba[0]), fnorm(rgba[1]), fnorm(rgba[2]));
	let max = maxf(maxf(r , g), b);
	let min = minf(minf(r , g), b);
	let c = max - min;
	let h =
		if c == 0.0 {
			0.0
		} else {
			(if max == r {
				(g - b) / c
			} else if max == g {
				(b - r) / c + 2.0
			} else {
				(r - g) / c + 4.0
			}) / 6.0
		};

	let s = if max == 0.0 { 0.0 } else { c / max };
	[bnorm(h), bnorm(s), bnorm(max), rgba[3]]
}

fn to_rgba(hsva: &Hsva) -> Rgba {
	let v = fnorm(hsva[2]);
	let c = v * fnorm(hsva[3]);
	let h = fnorm(hsva[0]) * 6.0;
	let x = c * (1.0 - (h % 2.0 - 1.0).abs());
	let rgb1 =
		if h < 1.0 {
			(c, x, 0.0)
		} else if h < 2.0 {
			(x, c, 0.0)
		} else if h < 3.0 {
			(0.0, c, x)
		} else if h < 4.0 {
			(0.0, x, c)
		} else if h < 5.0 {
			(x, 0.0, c)
		} else {
			(c, 0.0, x)
		};
	let m = v - c;
	[bnorm(rgb1.0 + m),
	bnorm(rgb1.1 + m),
	bnorm(rgb1.2 + m),
	hsva[3]]
}*/

fn bc1_dist(a: &Rgba, b: &Rgba) -> u32 {
	fn bc1_dist_one(a: u8, b: u8) -> u32 {
		let x = a as i32 - b as i32;
		(x * x) as u32
	}
	bc1_dist_one(a[0], b[0]) +
	bc1_dist_one(a[1], b[1]) +
	bc1_dist_one(a[2], b[2])
}

fn bc1_total_dist(table: &[Rgba; 4], pixels: &[Rgba; 16]) -> u32 {
	let mut sum = 0u32;
	let mut max = 0u32;
	for pix in pixels.into_iter().rev() {
		let e = (0..4).into_iter().map(|x| bc1_dist(&table[x], pix)).min().unwrap();
		sum += e;
		max = cmp::max(max, e);
	}
	sum + max * 16
}

fn bc1_build_entry(min: &Rgba, max: &Rgba, index: usize) -> Rgba {
	let coefs = match index {
		0x0 => (3, 0),
		0x1 => (0, 3),
		0x2 => (2 ,1),
		_ => (1, 2)
	};
	[((coefs.1 * min[0] as u16 + coefs.0 * max[0] as u16) / 3) as u8,
	 ((coefs.1 * min[1] as u16 + coefs.0 * max[1] as u16) / 3) as u8,
	 ((coefs.1 * min[2] as u16 + coefs.0 * max[2] as u16) / 3) as u8,
	 ((coefs.1 * min[3] as u16 + coefs.0 * max[3] as u16) / 3) as u8]
}

fn bc1_build_table(min: &Rgba, max: &Rgba) -> [Rgba; 4] {
	let mut interps = [[0u8; 4]; 4];
	for i in 0..4 {
		interps[i] = bc1_build_entry(&min, &max, i);
	}
	interps
}

fn bc1_minmax(pixels: &[Rgba; 16]) -> (Rgba, Rgba) {
	let mut min = [u8::max_value(); 4];
	let mut max = [0u8; 4];
	for p in pixels.into_iter() {
		for i in 0..4 {
			min[i] = cmp::min(min[i], p[i]);
			max[i] = cmp::max(max[i], p[i]);
		}
	}
	(min, max)
}

fn bc1_extrapolate_endpoints(e: &(Rgba, Rgba)) -> (Rgba, Rgba) {
	let mut a = e.0;
	let mut b = e.1;
	for i in 0..3 {
		let f = (fnorm(e.0[i]) - fnorm(e.1[i])) * 1.5;
		a[i] = bnorm(fnorm(e.0[i]) - f);
		b[i] = bnorm(fnorm(e.1[i]) + f);
	}
	(a, b)
}

fn bc1_sort_endpoints(e: &(Rgba, Rgba)) -> (Rgba, Rgba) {
	if bc1_encode_endpoint(&e.0) > bc1_encode_endpoint(&e.1) {
		(e.1, e.0)
	} else {
		(e.0, e.1)
	}
}

fn bc1_build_endpoints(pixels: &[Rgba; 16], quality: u8) -> Vec<(Rgba, Rgba)> {
	let (min, max) = bc1_minmax(pixels);

	let mut out = Vec::new();
	out.push((min, max));

	if quality > 0 && min != max {
		for i in 0..15 {
			for j in (i + 1)..16 {
				let px = (pixels[i], pixels[j]);
				out.push(bc1_sort_endpoints(&px));
				if quality > 1 {
					out.push(bc1_sort_endpoints(&bc1_extrapolate_endpoints(&px)));
				}
			}
		}
	}
	out
}

fn bc1_encode_endpoint(pix: &Rgba) -> u16 {
	((pix[0] as u16 >> 3) << 11) |
	((pix[1] as u16 >> 2) << 5) |
	(pix[2] as u16 >> 3)
}

fn bc1_encode_pixel(table: &[Rgba; 4], pixels: &[Rgba; 16]) -> u32 {
	let mut mask = 0u32;
	for pix in pixels.into_iter().rev() {
		let best = (0..4).into_iter().min_by_key(|x| bc1_dist(&table[*x], pix)).unwrap() as u32;
		mask = (mask << 2) | (best & 0x03);
	}
	mask
}

fn bc1_encode_block(pixels: &[Rgba; 16], quality: u8) -> (u64, u32) {
	/*let (min, max) = bc1_build_endpoints(&pixels)[0];
	let table = bc1_build_table(&min, &max);*/

	let ((min, max), table) = bc1_build_endpoints(pixels, quality).iter()
		.map(|pts| (*pts, bc1_build_table(&pts.0, &pts.1)))
		.min_by_key(|tbl| bc1_total_dist(&tbl.1, pixels)).unwrap();

	let dist = bc1_total_dist(&table, pixels);

	let min = bc1_encode_endpoint(&min) as u64;
	let max = bc1_encode_endpoint(&max) as u64;

	let encoded = bc1_encode_pixel(&table, &pixels) as u64;

	((encoded << 32) | (min << 16) | max, dist)
}

pub fn bc1(image: &Vec<u8>, size: (usize, usize), quality: u8) -> Result<Vec<u8>, ()> {
	if !(size.0 % 4 == 0 && size.1 % 4 == 0) {
		return Err(());
	}

    let mut out = Vec::with_capacity(image.len() / 8);
    let mut total_dist = 0u32;

    let block_size = 4;
    let blk_count = (size.0 / block_size, size.1 / block_size);

   	for x in 0..blk_count.0 {
   		for y in 0..blk_count.1 {

   			let mut pixels = [[0u8; 4]; 16]; // No compile time constants
   			for px in 0..block_size {
   				for py in 0..block_size {
   					let x = x * block_size + px;
   					let y = y * block_size + py;

   					let pi = (x * size.0 + y) * 4; // in bytes
   					let pix = [image[pi], image[pi + 1], image[pi + 2], image[pi + 3]];

   					pixels[px * block_size + py] = pix;
   				}
   			}

   			let (mut encoded, dist) = bc1_encode_block(&pixels, quality);
   			total_dist += dist;

   			for _ in 0..8 {
   				out.push((encoded & 0xFF) as u8);
   				encoded >>= 8;
   			}
		}
	}
	//println!("per-pixel dist = {:?}", total_dist / (size.0 * size.1) as u32);
	Ok(out)
}
<|endoftext|>


<commit_before>use cpp_data::CppData;
use clang_cpp_data::{CLangCppData, CLangCppTypeKind};
use log;
use enums::{CppTypeOrigin, CppTypeKind};

pub fn check(result1: &CLangCppData, result2: &CppData) {
  log::info("Checking parsers consistency...");
  for (_, ref type_info2) in &result2.types.0 {
    if let CppTypeOrigin::Qt { ref include_file } = type_info2.origin {
      match type_info2.kind {
        // typedefs are not supposed to be in result1
        CppTypeKind::TypeDef { .. } | CppTypeKind::Flags { .. } => {}
        _ => {
          if let Some(type_info1) = result1.types.iter().find(|x| x.name == type_info2.name) {
            match type_info2.kind {
              CppTypeKind::Enum { ref values } => {
                let values2 = values.iter().map(|x| x.name.clone()).collect::<Vec<_>>();
                if let CLangCppTypeKind::Enum { ref values } = type_info1.kind {
                  let values1 = values.iter().map(|x| x.name.clone()).collect::<Vec<_>>();
                  for val1 in &values1 {
                    if values2.iter().find(|&x| x == val1).is_none() {
                      log::warning(format!("Result 2 misses enum value: {}; {}", type_info2.name, val1));
                    }
                  }
                  for val2 in &values2 {
                    if values1.iter().find(|&x| x == val2).is_none() {
                      log::warning(format!("Result 1 misses enum value: {}; {}", type_info2.name, val2));
                    }
                  }

                } else {
                  log::warning(format!("Result 1 type mismatch: {} is {:?} (result2: {:?})",
                                       type_info2.name,
                                       type_info1.kind,
                                       type_info2.kind));
                }

              }
              _ => {}
            }
          } else {
            log::warning(format!("Result 1 lacks type: {}", type_info2.name));
          }
        }
      }
    }
  }
  for type_info1 in &result1.types {
    if !result2.types.0.contains_key(&type_info1.name) {
      log::warning(format!("Result 2 lacks type: {}", type_info1.name));
    }
  }
}
<commit_msg>more compact messages<commit_after>use cpp_data::CppData;
use clang_cpp_data::{CLangCppData, CLangCppTypeKind};
use log;
use enums::{CppTypeOrigin, CppTypeKind};
use std::collections::HashMap;

pub fn check(result1: &CLangCppData, result2: &CppData) {
  log::info("Checking parsers consistency...");
  let mut missing_enum_values1: HashMap<String, Vec<String>> = HashMap::new();
  let mut missing_enum_values2: HashMap<String, Vec<String>> = HashMap::new();
  let mut missing_types1 = Vec::new();
  let mut missing_types2 = Vec::new();
  for (_, ref type_info2) in &result2.types.0 {
    if let CppTypeOrigin::Qt { ref include_file } = type_info2.origin {
      match type_info2.kind {
        // typedefs are not supposed to be in result1
        CppTypeKind::TypeDef { .. } | CppTypeKind::Flags { .. } | CppTypeKind::Unknown { .. } => {}
        _ => {
          if let Some(type_info1) = result1.types.iter().find(|x| x.name == type_info2.name) {
            match type_info2.kind {
              CppTypeKind::Enum { ref values } => {
                let values2 = values.iter().map(|x| x.name.clone()).collect::<Vec<_>>();
                if let CLangCppTypeKind::Enum { ref values } = type_info1.kind {
                  let values1 = values.iter().map(|x| x.name.clone()).collect::<Vec<_>>();
                  for val1 in &values1 {
                    if values2.iter().find(|&x| x == val1).is_none() {
                      if missing_enum_values2.contains_key(&type_info2.name) {
                        missing_enum_values2.get_mut(&type_info2.name).unwrap().push(val1.clone());
                      } else {
                        missing_enum_values2.insert(type_info2.name.clone(), vec![val1.clone()]);
                      }
                    }
                  }
                  for val2 in &values2 {
                    if values1.iter().find(|&x| x == val2).is_none() {
                      if missing_enum_values1.contains_key(&type_info2.name) {
                        missing_enum_values1.get_mut(&type_info2.name).unwrap().push(val2.clone());
                      } else {
                        missing_enum_values1.insert(type_info2.name.clone(), vec![val2.clone()]);
                      }
                    }
                  }

                } else {
                  log::warning(format!("Result 1 type mismatch: {} is {:?} (result2: {:?})",
                                       type_info2.name,
                                       type_info1.kind,
                                       type_info2.kind));
                }

              }
              _ => {}
            }
          } else {
            missing_types1.push(type_info2.name.clone());
          }
        }
      }
    }
  }
  for type_info1 in &result1.types {
    if !result2.types.0.contains_key(&type_info1.name) {
      missing_types2.push(type_info1.name.clone());
    }
  }
  if !missing_types1.is_empty() {
    log::warning(format!("Result 1 lacks types: {:?}", missing_types1));
  }
  if !missing_enum_values1.is_empty() {
    log::warning(format!("Result 1 misses enum values:"));
    for (enu, values) in missing_enum_values1 {
      log::warning(format!("  {}: {:?}", enu, values));
    }
  }

  if !missing_types2.is_empty() {
    log::warning(format!("Result 2 lacks types: {:?}", missing_types2));
  }
  if !missing_enum_values2.is_empty() {
    log::warning(format!("Result 2 misses enum values:"));
    for (enu, values) in missing_enum_values2 {
      log::warning(format!("  {}: {:?}", enu, values));
    }
  }
}
<|endoftext|>


<commit_before>use std::fmt::Debug;
use std::hash::Hash;
use std::rc::Rc;
use std::mem::replace;

#[macro_use]
use adapton_syntax::* ;
use adapton_sigs::* ;

pub trait ListT<A:Adapton,Hd> : AdaptonData {
    type List : AdaptonData ;

    fn nil  (&mut A) -> Self::List ;
    fn cons (&mut A, Hd, Box<Self::List>) -> Self::List ;
    fn rc   (&mut A, Rc<Self::List>) -> Self::List ;

    // requisite "adaptonic" constructors: `name` and `art`:
    fn name (&mut A, A::Name, Box<Self::List>) -> Self::List ;
    fn art  (&mut A, Art<Self::List,A::Loc>) -> Self::List ;

    fn elim<Res,Nil,Cons,Name> (self:&Self, &mut A, &Self::List, Nil, Cons, Name) -> Res
        where Nil:FnOnce(&mut A) -> Res
        ,    Cons:FnOnce(&mut A, &Hd, &Box<Self::List>) -> Res
        ,    Name:FnOnce(&mut A, &A::Name, &Box<Self::List>) -> Res ;

    // Derived from above:
    fn is_empty (self:&Self, st:&mut A, list:&Self::List) -> bool {
        self.elim(st, &list, |_|true, |_,_,_|false, |_,_,_|false)
    }
}

// Questions:
//  - Should `Name`s always be passed by reference?
//  - Do these Fn argss for fold need to be passed in `Rc<Box<_>>`s ?

pub trait TreeT<A:Adapton,Leaf,Bin:Hash> : AdaptonData {
    type Tree : AdaptonData ;

    fn nil  (&mut A) -> Self::Tree ;
    fn leaf (&mut A, Leaf) -> Self::Tree ;
    fn bin  (&mut A, Bin, Box<Self::Tree>, Box<Self::Tree>) -> Self::Tree ;

    // requisite "adaptonic" constructors: `name` and `art`:
    fn name (&mut A, A::Name, Box<Self::Tree>, Box<Self::Tree>) -> Self::Tree ;
    fn art  (&mut A, Art<Self::Tree,A::Loc>) -> Self::Tree ;

    fn fold<Res,LeafC,BinC> (&mut A, Self::Tree, Res, LeafC, BinC) -> Res
        where LeafC:Fn(&mut A, Res, Leaf) -> Res
        ,      BinC:Fn(&mut A, Res, Bin ) -> Res ;

    fn fold_up<Arg,Res,LeafC,BinC> (&mut A, Self::Tree, LeafC, BinC) -> Res
        where LeafC:Fn(&mut A, Leaf) -> Res
        ,      BinC:Fn(&mut A, Bin, Res, Res ) -> Res ;

    // TODO: Add derived operations (max, min, sum, etc.) for fold_up.
}

#[derive(Debug,PartialEq,Eq,Hash,Clone)]
enum List<A:Adapton,Hd> {
    Nil,
    Cons(Hd,      Box<List<A,Hd>>),
    Rc(           Rc<List<A,Hd>>),
    Name(A::Name, Box<List<A,Hd>>),
    Art(          Art<List<A,Hd>, A::Loc>),
}

// TODO: Why Does Adapton have to implement all of these?
//       It's not actually *contained* within the List structure; it cannot be ecountered there.
//       It's only ever present in a negative position (as a function parameter).
impl<A:Adapton+AdaptonData,Hd:AdaptonData> ListT<A,Hd> for List<A,Hd> {
    type List = List<A,Hd>;

    fn nil  (_:&mut A)                                  -> Self::List { List::Nil }
    fn cons (_:&mut A, hd:Hd, tl:Box<Self::List>)       -> Self::List { List::Cons(hd,tl) }
    fn name (_:&mut A, nm:A::Name, tl:Box<Self::List>)  -> Self::List { List::Name(nm, tl) }
    fn rc   (_:&mut A, rc:Rc<List<A,Hd>>)               -> Self::List { List::Rc(rc) }
    fn art  (_:&mut A, art:Art<List<A,Hd>,A::Loc>)      -> Self::List { List::Art(art) }

    fn elim<Res,Nil,Cons,Name> (self:&Self, st:&mut A, list:&Self::List, nilf:Nil, consf:Cons, namef:Name) -> Res
        where Nil:FnOnce(&mut A) -> Res
        ,    Cons:FnOnce(&mut A, &Hd, &Box<Self::List>) -> Res
        ,    Name:FnOnce(&mut A, &A::Name, &Box<Self::List>) -> Res
    {
        match *list {
            List::Nil => nilf(st),
            List::Cons(ref hd, ref tl) => consf(st, hd, tl),
            List::Name(ref nm, ref tl) => namef(st, nm, tl),
            List::Art(ref art) => {
                let list = st.force(art);
                self.elim(st, &list, nilf, consf, namef)
            }
        }
    }
}

fn tree_of_list_rec_memo <A:Adapton, X:Hash+Clone, T:TreeT<A,X,X>, L:ListT<A,X>>
    (st:&mut A, l:&L, list:&L::List, left_tree:&T::Tree, left_tree_lev:u32, parent_lev:u32) ->
    (T::Tree, L::List)
{
    let t = st.thunk (ArtId::Eager, prog_pt!(tree_of_list_rec),
                      Rc::new(Box::new(|st, args|{
                          let (l, list, left_tree, left_tree_lev, parent_lev) = args ;
                          tree_of_list_rec::<A,X,T,L>
                              (st, l, list, left_tree, left_tree_lev, parent_lev)
                      })),
                      (l, list, left_tree, left_tree_lev, parent_lev)
                      ) ;
    st.force( &t )
}

fn tree_of_list_rec <A:Adapton, X:Hash+Clone, T:TreeT<A,X,X>, L:ListT<A,X>>
    (st:&mut A, l:&L, list:&L::List, left_tree:&T::Tree, left_tree_lev:u32, parent_lev:u32)
     -> (T::Tree, L::List)
{
    l.elim (
        st, &list,
        /* Nil */  |st| ( T::nil(st), L::nil(st) ),
        /* Cons */ |st, hd, rest| {
            let lev_hd = (1 + (my_hash(hd).leading_zeros())) as u32 ;
            if left_tree_lev <= lev_hd && lev_hd <= parent_lev {
                let nil = T::nil(st) ;
                let (right_tree, rest) = tree_of_list_rec_memo::<A,X,T,L> ( st, l, rest, &nil, 0 as u32, lev_hd ) ;
                let tree = T::bin ( st, hd.clone(), Box::new(left_tree.clone()), Box::new(right_tree) ) ;
                tree_of_list_rec_memo::<A,X,T,L> ( st, l, &rest, &tree, lev_hd, parent_lev )
            }
            else {
                let rest = L::cons(st, hd.clone(), rest.clone()) ;
                (left_tree.clone(), rest)
            }},
        /* Name */ |st, nm, rest| {
            let lev_nm = (1 + 64 + (my_hash(nm).leading_zeros())) as u32 ;
            if left_tree_lev <= lev_nm && lev_nm <= parent_lev {
                let nil = T::nil(st) ;
                let (right_tree, rest) = tree_of_list_rec::<A,X,T,L> ( st, l, rest, &nil, 0 as u32, lev_nm ) ;
                // TODO: Place left_ and right_ trees into articulations, named by name.
                // TODO: Memoize the recursive calls to tree_of_list_rec.
                let tree = T::name( st, nm.clone(), Box::new(left_tree.clone()), Box::new(right_tree) ) ;
                tree_of_list_rec::<A,X,T,L> ( st, l, &rest, &tree, lev_nm, parent_lev )
            }
            else {
                let rest = L::name(st, nm.clone(), rest.clone()) ;
                (left_tree.clone(), rest)
            }}
        )
}

pub fn tree_of_list <A:Adapton, X:Hash+Clone, T:TreeT<A,X,X>, L:ListT<A,X>>
    (l:&L, st:&mut A, list:&Rc<L::List>)
     -> Rc<T::Tree>
{
    let nil = T::nil(st) ;
    let (tree, rest) = tree_of_list_rec::<A,X,T,L> (st, l, list, &nil, 0 as u32, u32::max_value()) ;
    assert!( l.is_empty( st, &rest ) );
    tree
}
<commit_msg>temp workaround<commit_after>use std::fmt::Debug;
use std::hash::Hash;
use std::rc::Rc;
use std::mem::replace;

#[macro_use]
use adapton_syntax::* ;
use adapton_sigs::* ;

pub trait ListT<A:Adapton,Hd> : Debug+Hash+PartialEq+Eq+Clone {
    type List : Debug+Hash+PartialEq+Eq+Clone ;

    fn nil  (&mut A) -> Self::List ;
    fn cons (&mut A, Hd, Box<Self::List>) -> Self::List ;
    fn rc   (&mut A, Rc<Self::List>) -> Self::List ;

    // requisite "adaptonic" constructors: `name` and `art`:
    fn name (&mut A, A::Name, Box<Self::List>) -> Self::List ;
    fn art  (&mut A, Art<Self::List,A::Loc>) -> Self::List ;

    fn elim<Res,Nil,Cons,Name> (self:&Self, &mut A, &Self::List, Nil, Cons, Name) -> Res
        where Nil:FnOnce(&mut A) -> Res
        ,    Cons:FnOnce(&mut A, &Hd, &Box<Self::List>) -> Res
        ,    Name:FnOnce(&mut A, &A::Name, &Box<Self::List>) -> Res ;

    // Derived from above:
    fn is_empty (self:&Self, st:&mut A, list:&Self::List) -> bool {
        self.elim(st, &list, |_|true, |_,_,_|false, |_,_,_|false)
    }
}

// Questions:
//  - Should `Name`s always be passed by reference?
//  - Do these Fn argss for fold need to be passed in `Rc<Box<_>>`s ?

pub trait TreeT<A:Adapton,Leaf,Bin:Hash> : Debug+Hash+PartialEq+Eq+Clone {
    type Tree : Debug+Hash+PartialEq+Eq+Clone ;

    fn nil  (&mut A) -> Self::Tree ;
    fn leaf (&mut A, Leaf) -> Self::Tree ;
    fn bin  (&mut A, Bin, Box<Self::Tree>, Box<Self::Tree>) -> Self::Tree ;

    // requisite "adaptonic" constructors: `name` and `art`:
    fn name (&mut A, A::Name, Box<Self::Tree>, Box<Self::Tree>) -> Self::Tree ;
    fn art  (&mut A, Art<Self::Tree,A::Loc>) -> Self::Tree ;

    fn fold<Res,LeafC,BinC> (&mut A, Self::Tree, Res, LeafC, BinC) -> Res
        where LeafC:Fn(&mut A, Res, Leaf) -> Res
        ,      BinC:Fn(&mut A, Res, Bin ) -> Res ;

    fn fold_up<Arg,Res,LeafC,BinC> (&mut A, Self::Tree, LeafC, BinC) -> Res
        where LeafC:Fn(&mut A, Leaf) -> Res
        ,      BinC:Fn(&mut A, Bin, Res, Res ) -> Res ;

    // TODO: Add derived operations (max, min, sum, etc.) for fold_up.
}

#[derive(Debug,PartialEq,Eq,Hash,Clone)]
enum List<A:Adapton,Hd> {
    Nil,
    Cons(Hd,      Box<List<A,Hd>>),
    Rc(           Rc<List<A,Hd>>),
    Name(A::Name, Box<List<A,Hd>>),
    Art(          Art<List<A,Hd>, A::Loc>),
}

// TODO: Why Does Adapton have to implement all of these?
//       It's not actually *contained* within the List structure; it cannot be ecountered there.
//       It's only ever present in a negative position (as a function parameter).
impl<A:Adapton+Debug+Hash+PartialEq+Eq+Clone,Hd:Debug+Hash+PartialEq+Eq+Clone> ListT<A,Hd> for List<A,Hd> {
    type List = List<A,Hd>;

    fn nil  (_:&mut A)                                  -> Self::List { List::Nil }
    fn cons (_:&mut A, hd:Hd, tl:Box<Self::List>)       -> Self::List { List::Cons(hd,tl) }
    fn name (_:&mut A, nm:A::Name, tl:Box<Self::List>)  -> Self::List { List::Name(nm, tl) }
    fn rc   (_:&mut A, rc:Rc<List<A,Hd>>)               -> Self::List { List::Rc(rc) }
    fn art  (_:&mut A, art:Art<List<A,Hd>,A::Loc>)      -> Self::List { List::Art(art) }

    fn elim<Res,Nil,Cons,Name> (self:&Self, st:&mut A, list:&Self::List, nilf:Nil, consf:Cons, namef:Name) -> Res
        where Nil:FnOnce(&mut A) -> Res
        ,    Cons:FnOnce(&mut A, &Hd, &Box<Self::List>) -> Res
        ,    Name:FnOnce(&mut A, &A::Name, &Box<Self::List>) -> Res
    {
        match *list {
            List::Nil => nilf(st),
            List::Cons(ref hd, ref tl) => consf(st, hd, tl),
            List::Name(ref nm, ref tl) => namef(st, nm, tl),
            List::Art(ref art) => {
                let list = st.force(art);
                self.elim(st, &list, nilf, consf, namef)
            }
        }
    }
}

fn tree_of_list_rec_memo <A:Adapton, X:Hash+Clone, T:TreeT<A,X,X>, L:ListT<A,X>>
    (st:&mut A, l:&L, list:&L::List, left_tree:&T::Tree, left_tree_lev:u32, parent_lev:u32) ->
    (T::Tree, L::List)
{
    let t = st.thunk (ArtId::Eager, prog_pt!(tree_of_list_rec),
                      Rc::new(Box::new(|st, args|{
                          let (l, list, left_tree, left_tree_lev, parent_lev) = args ;
                          tree_of_list_rec::<A,X,T,L>
                              (st, l, list, left_tree, left_tree_lev, parent_lev)
                      })),
                      (l, list, left_tree, left_tree_lev, parent_lev)
                      ) ;
    st.force( &t )
}

fn tree_of_list_rec <A:Adapton, X:Hash+Clone, T:TreeT<A,X,X>, L:ListT<A,X>>
    (st:&mut A, l:&L, list:&L::List, left_tree:&T::Tree, left_tree_lev:u32, parent_lev:u32)
     -> (T::Tree, L::List)
{
    l.elim (
        st, &list,
        /* Nil */  |st| ( T::nil(st), L::nil(st) ),
        /* Cons */ |st, hd, rest| {
            let lev_hd = (1 + (my_hash(hd).leading_zeros())) as u32 ;
            if left_tree_lev <= lev_hd && lev_hd <= parent_lev {
                let nil = T::nil(st) ;
                let (right_tree, rest) = tree_of_list_rec_memo::<A,X,T,L> ( st, l, rest, &nil, 0 as u32, lev_hd ) ;
                let tree = T::bin ( st, hd.clone(), Box::new(left_tree.clone()), Box::new(right_tree) ) ;
                tree_of_list_rec_memo::<A,X,T,L> ( st, l, &rest, &tree, lev_hd, parent_lev )
            }
            else {
                let rest = L::cons(st, hd.clone(), rest.clone()) ;
                (left_tree.clone(), rest)
            }},
        /* Name */ |st, nm, rest| {
            let lev_nm = (1 + 64 + (my_hash(nm).leading_zeros())) as u32 ;
            if left_tree_lev <= lev_nm && lev_nm <= parent_lev {
                let nil = T::nil(st) ;
                let (right_tree, rest) = tree_of_list_rec::<A,X,T,L> ( st, l, rest, &nil, 0 as u32, lev_nm ) ;
                // TODO: Place left_ and right_ trees into articulations, named by name.
                // TODO: Memoize the recursive calls to tree_of_list_rec.
                let tree = T::name( st, nm.clone(), Box::new(left_tree.clone()), Box::new(right_tree) ) ;
                tree_of_list_rec::<A,X,T,L> ( st, l, &rest, &tree, lev_nm, parent_lev )
            }
            else {
                let rest = L::name(st, nm.clone(), rest.clone()) ;
                (left_tree.clone(), rest)
            }}
        )
}

pub fn tree_of_list <A:Adapton, X:Hash+Clone, T:TreeT<A,X,X>, L:ListT<A,X>>
    (l:&L, st:&mut A, list:&Rc<L::List>)
     -> Rc<T::Tree>
{
    let nil = T::nil(st) ;
    let (tree, rest) = tree_of_list_rec::<A,X,T,L> (st, l, list, &nil, 0 as u32, u32::max_value()) ;
    assert!( l.is_empty( st, &rest ) );
    tree
}
<|endoftext|>


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

// ignore-test
//
// This is ignored because it depends on #16122.

#![feature(overloaded_calls, unboxed_closures)]

fn each<'a,T,F:|&mut: &'a T|>(x: &'a [T], mut f: F) {
    for val in x.iter() {
        f(val)
    }
}

fn main() {
    let mut sum = 0u;
    let elems = [ 1u, 2, 3, 4, 5 ];
    each(elems, ref |&mut: val: &uint| sum += *val);
    assert_eq!(sum, 15);
}

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

#![feature(overloaded_calls, unboxed_closures)]

fn each<'a,T,F:FnMut(&'a T)>(x: &'a [T], mut f: F) {
    for val in x.iter() {
        f(val)
    }
}

fn main() {
    let mut sum = 0u;
    let elems = [ 1u, 2, 3, 4, 5 ];
    each(elems, |&mut: val: &uint| sum += *val);
    assert_eq!(sum, 15);
}
<|endoftext|>