<commit_before>#[cfg(any(feature = "postgres", feature = "mysql"))]
extern crate bigdecimal;
extern crate chrono;

pub use quickcheck::quickcheck;
use self::chrono::{DateTime, Duration, NaiveDate, NaiveDateTime, NaiveTime, Utc};

pub use schema::{connection, TestConnection};
pub use diesel::*;
pub use diesel::result::Error;
pub use diesel::data_types::*;
pub use diesel::types::{HasSqlType, ToSql};

use diesel::expression::AsExpression;
use diesel::query_builder::{QueryFragment, QueryId};
use std::collections::Bound;

pub fn test_type_round_trips<ST, T>(value: T) -> bool
where
    ST: QueryId,
    <TestConnection as Connection>::Backend: HasSqlType<ST>,
    T: AsExpression<ST>
        + Queryable<ST, <TestConnection as Connection>::Backend>
        + PartialEq
        + Clone
        + ::std::fmt::Debug,
    <T as AsExpression<ST>>::Expression: SelectableExpression<(), SqlType = ST>
        + QueryFragment<<TestConnection as Connection>::Backend>
        + QueryId,
{
    let connection = connection();
    let query = select(value.clone().into_sql::<ST>());
    let result = query.get_result::<T>(&connection);
    match result {
        Ok(res) => if value != res {
            println!("{:?}, {:?}", value, res);
            false
        } else {
            true
        },
        Err(Error::DatabaseError(_, ref e))
            if e.message() == "invalid byte sequence for encoding \"UTF8\": 0x00" =>
        {
            true
        }
        Err(e) => panic!("Query failed: {:?}", e),
    }
}

pub fn id<A>(a: A) -> A {
    a
}

macro_rules! test_round_trip {
    ($test_name:ident, $sql_type:ty, $tpe:ty) => {
        test_round_trip!($test_name, $sql_type, $tpe, id);
    };

    ($test_name:ident, $sql_type:ty, $tpe:ty, $map_fn:ident) => {
        #[test]
        fn $test_name() {
            use diesel::types::*;

            fn round_trip(val: $tpe) -> bool {
                test_type_round_trips::<$sql_type, _>($map_fn(val))
            }

            fn option_round_trip(val: Option<$tpe>) -> bool {
                let val = val.map($map_fn);
                test_type_round_trips::<Nullable<$sql_type>, _>(val)
            }

            quickcheck(round_trip as fn($tpe) -> bool);
            quickcheck(option_round_trip as fn(Option<$tpe>) -> bool);
        }
    }
}

test_round_trip!(i16_roundtrips, SmallInt, i16);
test_round_trip!(i32_roundtrips, Integer, i32);
test_round_trip!(i64_roundtrips, BigInt, i64);
test_round_trip!(f32_roundtrips, Float, f32);
test_round_trip!(f64_roundtrips, Double, f64);
test_round_trip!(string_roundtrips, VarChar, String);
test_round_trip!(text_roundtrips, Text, String);
test_round_trip!(binary_roundtrips, Binary, Vec<u8>);
test_round_trip!(bool_roundtrips, Bool, bool);

#[cfg(feature = "sqlite")]
mod sqlite_types {
    use super::*;

    test_round_trip!(date_roundtrips, Date, String);
    test_round_trip!(time_roundtrips, Time, String);
    test_round_trip!(timestamp_roundtrips, Timestamp, String);
    test_round_trip!(naive_time_roundtrips, Time, (u32, u32), mk_naive_time);
    test_round_trip!(naive_date_roundtrips, Date, u32, mk_naive_date);
    test_round_trip!(
        naive_datetime_roundtrips,
        Timestamp,
        (i64, u32),
        mk_naive_datetime
    );
}

#[cfg(feature = "postgres")]
mod pg_types {
    extern crate ipnetwork;
    extern crate uuid;

    use super::*;
    use self::bigdecimal::BigDecimal;

    test_round_trip!(date_roundtrips, Date, PgDate);
    test_round_trip!(time_roundtrips, Time, PgTime);
    test_round_trip!(timestamp_roundtrips, Timestamp, PgTimestamp);
    test_round_trip!(interval_roundtrips, Interval, PgInterval);
    test_round_trip!(numeric_roundtrips, Numeric, PgNumeric);
    test_round_trip!(money_roundtrips, Money, PgMoney);
    test_round_trip!(
        naive_datetime_roundtrips,
        Timestamp,
        (i64, u32),
        mk_naive_datetime
    );
    test_round_trip!(naive_time_roundtrips, Time, (u32, u32), mk_naive_time);
    test_round_trip!(naive_date_roundtrips, Date, u32, mk_naive_date);
    test_round_trip!(datetime_roundtrips, Timestamptz, (i64, u32), mk_datetime);
    test_round_trip!(
        naive_datetime_roundtrips_tz,
        Timestamptz,
        (i64, u32),
        mk_naive_datetime
    );
    test_round_trip!(
        uuid_roundtrips,
        Uuid,
        (u32, u16, u16, (u8, u8, u8, u8, u8, u8, u8, u8)),
        mk_uuid
    );
    test_round_trip!(array_of_int_roundtrips, Array<Integer>, Vec<i32>);
    test_round_trip!(array_of_bigint_roundtrips, Array<BigInt>, Vec<i64>);
    test_round_trip!(array_of_dynamic_size_roundtrips, Array<Text>, Vec<String>);
    test_round_trip!(
        array_of_nullable_roundtrips,
        Array<Nullable<Text>>,
        Vec<Option<String>>
    );
    test_round_trip!(
        macaddr_roundtrips,
        MacAddr,
        (u8, u8, u8, u8, u8, u8),
        mk_macaddr
    );
    test_round_trip!(cidr_v4_roundtrips, Cidr, (u8, u8, u8, u8), mk_ipv4);
    test_round_trip!(
        cidr_v6_roundtrips,
        Cidr,
        (u16, u16, u16, u16, u16, u16, u16, u16),
        mk_ipv6
    );
    test_round_trip!(inet_v4_roundtrips, Inet, (u8, u8, u8, u8), mk_ipv4);
    test_round_trip!(
        inet_v6_roundtrips,
        Inet,
        (u16, u16, u16, u16, u16, u16, u16, u16),
        mk_ipv6
    );
    test_round_trip!(bigdecimal_roundtrips, Numeric, (i64, u64), mk_bigdecimal);
    test_round_trip!(int4range_roundtrips, Range<Int4>, (i32, i32), mk_bounds);
    test_round_trip!(int8range_roundtrips, Range<Int8>, (i64, i64), mk_bounds);
    test_round_trip!(
        daterange_roundtrips,
        Range<Date>,
        (u32, u32),
        mk_date_bounds
    );
    test_round_trip!(
        numrange_roundtrips,
        Range<Numeric>,
        (i64, u64, i64, u64),
        mk_num_bounds
    );
    test_round_trip!(
        tsrange_roundtrips,
        Range<Timestamp>,
        (i64, u32, i64, u32),
        mk_ts_bounds
    );
    test_round_trip!(
        tstzrange_roundtrips,
        Range<Timestamptz>,
        (i64, u32, i64, u32),
        mk_tstz_bounds
    );

    fn mk_uuid(data: (u32, u16, u16, (u8, u8, u8, u8, u8, u8, u8, u8))) -> self::uuid::Uuid {
        let a = data.3;
        let b = [a.0, a.1, a.2, a.3, a.4, a.5, a.6, a.7];
        uuid::Uuid::from_fields(data.0, data.1, data.2, &b).unwrap()
    }

    fn mk_macaddr(data: (u8, u8, u8, u8, u8, u8)) -> [u8; 6] {
        [data.0, data.1, data.2, data.3, data.4, data.5]
    }

    fn mk_ipv4(data: (u8, u8, u8, u8)) -> ipnetwork::IpNetwork {
        use std::net::Ipv4Addr;
        let ip = Ipv4Addr::new(data.0, data.1, data.2, data.3);
        ipnetwork::IpNetwork::V4(ipnetwork::Ipv4Network::new(ip, 32).unwrap())
    }

    fn mk_ipv6(data: (u16, u16, u16, u16, u16, u16, u16, u16)) -> ipnetwork::IpNetwork {
        use std::net::Ipv6Addr;
        let ip = Ipv6Addr::new(
            data.0,
            data.1,
            data.2,
            data.3,
            data.4,
            data.5,
            data.6,
            data.7,
        );
        ipnetwork::IpNetwork::V6(ipnetwork::Ipv6Network::new(ip, 128).unwrap())
    }

    fn mk_bounds<T: Ord + PartialEq>(data: (T, T)) -> (Bound<T>, Bound<T>) {
        if data.0 == data.1 {
            // This is invalid but we don't have a way to say that to quickcheck
            return (Bound::Included(data.0), Bound::Unbounded);
        }

        if data.0 < data.1 {
            (Bound::Included(data.0), Bound::Excluded(data.1))
        } else {
            (Bound::Included(data.1), Bound::Excluded(data.0))
        }
    }

    fn mk_date_bounds(data: (u32, u32)) -> (Bound<NaiveDate>, Bound<NaiveDate>) {
        let d1 = mk_naive_date(data.0);
        let d2 = mk_naive_date(data.1);
        mk_bounds((d1, d2))
    }

    fn mk_num_bounds(data: (i64, u64, i64, u64)) -> (Bound<BigDecimal>, Bound<BigDecimal>) {
        let b1 = mk_bigdecimal((data.0, data.1));
        let b2 = mk_bigdecimal((data.2, data.3));
        mk_bounds((b1, b2))
    }

    fn mk_ts_bounds(data: (i64, u32, i64, u32)) -> (Bound<NaiveDateTime>, Bound<NaiveDateTime>) {
        let ts1 = mk_naive_datetime((data.0, data.1));
        let ts2 = mk_naive_datetime((data.2, data.3));
        mk_bounds((ts1, ts2))
    }

    fn mk_tstz_bounds(data: (i64, u32, i64, u32)) -> (Bound<DateTime<Utc>>, Bound<DateTime<Utc>>) {
        let tstz1 = mk_datetime((data.0, data.1));
        let tstz2 = mk_datetime((data.2, data.3));
        mk_bounds((tstz1, tstz2))
    }
}

#[cfg(feature = "mysql")]
mod mysql_types {
    use super::*;

    test_round_trip!(i8_roundtrips, Tinyint, i8);
    test_round_trip!(
        naive_datetime_roundtrips,
        Timestamp,
        (i64, u32),
        mk_naive_datetime
    );
    test_round_trip!(
        naive_datetime_roundtrips_to_datetime,
        Datetime,
        (i64, u32),
        mk_naive_datetime
    );
    test_round_trip!(naive_time_roundtrips, Time, (u32, u32), mk_naive_time);
    test_round_trip!(naive_date_roundtrips, Date, u32, mk_naive_date);
    test_round_trip!(bigdecimal_roundtrips, Numeric, (i64, u64), mk_bigdecimal);
}

pub fn mk_naive_datetime(data: (i64, u32)) -> NaiveDateTime {
    NaiveDateTime::from_timestamp(data.0, data.1 / 1000)
}

pub fn mk_naive_time(data: (u32, u32)) -> NaiveTime {
    NaiveTime::from_num_seconds_from_midnight(data.0, data.1 / 1000)
}

pub fn mk_datetime(data: (i64, u32)) -> DateTime<Utc> {
    DateTime::from_utc(mk_naive_datetime(data), Utc)
}

#[cfg(any(feature = "postgres", feature = "mysql"))]
fn mk_bigdecimal(data: (i64, u64)) -> bigdecimal::BigDecimal {
    format!("{}.{}", data.0, data.1)
        .parse()
        .expect("Could not interpret as bigdecimal")
}

#[cfg(feature = "postgres")]
pub fn mk_naive_date(days: u32) -> NaiveDate {
    use self::chrono::naive::MAX_DATE;

    let earliest_pg_date = NaiveDate::from_ymd(-4713, 11, 24);
    let latest_chrono_date = MAX_DATE;
    let num_days_representable = latest_chrono_date
        .signed_duration_since(earliest_pg_date)
        .num_days();
    earliest_pg_date + Duration::days(days as i64 % num_days_representable)
}

