<commit_before>use std::collections::HashMap;
use std::io;
use std::fs::File;

//use test::Bencher;

use blob::Blob;
use error::Error;
use value::Value;

#[test]
fn nbt_nonempty() {
    let mut nbt = Blob::new();
    nbt.insert("name", "Herobrine").unwrap();
    nbt.insert("health", 100i8).unwrap();
    nbt.insert("food", 20.0f32).unwrap();
    nbt.insert("emeralds", 12345i16).unwrap();
    nbt.insert("timestamp", 1424778774i32).unwrap();

    let bytes = vec![
        0x0a,
            0x00, 0x00,
            0x08,
                0x00, 0x04,
                0x6e, 0x61, 0x6d, 0x65,
                0x00, 0x09,
                0x48, 0x65, 0x72, 0x6f, 0x62, 0x72, 0x69, 0x6e, 0x65,
            0x01,
                0x00, 0x06,
                0x68, 0x65, 0x61, 0x6c, 0x74, 0x68,
                0x64,
            0x05,
                0x00, 0x04,
                0x66, 0x6f, 0x6f, 0x64,
                0x41, 0xa0, 0x00, 0x00,
            0x02,
                0x00, 0x08,
                0x65, 0x6d, 0x65, 0x72, 0x61, 0x6c, 0x64, 0x73,
                0x30, 0x39,
            0x03,
                0x00, 0x09,
                0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
                0x54, 0xec, 0x66, 0x16,
        0x00
    ];

    // Test correct length.
    let mut dst = Vec::new();
    nbt.to_writer(&mut dst).unwrap();
    assert_eq!(bytes.len(), dst.len());

    // We can only test if the decoded bytes match, since the HashMap does
    // not guarantee order (and so encoding is likely to be different, but
    // still correct).
    let mut src = io::Cursor::new(bytes);
    let file = Blob::from_reader(&mut src).unwrap();
    assert_eq!(&file, &nbt);
}

#[test]
fn nbt_empty_nbtfile() {
    let nbt = Blob::new();

    let bytes = vec![
        0x0a,
            0x00, 0x00,
        0x00
    ];

    // Test encoding.
    let mut dst = Vec::new();
    nbt.to_writer(&mut dst).unwrap();
    assert_eq!(&dst, &bytes);

    // Test decoding.
    let mut src = io::Cursor::new(bytes);
    let file = Blob::from_reader(&mut src).unwrap();
    assert_eq!(&file, &nbt);
}

#[test]
fn nbt_nested_compound() {
    let mut inner = HashMap::new();
    inner.insert("test".to_string(), Value::Byte(123));
    let mut nbt = Blob::new();
    nbt.insert("inner", Value::Compound(inner)).unwrap();

    let bytes = vec![
        0x0a,
            0x00, 0x00,
            0x0a,
                0x00, 0x05,
                0x69, 0x6e, 0x6e, 0x65, 0x72,
                0x01,
                0x00, 0x04,
                0x74, 0x65, 0x73, 0x74,
                0x7b,
            0x00,
        0x00
    ];

    // Test encoding.
    let mut dst = Vec::new();
    nbt.to_writer(&mut dst).unwrap();
    assert_eq!(&dst, &bytes);

    // Test decoding.
    let mut src = io::Cursor::new(bytes);
    let file = Blob::from_reader(&mut src).unwrap();
    assert_eq!(&file, &nbt);
}

#[test]
fn nbt_empty_list() {
    let mut nbt = Blob::new();
    nbt.insert("list", Value::List(Vec::new())).unwrap();

    let bytes = vec![
        0x0a,
            0x00, 0x00,
            0x09,
                0x00, 0x04,
                0x6c, 0x69, 0x73, 0x74,
                0x01,
                0x00, 0x00, 0x00, 0x00,
        0x00
    ];

    // Test encoding.
    let mut dst = Vec::new();
    nbt.to_writer(&mut dst).unwrap();
    assert_eq!(&dst, &bytes);

    // Test decoding.
    let mut src = io::Cursor::new(bytes);
    let file = Blob::from_reader(&mut src).unwrap();
    assert_eq!(&file, &nbt);
}

#[test]
fn nbt_no_root() {
    let bytes = vec![0x00];
    // Will fail, because the root is not a compound.
    assert_eq!(Blob::from_reader(&mut io::Cursor::new(&bytes[..])),
            Err(Error::NoRootCompound));
}

#[test]
fn nbt_no_end_tag() {
    let bytes = vec![
        0x0a,
            0x00, 0x00,
            0x09,
                0x00, 0x04,
                0x6c, 0x69, 0x73, 0x74,
                0x01,
                0x00, 0x00, 0x00, 0x00
    ];

    // Will fail, because there is no end tag.
    assert_eq!(Blob::from_reader(&mut io::Cursor::new(&bytes[..])),
            Err(Error::IncompleteNbtValue));
}

#[test]
fn nbt_invalid_id() {
    let bytes = vec![
        0x0a,
            0x00, 0x00,
            0x0f, // No tag associated with 0x0f.
                0x00, 0x04,
                0x6c, 0x69, 0x73, 0x74,
                0x01,
        0x00
    ];
    assert_eq!(Blob::from_reader(&mut io::Cursor::new(&bytes[..])),
               Err(Error::InvalidTypeId(15)));
}

#[test]
fn nbt_invalid_list() {
    let mut nbt = Blob::new();
    let mut badlist = Vec::new();
    badlist.push(Value::Byte(1));
    badlist.push(Value::Short(1));
    // Will fail to insert, because the List is heterogeneous.
    assert_eq!(nbt.insert("list", Value::List(badlist)),
               Err(Error::HeterogeneousList));
}

#[test]
fn nbt_bad_compression() {
    // These aren't in the zlib or gzip format, so they'll fail.
    let bytes = vec![0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
    assert!(Blob::from_gzip_reader(&mut io::Cursor::new(&bytes[..])).is_err());
    assert!(Blob::from_zlib_reader(&mut io::Cursor::new(&bytes[..])).is_err());
}

#[test]
fn nbt_compression() {
    // Create a non-trivial Blob.
    let mut nbt = Blob::new();
    nbt.insert("name", Value::String("Herobrine".to_string())).unwrap();
    nbt.insert("health", Value::Byte(100)).unwrap();
    nbt.insert("food", Value::Float(20.0)).unwrap();
    nbt.insert("emeralds", Value::Short(12345)).unwrap();
    nbt.insert("timestamp", Value::Int(1424778774)).unwrap();

    // Test zlib encoding/decoding.
    let mut zlib_dst = Vec::new();
    nbt.to_zlib_writer(&mut zlib_dst).unwrap();
    let zlib_file = Blob::from_zlib_reader(&mut io::Cursor::new(zlib_dst)).unwrap();
    assert_eq!(&nbt, &zlib_file);

    // Test gzip encoding/decoding.
    let mut gzip_dst = Vec::new();
    nbt.to_gzip_writer(&mut gzip_dst).unwrap();
    let gz_file = Blob::from_gzip_reader(&mut io::Cursor::new(gzip_dst)).unwrap();
    assert_eq!(&nbt, &gz_file);
}

#[test]
fn nbt_bigtest() {
    let mut bigtest_file = File::open("tests/big1.nbt").unwrap();
    let bigtest = Blob::from_gzip_reader(&mut bigtest_file).unwrap();
    // This is a pretty indirect way of testing correctness.
    let mut dst = Vec::new();
    bigtest.to_writer(&mut dst).unwrap();
    assert_eq!(1544, dst.len());
}

#[test]
fn nbt_arrays() {
    let mut arrays_file = File::open("tests/arrays.nbt").unwrap();
    let arrays = Blob::from_reader(&mut arrays_file).unwrap();
    match &arrays["ia"] {
        &Value::IntArray(ref arr) => assert_eq!(&[-2, -1, 0, 1, 2], &**arr),
        _ => panic!("ia was not TAG_IntArray"),
    }

    match &arrays["ba"] {
        &Value::ByteArray(ref arr) => assert_eq!(&[-2, -1, 0, 1, 2], &**arr),
        _ => panic!("ba was not TAG_ByteArray"),
    }

    match &arrays["la"] {
        &Value::LongArray(ref arr) => assert_eq!(&[-2, -1, 0, 1, 2], &**arr),
        _ => panic!("la was not TAG_LongArray"),
    }
}

//#[bench]
//fn nbt_bench_bigwrite(b: &mut Bencher) {
//    let mut file = File::open("tests/big1.nbt").unwrap();
//    let nbt = Blob::from_gzip(&mut file).unwrap();
//    b.iter(|| {
//        nbt.write(&mut io::sink())
//    });
//}

//#[bench]
//fn nbt_bench_smallwrite(b: &mut Bencher) {
//    let mut file = File::open("tests/small4.nbt").unwrap();
//    let nbt = Blob::from_reader(&mut file).unwrap();
//    b.iter(|| {
//        nbt.write(&mut io::sink())
//    });
//}

#[test]
#[cfg(feature = "serde")]
fn serde_blob() {
    use de::from_reader;
    use ser::to_writer;

    let mut nbt = Blob::new();
    nbt.insert("name", "Herobrine").unwrap();
    nbt.insert("health", 100i8).unwrap();
    nbt.insert("food", 20.0f32).unwrap();
    nbt.insert("emeralds", 12345i16).unwrap();
    nbt.insert("timestamp", 1424778774i32).unwrap();

    let bytes = vec![
        0x0a,
            0x00, 0x00,
            0x08,
                0x00, 0x04,
                0x6e, 0x61, 0x6d, 0x65,
                0x00, 0x09,
                0x48, 0x65, 0x72, 0x6f, 0x62, 0x72, 0x69, 0x6e, 0x65,
            0x01,
                0x00, 0x06,
                0x68, 0x65, 0x61, 0x6c, 0x74, 0x68,
                0x64,
            0x05,
                0x00, 0x04,
                0x66, 0x6f, 0x6f, 0x64,
                0x41, 0xa0, 0x00, 0x00,
            0x02,
                0x00, 0x08,
                0x65, 0x6d, 0x65, 0x72, 0x61, 0x6c, 0x64, 0x73,
                0x30, 0x39,
            0x03,
                0x00, 0x09,
                0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
                0x54, 0xec, 0x66, 0x16,
        0x00
    ];

    // Roundtrip.

    let mut src = io::Cursor::new(bytes.clone());
    let file: Blob = from_reader(&mut src).unwrap();
    assert_eq!(&file, &nbt);
    let mut dst = Vec::new();
    to_writer(&mut dst, &nbt, None).unwrap();
    // We can only test if the decoded bytes match, since the HashMap does
    // not guarantee order (and so encoding is likely to be different, but
    // still correct).
    assert_eq!(&bytes.len(), &dst.len());
}
<commit_msg>Removes the dead benchmarking code.<commit_after>use std::collections::HashMap;
use std::io;
use std::fs::File;

//use test::Bencher;

use blob::Blob;
use error::Error;
use value::Value;

#[test]
fn nbt_nonempty() {
    let mut nbt = Blob::new();
    nbt.insert("name", "Herobrine").unwrap();
    nbt.insert("health", 100i8).unwrap();
    nbt.insert("food", 20.0f32).unwrap();
    nbt.insert("emeralds", 12345i16).unwrap();
    nbt.insert("timestamp", 1424778774i32).unwrap();

    let bytes = vec![
        0x0a,
            0x00, 0x00,
            0x08,
                0x00, 0x04,
                0x6e, 0x61, 0x6d, 0x65,
                0x00, 0x09,
                0x48, 0x65, 0x72, 0x6f, 0x62, 0x72, 0x69, 0x6e, 0x65,
            0x01,
                0x00, 0x06,
                0x68, 0x65, 0x61, 0x6c, 0x74, 0x68,
                0x64,
            0x05,
                0x00, 0x04,
                0x66, 0x6f, 0x6f, 0x64,
                0x41, 0xa0, 0x00, 0x00,
            0x02,
                0x00, 0x08,
                0x65, 0x6d, 0x65, 0x72, 0x61, 0x6c, 0x64, 0x73,
                0x30, 0x39,
            0x03,
                0x00, 0x09,
                0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
                0x54, 0xec, 0x66, 0x16,
        0x00
    ];

    // Test correct length.
    let mut dst = Vec::new();
    nbt.to_writer(&mut dst).unwrap();
    assert_eq!(bytes.len(), dst.len());

    // We can only test if the decoded bytes match, since the HashMap does
    // not guarantee order (and so encoding is likely to be different, but
    // still correct).
    let mut src = io::Cursor::new(bytes);
    let file = Blob::from_reader(&mut src).unwrap();
    assert_eq!(&file, &nbt);
}

#[test]
fn nbt_empty_nbtfile() {
    let nbt = Blob::new();

    let bytes = vec![
        0x0a,
            0x00, 0x00,
        0x00
    ];

    // Test encoding.
    let mut dst = Vec::new();
    nbt.to_writer(&mut dst).unwrap();
    assert_eq!(&dst, &bytes);

    // Test decoding.
    let mut src = io::Cursor::new(bytes);
    let file = Blob::from_reader(&mut src).unwrap();
    assert_eq!(&file, &nbt);
}

#[test]
fn nbt_nested_compound() {
    let mut inner = HashMap::new();
    inner.insert("test".to_string(), Value::Byte(123));
    let mut nbt = Blob::new();
    nbt.insert("inner", Value::Compound(inner)).unwrap();

    let bytes = vec![
        0x0a,
            0x00, 0x00,
            0x0a,
                0x00, 0x05,
                0x69, 0x6e, 0x6e, 0x65, 0x72,
                0x01,
                0x00, 0x04,
                0x74, 0x65, 0x73, 0x74,
                0x7b,
            0x00,
        0x00
    ];

    // Test encoding.
    let mut dst = Vec::new();
    nbt.to_writer(&mut dst).unwrap();
    assert_eq!(&dst, &bytes);

    // Test decoding.
    let mut src = io::Cursor::new(bytes);
    let file = Blob::from_reader(&mut src).unwrap();
    assert_eq!(&file, &nbt);
}

#[test]
fn nbt_empty_list() {
    let mut nbt = Blob::new();
    nbt.insert("list", Value::List(Vec::new())).unwrap();

    let bytes = vec![
        0x0a,
            0x00, 0x00,
            0x09,
                0x00, 0x04,
                0x6c, 0x69, 0x73, 0x74,
                0x01,
                0x00, 0x00, 0x00, 0x00,
        0x00
    ];

    // Test encoding.
    let mut dst = Vec::new();
    nbt.to_writer(&mut dst).unwrap();
    assert_eq!(&dst, &bytes);

    // Test decoding.
    let mut src = io::Cursor::new(bytes);
    let file = Blob::from_reader(&mut src).unwrap();
    assert_eq!(&file, &nbt);
}

#[test]
fn nbt_no_root() {
    let bytes = vec![0x00];
    // Will fail, because the root is not a compound.
    assert_eq!(Blob::from_reader(&mut io::Cursor::new(&bytes[..])),
            Err(Error::NoRootCompound));
}

#[test]
fn nbt_no_end_tag() {
    let bytes = vec![
        0x0a,
            0x00, 0x00,
            0x09,
                0x00, 0x04,
                0x6c, 0x69, 0x73, 0x74,
                0x01,
                0x00, 0x00, 0x00, 0x00
    ];

    // Will fail, because there is no end tag.
    assert_eq!(Blob::from_reader(&mut io::Cursor::new(&bytes[..])),
            Err(Error::IncompleteNbtValue));
}

#[test]
fn nbt_invalid_id() {
    let bytes = vec![
        0x0a,
            0x00, 0x00,
            0x0f, // No tag associated with 0x0f.
                0x00, 0x04,
                0x6c, 0x69, 0x73, 0x74,
                0x01,
        0x00
    ];
    assert_eq!(Blob::from_reader(&mut io::Cursor::new(&bytes[..])),
               Err(Error::InvalidTypeId(15)));
}

#[test]
fn nbt_invalid_list() {
    let mut nbt = Blob::new();
    let mut badlist = Vec::new();
    badlist.push(Value::Byte(1));
    badlist.push(Value::Short(1));
    // Will fail to insert, because the List is heterogeneous.
    assert_eq!(nbt.insert("list", Value::List(badlist)),
               Err(Error::HeterogeneousList));
}

#[test]
fn nbt_bad_compression() {
    // These aren't in the zlib or gzip format, so they'll fail.
    let bytes = vec![0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
    assert!(Blob::from_gzip_reader(&mut io::Cursor::new(&bytes[..])).is_err());
    assert!(Blob::from_zlib_reader(&mut io::Cursor::new(&bytes[..])).is_err());
}

#[test]
fn nbt_compression() {
    // Create a non-trivial Blob.
    let mut nbt = Blob::new();
    nbt.insert("name", Value::String("Herobrine".to_string())).unwrap();
    nbt.insert("health", Value::Byte(100)).unwrap();
    nbt.insert("food", Value::Float(20.0)).unwrap();
    nbt.insert("emeralds", Value::Short(12345)).unwrap();
    nbt.insert("timestamp", Value::Int(1424778774)).unwrap();

    // Test zlib encoding/decoding.
    let mut zlib_dst = Vec::new();
    nbt.to_zlib_writer(&mut zlib_dst).unwrap();
    let zlib_file = Blob::from_zlib_reader(&mut io::Cursor::new(zlib_dst)).unwrap();
    assert_eq!(&nbt, &zlib_file);

    // Test gzip encoding/decoding.
    let mut gzip_dst = Vec::new();
    nbt.to_gzip_writer(&mut gzip_dst).unwrap();
    let gz_file = Blob::from_gzip_reader(&mut io::Cursor::new(gzip_dst)).unwrap();
    assert_eq!(&nbt, &gz_file);
}

#[test]
fn nbt_bigtest() {
    let mut bigtest_file = File::open("tests/big1.nbt").unwrap();
    let bigtest = Blob::from_gzip_reader(&mut bigtest_file).unwrap();
    // This is a pretty indirect way of testing correctness.
    let mut dst = Vec::new();
    bigtest.to_writer(&mut dst).unwrap();
    assert_eq!(1544, dst.len());
}

#[test]
fn nbt_arrays() {
    let mut arrays_file = File::open("tests/arrays.nbt").unwrap();
    let arrays = Blob::from_reader(&mut arrays_file).unwrap();
    match &arrays["ia"] {
        &Value::IntArray(ref arr) => assert_eq!(&[-2, -1, 0, 1, 2], &**arr),
        _ => panic!("ia was not TAG_IntArray"),
    }

    match &arrays["ba"] {
        &Value::ByteArray(ref arr) => assert_eq!(&[-2, -1, 0, 1, 2], &**arr),
        _ => panic!("ba was not TAG_ByteArray"),
    }

    match &arrays["la"] {
        &Value::LongArray(ref arr) => assert_eq!(&[-2, -1, 0, 1, 2], &**arr),
        _ => panic!("la was not TAG_LongArray"),
    }
}

#[test]
#[cfg(feature = "serde")]
fn serde_blob() {
    use de::from_reader;
    use ser::to_writer;

    let mut nbt = Blob::new();
    nbt.insert("name", "Herobrine").unwrap();
    nbt.insert("health", 100i8).unwrap();
    nbt.insert("food", 20.0f32).unwrap();
    nbt.insert("emeralds", 12345i16).unwrap();
    nbt.insert("timestamp", 1424778774i32).unwrap();

    let bytes = vec![
        0x0a,
            0x00, 0x00,
            0x08,
                0x00, 0x04,
                0x6e, 0x61, 0x6d, 0x65,
                0x00, 0x09,
                0x48, 0x65, 0x72, 0x6f, 0x62, 0x72, 0x69, 0x6e, 0x65,
            0x01,
                0x00, 0x06,
                0x68, 0x65, 0x61, 0x6c, 0x74, 0x68,
                0x64,
            0x05,
                0x00, 0x04,
                0x66, 0x6f, 0x6f, 0x64,
                0x41, 0xa0, 0x00, 0x00,
            0x02,
                0x00, 0x08,
                0x65, 0x6d, 0x65, 0x72, 0x61, 0x6c, 0x64, 0x73,
                0x30, 0x39,
            0x03,
                0x00, 0x09,
                0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
                0x54, 0xec, 0x66, 0x16,
        0x00
    ];

    // Roundtrip.

    let mut src = io::Cursor::new(bytes.clone());
    let file: Blob = from_reader(&mut src).unwrap();
    assert_eq!(&file, &nbt);
    let mut dst = Vec::new();
    to_writer(&mut dst, &nbt, None).unwrap();
    // We can only test if the decoded bytes match, since the HashMap does
    // not guarantee order (and so encoding is likely to be different, but
    // still correct).
    assert_eq!(&bytes.len(), &dst.len());
}
<|endoftext|>


<commit_before>use {Discard, Logger, Never, KV, Drain, OwnedKVList, Record, AsFmtSerializer};

// Separate module to test lack of imports
mod no_imports {
    use {Discard, Logger};
    /// ensure o! macro expands without error inside a module
    #[test]
    fn test_o_macro_expansion() {
        let _ = Logger::root(Discard, o!("a" => "aa"));
    }
    /// ensure o! macro expands without error inside a module
    #[test]
    fn test_slog_o_macro_expansion() {
        let _ = Logger::root(Discard, slog_o!("a" => "aa"));
    }
}

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

    #[test]
    fn logger_fmt_debug_sanity() {
        let root = Logger::root(Discard, o!("a" => "aa"));
        let log = root.new(o!("b" => "bb", "c" => "cc"));

        assert_eq!(format!("{:?}", log), "Logger(c, b, a)");
    }

    #[test]
    fn multichain() {
        #[derive(Clone)]
        struct CheckOwned;

        impl Drain for CheckOwned {
            type Ok = ();
            type Err = Never;
            fn log(
                &self,
                record: &Record,
                values: &OwnedKVList,
            ) -> std::result::Result<Self::Ok, Self::Err> {
                assert_eq!(
                    format!("{}", record.msg()),
                    format!("{:?}", values)
                );
                Ok(())
            }
        }

        let root = Logger::root(CheckOwned, o!("a" => "aa"));
        let log = root.new(o!("b1" => "bb", "b2" => "bb"));

        info!(log, "(b2, b1, a)");

        let log = Logger::root(log, o!("c" => "cc"));
        info!(log, "(c, b2, b1, a)");
        let log = Logger::root(log, o!("d1" => "dd", "d2" => "dd"));
        info!(log, "(d2, d1, c, b2, b1, a)");
    }
}

#[test]
fn expressions() {
    use super::{Record, Result, Serializer, KV};

    struct Foo;

    impl Foo {
        fn bar(&self) -> u32 {
            1
        }
    }

    struct X {
        foo: Foo,
    }

    let log = Logger::root(Discard, o!("version" => env!("CARGO_PKG_VERSION")));

    let foo = Foo;
    let r = X { foo: foo };

    warn!(log, "logging message");
    slog_warn!(log, "logging message");

    info!(log, #"with tag", "logging message");
    slog_info!(log, #"with tag", "logging message");

    warn!(log, "logging message"; "a" => "b");
    slog_warn!(log, "logging message"; "a" => "b");

    warn!(log, "logging message bar={}", r.foo.bar());
    slog_warn!(log, "logging message bar={}", r.foo.bar());

    warn!(
        log,
        "logging message bar={} foo={}",
        r.foo.bar(),
        r.foo.bar()
    );
    slog_warn!(
        log,
        "logging message bar={} foo={}",
        r.foo.bar(),
        r.foo.bar()
    );

    // trailing comma check
    warn!(
        log,
        "logging message bar={} foo={}",
        r.foo.bar(),
        r.foo.bar(),
    );
    slog_warn!(
        log,
        "logging message bar={} foo={}",
        r.foo.bar(),
        r.foo.bar(),
    );

    warn!(log, "logging message bar={}", r.foo.bar(); "x" => 1);
    slog_warn!(log, "logging message bar={}", r.foo.bar(); "x" => 1);

    // trailing comma check
    warn!(log, "logging message bar={}", r.foo.bar(); "x" => 1,);
    slog_warn!(log, "logging message bar={}", r.foo.bar(); "x" => 1,);

    warn!(log,
          "logging message bar={}", r.foo.bar(); "x" => 1, "y" => r.foo.bar());
    slog_warn!(log,
               "logging message bar={}", r.foo.bar();
               "x" => 1, "y" => r.foo.bar());

    warn!(log, "logging message bar={}", r.foo.bar(); "x" => r.foo.bar());
    slog_warn!(log, "logging message bar={}", r.foo.bar(); "x" => r.foo.bar());

    warn!(log, "logging message bar={}", r.foo.bar();
          "x" => r.foo.bar(), "y" => r.foo.bar());
    slog_warn!(log,
               "logging message bar={}", r.foo.bar();
               "x" => r.foo.bar(), "y" => r.foo.bar());

    // trailing comma check
    warn!(log,
          "logging message bar={}", r.foo.bar();
          "x" => r.foo.bar(), "y" => r.foo.bar(),);
    slog_warn!(log,
               "logging message bar={}", r.foo.bar();
               "x" => r.foo.bar(), "y" => r.foo.bar(),);

    {
        #[derive(Clone)]
        struct K;

        impl KV for K {
            fn serialize(
                &self,
                _record: &Record,
                _serializer: &mut Serializer,
            ) -> Result {
                Ok(())
            }
        }

        let x = K;

        let _log = log.new(o!(x.clone()));
        let _log = log.new(o!("foo" => "bar", x.clone()));
        let _log = log.new(o!("foo" => "bar", x.clone(), x.clone()));
        let _log = log.new(
            slog_o!("foo" => "bar", x.clone(), x.clone(), "aaa" => "bbb"),
        );

        info!(log, "message"; "foo" => "bar", &x, &x, "aaa" => "bbb");
    }

    info!(
        log,
        "message {}",
          { 3 + 3; 2};
          "foo" => "bar",
          "foo" => { 3 + 3; 2},
          "aaa" => "bbb");
}

#[cfg(integer128)]
#[test]
fn integer_128_types() {
    let log = Logger::root(Discard, o!("version" => env!("CARGO_PKG_VERSION")));

    info!(log, "i128 = {}", 42i128; "foo" => 7i128);
    info!(log, "u128 = {}", 42u128; "foo" => 7u128);
}

#[test]
fn expressions_fmt() {
    let log = Logger::root(Discard, o!("version" => env!("CARGO_PKG_VERSION")));

    let f = "f";
    let d = (1, 2);

    info!(log, "message"; "f" => %f, "d" => ?d);
}

#[test]
fn display_and_alternate_display() {
    use core::fmt;
    use core::cell::Cell;

    struct Example;

    impl fmt::Display for Example {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            if f.alternate() {
                f.write_str("alternate")
            } else {
                f.write_str("normal")
            }
        }
    }

    #[derive(Clone, Default)]
    struct CheckExample;

    impl Drain for CheckExample {
        type Ok = ();
        type Err = Never;

        fn log(&self, record: &Record, values: &OwnedKVList) -> Result<(), Never> {
            let mut checked_n = false;
            let mut checked_a = false;
            let mut serializer = AsFmtSerializer(|key, fmt_args| {
                if key == "n" {
                    assert_eq!(format!("{}", fmt_args), "normal");
                    checked_n = true;
                } else if key == "a" {
                    assert_eq!(format!("{}", fmt_args), "alternate");
                    checked_a = true;
                } else {
                    panic!("Unexpected key: {}", key);
                }
                Ok(())
            });

            record.kv.serialize(record, &mut serializer).unwrap();

            assert!(checked_n, "Expected the normal formatter to be used");
            assert!(checked_a, "Expected the alternate formatter to be used");

            Ok(())
        }
    }

    let log = Logger::root(CheckExample, o!());

    info!(log, ""; "n" => %Example, "a" => #%Example);
}

#[test]
fn makers() {
    use ::*;
    let drain = Duplicate(
        Discard.filter(|r| r.level().is_at_least(Level::Info)),
        Discard.filter_level(Level::Warning),
    ).map(Fuse);
    let _log = Logger::root(
        Arc::new(drain),
        o!("version" => env!("CARGO_PKG_VERSION")),
    );
}

#[test]
fn simple_logger_erased() {
    use ::*;

    fn takes_arced_drain(_l: Logger) {}

    let drain = Discard.filter_level(Level::Warning).map(Fuse);
    let log =
        Logger::root_typed(drain, o!("version" => env!("CARGO_PKG_VERSION")));

    takes_arced_drain(log.to_erased());
}

#[test]
fn logger_to_erased() {
    use ::*;

    fn takes_arced_drain(_l: Logger) {}

    let drain = Duplicate(
        Discard.filter(|r| r.level().is_at_least(Level::Info)),
        Discard.filter_level(Level::Warning),
    ).map(Fuse);
    let log =
        Logger::root_typed(drain, o!("version" => env!("CARGO_PKG_VERSION")));

    takes_arced_drain(log.into_erased());
}

#[test]
fn logger_by_ref() {
    use ::*;
    let drain = Discard.filter_level(Level::Warning).map(Fuse);
    let log = Logger::root_typed(drain, o!("version" => env!("CARGO_PKG_VERSION")));
    let f = "f";
    let d = (1, 2);
    info!(&log, "message"; "f" => %f, "d" => ?d);
}

#[test]
fn test_never_type_clone() {
    // We just want to make sure that this compiles
    fn _do_not_run() {
        let x: Never = panic!("Can't actually construct a Never type here!");
        let y = x.clone();
    }
    // Always pass if we compiled
}

#[test]
fn can_hash_keys() {
    use std::collections::HashSet;
    use Key;
    let tab: HashSet<Key> = ["foo"].iter().map(|&k| k.into()).collect();
}
<commit_msg>Fixed no_std tests<commit_after>use {Discard, Logger, Never, KV, Drain, OwnedKVList, Record, AsFmtSerializer};

// Separate module to test lack of imports
mod no_imports {
    use {Discard, Logger};
    /// ensure o! macro expands without error inside a module
    #[test]
    fn test_o_macro_expansion() {
        let _ = Logger::root(Discard, o!("a" => "aa"));
    }
    /// ensure o! macro expands without error inside a module
    #[test]
    fn test_slog_o_macro_expansion() {
        let _ = Logger::root(Discard, slog_o!("a" => "aa"));
    }
}

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

    #[test]
    fn logger_fmt_debug_sanity() {
        let root = Logger::root(Discard, o!("a" => "aa"));
        let log = root.new(o!("b" => "bb", "c" => "cc"));

        assert_eq!(format!("{:?}", log), "Logger(c, b, a)");
    }

    #[test]
    fn multichain() {
        #[derive(Clone)]
        struct CheckOwned;

        impl Drain for CheckOwned {
            type Ok = ();
            type Err = Never;
            fn log(
                &self,
                record: &Record,
                values: &OwnedKVList,
            ) -> std::result::Result<Self::Ok, Self::Err> {
                assert_eq!(
                    format!("{}", record.msg()),
                    format!("{:?}", values)
                );
                Ok(())
            }
        }

        let root = Logger::root(CheckOwned, o!("a" => "aa"));
        let log = root.new(o!("b1" => "bb", "b2" => "bb"));

        info!(log, "(b2, b1, a)");

        let log = Logger::root(log, o!("c" => "cc"));
        info!(log, "(c, b2, b1, a)");
        let log = Logger::root(log, o!("d1" => "dd", "d2" => "dd"));
        info!(log, "(d2, d1, c, b2, b1, a)");
    }
}

#[test]
fn expressions() {
    use super::{Record, Result, Serializer, KV};

    struct Foo;

    impl Foo {
        fn bar(&self) -> u32 {
            1
        }
    }

    struct X {
        foo: Foo,
    }

    let log = Logger::root(Discard, o!("version" => env!("CARGO_PKG_VERSION")));

    let foo = Foo;
    let r = X { foo: foo };

    warn!(log, "logging message");
    slog_warn!(log, "logging message");

    info!(log, #"with tag", "logging message");
    slog_info!(log, #"with tag", "logging message");

    warn!(log, "logging message"; "a" => "b");
    slog_warn!(log, "logging message"; "a" => "b");

    warn!(log, "logging message bar={}", r.foo.bar());
    slog_warn!(log, "logging message bar={}", r.foo.bar());

    warn!(
        log,
        "logging message bar={} foo={}",
        r.foo.bar(),
        r.foo.bar()
    );
    slog_warn!(
        log,
        "logging message bar={} foo={}",
        r.foo.bar(),
        r.foo.bar()
    );

    // trailing comma check
    warn!(
        log,
        "logging message bar={} foo={}",
        r.foo.bar(),
        r.foo.bar(),
    );
    slog_warn!(
        log,
        "logging message bar={} foo={}",
        r.foo.bar(),
        r.foo.bar(),
    );

    warn!(log, "logging message bar={}", r.foo.bar(); "x" => 1);
    slog_warn!(log, "logging message bar={}", r.foo.bar(); "x" => 1);

    // trailing comma check
    warn!(log, "logging message bar={}", r.foo.bar(); "x" => 1,);
    slog_warn!(log, "logging message bar={}", r.foo.bar(); "x" => 1,);

    warn!(log,
          "logging message bar={}", r.foo.bar(); "x" => 1, "y" => r.foo.bar());
    slog_warn!(log,
               "logging message bar={}", r.foo.bar();
               "x" => 1, "y" => r.foo.bar());

    warn!(log, "logging message bar={}", r.foo.bar(); "x" => r.foo.bar());
    slog_warn!(log, "logging message bar={}", r.foo.bar(); "x" => r.foo.bar());

    warn!(log, "logging message bar={}", r.foo.bar();
          "x" => r.foo.bar(), "y" => r.foo.bar());
    slog_warn!(log,
               "logging message bar={}", r.foo.bar();
               "x" => r.foo.bar(), "y" => r.foo.bar());

    // trailing comma check
    warn!(log,
          "logging message bar={}", r.foo.bar();
          "x" => r.foo.bar(), "y" => r.foo.bar(),);
    slog_warn!(log,
               "logging message bar={}", r.foo.bar();
               "x" => r.foo.bar(), "y" => r.foo.bar(),);

    {
        #[derive(Clone)]
        struct K;

        impl KV for K {
            fn serialize(
                &self,
                _record: &Record,
                _serializer: &mut Serializer,
            ) -> Result {
                Ok(())
            }
        }

        let x = K;

        let _log = log.new(o!(x.clone()));
        let _log = log.new(o!("foo" => "bar", x.clone()));
        let _log = log.new(o!("foo" => "bar", x.clone(), x.clone()));
        let _log = log.new(
            slog_o!("foo" => "bar", x.clone(), x.clone(), "aaa" => "bbb"),
        );

        info!(log, "message"; "foo" => "bar", &x, &x, "aaa" => "bbb");
    }

    info!(
        log,
        "message {}",
          { 3 + 3; 2};
          "foo" => "bar",
          "foo" => { 3 + 3; 2},
          "aaa" => "bbb");
}

#[cfg(integer128)]
#[test]
fn integer_128_types() {
    let log = Logger::root(Discard, o!("version" => env!("CARGO_PKG_VERSION")));

    info!(log, "i128 = {}", 42i128; "foo" => 7i128);
    info!(log, "u128 = {}", 42u128; "foo" => 7u128);
}

#[test]
fn expressions_fmt() {
    let log = Logger::root(Discard, o!("version" => env!("CARGO_PKG_VERSION")));

    let f = "f";
    let d = (1, 2);

    info!(log, "message"; "f" => %f, "d" => ?d);
}

#[cfg(feature = "std")]
#[test]
fn display_and_alternate_display() {
    use core::fmt;
    use core::cell::Cell;

    struct Example;

    impl fmt::Display for Example {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            if f.alternate() {
                f.write_str("alternate")
            } else {
                f.write_str("normal")
            }
        }
    }

    #[derive(Clone, Default)]
    struct CheckExample;

    impl Drain for CheckExample {
        type Ok = ();
        type Err = Never;

        fn log(&self, record: &Record, values: &OwnedKVList) -> Result<(), Never> {
            let mut checked_n = false;
            let mut checked_a = false;
            let mut serializer = AsFmtSerializer(|key, fmt_args| {
                if key == "n" {
                    assert_eq!(format!("{}", fmt_args), "normal");
                    checked_n = true;
                } else if key == "a" {
                    assert_eq!(format!("{}", fmt_args), "alternate");
                    checked_a = true;
                } else {
                    panic!("Unexpected key: {}", key);
                }
                Ok(())
            });

            record.kv.serialize(record, &mut serializer).unwrap();

            assert!(checked_n, "Expected the normal formatter to be used");
            assert!(checked_a, "Expected the alternate formatter to be used");

            Ok(())
        }
    }

    let log = Logger::root(CheckExample, o!());

    info!(log, ""; "n" => %Example, "a" => #%Example);
}

#[test]
fn makers() {
    use ::*;
    let drain = Duplicate(
        Discard.filter(|r| r.level().is_at_least(Level::Info)),
        Discard.filter_level(Level::Warning),
    ).map(Fuse);
    let _log = Logger::root(
        Arc::new(drain),
        o!("version" => env!("CARGO_PKG_VERSION")),
    );
}

#[test]
fn simple_logger_erased() {
    use ::*;

    fn takes_arced_drain(_l: Logger) {}

    let drain = Discard.filter_level(Level::Warning).map(Fuse);
    let log =
        Logger::root_typed(drain, o!("version" => env!("CARGO_PKG_VERSION")));

    takes_arced_drain(log.to_erased());
}

#[test]
fn logger_to_erased() {
    use ::*;

    fn takes_arced_drain(_l: Logger) {}

    let drain = Duplicate(
        Discard.filter(|r| r.level().is_at_least(Level::Info)),
        Discard.filter_level(Level::Warning),
    ).map(Fuse);
    let log =
        Logger::root_typed(drain, o!("version" => env!("CARGO_PKG_VERSION")));

    takes_arced_drain(log.into_erased());
}

#[test]
fn logger_by_ref() {
    use ::*;
    let drain = Discard.filter_level(Level::Warning).map(Fuse);
    let log = Logger::root_typed(drain, o!("version" => env!("CARGO_PKG_VERSION")));
    let f = "f";
    let d = (1, 2);
    info!(&log, "message"; "f" => %f, "d" => ?d);
}

#[test]
fn test_never_type_clone() {
    // We just want to make sure that this compiles
    fn _do_not_run() {
        let x: Never = panic!("Can't actually construct a Never type here!");
        let y = x.clone();
    }
    // Always pass if we compiled
}

#[cfg(feature = "std")]
#[test]
fn can_hash_keys() {
    use std::collections::HashSet;
    use Key;
    let tab: HashSet<Key> = ["foo"].iter().map(|&k| k.into()).collect();
}
<|endoftext|>


<commit_before>use quick_check::{
    quickcheck,
    quicktest,
    QuickCheck
};

use property::{
    Property
};

use testable::{
    IntoTestable
};

#[test]
fn prop_reverse_reverse() {
    fn prop(input: Vec<u8>) -> bool {
        let mut revrev = input.clone();
        revrev.reverse();
        revrev.reverse();
        revrev == input
    }
    quickcheck(prop as fn(Vec<u8>) -> bool);
}

#[test]
#[should_panic]
fn prop_oob() {
    fn prop() -> bool {
        let zero: Vec<bool> = vec![];
        zero[0]
    }
    quicktest(prop as fn() -> bool);
    // match quicktest(prop as fn() -> bool) {
    //     Ok(n) => panic!("prop_oob should fail with a runtime error \
    //                      but instead it passed {} tests.", n),
    //     _ => return
    // }
}

#[test]
fn reverse_single() {
    let prop = Property::<(Vec<usize>,)>
        ::when(|xs| xs.len() == 1)
        .property(|xs| xs == xs.clone().into_iter().rev().collect::<Vec<_>>())
        .resize(|_| 5);

    quickcheck(prop);
}

#[test]
fn reverse_app() {
    fn prop(xs: Vec<usize>, ys: Vec<usize>) -> bool {
        let mut app = xs.clone();
        app.extend(ys.iter().cloned());
        let app_rev: Vec<usize> = app.into_iter().rev().collect();

        let rxs: Vec<usize> = xs.into_iter().rev().collect();
        let mut rev_app = ys.into_iter().rev().collect::<Vec<usize>>();
        rev_app.extend(rxs.into_iter());

        app_rev == rev_app
    }
    quickcheck(prop as fn(Vec<usize>, Vec<usize>) -> bool);
}

#[test]
fn max() {
    let prop = Property::<(isize, isize)>
        ::when(|x, y| x <= y)
        .property(|x, y| ::std::cmp::max(x, y) == y);

    quickcheck(prop);
}

#[test]
fn sort() {
    fn prop(mut xs: Vec<isize>) -> bool {
        xs.sort_by(|x, y| x.cmp(y));
        let upto = if xs.len() == 0 { 0 } else { xs.len()-1 };
        for i in 0..upto {
            if xs[i] > xs[i+1] {
                return false
            }
        }
        true
    }
    quickcheck(prop as fn(Vec<isize>) -> bool);
}

fn sieve(n: usize) -> Vec<usize> {
    if n <= 1 {
        return vec![];
    }

    let mut marked = vec![false; n+1];
    marked[0] = true;
    marked[1] = true;
    marked[2] = true;
    for p in 2..n {
        for i in (2*p..n).filter(|&n| n % p == 0) {
            marked[i] = true;
        }
    }
    marked.iter()
          .enumerate()
          .filter_map(|(i, &m)| if m { None } else { Some(i) })
          .collect()
}

fn is_prime(n: usize) -> bool {
    n != 0 && n != 1 && (2..).take_while(|i| i*i <= n).all(|i| n % i != 0)
}

#[test]
fn sieve_not_prime() {
    let prop_all_prime = Property::<(usize,)>
        ::new(|n| sieve(n).into_iter().all(is_prime))
        .expect_failure();
    quickcheck(prop_all_prime);
}

#[test]
fn sieve_not_all_primes() {
    let prop_prime_iff_in_the_sieve = Property::<(usize,)>
        ::new(|n| sieve(n) == (0..(n + 1)).filter(|&i| is_prime(i)).collect::<Vec<_>>())
        .expect_failure();
    quickcheck(prop_prime_iff_in_the_sieve);
}

#[test]
fn testable_result() {
    let prop = Property::<()>::new(|| -> Result<bool, String> { Ok(true) });
    quickcheck(prop);
}

#[test]
#[should_panic]
fn testable_result_err() {
    quickcheck(Err::<bool, i32> as fn(i32) -> Result<bool, i32>);
}

#[test]
fn testable_result_err2() {
    quickcheck((Err::<bool, i32> as fn(i32) -> Result<bool, i32>).expect_failure());
}

#[test]
fn testable_unit() {
    fn do_nothing() {}
    quickcheck(do_nothing as fn());
}

#[test]
#[should_panic]
fn failing_property() {
    fn all_equal1(x: isize, y: isize, z: isize) -> bool { (x == y) && (y == z) }
    fn all_equal2(x: isize, y: isize, z: isize) -> bool { 2*x == y + z }

    let prop = Property::<(isize, isize, isize)>
        ::new(|x, y, z| all_equal1(x, y, z) == all_equal2(x, y, z));

    QuickCheck::new().max_size(10).quickcheck(prop);
}
<commit_msg>Remove commented code.<commit_after>use quick_check::{
    quickcheck,
    quicktest,
    QuickCheck
};

use property::{
    Property
};

use testable::{
    IntoTestable
};

#[test]
fn prop_reverse_reverse() {
    fn prop(input: Vec<u8>) -> bool {
        let mut revrev = input.clone();
        revrev.reverse();
        revrev.reverse();
        revrev == input
    }
    quickcheck(prop as fn(Vec<u8>) -> bool);
}

#[test]
#[should_panic]
fn prop_oob() {
    fn prop() -> bool {
        let zero: Vec<bool> = vec![];
        zero[0]
    }
    quicktest(prop as fn() -> bool);
}

#[test]
fn reverse_single() {
    let prop = Property::<(Vec<usize>,)>
        ::when(|xs| xs.len() == 1)
        .property(|xs| xs == xs.clone().into_iter().rev().collect::<Vec<_>>())
        .resize(|_| 5);

    quickcheck(prop);
}

#[test]
fn reverse_app() {
    fn prop(xs: Vec<usize>, ys: Vec<usize>) -> bool {
        let mut app = xs.clone();
        app.extend(ys.iter().cloned());
        let app_rev: Vec<usize> = app.into_iter().rev().collect();

        let rxs: Vec<usize> = xs.into_iter().rev().collect();
        let mut rev_app = ys.into_iter().rev().collect::<Vec<usize>>();
        rev_app.extend(rxs.into_iter());

        app_rev == rev_app
    }
    quickcheck(prop as fn(Vec<usize>, Vec<usize>) -> bool);
}

#[test]
fn max() {
    let prop = Property::<(isize, isize)>
        ::when(|x, y| x <= y)
        .property(|x, y| ::std::cmp::max(x, y) == y);

    quickcheck(prop);
}

#[test]
fn sort() {
    fn prop(mut xs: Vec<isize>) -> bool {
        xs.sort_by(|x, y| x.cmp(y));
        let upto = if xs.len() == 0 { 0 } else { xs.len()-1 };
        for i in 0..upto {
            if xs[i] > xs[i+1] {
                return false
            }
        }
        true
    }
    quickcheck(prop as fn(Vec<isize>) -> bool);
}

fn sieve(n: usize) -> Vec<usize> {
    if n <= 1 {
        return vec![];
    }

    let mut marked = vec![false; n+1];
    marked[0] = true;
    marked[1] = true;
    marked[2] = true;
    for p in 2..n {
        for i in (2*p..n).filter(|&n| n % p == 0) {
            marked[i] = true;
        }
    }
    marked.iter()
          .enumerate()
          .filter_map(|(i, &m)| if m { None } else { Some(i) })
          .collect()
}

fn is_prime(n: usize) -> bool {
    n != 0 && n != 1 && (2..).take_while(|i| i*i <= n).all(|i| n % i != 0)
}

#[test]
fn sieve_not_prime() {
    let prop_all_prime = Property::<(usize,)>
        ::new(|n| sieve(n).into_iter().all(is_prime))
        .expect_failure();
    quickcheck(prop_all_prime);
}

#[test]
fn sieve_not_all_primes() {
    let prop_prime_iff_in_the_sieve = Property::<(usize,)>
        ::new(|n| sieve(n) == (0..(n + 1)).filter(|&i| is_prime(i)).collect::<Vec<_>>())
        .expect_failure();
    quickcheck(prop_prime_iff_in_the_sieve);
}

#[test]
fn testable_result() {
    let prop = Property::<()>::new(|| -> Result<bool, String> { Ok(true) });
    quickcheck(prop);
}

#[test]
#[should_panic]
fn testable_result_err() {
    quickcheck(Err::<bool, i32> as fn(i32) -> Result<bool, i32>);
}

#[test]
fn testable_result_err2() {
    quickcheck((Err::<bool, i32> as fn(i32) -> Result<bool, i32>).expect_failure());
}

#[test]
fn testable_unit() {
    fn do_nothing() {}
    quickcheck(do_nothing as fn());
}

#[test]
#[should_panic]
fn failing_property() {
    fn all_equal1(x: isize, y: isize, z: isize) -> bool { (x == y) && (y == z) }
    fn all_equal2(x: isize, y: isize, z: isize) -> bool { 2*x == y + z }

    let prop = Property::<(isize, isize, isize)>
        ::new(|x, y, z| all_equal1(x, y, z) == all_equal2(x, y, z));

    QuickCheck::new().max_size(10).quickcheck(prop);
}
<|endoftext|>


<commit_before>use {AtomicDateTime, Run, Time, TimerPhase, TimingMethod, TimeStamp, TimeSpan, Segment};
use TimerPhase::*;
use run::PERSONAL_BEST_COMPARISON_NAME;
use parking_lot::RwLock;
use std::sync::Arc;

#[derive(Debug, Clone)]
pub struct Timer {
    run: Run,
    phase: TimerPhase,
    current_split_index: isize,
    current_timing_method: TimingMethod,
    current_comparison: String,
    attempt_started: Option<AtomicDateTime>,
    attempt_ended: Option<AtomicDateTime>,
    start_time: TimeStamp,
    start_time_with_offset: TimeStamp,
    // This gets adjusted after unpausing
    adjusted_start_time: TimeStamp,
    time_paused_at: TimeSpan,
    is_game_time_paused: bool,
    game_time_pause_time: Option<TimeSpan>,
    loading_times: Option<TimeSpan>,
}

pub type SharedTimer = Arc<RwLock<Timer>>;

impl Timer {
    #[inline]
    pub fn new(mut run: Run) -> Self {
        assert!(run.len() > 0);

        run.regenerate_comparisons();
        let now = TimeStamp::now();

        Timer {
            run: run,
            phase: NotRunning,
            current_split_index: -1,
            current_timing_method: TimingMethod::RealTime,
            current_comparison: PERSONAL_BEST_COMPARISON_NAME.into(),
            attempt_started: None,
            attempt_ended: None,
            start_time: now,
            start_time_with_offset: now,
            adjusted_start_time: now,
            time_paused_at: TimeSpan::zero(),
            is_game_time_paused: false,
            game_time_pause_time: None,
            loading_times: None,
        }
    }

    pub fn into_shared(self) -> SharedTimer {
        Arc::new(RwLock::new(self))
    }

    #[inline]
    pub fn run(&self) -> &Run {
        &self.run
    }

    #[inline]
    pub fn current_phase(&self) -> TimerPhase {
        self.phase
    }

    pub fn current_time(&self) -> Time {
        let real_time = match self.phase {
            NotRunning => Some(self.run.offset()),
            Running => Some(TimeStamp::now() - self.adjusted_start_time),
            Paused => Some(self.time_paused_at),
            Ended => {
                self.run
                    .segments()
                    .last()
                    .unwrap()
                    .split_time()
                    .real_time
            }
        };

        let game_time = match self.phase {
            NotRunning => Some(self.run.offset()),
            Ended => {
                self.run
                    .segments()
                    .last()
                    .unwrap()
                    .split_time()
                    .game_time
            }
            _ => {
                if self.is_game_time_paused() {
                    self.game_time_pause_time
                } else {
                    TimeSpan::option_op(real_time,
                                        if self.is_game_time_initialized() {
                                            Some(self.loading_times())
                                        } else {
                                            None
                                        },
                                        |a, b| a - b)
                }
            }
        };

        Time::new()
            .with_real_time(real_time)
            .with_game_time(game_time)
    }

    #[inline]
    pub fn current_timing_method(&self) -> TimingMethod {
        self.current_timing_method
    }

    #[inline]
    pub fn set_current_timing_method(&mut self, method: TimingMethod) {
        self.current_timing_method = method;
    }

    #[inline]
    pub fn current_comparison(&self) -> &str {
        &self.current_comparison
    }

    pub fn current_split(&self) -> Option<&Segment> {
        if self.current_split_index >= 0 {
            self.run
                .segments()
                .get(self.current_split_index as usize)
        } else {
            None
        }
    }

    fn current_split_mut(&mut self) -> Option<&mut Segment> {
        if self.current_split_index >= 0 {
            self.run
                .segments_mut()
                .get_mut(self.current_split_index as usize)
        } else {
            None
        }
    }

    #[inline]
    pub fn current_split_index(&self) -> isize {
        self.current_split_index
    }

    pub fn split(&mut self) {
        if self.phase == NotRunning {
            self.phase = Running;
            self.current_split_index = 0;
            self.attempt_started = Some(AtomicDateTime::now());
            self.start_time = TimeStamp::now();
            self.start_time_with_offset = self.start_time - self.run.offset();
            self.adjusted_start_time = self.start_time_with_offset;
            self.time_paused_at = self.run.offset();
            self.uninitialize_game_time();
            self.run.start_next_run();

            // TODO OnStart
        } else {
            let current_time = self.current_time();
            if self.phase == Running &&
               current_time
                   .real_time
                   .map_or(false, |t| t >= TimeSpan::zero()) {
                self.current_split_mut()
                    .unwrap()
                    .set_split_time(current_time);
                self.current_split_index += 1;
                if self.run.len() as isize == self.current_split_index {
                    self.phase = Ended;
                    self.attempt_ended = Some(AtomicDateTime::now());
                }
                self.run.mark_as_changed();

                // TODO OnSplit
            }
        }
    }

    pub fn skip_split(&mut self) {
        if (self.phase == Running || self.phase == Paused) &&
           self.current_split_index < self.run.len() as isize - 1 {
            self.current_split_mut().unwrap().clear_split_time();
            self.current_split_index += 1;
            self.run.mark_as_changed();

            // TODO OnSkipSplit
        }
    }

    pub fn undo_split(&mut self) {
        if self.phase != NotRunning && self.current_split_index > 0 {
            if self.phase == Ended {
                self.phase = Running;
            }
            self.current_split_index -= 1;
            self.current_split_mut().unwrap().clear_split_time();
            self.run.mark_as_changed();

            // TODO OnUndoSplit
        }
    }

    pub fn reset(&mut self, update_splits: bool) {
        if self.phase != NotRunning {
            if self.phase != Ended {
                self.attempt_ended = Some(AtomicDateTime::now());
            }
            self.unpause_game_time();
            self.set_loading_times(TimeSpan::zero());

            if update_splits {
                self.update_attempt_history();
                self.update_best_segments();
                self.update_pb_splits();
                self.update_segment_history();
            }

            self.reset_splits();
            self.run.fix_splits();
            self.run.regenerate_comparisons();
        }
    }

    fn reset_splits(&mut self) {
        self.phase = NotRunning;
        self.current_split_index = -1;

        // Reset Splits
        for segment in self.run.segments_mut() {
            segment.clear_split_time();
        }

        // TODO OnReset
    }

    pub fn pause(&mut self) {
        match self.phase {
            Running => {
                self.time_paused_at = self.current_time().real_time.unwrap();
                self.phase = Paused;

                // TODO OnPause
            }
            Paused => {
                self.adjusted_start_time = TimeStamp::now() - self.time_paused_at;
                self.phase = Running;

                // TODO OnResume
            }
            NotRunning => self.split(), // Fuck abahbob
            _ => {}
        }
    }

    pub fn undo_all_pauses(&mut self) {
        match self.current_phase() {
            Paused => self.pause(),
            Ended => {
                let pause_time = Some(self.get_pause_time().unwrap_or_default());

                let split_time = self.run
                    .segments_mut()
                    .iter_mut()
                    .last()
                    .unwrap()
                    .split_time_mut();

                *split_time += Time::new()
                    .with_real_time(pause_time)
                    .with_game_time(pause_time);
            }
            _ => {}
        }

        self.adjusted_start_time = self.start_time_with_offset;

        // TODO OnUndoAllPauses
    }

    pub fn switch_to_next_comparison(&mut self) {
        let mut comparisons = self.run.comparisons();
        let len = comparisons.len();
        let index = comparisons
            .position(|c| c == self.current_comparison)
            .unwrap();
        let index = (index + 1) % len;
        self.current_comparison = self.run.comparisons().nth(index).unwrap().to_owned();

        // TODO OnNextComparison
    }

    pub fn switch_to_previous_comparison(&mut self) {
        let mut comparisons = self.run.comparisons();
        let len = comparisons.len();
        let index = comparisons
            .position(|c| c == self.current_comparison)
            .unwrap();
        let index = (index + len - 1) % len;
        self.current_comparison = self.run.comparisons().nth(index).unwrap().to_owned();

        // TODO OnPreviousComparison
    }

    pub fn current_attempt_duration(&self) -> TimeSpan {
        match self.current_phase() {
            NotRunning => TimeSpan::zero(),
            Paused | Running => TimeStamp::now() - self.start_time,
            Ended => self.attempt_ended.unwrap() - self.attempt_started.unwrap(),
        }
    }

    pub fn get_pause_time(&self) -> Option<TimeSpan> {
        match self.current_phase() {
            Paused => Some(TimeStamp::now() - self.start_time_with_offset - self.time_paused_at),
            Running | Ended if self.start_time_with_offset != self.adjusted_start_time => {
                Some(self.adjusted_start_time - self.start_time_with_offset)
            }
            _ => None,
        }
    }

    #[inline]
    pub fn is_game_time_initialized(&self) -> bool {
        self.loading_times.is_some()
    }

    #[inline]
    pub fn initialize_game_time(&mut self) {
        self.loading_times = Some(self.loading_times());
    }

    #[inline]
    pub fn uninitialize_game_time(&mut self) {
        self.loading_times = None;
    }

    #[inline]
    pub fn is_game_time_paused(&self) -> bool {
        self.is_game_time_paused
    }

    pub fn pause_game_time(&mut self) {
        if !self.is_game_time_paused() {
            let current_time = self.current_time();
            self.game_time_pause_time = current_time.game_time.or(current_time.real_time);
            self.is_game_time_paused = true;
        }
    }

    pub fn unpause_game_time(&mut self) {
        if self.is_game_time_paused() {
            let current_time = self.current_time();
            self.set_loading_times(TimeSpan::option_op(current_time.real_time,
                                                       current_time.game_time,
                                                       |r, g| r - g)
                                           .unwrap_or_default());
            self.is_game_time_paused = false;
        }
    }

    #[inline]
    pub fn set_game_time(&mut self, game_time: TimeSpan) {
        if self.is_game_time_paused() {
            self.game_time_pause_time = Some(game_time);
        }
        let loading_times = self.current_time().real_time.unwrap() - game_time;
        self.loading_times = Some(loading_times);
    }

    #[inline]
    pub fn loading_times(&self) -> TimeSpan {
        self.loading_times.unwrap_or_default()
    }

    #[inline]
    pub fn set_loading_times(&mut self, time: TimeSpan) {
        self.loading_times = Some(time);
        if self.is_game_time_paused() {
            self.game_time_pause_time = Some(self.current_time().real_time.unwrap() - time);
        }
    }

    fn update_attempt_history(&mut self) {
        let (time, pause_time) = if self.phase == Ended {
            (self.current_time(), self.get_pause_time())
        } else {
            Default::default()
        };
        self.run
            .add_attempt(time, self.attempt_started, self.attempt_ended, pause_time);
    }

    fn update_best_segments(&mut self) {
        let mut previous_split_time_rta = Some(TimeSpan::zero());
        let mut previous_split_time_game_time = Some(TimeSpan::zero());

        for split in self.run.segments_mut() {
            let mut new_best_segment = split.best_segment_time();
            if let Some(split_time) = split.split_time().real_time {
                let current_segment = previous_split_time_rta.map(|previous| split_time - previous);
                previous_split_time_rta = Some(split_time);
                if split
                       .best_segment_time()
                       .real_time
                       .map_or(true, |b| current_segment.map_or(false, |c| c < b)) {
                    new_best_segment.real_time = current_segment;
                }
            }
            if let Some(split_time) = split.split_time().game_time {
                let current_segment =
                    previous_split_time_game_time.map(|previous| split_time - previous);
                previous_split_time_game_time = Some(split_time);
                if split
                       .best_segment_time()
                       .game_time
                       .map_or(true, |b| current_segment.map_or(false, |c| c < b)) {
                    new_best_segment.game_time = current_segment;
                }
            }
            split.set_best_segment_time(new_best_segment);
        }
    }

    fn update_pb_splits(&mut self) {
        let method = self.current_timing_method;
        let (split_time, pb_split_time) = {
            let last_segment = self.run.segments().last().unwrap();
            (last_segment.split_time()[method], last_segment.personal_best_split_time()[method])
        };
        if split_time.map_or(false, |s| pb_split_time.map_or(true, |pb| s < pb)) {
            self.set_run_as_pb();
        }
    }

    fn update_segment_history(&mut self) {
        self.run.update_segment_history(self.current_split_index);
    }

    fn set_run_as_pb(&mut self) {
        self.run.import_segment_history();
        self.run.fix_splits();
        for segment in self.run.segments_mut() {
            let split_time = segment.split_time();
            segment.set_personal_best_split_time(split_time);
        }
    }
}
<commit_msg>Always save Pause Time in Attempt History<commit_after>use {AtomicDateTime, Run, Time, TimerPhase, TimingMethod, TimeStamp, TimeSpan, Segment};
use TimerPhase::*;
use run::PERSONAL_BEST_COMPARISON_NAME;
use parking_lot::RwLock;
use std::sync::Arc;

#[derive(Debug, Clone)]
pub struct Timer {
    run: Run,
    phase: TimerPhase,
    current_split_index: isize,
    current_timing_method: TimingMethod,
    current_comparison: String,
    attempt_started: Option<AtomicDateTime>,
    attempt_ended: Option<AtomicDateTime>,
    start_time: TimeStamp,
    start_time_with_offset: TimeStamp,
    // This gets adjusted after unpausing
    adjusted_start_time: TimeStamp,
    time_paused_at: TimeSpan,
    is_game_time_paused: bool,
    game_time_pause_time: Option<TimeSpan>,
    loading_times: Option<TimeSpan>,
}

pub type SharedTimer = Arc<RwLock<Timer>>;

impl Timer {
    #[inline]
    pub fn new(mut run: Run) -> Self {
        assert!(run.len() > 0);

        run.regenerate_comparisons();
        let now = TimeStamp::now();

        Timer {
            run: run,
            phase: NotRunning,
            current_split_index: -1,
            current_timing_method: TimingMethod::RealTime,
            current_comparison: PERSONAL_BEST_COMPARISON_NAME.into(),
            attempt_started: None,
            attempt_ended: None,
            start_time: now,
            start_time_with_offset: now,
            adjusted_start_time: now,
            time_paused_at: TimeSpan::zero(),
            is_game_time_paused: false,
            game_time_pause_time: None,
            loading_times: None,
        }
    }

    pub fn into_shared(self) -> SharedTimer {
        Arc::new(RwLock::new(self))
    }

    #[inline]
    pub fn run(&self) -> &Run {
        &self.run
    }

    #[inline]
    pub fn current_phase(&self) -> TimerPhase {
        self.phase
    }

    pub fn current_time(&self) -> Time {
        let real_time = match self.phase {
            NotRunning => Some(self.run.offset()),
            Running => Some(TimeStamp::now() - self.adjusted_start_time),
            Paused => Some(self.time_paused_at),
            Ended => {
                self.run
                    .segments()
                    .last()
                    .unwrap()
                    .split_time()
                    .real_time
            }
        };

        let game_time = match self.phase {
            NotRunning => Some(self.run.offset()),
            Ended => {
                self.run
                    .segments()
                    .last()
                    .unwrap()
                    .split_time()
                    .game_time
            }
            _ => {
                if self.is_game_time_paused() {
                    self.game_time_pause_time
                } else {
                    TimeSpan::option_op(real_time,
                                        if self.is_game_time_initialized() {
                                            Some(self.loading_times())
                                        } else {
                                            None
                                        },
                                        |a, b| a - b)
                }
            }
        };

        Time::new()
            .with_real_time(real_time)
            .with_game_time(game_time)
    }

    #[inline]
    pub fn current_timing_method(&self) -> TimingMethod {
        self.current_timing_method
    }

    #[inline]
    pub fn set_current_timing_method(&mut self, method: TimingMethod) {
        self.current_timing_method = method;
    }

    #[inline]
    pub fn current_comparison(&self) -> &str {
        &self.current_comparison
    }

    pub fn current_split(&self) -> Option<&Segment> {
        if self.current_split_index >= 0 {
            self.run
                .segments()
                .get(self.current_split_index as usize)
        } else {
            None
        }
    }

    fn current_split_mut(&mut self) -> Option<&mut Segment> {
        if self.current_split_index >= 0 {
            self.run
                .segments_mut()
                .get_mut(self.current_split_index as usize)
        } else {
            None
        }
    }

    #[inline]
    pub fn current_split_index(&self) -> isize {
        self.current_split_index
    }

    pub fn split(&mut self) {
        if self.phase == NotRunning {
            self.phase = Running;
            self.current_split_index = 0;
            self.attempt_started = Some(AtomicDateTime::now());
            self.start_time = TimeStamp::now();
            self.start_time_with_offset = self.start_time - self.run.offset();
            self.adjusted_start_time = self.start_time_with_offset;
            self.time_paused_at = self.run.offset();
            self.uninitialize_game_time();
            self.run.start_next_run();

            // TODO OnStart
        } else {
            let current_time = self.current_time();
            if self.phase == Running &&
               current_time
                   .real_time
                   .map_or(false, |t| t >= TimeSpan::zero()) {
                self.current_split_mut()
                    .unwrap()
                    .set_split_time(current_time);
                self.current_split_index += 1;
                if self.run.len() as isize == self.current_split_index {
                    self.phase = Ended;
                    self.attempt_ended = Some(AtomicDateTime::now());
                }
                self.run.mark_as_changed();

                // TODO OnSplit
            }
        }
    }

    pub fn skip_split(&mut self) {
        if (self.phase == Running || self.phase == Paused) &&
           self.current_split_index < self.run.len() as isize - 1 {
            self.current_split_mut().unwrap().clear_split_time();
            self.current_split_index += 1;
            self.run.mark_as_changed();

            // TODO OnSkipSplit
        }
    }

    pub fn undo_split(&mut self) {
        if self.phase != NotRunning && self.current_split_index > 0 {
            if self.phase == Ended {
                self.phase = Running;
            }
            self.current_split_index -= 1;
            self.current_split_mut().unwrap().clear_split_time();
            self.run.mark_as_changed();

            // TODO OnUndoSplit
        }
    }

    pub fn reset(&mut self, update_splits: bool) {
        if self.phase != NotRunning {
            if self.phase != Ended {
                self.attempt_ended = Some(AtomicDateTime::now());
            }
            self.unpause_game_time();
            self.set_loading_times(TimeSpan::zero());

            if update_splits {
                self.update_attempt_history();
                self.update_best_segments();
                self.update_pb_splits();
                self.update_segment_history();
            }

            self.reset_splits();
            self.run.fix_splits();
            self.run.regenerate_comparisons();
        }
    }

    fn reset_splits(&mut self) {
        self.phase = NotRunning;
        self.current_split_index = -1;

        // Reset Splits
        for segment in self.run.segments_mut() {
            segment.clear_split_time();
        }

        // TODO OnReset
    }

    pub fn pause(&mut self) {
        match self.phase {
            Running => {
                self.time_paused_at = self.current_time().real_time.unwrap();
                self.phase = Paused;

                // TODO OnPause
            }
            Paused => {
                self.adjusted_start_time = TimeStamp::now() - self.time_paused_at;
                self.phase = Running;

                // TODO OnResume
            }
            NotRunning => self.split(), // Fuck abahbob
            _ => {}
        }
    }

    pub fn undo_all_pauses(&mut self) {
        match self.current_phase() {
            Paused => self.pause(),
            Ended => {
                let pause_time = Some(self.get_pause_time().unwrap_or_default());

                let split_time = self.run
                    .segments_mut()
                    .iter_mut()
                    .last()
                    .unwrap()
                    .split_time_mut();

                *split_time += Time::new()
                    .with_real_time(pause_time)
                    .with_game_time(pause_time);
            }
            _ => {}
        }

        self.adjusted_start_time = self.start_time_with_offset;

        // TODO OnUndoAllPauses
    }

    pub fn switch_to_next_comparison(&mut self) {
        let mut comparisons = self.run.comparisons();
        let len = comparisons.len();
        let index = comparisons
            .position(|c| c == self.current_comparison)
            .unwrap();
        let index = (index + 1) % len;
        self.current_comparison = self.run.comparisons().nth(index).unwrap().to_owned();

        // TODO OnNextComparison
    }

    pub fn switch_to_previous_comparison(&mut self) {
        let mut comparisons = self.run.comparisons();
        let len = comparisons.len();
        let index = comparisons
            .position(|c| c == self.current_comparison)
            .unwrap();
        let index = (index + len - 1) % len;
        self.current_comparison = self.run.comparisons().nth(index).unwrap().to_owned();

        // TODO OnPreviousComparison
    }

    pub fn current_attempt_duration(&self) -> TimeSpan {
        match self.current_phase() {
            NotRunning => TimeSpan::zero(),
            Paused | Running => TimeStamp::now() - self.start_time,
            Ended => self.attempt_ended.unwrap() - self.attempt_started.unwrap(),
        }
    }

    pub fn get_pause_time(&self) -> Option<TimeSpan> {
        match self.current_phase() {
            Paused => Some(TimeStamp::now() - self.start_time_with_offset - self.time_paused_at),
            Running | Ended if self.start_time_with_offset != self.adjusted_start_time => {
                Some(self.adjusted_start_time - self.start_time_with_offset)
            }
            _ => None,
        }
    }

    #[inline]
    pub fn is_game_time_initialized(&self) -> bool {
        self.loading_times.is_some()
    }

    #[inline]
    pub fn initialize_game_time(&mut self) {
        self.loading_times = Some(self.loading_times());
    }

    #[inline]
    pub fn uninitialize_game_time(&mut self) {
        self.loading_times = None;
    }

    #[inline]
    pub fn is_game_time_paused(&self) -> bool {
        self.is_game_time_paused
    }

    pub fn pause_game_time(&mut self) {
        if !self.is_game_time_paused() {
            let current_time = self.current_time();
            self.game_time_pause_time = current_time.game_time.or(current_time.real_time);
            self.is_game_time_paused = true;
        }
    }

    pub fn unpause_game_time(&mut self) {
        if self.is_game_time_paused() {
            let current_time = self.current_time();
            self.set_loading_times(TimeSpan::option_op(current_time.real_time,
                                                       current_time.game_time,
                                                       |r, g| r - g)
                                           .unwrap_or_default());
            self.is_game_time_paused = false;
        }
    }

    #[inline]
    pub fn set_game_time(&mut self, game_time: TimeSpan) {
        if self.is_game_time_paused() {
            self.game_time_pause_time = Some(game_time);
        }
        let loading_times = self.current_time().real_time.unwrap() - game_time;
        self.loading_times = Some(loading_times);
    }

    #[inline]
    pub fn loading_times(&self) -> TimeSpan {
        self.loading_times.unwrap_or_default()
    }

    #[inline]
    pub fn set_loading_times(&mut self, time: TimeSpan) {
        self.loading_times = Some(time);
        if self.is_game_time_paused() {
            self.game_time_pause_time = Some(self.current_time().real_time.unwrap() - time);
        }
    }

    fn update_attempt_history(&mut self) {
        let time = if self.phase == Ended {
            self.current_time()
        } else {
            Default::default()
        };

        let pause_time = self.get_pause_time();

        self.run
            .add_attempt(time, self.attempt_started, self.attempt_ended, pause_time);
    }

    fn update_best_segments(&mut self) {
        let mut previous_split_time_rta = Some(TimeSpan::zero());
        let mut previous_split_time_game_time = Some(TimeSpan::zero());

        for split in self.run.segments_mut() {
            let mut new_best_segment = split.best_segment_time();
            if let Some(split_time) = split.split_time().real_time {
                let current_segment = previous_split_time_rta.map(|previous| split_time - previous);
                previous_split_time_rta = Some(split_time);
                if split
                       .best_segment_time()
                       .real_time
                       .map_or(true, |b| current_segment.map_or(false, |c| c < b)) {
                    new_best_segment.real_time = current_segment;
                }
            }
            if let Some(split_time) = split.split_time().game_time {
                let current_segment =
                    previous_split_time_game_time.map(|previous| split_time - previous);
                previous_split_time_game_time = Some(split_time);
                if split
                       .best_segment_time()
                       .game_time
                       .map_or(true, |b| current_segment.map_or(false, |c| c < b)) {
                    new_best_segment.game_time = current_segment;
                }
            }
            split.set_best_segment_time(new_best_segment);
        }
    }

    fn update_pb_splits(&mut self) {
        let method = self.current_timing_method;
        let (split_time, pb_split_time) = {
            let last_segment = self.run.segments().last().unwrap();
            (last_segment.split_time()[method], last_segment.personal_best_split_time()[method])
        };
        if split_time.map_or(false, |s| pb_split_time.map_or(true, |pb| s < pb)) {
            self.set_run_as_pb();
        }
    }

    fn update_segment_history(&mut self) {
        self.run.update_segment_history(self.current_split_index);
    }

    fn set_run_as_pb(&mut self) {
        self.run.import_segment_history();
        self.run.fix_splits();
        for segment in self.run.segments_mut() {
            let split_time = segment.split_time();
            segment.set_personal_best_split_time(split_time);
        }
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::error;
use gl;

pub struct Color {
    pub r: f32,
    pub g: f32,
    pub b: f32,
    pub a: f32
}

impl Color {
    pub fn rgba(r: f32, g: f32, b: f32, a: f32) -> Self {
        Color { r: r, g: g, b: b, a: a}
    }
}

#[derive(Clone, Copy)]
pub struct Viewport {
    pub x: u32,
    pub y: u32,
    pub width: u32,
    pub height: u32
}

impl Viewport {
    pub fn new(x: u32, y: u32, width: u32, height: u32) -> Self {
        Viewport {
            x: x,
            y: y,
            width: width,
            height: height
        }
    }
}

bitflags! {
    flags BufferBits: gl::types::GLbitfield {
        const COLOR_BUFFER_BIT = gl::COLOR_BUFFER_BIT,
        const DEPTH_BUFFER_BIT = gl::DEPTH_BUFFER_BIT,
        const STENCIL_BUFFER_BIT = gl::STENCIL_BUFFER_BIT
    }
}

#[derive(Debug)]
pub enum GLError {
    InvalidEnum,
    InvalidValue,
    InvalidOperation,
    InvalidFramebufferOperation,
    OutOfMemory,
    Message(String)
}

impl fmt::Display for GLError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            GLError::InvalidEnum => {
                write!(f, "Invalid enum")
            },
            GLError::InvalidValue => {
                write!(f, "Invalid value")
            },
            GLError::InvalidOperation => {
                write!(f, "Invalid operation")
            },
            GLError::InvalidFramebufferOperation => {
                write!(f, "Invalid framebuffer operation")
            },
            GLError::OutOfMemory => {
                write!(f, "Out of memory")
            },
            GLError::Message(ref s) => {
                write!(f, "{}", s)
            }
        }
    }
}

impl error::Error for GLError {
    fn description(&self) -> &str {
        match *self {
            GLError::InvalidEnum => "Invalid enum variant in OpenGL call.",
            GLError::InvalidValue => "Out-of-range value in OpenGL call.",
            GLError::InvalidOperation => "The specified OpenGL operation is not allowed in the current state.",
            GLError::InvalidFramebufferOperation => "OpenGL command tried to read or write to an incomplete framebuffer.",
            GLError::OutOfMemory => "There is not enough memory left to execute the specified OpenGL command.",
            GLError::Message(ref s) => &s
        }
    }
}

#[derive(Debug)]
pub enum GLFramebufferError {
    IncompleteAttachment,
    IncompleteDimensions,
    IncompleteMissingAttachment,
    Unsupported
}

impl fmt::Display for GLFramebufferError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            GLFramebufferError::IncompleteAttachment => {
                write!(f, "Incomplete attachment")
            },
            GLFramebufferError::IncompleteDimensions => {
                write!(f, "Incomplete dimensions")
            },
            GLFramebufferError::IncompleteMissingAttachment => {
                write!(f, "Missing attachments")
            },
            GLFramebufferError::Unsupported => {
                write!(f, "Unsupported")
            }
        }
    }
}