#[cfg(feature = "mysql")]
pub fn mk_naive_date(days: u32) -> NaiveDate {
    let earliest_mysql_date = NaiveDate::from_ymd(1000, 01, 01);
    let latest_mysql_date = NaiveDate::from_ymd(9999, 12, 31);
    let num_days_representable = latest_mysql_date
        .signed_duration_since(earliest_mysql_date)
        .num_days();
    earliest_mysql_date + Duration::days(days as i64 % num_days_representable)
}

#[cfg(feature = "sqlite")]
pub fn mk_naive_date(days: u32) -> NaiveDate {
    use self::chrono::naive::{MAX_DATE, MIN_DATE};

    let earliest_sqlite_date = MIN_DATE;
    let latest_sqlite_date = MAX_DATE;
    let num_days_representable = latest_sqlite_date
        .signed_duration_since(earliest_sqlite_date)
        .num_days();
    earliest_sqlite_date + Duration::days(days as i64 % num_days_representable)
}

#[cfg(feature = "postgres")]
mod unstable_types {
    use super::{quickcheck, test_type_round_trips};
    use std::time::*;

    fn strip_nanosecond_precision(time: SystemTime) -> SystemTime {
        match time.duration_since(UNIX_EPOCH) {
            Ok(duration) => time - Duration::new(0, duration.subsec_nanos() % 1000),
            Err(e) => time + Duration::new(0, e.duration().subsec_nanos() % 1000),
        }
    }

    test_round_trip!(
        systemtime_roundtrips,
        Timestamp,
        SystemTime,
        strip_nanosecond_precision
    );
}
<commit_msg>Speed up our integration test suite<commit_after>#[cfg(any(feature = "postgres", feature = "mysql"))]
extern crate bigdecimal;
extern crate chrono;

pub use quickcheck::quickcheck;
use self::chrono::{DateTime, Duration, NaiveDate, NaiveDateTime, NaiveTime, Utc};

pub use schema::{connection_without_transaction, TestConnection};
pub use diesel::*;
pub use diesel::result::Error;
pub use diesel::data_types::*;
pub use diesel::types::{HasSqlType, ToSql};

use diesel::expression::AsExpression;
use diesel::query_builder::{QueryFragment, QueryId};
use std::collections::Bound;

thread_local! {
    static CONN: TestConnection = connection_without_transaction();
}

pub fn test_type_round_trips<ST, T>(value: T) -> bool
where
    ST: QueryId,
    <TestConnection as Connection>::Backend: HasSqlType<ST>,
    T: AsExpression<ST>
        + Queryable<ST, <TestConnection as Connection>::Backend>
        + PartialEq
        + Clone
        + ::std::fmt::Debug,
    <T as AsExpression<ST>>::Expression: SelectableExpression<(), SqlType = ST>
        + QueryFragment<<TestConnection as Connection>::Backend>
        + QueryId,
{
    CONN.with(|connection| {
        let query = select(value.clone().into_sql::<ST>());
        let result = query.get_result::<T>(connection);
        match result {
            Ok(res) => if value != res {
                println!("{:?}, {:?}", value, res);
                false
            } else {
                true
            },
            Err(Error::DatabaseError(_, ref e))
                if e.message() == "invalid byte sequence for encoding \"UTF8\": 0x00" =>
            {
                true
            }
            Err(e) => panic!("Query failed: {:?}", e),
        }
    })
}

pub fn id<A>(a: A) -> A {
    a
}

macro_rules! test_round_trip {
    ($test_name:ident, $sql_type:ty, $tpe:ty) => {
        test_round_trip!($test_name, $sql_type, $tpe, id);
    };

    ($test_name:ident, $sql_type:ty, $tpe:ty, $map_fn:ident) => {
        #[test]
        fn $test_name() {
            use diesel::types::*;

            fn round_trip(val: $tpe) -> bool {
                test_type_round_trips::<$sql_type, _>($map_fn(val))
            }

            fn option_round_trip(val: Option<$tpe>) -> bool {
                let val = val.map($map_fn);
                test_type_round_trips::<Nullable<$sql_type>, _>(val)
            }

            quickcheck(round_trip as fn($tpe) -> bool);
            quickcheck(option_round_trip as fn(Option<$tpe>) -> bool);
        }
    }
}

test_round_trip!(i16_roundtrips, SmallInt, i16);
test_round_trip!(i32_roundtrips, Integer, i32);
test_round_trip!(i64_roundtrips, BigInt, i64);
test_round_trip!(f32_roundtrips, Float, f32);
test_round_trip!(f64_roundtrips, Double, f64);
test_round_trip!(string_roundtrips, VarChar, String);
test_round_trip!(text_roundtrips, Text, String);
test_round_trip!(binary_roundtrips, Binary, Vec<u8>);
test_round_trip!(bool_roundtrips, Bool, bool);

#[cfg(feature = "sqlite")]
mod sqlite_types {
    use super::*;

    test_round_trip!(date_roundtrips, Date, String);
    test_round_trip!(time_roundtrips, Time, String);
    test_round_trip!(timestamp_roundtrips, Timestamp, String);
    test_round_trip!(naive_time_roundtrips, Time, (u32, u32), mk_naive_time);
    test_round_trip!(naive_date_roundtrips, Date, u32, mk_naive_date);
    test_round_trip!(
        naive_datetime_roundtrips,
        Timestamp,
        (i64, u32),
        mk_naive_datetime
    );
}

#[cfg(feature = "postgres")]
mod pg_types {
    extern crate ipnetwork;
    extern crate uuid;

    use super::*;
    use self::bigdecimal::BigDecimal;

    test_round_trip!(date_roundtrips, Date, PgDate);
    test_round_trip!(time_roundtrips, Time, PgTime);
    test_round_trip!(timestamp_roundtrips, Timestamp, PgTimestamp);
    test_round_trip!(interval_roundtrips, Interval, PgInterval);
    test_round_trip!(numeric_roundtrips, Numeric, PgNumeric);
    test_round_trip!(money_roundtrips, Money, PgMoney);
    test_round_trip!(
        naive_datetime_roundtrips,
        Timestamp,
        (i64, u32),
        mk_naive_datetime
    );
    test_round_trip!(naive_time_roundtrips, Time, (u32, u32), mk_naive_time);
    test_round_trip!(naive_date_roundtrips, Date, u32, mk_naive_date);
    test_round_trip!(datetime_roundtrips, Timestamptz, (i64, u32), mk_datetime);
    test_round_trip!(
        naive_datetime_roundtrips_tz,
        Timestamptz,
        (i64, u32),
        mk_naive_datetime
    );
    test_round_trip!(
        uuid_roundtrips,
        Uuid,
        (u32, u16, u16, (u8, u8, u8, u8, u8, u8, u8, u8)),
        mk_uuid
    );
    test_round_trip!(array_of_int_roundtrips, Array<Integer>, Vec<i32>);
    test_round_trip!(array_of_bigint_roundtrips, Array<BigInt>, Vec<i64>);
    test_round_trip!(array_of_dynamic_size_roundtrips, Array<Text>, Vec<String>);
    test_round_trip!(
        array_of_nullable_roundtrips,
        Array<Nullable<Text>>,
        Vec<Option<String>>
    );
    test_round_trip!(
        macaddr_roundtrips,
        MacAddr,
        (u8, u8, u8, u8, u8, u8),
        mk_macaddr
    );
    test_round_trip!(cidr_v4_roundtrips, Cidr, (u8, u8, u8, u8), mk_ipv4);
    test_round_trip!(
        cidr_v6_roundtrips,
        Cidr,
        (u16, u16, u16, u16, u16, u16, u16, u16),
        mk_ipv6
    );
    test_round_trip!(inet_v4_roundtrips, Inet, (u8, u8, u8, u8), mk_ipv4);
    test_round_trip!(
        inet_v6_roundtrips,
        Inet,
        (u16, u16, u16, u16, u16, u16, u16, u16),
        mk_ipv6
    );
    test_round_trip!(bigdecimal_roundtrips, Numeric, (i64, u64), mk_bigdecimal);
    test_round_trip!(int4range_roundtrips, Range<Int4>, (i32, i32), mk_bounds);
    test_round_trip!(int8range_roundtrips, Range<Int8>, (i64, i64), mk_bounds);
    test_round_trip!(
        daterange_roundtrips,
        Range<Date>,
        (u32, u32),
        mk_date_bounds
    );
    test_round_trip!(
        numrange_roundtrips,
        Range<Numeric>,
        (i64, u64, i64, u64),
        mk_num_bounds
    );
    test_round_trip!(
        tsrange_roundtrips,
        Range<Timestamp>,
        (i64, u32, i64, u32),
        mk_ts_bounds
    );
    test_round_trip!(
        tstzrange_roundtrips,
        Range<Timestamptz>,
        (i64, u32, i64, u32),
        mk_tstz_bounds
    );

    fn mk_uuid(data: (u32, u16, u16, (u8, u8, u8, u8, u8, u8, u8, u8))) -> self::uuid::Uuid {
        let a = data.3;
        let b = [a.0, a.1, a.2, a.3, a.4, a.5, a.6, a.7];
        uuid::Uuid::from_fields(data.0, data.1, data.2, &b).unwrap()
    }

    fn mk_macaddr(data: (u8, u8, u8, u8, u8, u8)) -> [u8; 6] {
        [data.0, data.1, data.2, data.3, data.4, data.5]
    }

    fn mk_ipv4(data: (u8, u8, u8, u8)) -> ipnetwork::IpNetwork {
        use std::net::Ipv4Addr;
        let ip = Ipv4Addr::new(data.0, data.1, data.2, data.3);
        ipnetwork::IpNetwork::V4(ipnetwork::Ipv4Network::new(ip, 32).unwrap())
    }

    fn mk_ipv6(data: (u16, u16, u16, u16, u16, u16, u16, u16)) -> ipnetwork::IpNetwork {
        use std::net::Ipv6Addr;
        let ip = Ipv6Addr::new(
            data.0,
            data.1,
            data.2,
            data.3,
            data.4,
            data.5,
            data.6,
            data.7,
        );
        ipnetwork::IpNetwork::V6(ipnetwork::Ipv6Network::new(ip, 128).unwrap())
    }

    fn mk_bounds<T: Ord + PartialEq>(data: (T, T)) -> (Bound<T>, Bound<T>) {
        if data.0 == data.1 {
            // This is invalid but we don't have a way to say that to quickcheck
            return (Bound::Included(data.0), Bound::Unbounded);
        }

        if data.0 < data.1 {
            (Bound::Included(data.0), Bound::Excluded(data.1))
        } else {
            (Bound::Included(data.1), Bound::Excluded(data.0))
        }
    }

    fn mk_date_bounds(data: (u32, u32)) -> (Bound<NaiveDate>, Bound<NaiveDate>) {
        let d1 = mk_naive_date(data.0);
        let d2 = mk_naive_date(data.1);
        mk_bounds((d1, d2))
    }

    fn mk_num_bounds(data: (i64, u64, i64, u64)) -> (Bound<BigDecimal>, Bound<BigDecimal>) {
        let b1 = mk_bigdecimal((data.0, data.1));
        let b2 = mk_bigdecimal((data.2, data.3));
        mk_bounds((b1, b2))
    }

    fn mk_ts_bounds(data: (i64, u32, i64, u32)) -> (Bound<NaiveDateTime>, Bound<NaiveDateTime>) {
        let ts1 = mk_naive_datetime((data.0, data.1));
        let ts2 = mk_naive_datetime((data.2, data.3));
        mk_bounds((ts1, ts2))
    }

    fn mk_tstz_bounds(data: (i64, u32, i64, u32)) -> (Bound<DateTime<Utc>>, Bound<DateTime<Utc>>) {
        let tstz1 = mk_datetime((data.0, data.1));
        let tstz2 = mk_datetime((data.2, data.3));
        mk_bounds((tstz1, tstz2))
    }
}

#[cfg(feature = "mysql")]
mod mysql_types {
    use super::*;