impl error::Error for GLFramebufferError {
    fn description(&self) -> &str {
        match *self {
            GLFramebufferError::IncompleteAttachment => "One or more framebuffer attachments are not complete",
            GLFramebufferError::IncompleteDimensions => "Not all images attached to the framebuffer have the same width and height",
            GLFramebufferError::IncompleteMissingAttachment => "The framebuffer has no images attached",
            GLFramebufferError::Unsupported => "The framebuffer contains an unsupported combination of attachments",
        }
    }
}

gl_enum! {
    pub gl_enum DrawingMode {
        Points as POINTS = gl::POINTS,
        LineStrip as LINE_STRIP = gl::LINE_STRIP,
        LineLoop as LINE_LOOP = gl::LINE_LOOP,
        Lines as LINES = gl::LINES,
        TriangleStrip as TRIANGLE_STRIP = gl::TRIANGLE_STRIP,
        TriangleFan as TRIANGLE_FAN = gl::TRIANGLE_FAN,
        Triangles as TRIANGLES = gl::TRIANGLES
    }
}

gl_enum! {
    pub gl_enum DataType {
        Byte as BYTE = gl::BYTE,
        UnsignedByte as UNSIGNED_BYTE = gl::UNSIGNED_BYTE,
        Short as SHORT = gl::SHORT,
        UnsignedShort as UNSIGNED_SHORT = gl::UNSIGNED_SHORT,
        Fixed as FIXED = gl::FIXED,
        Float as FLOAT = gl::FLOAT
    }
}
<commit_msg>Add `FramebufferError` variant to `GLError`<commit_after>use std::fmt;
use std::error;
use gl;