    test_round_trip!(i8_roundtrips, Tinyint, i8);
    test_round_trip!(
        naive_datetime_roundtrips,
        Timestamp,
        (i64, u32),
        mk_naive_datetime
    );
    test_round_trip!(
        naive_datetime_roundtrips_to_datetime,
        Datetime,
        (i64, u32),
        mk_naive_datetime
    );
    test_round_trip!(naive_time_roundtrips, Time, (u32, u32), mk_naive_time);
    test_round_trip!(naive_date_roundtrips, Date, u32, mk_naive_date);
    test_round_trip!(bigdecimal_roundtrips, Numeric, (i64, u64), mk_bigdecimal);
}

pub fn mk_naive_datetime(data: (i64, u32)) -> NaiveDateTime {
    NaiveDateTime::from_timestamp(data.0, data.1 / 1000)
}

pub fn mk_naive_time(data: (u32, u32)) -> NaiveTime {
    NaiveTime::from_num_seconds_from_midnight(data.0, data.1 / 1000)
}

pub fn mk_datetime(data: (i64, u32)) -> DateTime<Utc> {
    DateTime::from_utc(mk_naive_datetime(data), Utc)
}

#[cfg(any(feature = "postgres", feature = "mysql"))]
fn mk_bigdecimal(data: (i64, u64)) -> bigdecimal::BigDecimal {
    format!("{}.{}", data.0, data.1)
        .parse()
        .expect("Could not interpret as bigdecimal")
}

#[cfg(feature = "postgres")]
pub fn mk_naive_date(days: u32) -> NaiveDate {
    use self::chrono::naive::MAX_DATE;

    let earliest_pg_date = NaiveDate::from_ymd(-4713, 11, 24);
    let latest_chrono_date = MAX_DATE;
    let num_days_representable = latest_chrono_date
        .signed_duration_since(earliest_pg_date)
        .num_days();
    earliest_pg_date + Duration::days(days as i64 % num_days_representable)
}

#[cfg(feature = "mysql")]
pub fn mk_naive_date(days: u32) -> NaiveDate {
    let earliest_mysql_date = NaiveDate::from_ymd(1000, 01, 01);
    let latest_mysql_date = NaiveDate::from_ymd(9999, 12, 31);
    let num_days_representable = latest_mysql_date
        .signed_duration_since(earliest_mysql_date)
        .num_days();
    earliest_mysql_date + Duration::days(days as i64 % num_days_representable)
}

#[cfg(feature = "sqlite")]
pub fn mk_naive_date(days: u32) -> NaiveDate {
    use self::chrono::naive::{MAX_DATE, MIN_DATE};

    let earliest_sqlite_date = MIN_DATE;
    let latest_sqlite_date = MAX_DATE;
    let num_days_representable = latest_sqlite_date
        .signed_duration_since(earliest_sqlite_date)
        .num_days();
    earliest_sqlite_date + Duration::days(days as i64 % num_days_representable)
}

#[cfg(feature = "postgres")]
mod unstable_types {
    use super::{quickcheck, test_type_round_trips};
    use std::time::*;

    fn strip_nanosecond_precision(time: SystemTime) -> SystemTime {
        match time.duration_since(UNIX_EPOCH) {
            Ok(duration) => time - Duration::new(0, duration.subsec_nanos() % 1000),
            Err(e) => time + Duration::new(0, e.duration().subsec_nanos() % 1000),
        }
    }

    test_round_trip!(
        systemtime_roundtrips,
        Timestamp,
        SystemTime,
        strip_nanosecond_precision
    );
}
<|endoftext|>


<commit_before>use std::io;

pub trait ResourceLoader<T> {
	fn load(&self, key: &str) -> io::Result<Box<[T]>>;
}

pub mod filesystem {
	use std::fs;
	use std::io;
	use std::io::Read;
	use std::path;

	#[derive(Clone)]
	pub struct ResourceLoader {
		roots: Box<[path::PathBuf]>,
	}

	pub struct ResourceLoaderBuilder {
		roots: Vec<path::PathBuf>,
	}

	impl ResourceLoaderBuilder {
		pub fn new() -> Self { ResourceLoaderBuilder { roots: Vec::new() } }

		pub fn add(&mut self, root: &path::Path) -> &mut Self {
			self.roots.push(root.to_owned());
			self
		}

		pub fn build(&self) -> ResourceLoader {
			ResourceLoader {
				roots: self.roots.clone().into_boxed_slice(),
			}
		}
	}

	impl super::ResourceLoader<u8> for ResourceLoader {
		fn load(&self, key: &str) -> io::Result<Box<[u8]>> {
			// swallow the file whole into a buffer
			fn load_from_path(path: &path::Path) -> io::Result<Box<[u8]>> {
				fs::File::open(path).and_then(|mut f| {
					let mut buf = Vec::new();
					f.read_to_end(&mut buf).map(|_| buf.into_boxed_slice())
				})
				// 		Rust idiom
				// 		let mut f = fs::File::open(path.as_path())?;
				// 		let mut buf = Vec::new();
				// 		f.read_to_end(&buf)?;
				// 		Ok(buf.into_boxed_slice())
			}

			// look for the first file which exists
			match &self
				.roots
				.iter()
				.map(|ref r| {
					// try all roots in order, if some has it
					let mut path = path::PathBuf::from(r);
					path.push(key);
					path
				})
				.find(|path| path.exists() && path.is_file())
			{
				// and then either read it
				&Some(ref p) => load_from_path(p.as_path()),
				// or give up
				&None => {
					let mut err = String::from("Resource not found in path: ");
					err.push_str(key);
					Err(io::Error::new(io::ErrorKind::Other, err))
				}
			}
		}
	}
}
<commit_msg>Tidy up<commit_after>use std::io;

pub trait ResourceLoader<T> {
	fn load(&self, key: &str) -> io::Result<Box<[T]>>;
}

pub mod filesystem {
	use std::fs;
	use std::io;
	use std::io::Read;
	use std::path;

	#[derive(Clone)]
	pub struct ResourceLoader {
		roots: Box<[path::PathBuf]>,
	}

	pub struct ResourceLoaderBuilder {
		roots: Vec<path::PathBuf>,
	}

	impl ResourceLoaderBuilder {
		pub fn new() -> Self { ResourceLoaderBuilder { roots: Vec::new() } }

		pub fn add(&mut self, root: &path::Path) -> &mut Self {
			self.roots.push(root.to_owned());
			self
		}

		pub fn build(&self) -> ResourceLoader {
			ResourceLoader {
				roots: self.roots.clone().into_boxed_slice(),
			}
		}
	}

	impl super::ResourceLoader<u8> for ResourceLoader {
		fn load(&self, key: &str) -> io::Result<Box<[u8]>> {
			// swallow the file whole into a buffer
			fn load_from_path(path: &path::Path) -> io::Result<Box<[u8]>> {
				let mut buf = Vec::new();
				fs::File::open(path)?.read_to_end(&mut buf)?;
				Ok(buf.into_boxed_slice())
			}

			// look for the first file which exists
			match &self
				.roots
				.iter()
				.map(|ref r| {
					// try all roots in order, if some has it
					let mut path = path::PathBuf::from(r);
					path.push(key);
					path
				}).find(|path| path.exists() && path.is_file())
			{
				// and then either read it
				&Some(ref p) => load_from_path(p.as_path()),
				// or give up
				&None => {
					let mut err = String::from("Resource not found in path: ");
					err.push_str(key);
					Err(io::Error::new(io::ErrorKind::Other, err))
				}
			}
		}
	}
}
<|endoftext|>


<commit_before>#[feature(globs)];

extern mod native;
extern mod extra;
extern mod glfw;
extern mod gl;
extern mod cgmath;
extern mod noise;

use std::cast;
use std::ptr;
use std::str;
use std::vec;
use std::libc;
use std::io::Timer;
use std::hashmap::HashSet;

use gl::types::*;

use cgmath::matrix::Matrix;
use cgmath::matrix::Mat3;
use cgmath::matrix::Mat4;
use cgmath::matrix::ToMat4;
use cgmath::vector::Vector;
use cgmath::vector::Vec3;
use cgmath::vector::Vec4;
use cgmath::angle::rad;

#[link(name="GLU")]
extern {}

mod chunk;

static vertex_shader_src : &'static str = r"
#version 110

uniform mat4 modelview;
uniform mat4 projection;

attribute vec3 position;
attribute vec3 normal;

varying vec4 frag_color;

const vec4 obj_diffuse = vec4(0.2, 0.6, 0.2, 1.0);
const vec3 light_direction = vec3(0.408248, -0.816497, 0.408248);
const vec4 light_diffuse = vec4(0.8, 0.8, 0.8, 0.0);
const vec4 light_ambient = vec4(0.2, 0.2, 0.2, 1.0);

const float planet_radius = 6371000.0 / 10000.0;

void main() {
    vec4 eye_position = modelview * vec4(position, 1.0);

    /* Curvature of the planet */
    float distance_squared = pow(eye_position.x, 2) + pow(eye_position.z, 2);
    eye_position.y -= planet_radius - sqrt(pow(planet_radius, 2) - distance_squared);

    gl_Position = projection * eye_position;

    vec4 diffuse_factor
        = max(-dot(normal, light_direction), 0.0) * light_diffuse;
    vec4 ambient_diffuse_factor = diffuse_factor + light_ambient;

    frag_color = ambient_diffuse_factor * obj_diffuse;
}
";

static fragment_shader_src : &'static str = r"
#version 110

varying vec4 frag_color;

void main() {
    gl_FragColor = frag_color;
}
";

pub static WORLD_SIZE: uint = 4;
pub static CHUNK_SIZE: uint = 64;
pub static WORLD_SEED: u32 = 42;

static FRAME_TIME_TARGET_MS : u64 = 16;

struct GraphicsResources {
    program: GLuint,
    uniform_modelview: GLint,
    uniform_projection: GLint,
}

#[start]
fn start(argc: int, argv: **u8) -> int {
    do native::start(argc, argv) {
        main();
    }
}