pub struct Color {
    pub r: f32,
    pub g: f32,
    pub b: f32,
    pub a: f32
}

impl Color {
    pub fn rgba(r: f32, g: f32, b: f32, a: f32) -> Self {
        Color { r: r, g: g, b: b, a: a}
    }
}

#[derive(Clone, Copy)]
pub struct Viewport {
    pub x: u32,
    pub y: u32,
    pub width: u32,
    pub height: u32
}

impl Viewport {
    pub fn new(x: u32, y: u32, width: u32, height: u32) -> Self {
        Viewport {
            x: x,
            y: y,
            width: width,
            height: height
        }
    }
}

bitflags! {
    flags BufferBits: gl::types::GLbitfield {
        const COLOR_BUFFER_BIT = gl::COLOR_BUFFER_BIT,
        const DEPTH_BUFFER_BIT = gl::DEPTH_BUFFER_BIT,
        const STENCIL_BUFFER_BIT = gl::STENCIL_BUFFER_BIT
    }
}

#[derive(Debug)]
pub enum GLError {
    InvalidEnum,
    InvalidValue,
    InvalidOperation,
    InvalidFramebufferOperation,
    OutOfMemory,
    FramebufferError(GLFramebufferError),
    Message(String)
}

impl fmt::Display for GLError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            GLError::InvalidEnum => {
                write!(f, "Invalid enum")
            },
            GLError::InvalidValue => {
                write!(f, "Invalid value")
            },
            GLError::InvalidOperation => {
                write!(f, "Invalid operation")
            },
            GLError::InvalidFramebufferOperation => {
                write!(f, "Invalid framebuffer operation")
            },
            GLError::OutOfMemory => {
                write!(f, "Out of memory")
            },
            GLError::FramebufferError(ref e) => {
                write!(f, "{:?}", e)
            },
            GLError::Message(ref s) => {
                write!(f, "{}", s)
            }
        }
    }
}