fn main() {
   glfw::set_error_callback(~ErrorContext);

    do glfw::start {
        let mut window_width = 800;
        let mut window_height = 600;

        let window = glfw::Window::create(window_width, window_height, "Hello, I am a window.", glfw::Windowed)
            .expect("Failed to create GLFW window.");

        window.set_cursor_mode(glfw::CursorDisabled);
        window.make_context_current();

        gl::load_with(glfw::get_proc_address);

        gl::Enable(gl::DEPTH_TEST);
        gl::Enable(gl::CULL_FACE);

        glfw::set_swap_interval(1);

        let graphics_resources = load_graphics_resources();

        gl::UseProgram(graphics_resources.program);

        let mut chunk_loader = chunk::ChunkLoader::new(WORLD_SEED, &graphics_resources);

        window.set_key_callback(~KeyContext);

        let (fb_size_port, fb_size_chan): (Port<(u32,u32)>, Chan<(u32,u32)>) = std::comm::Chan::new();
        window.set_framebuffer_size_callback(~FramebufferSizeContext { chan: fb_size_chan });

        let start_time = extra::time::precise_time_ns();
        let mut last_frame_time = start_time;
        let mut num_frames = 0;

        let mut camera_position = Vec3::<f32>::new(0.0f32, 20.0f32, 40.0f32);

        //let mut timer = Timer::new().unwrap();

        let mut needed_chunks : HashSet<(i64, i64)> = HashSet::new();

        while !window.should_close() {
            let frame_start_time = extra::time::precise_time_ns();

            glfw::poll_events();

            loop {
                match fb_size_port.try_recv() {
                    Some((w,h)) => {
                        window_width = w;
                        window_height = h;
                    }
                    None => break
                }
            }

            let (cursor_x, cursor_y) = window.get_cursor_pos();
            let camera_angle_y = ((cursor_x * 0.0005) % 1.0) * std::f64::consts::PI * 2.0;
            let camera_angle_x = ((cursor_y * 0.0005) % 1.0) * std::f64::consts::PI * 2.0;

            let mut camera_velocity = Vec3::<f32>::new(0.0f32, 0.0f32, 0.0f32);

            match window.get_key(glfw::KeySpace) {
                glfw::Press => { camera_velocity.y += 1.0f32 }
                _ => {}
            }

            match window.get_key(glfw::KeyLeftControl) {
                glfw::Press => { camera_velocity.y += -1.0f32 }
                _ => {}
            }

            match window.get_key(glfw::KeyS) {
                glfw::Press => { camera_velocity.z += 1.0f32 }
                _ => {}
            }

            match window.get_key(glfw::KeyW) {
                glfw::Press => { camera_velocity.z += -1.0f32 }
                _ => {}
            }

            match window.get_key(glfw::KeyD) {
                glfw::Press => { camera_velocity.x += 1.0f32 }
                _ => {}
            }

            match window.get_key(glfw::KeyA) {
                glfw::Press => { camera_velocity.x += -1.0f32 }
                _ => {}
            }

            gl::Viewport(0,0, window_width as GLint, window_height as GLint);

            gl::ClearColor(0.0, 0.75, 1.0, 1.0);
            gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);

            let projection = cgmath::projection::perspective(
                rad(1.57f32),
                window_width as f32 / window_height as f32,
                0.1f32, 1000.0f32);

            unsafe {
                gl::UniformMatrix4fv(graphics_resources.uniform_projection, 1, gl::FALSE, cast::transmute(&projection));
            }

            let camera_translation = Mat4::<f32>::from_cols(
                Vec4::<f32>::unit_x(),
                Vec4::<f32>::unit_y(),
                Vec4::<f32>::unit_z(),
                camera_position.mul_s(-1.0f32).extend(1.0f32));
            let camera_rotation_x = Mat3::<f32>::from_angle_x(rad(camera_angle_x as f32)).to_mat4();
            let camera_rotation_y = Mat3::<f32>::from_angle_y(rad(camera_angle_y as f32)).to_mat4();
            let camera = camera_rotation_x.mul_m(&camera_rotation_y).mul_m(&camera_translation);

            let inv_camera_rotation = Mat3::<f32>::from_euler(rad(-camera_angle_x as f32), rad(-camera_angle_y as f32), rad(0.0f32));
            let absolute_camera_velocity = inv_camera_rotation.mul_v(&camera_velocity).mul_s(0.5f32);
            camera_position.add_self_v(&absolute_camera_velocity);

            let coords = visible_chunks(camera_position.x as i64,
                                        camera_position.z as i64);

            for &(cx, cz) in coords.iter() {
                match chunk_loader.cache.find_mut(&(cx, cz)) {
                    Some(chunk) => {
                        chunk.touch();

                        let chunk_translation = Mat4::<f32>::from_cols(
                            Vec4::<f32>::unit_x(),
                            Vec4::<f32>::unit_y(),
                            Vec4::<f32>::unit_z(),
                            Vec4::<f32>::new(chunk.x as f32, 0.0f32, chunk.z as f32, 1.0f32));

                        let modelview = camera.mul_m(&chunk_translation);

                        gl::BindVertexArray(chunk.vao);

                        unsafe {
                            gl::UniformMatrix4fv(graphics_resources.uniform_modelview, 1, gl::FALSE, cast::transmute(&modelview));
                            gl::DrawElements(gl::TRIANGLES, chunk.num_elements as i32, gl::UNSIGNED_INT, ptr::null());
                        }

                        gl::BindVertexArray(0);
                    },
                    None => {
                        needed_chunks.insert((cx, cz));
                    }
                }
            }

            window.swap_buffers();

            check_gl("main loop");

            let mut loaded = None;

            for &(cx, cz) in needed_chunks.iter() {
                chunk_loader.load(cx, cz);
                loaded = Some((cx, cz));
                break;
            }

            match loaded {
                Some((cx, cz)) => {
                    needed_chunks.remove(&(cx, cz));
                },
                None => {}
            }

            let cur_time = extra::time::precise_time_ns();
            num_frames += 1;
            if (cur_time - last_frame_time) > (1000*1000*1000) {
                println!("{} frames per second", num_frames);
                num_frames = 0;
                last_frame_time = cur_time;
            }

            let frame_end_time = extra::time::precise_time_ns();
            let frame_time_ms = (frame_end_time - frame_start_time)/(1000*1000);
            if (frame_time_ms < FRAME_TIME_TARGET_MS) {
                //timer.sleep(FRAME_TIME_TARGET_MS - frame_time_ms);
            }
        }
    }
}

fn visible_chunks(x: i64, z: i64) -> ~[(i64, i64)] {
    let mask : i64 = !(CHUNK_SIZE as i64 - 1);
    let mut coords = ~[];
    for ix in std::iter::range_inclusive(-(WORLD_SIZE as i64)/2, (WORLD_SIZE as i64)/2) {
        for iz in std::iter::range_inclusive(-(WORLD_SIZE as i64)/2, (WORLD_SIZE as i64)/2) {
            let cx : i64 = (x & mask) + ix*CHUNK_SIZE as i64;
            let cz : i64 = (z & mask) + iz*CHUNK_SIZE as i64;
            coords.push((cx, cz));
        }
    }
    coords
}

fn load_graphics_resources() -> GraphicsResources {
    let vs = compile_shader(vertex_shader_src.as_bytes(), gl::VERTEX_SHADER);
    let fs = compile_shader(fragment_shader_src.as_bytes(), gl::FRAGMENT_SHADER);
    let program = link_program(vs, fs);

    let uniform_modelview = unsafe { "modelview".with_c_str(|ptr| gl::GetUniformLocation(program, ptr)) };
    let uniform_projection = unsafe { "projection".with_c_str(|ptr| gl::GetUniformLocation(program, ptr)) };

    return GraphicsResources {
        program: program,
        uniform_modelview: uniform_modelview,
        uniform_projection: uniform_projection,
    };

}

extern "C" {
    fn gluErrorString(error: GLenum) -> *GLubyte;
}

fn check_gl(message : &str) {
    let err = gl::GetError();
    if (err != gl::NO_ERROR) {
        unsafe {
            let err = std::str::raw::from_c_str(gluErrorString(err) as *i8);
            fail!("GL error {} at {}", err, message);
        }
    }
}

fn compile_shader(src: &[u8], ty: GLenum) -> GLuint {
    let shader = gl::CreateShader(ty);
    unsafe {
        // Attempt to compile the shader
        //transmute is used here because `as` causes ICE
        //wait a sec, is `src` null-terminated properly?
        gl::ShaderSource(shader, 1, std::cast::transmute(std::ptr::to_unsafe_ptr(&src.as_ptr())), ptr::null());
        gl::CompileShader(shader);

        // Get the compile status
        let mut status = gl::FALSE as GLint;
        gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);

        // Fail on error
        if status != (gl::TRUE as GLint) {
            let mut len = 0;
            gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
            let mut buf = vec::from_elem(len as uint - 1, 0u8);     // subtract 1 to skip the trailing null character
            gl::GetShaderInfoLog(shader, len, ptr::mut_null(), buf.as_mut_ptr() as *mut GLchar);
            fail!(str::raw::from_utf8(buf).to_owned());
        }
    }
    shader
}

fn link_program(vs: GLuint, fs: GLuint) -> GLuint {
    let program = gl::CreateProgram();
    gl::AttachShader(program, vs);
    gl::AttachShader(program, fs);
    gl::LinkProgram(program);
    unsafe {
        // Get the link status
        let mut status = gl::FALSE as GLint;
        gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);

        // Fail on error
        if status != (gl::TRUE as GLint) {
            let mut len: GLint = 0;
            gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
            let mut buf = vec::from_elem(len as uint - 1, 0u8);     // subtract 1 to skip the trailing null character
            gl::GetProgramInfoLog(program, len, ptr::mut_null(), buf.as_mut_ptr() as *mut GLchar);
            fail!(str::raw::from_utf8(buf).to_owned());
        }
    }
    program
}

struct ErrorContext;
impl glfw::ErrorCallback for ErrorContext {
    fn call(&self, _: glfw::Error, description: ~str) {
        fail!("GLFW Error: {:s}", description);
    }
}

struct KeyContext;
impl glfw::KeyCallback for KeyContext {
    fn call(&self, window: &glfw::Window, key: glfw::Key, _: libc::c_int, action: glfw::Action, _: glfw::Modifiers) {
        match (action, key) {
            (glfw::Press, glfw::KeyEscape) => window.set_should_close(true),
            _ => {}
        }
    }
}

struct FramebufferSizeContext {
    chan: Chan<(u32,u32)>
}
impl glfw::FramebufferSizeCallback for FramebufferSizeContext {
    fn call(&self, _: &glfw::Window, width: i32, height: i32) {
        self.chan.send((width as u32,height as u32));
    }
}
<commit_msg>ratelimit chunk loading<commit_after>#[feature(globs)];

extern mod native;
extern mod extra;
extern mod glfw;
extern mod gl;
extern mod cgmath;
extern mod noise;

use std::cast;
use std::ptr;
use std::str;
use std::vec;
use std::libc;
use std::io::Timer;
use std::hashmap::HashSet;

use gl::types::*;

use cgmath::matrix::Matrix;
use cgmath::matrix::Mat3;
use cgmath::matrix::Mat4;
use cgmath::matrix::ToMat4;
use cgmath::vector::Vector;
use cgmath::vector::Vec3;
use cgmath::vector::Vec4;
use cgmath::angle::rad;

#[link(name="GLU")]
extern {}

mod chunk;
mod ratelimiter;

static vertex_shader_src : &'static str = r"
#version 110

uniform mat4 modelview;
uniform mat4 projection;

attribute vec3 position;
attribute vec3 normal;

varying vec4 frag_color;

const vec4 obj_diffuse = vec4(0.2, 0.6, 0.2, 1.0);
const vec3 light_direction = vec3(0.408248, -0.816497, 0.408248);
const vec4 light_diffuse = vec4(0.8, 0.8, 0.8, 0.0);
const vec4 light_ambient = vec4(0.2, 0.2, 0.2, 1.0);

const float planet_radius = 6371000.0 / 10000.0;

void main() {
    vec4 eye_position = modelview * vec4(position, 1.0);

    /* Curvature of the planet */
    float distance_squared = pow(eye_position.x, 2) + pow(eye_position.z, 2);
    eye_position.y -= planet_radius - sqrt(pow(planet_radius, 2) - distance_squared);

    gl_Position = projection * eye_position;

    vec4 diffuse_factor
        = max(-dot(normal, light_direction), 0.0) * light_diffuse;
    vec4 ambient_diffuse_factor = diffuse_factor + light_ambient;

    frag_color = ambient_diffuse_factor * obj_diffuse;
}
";

static fragment_shader_src : &'static str = r"
#version 110

varying vec4 frag_color;

void main() {
    gl_FragColor = frag_color;
}
";

pub static WORLD_SIZE: uint = 4;
pub static CHUNK_SIZE: uint = 64;
pub static WORLD_SEED: u32 = 42;

static FRAME_TIME_TARGET_MS : u64 = 16;

struct GraphicsResources {
    program: GLuint,
    uniform_modelview: GLint,
    uniform_projection: GLint,
}

#[start]
fn start(argc: int, argv: **u8) -> int {
    do native::start(argc, argv) {
        main();
    }
}

fn main() {
   glfw::set_error_callback(~ErrorContext);

    do glfw::start {
        let mut window_width = 800;
        let mut window_height = 600;

        let window = glfw::Window::create(window_width, window_height, "Hello, I am a window.", glfw::Windowed)
            .expect("Failed to create GLFW window.");

        window.set_cursor_mode(glfw::CursorDisabled);
        window.make_context_current();

        gl::load_with(glfw::get_proc_address);

        gl::Enable(gl::DEPTH_TEST);
        gl::Enable(gl::CULL_FACE);

        glfw::set_swap_interval(1);

        let graphics_resources = load_graphics_resources();

        gl::UseProgram(graphics_resources.program);

        let mut chunk_loader = chunk::ChunkLoader::new(WORLD_SEED, &graphics_resources);

        window.set_key_callback(~KeyContext);

        let (fb_size_port, fb_size_chan): (Port<(u32,u32)>, Chan<(u32,u32)>) = std::comm::Chan::new();
        window.set_framebuffer_size_callback(~FramebufferSizeContext { chan: fb_size_chan });

        let start_time = extra::time::precise_time_ns();
        let mut last_frame_time = start_time;
        let mut num_frames = 0;

        let mut camera_position = Vec3::<f32>::new(0.0f32, 20.0f32, 40.0f32);

        //let mut timer = Timer::new().unwrap();

        let mut needed_chunks : HashSet<(i64, i64)> = HashSet::new();
        let mut load_limiter = ratelimiter::RateLimiter::new(1000*1000*100);

        while !window.should_close() {
            let frame_start_time = extra::time::precise_time_ns();

            glfw::poll_events();

            loop {
                match fb_size_port.try_recv() {
                    Some((w,h)) => {
                        window_width = w;
                        window_height = h;
                    }
                    None => break
                }
            }

            let (cursor_x, cursor_y) = window.get_cursor_pos();
            let camera_angle_y = ((cursor_x * 0.0005) % 1.0) * std::f64::consts::PI * 2.0;
            let camera_angle_x = ((cursor_y * 0.0005) % 1.0) * std::f64::consts::PI * 2.0;

            let mut camera_velocity = Vec3::<f32>::new(0.0f32, 0.0f32, 0.0f32);

            match window.get_key(glfw::KeySpace) {
                glfw::Press => { camera_velocity.y += 1.0f32 }
                _ => {}
            }

            match window.get_key(glfw::KeyLeftControl) {
                glfw::Press => { camera_velocity.y += -1.0f32 }
                _ => {}
            }

            match window.get_key(glfw::KeyS) {
                glfw::Press => { camera_velocity.z += 1.0f32 }
                _ => {}
            }

            match window.get_key(glfw::KeyW) {
                glfw::Press => { camera_velocity.z += -1.0f32 }
                _ => {}
            }

            match window.get_key(glfw::KeyD) {
                glfw::Press => { camera_velocity.x += 1.0f32 }
                _ => {}
            }

            match window.get_key(glfw::KeyA) {
                glfw::Press => { camera_velocity.x += -1.0f32 }
                _ => {}
            }

            gl::Viewport(0,0, window_width as GLint, window_height as GLint);

            gl::ClearColor(0.0, 0.75, 1.0, 1.0);
            gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);

            let projection = cgmath::projection::perspective(
                rad(1.57f32),
                window_width as f32 / window_height as f32,
                0.1f32, 1000.0f32);

            unsafe {
                gl::UniformMatrix4fv(graphics_resources.uniform_projection, 1, gl::FALSE, cast::transmute(&projection));
            }

            let camera_translation = Mat4::<f32>::from_cols(
                Vec4::<f32>::unit_x(),
                Vec4::<f32>::unit_y(),
                Vec4::<f32>::unit_z(),
                camera_position.mul_s(-1.0f32).extend(1.0f32));
            let camera_rotation_x = Mat3::<f32>::from_angle_x(rad(camera_angle_x as f32)).to_mat4();
            let camera_rotation_y = Mat3::<f32>::from_angle_y(rad(camera_angle_y as f32)).to_mat4();
            let camera = camera_rotation_x.mul_m(&camera_rotation_y).mul_m(&camera_translation);

            let inv_camera_rotation = Mat3::<f32>::from_euler(rad(-camera_angle_x as f32), rad(-camera_angle_y as f32), rad(0.0f32));
            let absolute_camera_velocity = inv_camera_rotation.mul_v(&camera_velocity).mul_s(0.5f32);
            camera_position.add_self_v(&absolute_camera_velocity);

            let coords = visible_chunks(camera_position.x as i64,
                                        camera_position.z as i64);

            for &(cx, cz) in coords.iter() {
                match chunk_loader.cache.find_mut(&(cx, cz)) {
                    Some(chunk) => {
                        chunk.touch();

                        let chunk_translation = Mat4::<f32>::from_cols(
                            Vec4::<f32>::unit_x(),
                            Vec4::<f32>::unit_y(),
                            Vec4::<f32>::unit_z(),
                            Vec4::<f32>::new(chunk.x as f32, 0.0f32, chunk.z as f32, 1.0f32));

                        let modelview = camera.mul_m(&chunk_translation);

                        gl::BindVertexArray(chunk.vao);

                        unsafe {
                            gl::UniformMatrix4fv(graphics_resources.uniform_modelview, 1, gl::FALSE, cast::transmute(&modelview));
                            gl::DrawElements(gl::TRIANGLES, chunk.num_elements as i32, gl::UNSIGNED_INT, ptr::null());
                        }

                        gl::BindVertexArray(0);
                    },
                    None => {
                        needed_chunks.insert((cx, cz));
                    }
                }
            }

            window.swap_buffers();

            check_gl("main loop");

            if !needed_chunks.is_empty() && load_limiter.limit() {
                let mut loaded = None;

                for &(cx, cz) in needed_chunks.iter() {
                    chunk_loader.load(cx, cz);
                    loaded = Some((cx, cz));
                    break;
                }

                match loaded {
                    Some((cx, cz)) => {
                        needed_chunks.remove(&(cx, cz));
                    },
                    None => {}
                }
            }

            let cur_time = extra::time::precise_time_ns();
            num_frames += 1;
            if (cur_time - last_frame_time) > (1000*1000*1000) {
                println!("{} frames per second", num_frames);
                num_frames = 0;
                last_frame_time = cur_time;
            }

            let frame_end_time = extra::time::precise_time_ns();
            let frame_time_ms = (frame_end_time - frame_start_time)/(1000*1000);
            if (frame_time_ms < FRAME_TIME_TARGET_MS) {
                //timer.sleep(FRAME_TIME_TARGET_MS - frame_time_ms);
            }
        }
    }
}

fn visible_chunks(x: i64, z: i64) -> ~[(i64, i64)] {
    let mask : i64 = !(CHUNK_SIZE as i64 - 1);
    let mut coords = ~[];
    for ix in std::iter::range_inclusive(-(WORLD_SIZE as i64)/2, (WORLD_SIZE as i64)/2) {
        for iz in std::iter::range_inclusive(-(WORLD_SIZE as i64)/2, (WORLD_SIZE as i64)/2) {
            let cx : i64 = (x & mask) + ix*CHUNK_SIZE as i64;
            let cz : i64 = (z & mask) + iz*CHUNK_SIZE as i64;
            coords.push((cx, cz));
        }
    }
    coords
}

fn load_graphics_resources() -> GraphicsResources {
    let vs = compile_shader(vertex_shader_src.as_bytes(), gl::VERTEX_SHADER);
    let fs = compile_shader(fragment_shader_src.as_bytes(), gl::FRAGMENT_SHADER);
    let program = link_program(vs, fs);

    let uniform_modelview = unsafe { "modelview".with_c_str(|ptr| gl::GetUniformLocation(program, ptr)) };
    let uniform_projection = unsafe { "projection".with_c_str(|ptr| gl::GetUniformLocation(program, ptr)) };

    return GraphicsResources {
        program: program,
        uniform_modelview: uniform_modelview,
        uniform_projection: uniform_projection,
    };

}

extern "C" {
    fn gluErrorString(error: GLenum) -> *GLubyte;
}

fn check_gl(message : &str) {
    let err = gl::GetError();
    if (err != gl::NO_ERROR) {
        unsafe {
            let err = std::str::raw::from_c_str(gluErrorString(err) as *i8);
            fail!("GL error {} at {}", err, message);
        }
    }
}

fn compile_shader(src: &[u8], ty: GLenum) -> GLuint {
    let shader = gl::CreateShader(ty);
    unsafe {
        // Attempt to compile the shader
        //transmute is used here because `as` causes ICE
        //wait a sec, is `src` null-terminated properly?
        gl::ShaderSource(shader, 1, std::cast::transmute(std::ptr::to_unsafe_ptr(&src.as_ptr())), ptr::null());
        gl::CompileShader(shader);

        // Get the compile status
        let mut status = gl::FALSE as GLint;
        gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);

        // Fail on error
        if status != (gl::TRUE as GLint) {
            let mut len = 0;
            gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
            let mut buf = vec::from_elem(len as uint - 1, 0u8);     // subtract 1 to skip the trailing null character
            gl::GetShaderInfoLog(shader, len, ptr::mut_null(), buf.as_mut_ptr() as *mut GLchar);
            fail!(str::raw::from_utf8(buf).to_owned());
        }
    }
    shader
}

fn link_program(vs: GLuint, fs: GLuint) -> GLuint {
    let program = gl::CreateProgram();
    gl::AttachShader(program, vs);
    gl::AttachShader(program, fs);
    gl::LinkProgram(program);
    unsafe {
        // Get the link status
        let mut status = gl::FALSE as GLint;
        gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);

        // Fail on error
        if status != (gl::TRUE as GLint) {
            let mut len: GLint = 0;
            gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
            let mut buf = vec::from_elem(len as uint - 1, 0u8);     // subtract 1 to skip the trailing null character
            gl::GetProgramInfoLog(program, len, ptr::mut_null(), buf.as_mut_ptr() as *mut GLchar);
            fail!(str::raw::from_utf8(buf).to_owned());
        }
    }
    program
}

struct ErrorContext;
impl glfw::ErrorCallback for ErrorContext {
    fn call(&self, _: glfw::Error, description: ~str) {
        fail!("GLFW Error: {:s}", description);
    }
}

struct KeyContext;
impl glfw::KeyCallback for KeyContext {
    fn call(&self, window: &glfw::Window, key: glfw::Key, _: libc::c_int, action: glfw::Action, _: glfw::Modifiers) {
        match (action, key) {
            (glfw::Press, glfw::KeyEscape) => window.set_should_close(true),
            _ => {}
        }
    }
}

struct FramebufferSizeContext {
    chan: Chan<(u32,u32)>
}
impl glfw::FramebufferSizeCallback for FramebufferSizeContext {
    fn call(&self, _: &glfw::Window, width: i32, height: i32) {
        self.chan.send((width as u32,height as u32));
    }
}
<|endoftext|>


<commit_before>use index::btree::external::ExtNode;
use index::btree::node::read_unchecked;
use index::btree::node::NodeData;
use index::btree::BPlusTree;
use index::btree::NodeCellRef;
use index::id_from_key;
use index::EntryKey;
use index::Slice;
use serde_json;
use std::fmt::Debug;
use std::fs::File;
use std::io::Write;

#[derive(Serialize, Deserialize)]
struct DebugNode {
    keys: Vec<String>,
    nodes: Vec<DebugNode>,
    id: Option<String>,
    next: Option<String>,
    prev: Option<String>,
    len: usize,
    is_external: bool,
}

pub fn dump_tree<KS, PS>(tree: &BPlusTree<KS, PS>, f: &str)
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    debug!("dumping {}", f);
    let debug_root = cascading_dump_node::<KS, PS>(&tree.get_root());
    let json = serde_json::to_string_pretty(&debug_root).unwrap();
    let mut file = File::create(f).unwrap();
    file.write_all(json.as_bytes());
}