impl error::Error for GLError {
    fn description(&self) -> &str {
        match *self {
            GLError::InvalidEnum => "Invalid enum variant in OpenGL call.",
            GLError::InvalidValue => "Out-of-range value in OpenGL call.",
            GLError::InvalidOperation => "The specified OpenGL operation is not allowed in the current state.",
            GLError::InvalidFramebufferOperation => "OpenGL command tried to read or write to an incomplete framebuffer.",
            GLError::OutOfMemory => "There is not enough memory left to execute the specified OpenGL command.",
            GLError::FramebufferError(ref e) => {
                error::Error::description(e)
            },
            GLError::Message(ref s) => &s
        }
    }
}

#[derive(Debug)]
pub enum GLFramebufferError {
    IncompleteAttachment,
    IncompleteDimensions,
    IncompleteMissingAttachment,
    Unsupported
}

impl fmt::Display for GLFramebufferError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            GLFramebufferError::IncompleteAttachment => {
                write!(f, "Incomplete attachment")
            },
            GLFramebufferError::IncompleteDimensions => {
                write!(f, "Incomplete dimensions")
            },
            GLFramebufferError::IncompleteMissingAttachment => {
                write!(f, "Missing attachments")
            },
            GLFramebufferError::Unsupported => {
                write!(f, "Unsupported")
            }
        }
    }
}