fn cascading_dump_node<KS, PS>(node: &NodeCellRef) -> DebugNode
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    if node.is_default() {
        return DebugNode {
            keys: vec![String::from("<ERROR!!! DEFAULT NODE!!!>")],
            nodes: vec![],
            id: None,
            next: None,
            prev: None,
            len: 0,
            is_external: false,
        };
    }
    let node = read_unchecked(&*node);
    match &*node {
        &NodeData::External(ref node) => {
            let node: &ExtNode<KS, PS> = node;
            let keys = node.keys.as_slice_immute()[..node.len]
                .iter()
                .map(|key| {
                    let id = id_from_key(key);
                    format!("{}\t{:?}", id.lower, key)
                })
                .collect();
            return DebugNode {
                keys,
                nodes: vec![],
                id: Some(format!("{:?}", node.id)),
                next: Some(format!(
                    "{:?}",
                    read_unchecked::<KS, PS>(&node.next).ext_id()
                )),
                prev: Some(format!(
                    "{:?}",
                    read_unchecked::<KS, PS>(&node.prev).ext_id()
                )),
                len: node.len,
                is_external: true,
            };
        }
        &NodeData::Internal(ref innode) => {
            let len = innode.len;
            let keys = innode.keys.as_slice_immute()[..node.len()]
                .iter()
                .map(|key| format!("{:?}", key))
                .collect();
            let nodes = innode.ptrs.as_slice_immute()[..node.len() + 1]
                .iter()
                .map(|node_ref| cascading_dump_node::<KS, PS>(node_ref))
                .collect();
            return DebugNode {
                keys,
                nodes,
                id: None,
                next: Some(innode.right.to_string::<KS, PS>()),
                prev: None,
                len,
                is_external: false,
            };
        }
        &NodeData::None => {
            return DebugNode {
                keys: vec![String::from("<NOT FOUND>")],
                nodes: vec![],
                id: None,
                next: None,
                prev: None,
                len: 0,
                is_external: false,
            };
        }
        &NodeData::Empty(ref n) => {
            return DebugNode {
                keys: vec![String::from("<EMPTY>")],
                nodes: vec![],
                id: None,
                next: Some(n.right.to_string::<KS, PS>()),
                prev: None,
                len: 0,
                is_external: false,
            };
        }
    }
}
<commit_msg>dump bound<commit_after>use index::btree::external::ExtNode;
use index::btree::node::read_unchecked;
use index::btree::node::NodeData;
use index::btree::BPlusTree;
use index::btree::NodeCellRef;
use index::id_from_key;
use index::EntryKey;
use index::Slice;
use serde_json;
use std::fmt::Debug;
use std::fs::File;
use std::io::Write;

#[derive(Serialize, Deserialize)]
struct DebugNode {
    keys: Vec<String>,
    nodes: Vec<DebugNode>,
    id: Option<String>,
    next: Option<String>,
    prev: Option<String>,
    len: usize,
    is_external: bool,
    bound: String
}

pub fn dump_tree<KS, PS>(tree: &BPlusTree<KS, PS>, f: &str)
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    debug!("dumping {}", f);
    let debug_root = cascading_dump_node::<KS, PS>(&tree.get_root());
    let json = serde_json::to_string_pretty(&debug_root).unwrap();
    let mut file = File::create(f).unwrap();
    file.write_all(json.as_bytes());
}

fn cascading_dump_node<KS, PS>(node: &NodeCellRef) -> DebugNode
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    if node.is_default() {
        return DebugNode {
            keys: vec![String::from("<ERROR!!! DEFAULT NODE!!!>")],
            nodes: vec![],
            id: None,
            next: None,
            prev: None,
            len: 0,
            is_external: false,
            bound: "-".to_string()
        };
    }
    let node = read_unchecked(&*node);
    match &*node {
        &NodeData::External(ref node) => {
            let node: &ExtNode<KS, PS> = node;
            let keys = node.keys.as_slice_immute()[..node.len]
                .iter()
                .map(|key| {
                    let id = id_from_key(key);
                    format!("{}\t{:?}", id.lower, key)
                })
                .collect();
            return DebugNode {
                keys,
                nodes: vec![],
                id: Some(format!("{:?}", node.id)),
                next: Some(format!(
                    "{:?}",
                    read_unchecked::<KS, PS>(&node.next).ext_id()
                )),
                prev: Some(format!(
                    "{:?}",
                    read_unchecked::<KS, PS>(&node.prev).ext_id()
                )),
                len: node.len,
                is_external: true,
                bound: format!("{:?}", node.right_bound)
            };
        }
        &NodeData::Internal(ref innode) => {
            let len = innode.len;
            let keys = innode.keys.as_slice_immute()[..node.len()]
                .iter()
                .map(|key| format!("{:?}", key))
                .collect();
            let nodes = innode.ptrs.as_slice_immute()[..node.len() + 1]
                .iter()
                .map(|node_ref| cascading_dump_node::<KS, PS>(node_ref))
                .collect();
            return DebugNode {
                keys,
                nodes,
                id: None,
                next: Some(innode.right.to_string::<KS, PS>()),
                prev: None,
                len,
                is_external: false,
                bound: format!("{:?}", innode.right_bound)
            };
        }
        &NodeData::None => {
            return DebugNode {
                keys: vec![String::from("<NOT FOUND>")],
                nodes: vec![],
                id: None,
                next: None,
                prev: None,
                len: 0,
                is_external: false,
                bound: "-".to_string()
            };
        }
        &NodeData::Empty(ref n) => {
            return DebugNode {
                keys: vec![String::from("<EMPTY>")],
                nodes: vec![],
                id: None,
                next: Some(n.right.to_string::<KS, PS>()),
                prev: None,
                len: 0,
                is_external: false,
                bound: "-".to_string()
            };
        }
    }
}
<|endoftext|>


<commit_before>extern crate rand;
pub use self::rand::distributions;
use self::rand::distributions::IndependentSample;
use self::rand::{thread_rng, Rng};

extern crate num;
use self::num::{Num, Zero, One};
use self::num::traits::pow;

use std::fmt;
use std::cmp;
use std::ops::{Add, Sub, Mul};
use std::collections::HashSet;

use genetic::fitness::HasFitness;
use genetic::mutation::Mutation;

use genetic::helpers::{SimpleStepRange, Range};

// Individual Stuff
#[derive(Debug, Clone)]
pub struct Individual<T> {
    pub genome: Vec<T>,
}

impl<T> Individual<T>
    where T: Copy + PartialOrd
{
    pub fn new(size: usize, range: &Range<T>) -> Individual<T>
        where T: rand::Rand + rand::distributions::range::SampleRange + Add + Num
    {
        let mut genome: Vec<T> = Vec::new();
        let mut rng = rand::thread_rng();
        let rangeDist = distributions::Range::new(range.start, range.end + T::one());
        for _ in 0..size {
            let value = rangeDist.ind_sample(&mut rng);
            genome.push(value);
        }

        Individual::<T> { genome: genome }
    }

    pub fn new_ordered(size: usize) -> Individual<i32>
        where T: rand::Rand + rand::distributions::range::SampleRange + Add + Num
    {
        let mut genome: Vec<i32> = Vec::new();
        for i in 0..size {
            genome.push(i as i32);
        }
        let mut rng = rand::thread_rng();
        rng.shuffle(&mut genome);

        Individual::<i32> { genome: genome }
    }
}

// Population Stuff
pub struct Population<T>
    where T: PartialOrd
{
    pub individuals: Vec<Individual<T>>,
    pub fitnesses: Vec<f32>,
    pub best_individual_in_generation: Vec<Individual<T>>,
    pub best_fitness_in_generation: Vec<f32>,
    pub average_fitness_in_generation: Vec<f32>,
    pub diversity_in_generation: Vec<f32>,
    genome_length: usize,
    crossover_probability: f32,
    mutation_probability: f32,
    has_elitism: bool,
    range: Range<T>,

    diversity_function: fn(&Vec<T>, &Vec<T>) -> f32,
    fitness_function: fn(&Vec<T>, &Range<T>) -> f32,
    crossover_function: fn(&Vec<T>, &Vec<T>) -> (Vec<T>, Vec<T>),
    mutation_function: fn(&mut Vec<T>, f32, &Range<T>),
}

impl<T> Population<T>
    where T: Copy + PartialOrd + Num
{
    pub fn new(size: usize,
               genome_size: usize,
               crossover_probability: f32,
               mutation_probability: f32,
               range: Range<T>,
               has_elitism: bool,
               diversity_function: fn(&Vec<T>, &Vec<T>) -> f32,
               fitness_function: fn(&Vec<T>, &Range<T>) -> f32,
               crossover_function: fn(&Vec<T>, &Vec<T>) -> (Vec<T>, Vec<T>),
               mutation_function: fn(&mut Vec<T>, f32, &Range<T>))
               -> Population<T>
        where T: rand::Rand + rand::distributions::range::SampleRange
    {
        let mut individuals: Vec<Individual<T>> = Vec::new();
        let mut fitnesses: Vec<f32> = Vec::new();

        for i in 0..size {
            individuals.push(Individual::<T>::new(genome_size, &range));
            fitnesses.push(individuals[i].genome.fitness(&fitness_function, &range));
        }

        Population::<T> {
            individuals: individuals,
            fitnesses: fitnesses,
            best_individual_in_generation: Vec::<Individual<T>>::new(),
            best_fitness_in_generation: Vec::<f32>::new(),
            average_fitness_in_generation: Vec::<f32>::new(),
            diversity_in_generation: Vec::<f32>::new(),
            range: range,
            crossover_probability: crossover_probability,
            mutation_probability: mutation_probability,
            genome_length: genome_size,
            has_elitism: has_elitism,

            diversity_function: diversity_function,
            fitness_function: fitness_function,
            crossover_function: crossover_function,
            mutation_function: mutation_function,
        }
    }

    pub fn new_ordered(size: usize,
                       genome_size: usize,
                       crossover_probability: f32,
                       mutation_probability: f32,
                       range: Range<i32>,
                       has_elitism: bool,
                       diversity_function: fn(&Vec<i32>, &Vec<i32>) -> f32,
                       fitness_function: fn(&Vec<i32>, &Range<i32>) -> f32,
                       crossover_function: fn(&Vec<i32>, &Vec<i32>) -> (Vec<i32>, Vec<i32>),
                       mutation_function: fn(&mut Vec<i32>, f32, &Range<i32>))
                       -> Population<i32>
        where T: rand::Rand + rand::distributions::range::SampleRange
    {
        let mut population = Population::<i32>::new(size,
                                                    genome_size,
                                                    crossover_probability,
                                                    mutation_probability,
                                                    range,
                                                    has_elitism,
                                                    diversity_function,
                                                    fitness_function,
                                                    crossover_function,
                                                    mutation_function);

        {
            let mut individuals = &mut population.individuals;
            let mut fitnesses = &mut population.fitnesses;
            for i in 0..individuals.len() {
                individuals[i] = Individual::<i32>::new_ordered(genome_size);
                fitnesses[i] = individuals[i].genome.fitness(&fitness_function, &range);
            }
        }
        population

    }

    pub fn iterate_generation(&mut self) {
        let fittest_index = self.get_fittest_individual();
        let fittest_individual = self.individuals[fittest_index].clone();
        let fittest_fitness = self.fitnesses[fittest_index];

        let mut new_individuals = Vec::new();

        for _ in 0..self.individuals.len() {
            let fit_index = self.select_fit_individual();
            new_individuals.push(self.individuals[fit_index].clone());
        }

        for _ in SimpleStepRange(0, self.individuals.len(), 2) {
            if rand::random::<f32>() > self.crossover_probability {
                continue;
            }

            let dad_index = self.select_fit_individual();
            let mom_index = self.select_fit_individual_except(dad_index);

            //println!("dad: {}, mom: {}", dad_index, mom_index);
            let (boy_genome, girl_genome) = self.crossover(dad_index, mom_index);
            new_individuals[dad_index].genome.clone_from(&boy_genome);
            new_individuals[mom_index].genome.clone_from(&girl_genome);
        }
        self.individuals.clone_from(&new_individuals);

        for individual in &mut self.individuals {
            individual.genome.mutate(&self.mutation_function,
                                     self.mutation_probability,
                                     &self.range);
        }

        self.compute_fitnesses();
        // FIXME: Maybe getting the wrong worst individual
        if self.has_elitism {
            let (weakest_index, _) = self.get_weakest_couple();
            self.individuals[weakest_index] = fittest_individual.clone();
            self.fitnesses[weakest_index] = fittest_fitness;
        }

        // Save average and best fitness in this generation
        {
            let mut best_fitness = 0.0;
            let mut best_individual = self.individuals[0].clone();
            let mut sum_fitnesses = 0.0;
            for i in 0..self.fitnesses.len() {
                sum_fitnesses += self.fitnesses[i];
                if self.fitnesses[i] > best_fitness {
                    best_fitness = self.fitnesses[i];
                    best_individual = self.individuals[i].clone();
                }
            }
            let avg_fitness = sum_fitnesses / (self.fitnesses.len() as f32);

            self.average_fitness_in_generation.push(avg_fitness);
            self.best_individual_in_generation.push(best_individual);
            self.best_fitness_in_generation.push(best_fitness);
            let diversity = self.calculate_diversity();
            self.diversity_in_generation.push(diversity);
        }

    }

    fn select_fit_individual(&self) -> usize {
        self.tournament(2)
    }

        fn select_fit_individual_except(&self, dad_index: usize) -> usize {
            let mut mom_index: usize;

            loop {
                mom_index = self.roulette();

                if mom_index != dad_index {
                    break;
                }
            }
            mom_index
        }

        fn get_fittest_individual(&self) -> usize {
            let mut fittest_index = 0;

            for i in 1..self.individuals.len() {
                if self.fitnesses[i] > self.fitnesses[fittest_index] {
                    fittest_index = i;
                }
            }
            fittest_index
        }

        fn get_weakest_couple(&self) -> (usize, usize) {
        let mut weakest_index = 0;
        let mut second_weakest_index = 0;

        for i in 1..self.individuals.len() {
            if self.fitnesses[i] < self.fitnesses[weakest_index] {
                second_weakest_index = weakest_index;
                weakest_index = i;
            }
        }
        (weakest_index, second_weakest_index)
    }

    fn compute_fitnesses(&mut self) {
        for i in 0..self.individuals.len() {
            self.fitnesses[i] = self.individuals[i].genome.fitness(&self.fitness_function,
                                                                   &self.range);
        }
    }

    fn crossover(&mut self, index_dad: usize, index_mom: usize) -> (Vec<T>, Vec<T>) {
        let max_index = cmp::max(index_dad, index_mom);
        let min_index = cmp::min(index_dad, index_mom);

        let (split_left, split_right) = self.individuals.split_at_mut(max_index);
        let (dad, mom) = (&mut split_left[min_index], &mut split_right[0]);

        let (boy_genome, girl_genome) = (self.crossover_function)(&dad.genome, &mom.genome);

        (boy_genome, girl_genome)
    }

    fn tournament(&self, k: usize) -> usize {
        let rangeDist = distributions::Range::new(0, self.individuals.len());

        let mut biggest: usize = 0;
        let mut processed_candidates = HashSet::<usize>::new();
        let mut rng = rand::thread_rng();

        while processed_candidates.len() < k {
            let picked = rangeDist.ind_sample(&mut rng);

            if processed_candidates.contains(&picked) {
                continue;
            }

            processed_candidates.insert(picked);

            if self.fitnesses[picked] > self.fitnesses[biggest] {
                biggest = picked;
            }
        }

        biggest
    }

    fn calculate_diversity(&self) -> f32 {
        let mut total_diversity = 0.0;

        for i in 0..self.individuals.len() {
            for j in i..self.individuals.len() {
                total_diversity += (self.diversity_function)(&self.individuals[i].genome,
                                                             &self.individuals[j].genome);
            }
        }

        total_diversity
    }

    fn roulette(&self) -> usize {
        let chance = rand::random::<f32>();
        let sum = self.fitnesses.iter().fold(0.0, |acc, &x| acc + x);

        let mut winner: usize = 0;
        let mut last_probability = 0.0;
        for i in 0..self.fitnesses.len() {
            let fitness = self.fitnesses[i];
            let probability = fitness / sum + last_probability;

            if chance < probability {
                winner = i;
                break;
            }

            last_probability = probability;
        }
        winner
    }

    pub fn print(&self)
        where T: fmt::Debug
    {
        for i in 0..self.individuals.len() {
            let individual = &self.individuals[i];
            let fitness = self.fitnesses[i];
            println!("{:?} : {}", individual.genome, fitness);
            // println!("Best vector: {:?}", population.best_fitness_in_generation);
            // println!("Average vector: {:?}", population.average_fitness_in_generation);
            // if let Some(best_fitness) = population.best_fitness_in_generation.last() {
            //     println!("The Best: {}", best_fitness);
            // }
        }

    }

    pub fn print_best_individual_diagnostic(&self)
        where T: fmt::Debug
    {
        if let Some(best_individual) = self.best_individual_in_generation.last() {
            if let Some(best_fitness) = self.best_fitness_in_generation.last() {
                println!("Best genome: {:?} : {}", best_individual.genome, best_fitness);
            }

            let mut is_valid = true;

            for gene in &best_individual.genome {
                if *gene > self.range.end || *gene < self.range.start {
                    is_valid = false;
                }
            }

            if is_valid == false {
                println!("***Invalid best individual***");
            }

        }

        //println!("Diversity test! {}", self.compute_diversity());
    }
}

<commit_msg>Tweaked parameters<commit_after>extern crate rand;
pub use self::rand::distributions;
use self::rand::distributions::IndependentSample;
use self::rand::{thread_rng, Rng};

extern crate num;
use self::num::{Num, Zero, One};
use self::num::traits::pow;

use std::fmt;
use std::cmp;
use std::ops::{Add, Sub, Mul};
use std::collections::HashSet;

use genetic::fitness::HasFitness;
use genetic::mutation::Mutation;

use genetic::helpers::{SimpleStepRange, Range};

// Individual Stuff
#[derive(Debug, Clone)]
pub struct Individual<T> {
    pub genome: Vec<T>,
}

impl<T> Individual<T>
    where T: Copy + PartialOrd
{
    pub fn new(size: usize, range: &Range<T>) -> Individual<T>
        where T: rand::Rand + rand::distributions::range::SampleRange + Add + Num
    {
        let mut genome: Vec<T> = Vec::new();
        let mut rng = rand::thread_rng();
        let rangeDist = distributions::Range::new(range.start, range.end + T::one());
        for _ in 0..size {
            let value = rangeDist.ind_sample(&mut rng);
            genome.push(value);
        }

        Individual::<T> { genome: genome }
    }

    pub fn new_ordered(size: usize) -> Individual<i32>
        where T: rand::Rand + rand::distributions::range::SampleRange + Add + Num
    {
        let mut genome: Vec<i32> = Vec::new();
        for i in 0..size {
            genome.push(i as i32);
        }
        let mut rng = rand::thread_rng();
        rng.shuffle(&mut genome);

        Individual::<i32> { genome: genome }
    }
}

// Population Stuff
pub struct Population<T>
    where T: PartialOrd
{
    pub individuals: Vec<Individual<T>>,
    pub fitnesses: Vec<f32>,
    pub best_individual_in_generation: Vec<Individual<T>>,
    pub best_fitness_in_generation: Vec<f32>,
    pub average_fitness_in_generation: Vec<f32>,
    pub diversity_in_generation: Vec<f32>,
    genome_length: usize,
    crossover_probability: f32,
    mutation_probability: f32,
    has_elitism: bool,
    range: Range<T>,

    diversity_function: fn(&Vec<T>, &Vec<T>) -> f32,
    fitness_function: fn(&Vec<T>, &Range<T>) -> f32,
    crossover_function: fn(&Vec<T>, &Vec<T>) -> (Vec<T>, Vec<T>),
    mutation_function: fn(&mut Vec<T>, f32, &Range<T>),
}

impl<T> Population<T>
    where T: Copy + PartialOrd + Num
{
    pub fn new(size: usize,
               genome_size: usize,
               crossover_probability: f32,
               mutation_probability: f32,
               range: Range<T>,
               has_elitism: bool,
               diversity_function: fn(&Vec<T>, &Vec<T>) -> f32,
               fitness_function: fn(&Vec<T>, &Range<T>) -> f32,
               crossover_function: fn(&Vec<T>, &Vec<T>) -> (Vec<T>, Vec<T>),
               mutation_function: fn(&mut Vec<T>, f32, &Range<T>))
               -> Population<T>
        where T: rand::Rand + rand::distributions::range::SampleRange
    {
        let mut individuals: Vec<Individual<T>> = Vec::new();
        let mut fitnesses: Vec<f32> = Vec::new();

        for i in 0..size {
            individuals.push(Individual::<T>::new(genome_size, &range));
            fitnesses.push(individuals[i].genome.fitness(&fitness_function, &range));
        }

        Population::<T> {
            individuals: individuals,
            fitnesses: fitnesses,
            best_individual_in_generation: Vec::<Individual<T>>::new(),
            best_fitness_in_generation: Vec::<f32>::new(),
            average_fitness_in_generation: Vec::<f32>::new(),
            diversity_in_generation: Vec::<f32>::new(),
            range: range,
            crossover_probability: crossover_probability,
            mutation_probability: mutation_probability,
            genome_length: genome_size,
            has_elitism: has_elitism,

            diversity_function: diversity_function,
            fitness_function: fitness_function,
            crossover_function: crossover_function,
            mutation_function: mutation_function,
        }
    }

    pub fn new_ordered(size: usize,
                       genome_size: usize,
                       crossover_probability: f32,
                       mutation_probability: f32,
                       range: Range<i32>,
                       has_elitism: bool,
                       diversity_function: fn(&Vec<i32>, &Vec<i32>) -> f32,
                       fitness_function: fn(&Vec<i32>, &Range<i32>) -> f32,
                       crossover_function: fn(&Vec<i32>, &Vec<i32>) -> (Vec<i32>, Vec<i32>),
                       mutation_function: fn(&mut Vec<i32>, f32, &Range<i32>))
                       -> Population<i32>
        where T: rand::Rand + rand::distributions::range::SampleRange
    {
        let mut population = Population::<i32>::new(size,
                                                    genome_size,
                                                    crossover_probability,
                                                    mutation_probability,
                                                    range,
                                                    has_elitism,
                                                    diversity_function,
                                                    fitness_function,
                                                    crossover_function,
                                                    mutation_function);

        {
            let mut individuals = &mut population.individuals;
            let mut fitnesses = &mut population.fitnesses;
            for i in 0..individuals.len() {
                individuals[i] = Individual::<i32>::new_ordered(genome_size);
                fitnesses[i] = individuals[i].genome.fitness(&fitness_function, &range);
            }
        }
        population

    }

    pub fn iterate_generation(&mut self) {
        let fittest_index = self.get_fittest_individual();
        let fittest_individual = self.individuals[fittest_index].clone();
        let fittest_fitness = self.fitnesses[fittest_index];

        let mut new_individuals = Vec::new();

        for _ in 0..self.individuals.len() {
            let fit_index = self.select_fit_individual();
            new_individuals.push(self.individuals[fit_index].clone());
        }

        for _ in SimpleStepRange(0, self.individuals.len(), 2) {
            if rand::random::<f32>() > self.crossover_probability {
                continue;
            }

            let dad_index = self.select_fit_individual();
            let mom_index = self.select_fit_individual_except(dad_index);

            //println!("dad: {}, mom: {}", dad_index, mom_index);
            let (boy_genome, girl_genome) = self.crossover(dad_index, mom_index);
            new_individuals[dad_index].genome.clone_from(&boy_genome);
            new_individuals[mom_index].genome.clone_from(&girl_genome);
        }
        self.individuals.clone_from(&new_individuals);

        for individual in &mut self.individuals {
            individual.genome.mutate(&self.mutation_function,
                                     self.mutation_probability,
                                     &self.range);
        }

        self.compute_fitnesses();
        // FIXME: Maybe getting the wrong worst individual
        if self.has_elitism {
            let (weakest_index, _) = self.get_weakest_couple();
            self.individuals[weakest_index] = fittest_individual.clone();
            self.fitnesses[weakest_index] = fittest_fitness;
        }

        // Save average and best fitness in this generation
        {
            let mut best_fitness = 0.0;
            let mut best_individual = self.individuals[0].clone();
            let mut sum_fitnesses = 0.0;
            for i in 0..self.fitnesses.len() {
                sum_fitnesses += self.fitnesses[i];
                if self.fitnesses[i] > best_fitness {
                    best_fitness = self.fitnesses[i];
                    best_individual = self.individuals[i].clone();
                }
            }
            let avg_fitness = sum_fitnesses / (self.fitnesses.len() as f32);

            self.average_fitness_in_generation.push(avg_fitness);
            self.best_individual_in_generation.push(best_individual);
            self.best_fitness_in_generation.push(best_fitness);
            let diversity = self.calculate_diversity();
            self.diversity_in_generation.push(diversity);
        }

    }

    fn select_fit_individual(&self) -> usize {
        self.roulette()
    }

    fn select_fit_individual_except(&self, dad_index: usize) -> usize {
        let mut mom_index: usize;

        loop {
            mom_index = self.roulette();

            if mom_index != dad_index {
                break;
            }
        }
        mom_index
    }

    fn get_fittest_individual(&self) -> usize {
        let mut fittest_index = 0;

        for i in 1..self.individuals.len() {
            if self.fitnesses[i] > self.fitnesses[fittest_index] {
                fittest_index = i;
            }
        }
        fittest_index
    }

    fn get_weakest_couple(&self) -> (usize, usize) {
        let mut weakest_index = 0;
        let mut second_weakest_index = 0;

        for i in 1..self.individuals.len() {
            if self.fitnesses[i] < self.fitnesses[weakest_index] {
                second_weakest_index = weakest_index;
                weakest_index = i;
            }
        }
        (weakest_index, second_weakest_index)
    }

    fn compute_fitnesses(&mut self) {
        for i in 0..self.individuals.len() {
            self.fitnesses[i] = self.individuals[i].genome.fitness(&self.fitness_function,
                                                                   &self.range);
        }
    }

    fn crossover(&mut self, index_dad: usize, index_mom: usize) -> (Vec<T>, Vec<T>) {
        let max_index = cmp::max(index_dad, index_mom);
        let min_index = cmp::min(index_dad, index_mom);

        let (split_left, split_right) = self.individuals.split_at_mut(max_index);
        let (dad, mom) = (&mut split_left[min_index], &mut split_right[0]);

        let (boy_genome, girl_genome) = (self.crossover_function)(&dad.genome, &mom.genome);

        (boy_genome, girl_genome)
    }

    fn tournament(&self, k: usize) -> usize {
        let rangeDist = distributions::Range::new(0, self.individuals.len());

        let mut biggest: usize = 0;
        let mut processed_candidates = HashSet::<usize>::new();
        let mut rng = rand::thread_rng();

        while processed_candidates.len() < k {
            let picked = rangeDist.ind_sample(&mut rng);

            if processed_candidates.contains(&picked) {
                continue;
            }

            processed_candidates.insert(picked);

            if self.fitnesses[picked] > self.fitnesses[biggest] {
                biggest = picked;
            }
        }

        biggest
    }

    fn calculate_diversity(&self) -> f32 {
        let mut total_diversity = 0.0;

        for i in 0..self.individuals.len() {
            for j in i..self.individuals.len() {
                total_diversity += (self.diversity_function)(&self.individuals[i].genome,
                                                             &self.individuals[j].genome);
            }
        }

        total_diversity
    }

    fn roulette(&self) -> usize {
        let chance = rand::random::<f32>();
        let sum = self.fitnesses.iter().fold(0.0, |acc, &x| acc + x);

        let mut winner: usize = 0;
        let mut last_probability = 0.0;
        for i in 0..self.fitnesses.len() {
            let fitness = self.fitnesses[i];
            let probability = fitness / sum + last_probability;

            if chance < probability {
                winner = i;
                break;
            }

            last_probability = probability;
        }
        winner
    }

    pub fn print(&self)
        where T: fmt::Debug
    {
        for i in 0..self.individuals.len() {
            let individual = &self.individuals[i];
            let fitness = self.fitnesses[i];
            println!("{:?} : {}", individual.genome, fitness);
            // println!("Best vector: {:?}", population.best_fitness_in_generation);
            // println!("Average vector: {:?}", population.average_fitness_in_generation);
            // if let Some(best_fitness) = population.best_fitness_in_generation.last() {
            //     println!("The Best: {}", best_fitness);
            // }
        }

    }

    pub fn print_best_individual_diagnostic(&self)
        where T: fmt::Debug
    {
        if let Some(best_individual) = self.best_individual_in_generation.last() {
            if let Some(best_fitness) = self.best_fitness_in_generation.last() {
                println!("Best genome: {:?} : {}", best_individual.genome, best_fitness);
            }

            let mut is_valid = true;

            for gene in &best_individual.genome {
                if *gene > self.range.end || *gene < self.range.start {
                    is_valid = false;
                }
            }

            if is_valid == false {
                println!("***Invalid best individual***");
            }

        }

        //println!("Diversity test! {}", self.compute_diversity());
    }
}