impl error::Error for GLFramebufferError {
    fn description(&self) -> &str {
        match *self {
            GLFramebufferError::IncompleteAttachment => "One or more framebuffer attachments are not complete",
            GLFramebufferError::IncompleteDimensions => "Not all images attached to the framebuffer have the same width and height",
            GLFramebufferError::IncompleteMissingAttachment => "The framebuffer has no images attached",
            GLFramebufferError::Unsupported => "The framebuffer contains an unsupported combination of attachments",
        }
    }
}

gl_enum! {
    pub gl_enum DrawingMode {
        Points as POINTS = gl::POINTS,
        LineStrip as LINE_STRIP = gl::LINE_STRIP,
        LineLoop as LINE_LOOP = gl::LINE_LOOP,
        Lines as LINES = gl::LINES,
        TriangleStrip as TRIANGLE_STRIP = gl::TRIANGLE_STRIP,
        TriangleFan as TRIANGLE_FAN = gl::TRIANGLE_FAN,
        Triangles as TRIANGLES = gl::TRIANGLES
    }
}

gl_enum! {
    pub gl_enum DataType {
        Byte as BYTE = gl::BYTE,
        UnsignedByte as UNSIGNED_BYTE = gl::UNSIGNED_BYTE,
        Short as SHORT = gl::SHORT,
        UnsignedShort as UNSIGNED_SHORT = gl::UNSIGNED_SHORT,
        Fixed as FIXED = gl::FIXED,
        Float as FLOAT = gl::FLOAT
    }
}
<|endoftext|>