<|endoftext|>


<commit_before>use crate::context::Context;
#[cfg(not(feature = "no_logging"))]
use crate::error::RenderError;
use crate::helpers::{HelperDef, HelperResult};
use crate::output::Output;
use crate::registry::Registry;
use crate::render::{Helper, RenderContext};
#[cfg(not(feature = "no_logging"))]
use crate::value::JsonRender;
#[cfg(not(feature = "no_logging"))]
use log::Level;
#[cfg(not(feature = "no_logging"))]
use std::str::FromStr;

#[derive(Clone, Copy)]
pub struct LogHelper;

#[cfg(not(feature = "no_logging"))]
impl HelperDef for LogHelper {
    fn call<'reg: 'rc, 'rc>(
        &self,
        h: &Helper<'reg, 'rc>,
        _: &'reg Registry,
        _: &'rc Context,
        _: &mut RenderContext<'reg>,
        _: &mut dyn Output,
    ) -> HelperResult {
        let param = h
            .param(0)
            .ok_or_else(|| RenderError::new("Param not found for helper \"log\""))?;
        let level = h
            .hash_get("level")
            .and_then(|v| v.value().as_str())
            .unwrap_or("info");

        if let Ok(log_level) = Level::from_str(level) {
            log!(
                log_level,
                "{}: {}",
                param.path().unwrap_or(&"".to_owned()),
                param.value().render()
            )
        } else {
            return Err(RenderError::new(&format!(
                "Unsupported logging level {}",
                level
            )));
        }
        Ok(())
    }
}

#[cfg(feature = "no_logging")]
impl HelperDef for LogHelper {
    fn call<'reg: 'rc, 'rc>(
        &self,
        _: &Helper,
        _: &Registry,
        _: &Context,
        _: &mut RenderContext,
        _: &mut Output,
    ) -> HelperResult {
        Ok(())
    }
}

pub static LOG_HELPER: LogHelper = LogHelper;
<commit_msg>(fix) dyn trait warnings in test<commit_after>use crate::context::Context;
#[cfg(not(feature = "no_logging"))]
use crate::error::RenderError;
use crate::helpers::{HelperDef, HelperResult};
use crate::output::Output;
use crate::registry::Registry;
use crate::render::{Helper, RenderContext};
#[cfg(not(feature = "no_logging"))]
use crate::value::JsonRender;
#[cfg(not(feature = "no_logging"))]
use log::Level;
#[cfg(not(feature = "no_logging"))]
use std::str::FromStr;

#[derive(Clone, Copy)]
pub struct LogHelper;

#[cfg(not(feature = "no_logging"))]
impl HelperDef for LogHelper {
    fn call<'reg: 'rc, 'rc>(
        &self,
        h: &Helper<'reg, 'rc>,
        _: &'reg Registry,
        _: &'rc Context,
        _: &mut RenderContext<'reg>,
        _: &mut dyn Output,
    ) -> HelperResult {
        let param = h
            .param(0)
            .ok_or_else(|| RenderError::new("Param not found for helper \"log\""))?;
        let level = h
            .hash_get("level")
            .and_then(|v| v.value().as_str())
            .unwrap_or("info");

        if let Ok(log_level) = Level::from_str(level) {
            log!(
                log_level,
                "{}: {}",
                param.path().unwrap_or(&"".to_owned()),
                param.value().render()
            )
        } else {
            return Err(RenderError::new(&format!(
                "Unsupported logging level {}",
                level
            )));
        }
        Ok(())
    }
}

#[cfg(feature = "no_logging")]
impl HelperDef for LogHelper {
    fn call<'reg: 'rc, 'rc>(
        &self,
        _: &Helper,
        _: &Registry,
        _: &Context,
        _: &mut RenderContext,
        _: &mut dyn Output,
    ) -> HelperResult {
        Ok(())
    }
}

pub static LOG_HELPER: LogHelper = LogHelper;
<|endoftext|>


<commit_before>use std::cmp::Ordering;
use std::hash::{Hash, Hasher};
use uuid::Uuid;

pub trait JsTrait {}

pub struct JsT {
    uid: Uuid,
    t: Box<JsTrait>,
}

impl JsT {
    pub fn new(t: Box<JsTrait>) -> JsT {
        JsT {
            uid: Uuid::new_v4(),
            t: t,
        }
    }
}

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

    fn ne(&self, other: &Self) -> bool {
        !self.eq(other)
    }
}

impl Eq for JsT {}

impl Hash for JsT {
    fn hash<H>(&self, state: &mut H) where H: Hasher {
        self.uid.hash(state);
    }

    fn hash_slice<H>(data: &[Self], state: &mut H) where H: Hasher {
        for ref d in data {
            d.uid.hash(state);
        }
    }
}

<commit_msg>Create new enum of all standard JS types<commit_after>use std::string::String;
use js_types::js_obj::JsObjStruct;
use js_types::js_str::JsStrStruct;
use std::cmp::Ordering;
use std::hash::{Hash, Hasher};
use uuid::Uuid;

pub struct JsT {
    pub uuid: Uuid,
    pub t: JsType,
}

impl JsT {
    pub fn new(t: JsType) -> JsT {
        JsT {
            uuid: Uuid::new_v4(),
            t: t,
        }
    }
}

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

    fn ne(&self, other: &Self) -> bool {
        !self.eq(other)
    }
}

impl Eq for JsT {}

impl Hash for JsT {
    fn hash<H>(&self, state: &mut H) where H: Hasher {
        self.uuid.hash(state);
    }

    fn hash_slice<H>(data: &[Self], state: &mut H) where H: Hasher {
        for ref d in data {
            d.uuid.hash(state);
        }
    }
}

pub enum JsType {
    JsUndef,
    JsNull,
    JsNum(f64),
    JsSym(String),
    JsStr(JsStrStruct),
    JsObj(JsObjStruct),
}

// `array`
pub type JsArr = Vec<JsType>;
<|endoftext|>


<commit_before>#[no_mangle]
pub unsafe extern "C" fn memset(ptr: *mut u8, val: i32, num: usize) -> *mut u8 {
    let mut i = 0;

    while i < num {
        *ptr.offset(i as isize) = val as u8;

        i += 1;
    }

    ptr
}

#[no_mangle]
pub unsafe extern fn memcpy(dest: *mut u8, src: *const u8,
                            n: usize) -> *mut u8 {
    let mut i = 0;

    while i < n {
        *dest.offset(i as isize) = *src.offset(i as isize);
        i += 1;
    }

    dest
}

#[no_mangle]
pub unsafe extern fn memmove(dest: *mut u8, src: *const u8,
                             n: usize) -> *mut u8 {
    if dest as *const u8 <= src {
        return memcpy(dest, src, n);
    }

    let mut i = n;
    while i != 0 {
        i -= 1;
        *dest.offset(i as isize) = *src.offset(i as isize);
    }

    dest
}
<commit_msg>libboot: Update memmove implementation<commit_after>#[no_mangle]
pub unsafe extern "C" fn memset(ptr: *mut u8, val: i32, num: usize) -> *mut u8 {
    let mut i = 0;

    while i < num {
        *ptr.offset(i as isize) = val as u8;

        i += 1;
    }

    ptr
}

#[no_mangle]
pub unsafe extern fn memcpy(dest: *mut u8, src: *const u8,
                            n: usize) -> *mut u8 {
    let mut i = 0;

    while i < n {
        *dest.offset(i as isize) = *src.offset(i as isize);
        i += 1;
    }

    dest
}

#[no_mangle]
pub unsafe extern fn memmove(dest: *mut u8, src: *const u8,
                             mut n: usize) -> *mut u8 {
    if dest as *const u8 <= src {
        return memcpy(dest, src, n);
    }

    while n != 0 {
        n -= 1;
        *dest.offset(n as isize) = *src.offset(n as isize);
    }

    dest
}
<|endoftext|>