<commit_before>#![allow(
    clippy::decimal_literal_representation,
    clippy::derive_partial_eq_without_eq,
    clippy::unreadable_literal,
    clippy::shadow_unrelated
)]

use indoc::indoc;
use serde_derive::{Deserialize, Serialize};
use serde_yaml::Value;
use std::collections::BTreeMap;
use std::fmt::Debug;

fn test_serde<T>(thing: &T, yaml: &str)
where
    T: serde::Serialize + serde::de::DeserializeOwned + PartialEq + Debug,
{
    let serialized = serde_yaml::to_string(&thing).unwrap();
    assert_eq!(yaml, serialized);

    let value = serde_yaml::to_value(&thing).unwrap();
    let serialized = serde_yaml::to_string(&value).unwrap();
    assert_eq!(yaml, serialized);

    let deserialized: T = serde_yaml::from_str(yaml).unwrap();
    assert_eq!(*thing, deserialized);

    let value: Value = serde_yaml::from_str(yaml).unwrap();
    let deserialized: T = serde_yaml::from_value(value).unwrap();
    assert_eq!(*thing, deserialized);

    serde_yaml::from_str::<serde::de::IgnoredAny>(yaml).unwrap();
}

#[test]
fn test_default() {
    assert_eq!(Value::default(), Value::Null);
}

#[test]
fn test_int() {
    let thing = 256;
    let yaml = indoc! {"
        256
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_int_max_u64() {
    let thing = u64::MAX;
    let yaml = indoc! {"
        18446744073709551615
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_int_min_i64() {
    let thing = i64::MIN;
    let yaml = indoc! {"
        -9223372036854775808
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_int_max_i64() {
    let thing = i64::MAX;
    let yaml = indoc! {"
        9223372036854775807
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_i128_small() {
    let thing: i128 = -256;
    let yaml = indoc! {"
        -256
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_u128_small() {
    let thing: u128 = 256;
    let yaml = indoc! {"
        256
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_float() {
    let thing = 25.6;
    let yaml = indoc! {"
        25.6
    "};
    test_serde(&thing, yaml);

    let thing = 25.;
    let yaml = indoc! {"
        25.0
    "};
    test_serde(&thing, yaml);

    let thing = f64::INFINITY;
    let yaml = indoc! {"
        .inf
    "};
    test_serde(&thing, yaml);

    let thing = f64::NEG_INFINITY;
    let yaml = indoc! {"
        -.inf
    "};
    test_serde(&thing, yaml);

    let float: f64 = serde_yaml::from_str(indoc! {"
        .nan
    "})
    .unwrap();
    assert!(float.is_nan());
}

#[test]
fn test_float32() {
    let thing: f32 = 25.5;
    let yaml = indoc! {"
        25.5
    "};
    test_serde(&thing, yaml);

    let thing = f32::INFINITY;
    let yaml = indoc! {"
        .inf
    "};
    test_serde(&thing, yaml);

    let thing = f32::NEG_INFINITY;
    let yaml = indoc! {"
        -.inf
    "};
    test_serde(&thing, yaml);

    let single_float: f32 = serde_yaml::from_str(indoc! {"
        .nan
    "})
    .unwrap();
    assert!(single_float.is_nan());
}

#[test]
fn test_vec() {
    let thing = vec![1, 2, 3];
    let yaml = indoc! {"
        - 1
        - 2
        - 3
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_map() {
    let mut thing = BTreeMap::new();
    thing.insert("x".to_owned(), 1);
    thing.insert("y".to_owned(), 2);
    let yaml = indoc! {"
        x: 1
        y: 2
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_basic_struct() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Basic {
        x: isize,
        y: String,
        z: bool,
    }
    let thing = Basic {
        x: -4,
        y: "hi\tquoted".to_owned(),
        z: true,
    };
    let yaml = indoc! {r#"
        x: -4
        y: "hi\tquoted"
        z: true
    "#};
    test_serde(&thing, yaml);
}

#[test]
fn test_multiline_string() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Struct {
        trailing_newline: String,
        no_trailing_newline: String,
    }
    let thing = Struct {
        trailing_newline: "aaa\nbbb\n".to_owned(),
        no_trailing_newline: "aaa\nbbb".to_owned(),
    };
    let yaml = indoc! {r#"
        trailing_newline: |
          aaa
          bbb
        no_trailing_newline: |-
          aaa
          bbb
    "#};
    test_serde(&thing, yaml);
}

#[test]
fn test_strings_needing_quote() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Struct {
        boolean: String,
        integer: String,
        void: String,
    }
    let thing = Struct {
        boolean: "true".to_owned(),
        integer: "1".to_owned(),
        void: "null".to_owned(),
    };
    let yaml = indoc! {r#"
        boolean: 'true'
        integer: '1'
        void: 'null'
    "#};
    test_serde(&thing, yaml);
}

#[test]
fn test_nested_vec() {
    let thing = vec![vec![1, 2, 3], vec![4, 5, 6]];
    let yaml = indoc! {"
        - - 1
          - 2
          - 3
        - - 4
          - 5
          - 6
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_nested_struct() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Outer {
        inner: Inner,
    }
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Inner {
        v: u16,
    }
    let thing = Outer {
        inner: Inner { v: 512 },
    };
    let yaml = indoc! {"
        inner:
          v: 512
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_option() {
    let thing = vec![Some(1), None, Some(3)];
    let yaml = indoc! {"
        - 1
        - null
        - 3
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_unit() {
    let thing = vec![(), ()];
    let yaml = indoc! {"
        - null
        - null
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_unit_struct() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Foo;
    let thing = Foo;
    let yaml = indoc! {"
        null
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_unit_variant() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    enum Variant {
        First,
        Second,
    }
    let thing = Variant::First;
    let yaml = indoc! {"
        First
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_newtype_struct() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct OriginalType {
        v: u16,
    }
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct NewType(OriginalType);
    let thing = NewType(OriginalType { v: 1 });
    let yaml = indoc! {"
        v: 1
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_newtype_variant() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    enum Variant {
        Size(usize),
    }
    let thing = Variant::Size(127);
    let yaml = indoc! {"
        Size: 127
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_tuple_variant() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    enum Variant {
        Rgb(u8, u8, u8),
    }
    let thing = Variant::Rgb(32, 64, 96);
    let yaml = indoc! {"
        Rgb:
        - 32
        - 64
        - 96
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_struct_variant() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    enum Variant {
        Color { r: u8, g: u8, b: u8 },
    }
    let thing = Variant::Color {
        r: 32,
        g: 64,
        b: 96,
    };
    let yaml = indoc! {"
        Color:
          r: 32
          g: 64
          b: 96
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_value() {
    use serde_yaml::{Mapping, Number};

    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    pub struct GenericInstructions {
        #[serde(rename = "type")]
        pub typ: String,
        pub config: Value,
    }
    let thing = GenericInstructions {
        typ: "primary".to_string(),
        config: Value::Sequence(vec![
            Value::Null,
            Value::Bool(true),
            Value::Number(Number::from(65535)),
            Value::Number(Number::from(0.54321)),
            Value::String("s".into()),
            Value::Mapping(Mapping::new()),
        ]),
    };
    let yaml = indoc! {"
        type: primary
        config:
        - null
        - true
        - 65535
        - 0.54321
        - s
        - {}
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_mapping() {
    use serde_yaml::Mapping;
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Data {
        pub substructure: Mapping,
    }

    let mut thing = Data {
        substructure: Mapping::new(),
    };
    thing.substructure.insert(
        Value::String("a".to_owned()),
        Value::String("foo".to_owned()),
    );
    thing.substructure.insert(
        Value::String("b".to_owned()),
        Value::String("bar".to_owned()),
    );

    let yaml = indoc! {"
        substructure:
          a: foo
          b: bar
    "};

    test_serde(&thing, yaml);
}
<commit_msg>Add test of serializing char<commit_after>#![allow(
    clippy::decimal_literal_representation,
    clippy::derive_partial_eq_without_eq,
    clippy::unreadable_literal,
    clippy::shadow_unrelated
)]

use indoc::indoc;
use serde_derive::{Deserialize, Serialize};
use serde_yaml::Value;
use std::collections::BTreeMap;
use std::fmt::Debug;

fn test_serde<T>(thing: &T, yaml: &str)
where
    T: serde::Serialize + serde::de::DeserializeOwned + PartialEq + Debug,
{
    let serialized = serde_yaml::to_string(&thing).unwrap();
    assert_eq!(yaml, serialized);

    let value = serde_yaml::to_value(&thing).unwrap();
    let serialized = serde_yaml::to_string(&value).unwrap();
    assert_eq!(yaml, serialized);

    let deserialized: T = serde_yaml::from_str(yaml).unwrap();
    assert_eq!(*thing, deserialized);

    let value: Value = serde_yaml::from_str(yaml).unwrap();
    let deserialized: T = serde_yaml::from_value(value).unwrap();
    assert_eq!(*thing, deserialized);

    serde_yaml::from_str::<serde::de::IgnoredAny>(yaml).unwrap();
}

#[test]
fn test_default() {
    assert_eq!(Value::default(), Value::Null);
}

#[test]
fn test_int() {
    let thing = 256;
    let yaml = indoc! {"
        256
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_int_max_u64() {
    let thing = u64::MAX;
    let yaml = indoc! {"
        18446744073709551615
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_int_min_i64() {
    let thing = i64::MIN;
    let yaml = indoc! {"
        -9223372036854775808
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_int_max_i64() {
    let thing = i64::MAX;
    let yaml = indoc! {"
        9223372036854775807
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_i128_small() {
    let thing: i128 = -256;
    let yaml = indoc! {"
        -256
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_u128_small() {
    let thing: u128 = 256;
    let yaml = indoc! {"
        256
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_float() {
    let thing = 25.6;
    let yaml = indoc! {"
        25.6
    "};
    test_serde(&thing, yaml);

    let thing = 25.;
    let yaml = indoc! {"
        25.0
    "};
    test_serde(&thing, yaml);

    let thing = f64::INFINITY;
    let yaml = indoc! {"
        .inf
    "};
    test_serde(&thing, yaml);

    let thing = f64::NEG_INFINITY;
    let yaml = indoc! {"
        -.inf
    "};
    test_serde(&thing, yaml);

    let float: f64 = serde_yaml::from_str(indoc! {"
        .nan
    "})
    .unwrap();
    assert!(float.is_nan());
}

#[test]
fn test_float32() {
    let thing: f32 = 25.5;
    let yaml = indoc! {"
        25.5
    "};
    test_serde(&thing, yaml);

    let thing = f32::INFINITY;
    let yaml = indoc! {"
        .inf
    "};
    test_serde(&thing, yaml);

    let thing = f32::NEG_INFINITY;
    let yaml = indoc! {"
        -.inf
    "};
    test_serde(&thing, yaml);

    let single_float: f32 = serde_yaml::from_str(indoc! {"
        .nan
    "})
    .unwrap();
    assert!(single_float.is_nan());
}

#[test]
fn test_vec() {
    let thing = vec![1, 2, 3];
    let yaml = indoc! {"
        - 1
        - 2
        - 3
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_map() {
    let mut thing = BTreeMap::new();
    thing.insert("x".to_owned(), 1);
    thing.insert("y".to_owned(), 2);
    let yaml = indoc! {"
        x: 1
        y: 2
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_basic_struct() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Basic {
        w: char,
        x: isize,
        y: String,
        z: bool,
    }
    let thing = Basic {
        w: '.',
        x: -4,
        y: "hi\tquoted".to_owned(),
        z: true,
    };
    let yaml = indoc! {r#"
        w: .
        x: -4
        y: "hi\tquoted"
        z: true
    "#};
    test_serde(&thing, yaml);
}

#[test]
fn test_multiline_string() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Struct {
        trailing_newline: String,
        no_trailing_newline: String,
    }
    let thing = Struct {
        trailing_newline: "aaa\nbbb\n".to_owned(),
        no_trailing_newline: "aaa\nbbb".to_owned(),
    };
    let yaml = indoc! {r#"
        trailing_newline: |
          aaa
          bbb
        no_trailing_newline: |-
          aaa
          bbb
    "#};
    test_serde(&thing, yaml);
}

#[test]
fn test_strings_needing_quote() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Struct {
        boolean: String,
        integer: String,
        void: String,
    }
    let thing = Struct {
        boolean: "true".to_owned(),
        integer: "1".to_owned(),
        void: "null".to_owned(),
    };
    let yaml = indoc! {r#"
        boolean: 'true'
        integer: '1'
        void: 'null'
    "#};
    test_serde(&thing, yaml);
}

#[test]
fn test_nested_vec() {
    let thing = vec![vec![1, 2, 3], vec![4, 5, 6]];
    let yaml = indoc! {"
        - - 1
          - 2
          - 3
        - - 4
          - 5
          - 6
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_nested_struct() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Outer {
        inner: Inner,
    }
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Inner {
        v: u16,
    }
    let thing = Outer {
        inner: Inner { v: 512 },
    };
    let yaml = indoc! {"
        inner:
          v: 512
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_option() {
    let thing = vec![Some(1), None, Some(3)];
    let yaml = indoc! {"
        - 1
        - null
        - 3
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_unit() {
    let thing = vec![(), ()];
    let yaml = indoc! {"
        - null
        - null
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_unit_struct() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Foo;
    let thing = Foo;
    let yaml = indoc! {"
        null
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_unit_variant() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    enum Variant {
        First,
        Second,
    }
    let thing = Variant::First;
    let yaml = indoc! {"
        First
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_newtype_struct() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct OriginalType {
        v: u16,
    }
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct NewType(OriginalType);
    let thing = NewType(OriginalType { v: 1 });
    let yaml = indoc! {"
        v: 1
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_newtype_variant() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    enum Variant {
        Size(usize),
    }
    let thing = Variant::Size(127);
    let yaml = indoc! {"
        Size: 127
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_tuple_variant() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    enum Variant {
        Rgb(u8, u8, u8),
    }
    let thing = Variant::Rgb(32, 64, 96);
    let yaml = indoc! {"
        Rgb:
        - 32
        - 64
        - 96
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_struct_variant() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    enum Variant {
        Color { r: u8, g: u8, b: u8 },
    }
    let thing = Variant::Color {
        r: 32,
        g: 64,
        b: 96,
    };
    let yaml = indoc! {"
        Color:
          r: 32
          g: 64
          b: 96
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_value() {
    use serde_yaml::{Mapping, Number};

    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    pub struct GenericInstructions {
        #[serde(rename = "type")]
        pub typ: String,
        pub config: Value,
    }
    let thing = GenericInstructions {
        typ: "primary".to_string(),
        config: Value::Sequence(vec![
            Value::Null,
            Value::Bool(true),
            Value::Number(Number::from(65535)),
            Value::Number(Number::from(0.54321)),
            Value::String("s".into()),
            Value::Mapping(Mapping::new()),
        ]),
    };
    let yaml = indoc! {"
        type: primary
        config:
        - null
        - true
        - 65535
        - 0.54321
        - s
        - {}
    "};
    test_serde(&thing, yaml);
}

#[test]
fn test_mapping() {
    use serde_yaml::Mapping;
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Data {
        pub substructure: Mapping,
    }

    let mut thing = Data {
        substructure: Mapping::new(),
    };
    thing.substructure.insert(
        Value::String("a".to_owned()),
        Value::String("foo".to_owned()),
    );
    thing.substructure.insert(
        Value::String("b".to_owned()),
        Value::String("bar".to_owned()),
    );

    let yaml = indoc! {"
        substructure:
          a: foo
          b: bar
    "};

    test_serde(&thing, yaml);
}
<|endoftext|>


<commit_before>#[macro_use] extern crate wlroots;

use std::ptr::null_mut;
use std::env;
use std::time::Instant;
use std::os::raw::{c_void, c_int};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Mutex;

use wlroots::compositor::{Compositor};
use wlroots::output::{Output};
use wlroots::manager::{DefaultInputHandler, OutputManagerHandler};
use wlroots::wlroots_sys::{wlr_input_device, wlr_output};

struct OutputHandler;

impl OutputManagerHandler for OutputHandler {
    fn output_frame(&mut self, output: Output) {
        wlr_log!(L_DEBUG, "OUTPUT FRAME");
        // TODO
    }
}

fn main() {
    let dummy = 0;
    let input_manager = DefaultInputHandler::new();
    let output_manager = OutputHandler;
    let mut compositor = Compositor::new(Box::new(input_manager),
                                         Box::new(output_manager));
    compositor.run();
}

/*
fn main() {
    if env::var("DISPLAY").is_ok() {
        panic!("Detected that X is running. Run this in its own virtual terminal.")
    } else if env::var("WAYLAND_DISPLAY").is_ok() {
        panic!("Detected that Wayland is running. Run this in its own virtual terminal")
    }
    let empty = ();
    {
        // NOTE that because we pass `done` to a timeout callback,
        // it must be declared before session to ensure they are dropped
        // in the correct order.
        // Try reordering `done` to after `session` and see the error.
        let done = AtomicBool::new(false);
        let mut session = wlroots::Session::new()
            .expect("Could not start session");
        // init output
        wlroots::output::init(&mut session);
        // set loop to break after 20 seconds.
        session.set_timeout(&done,
                            |done: &AtomicBool| {
                                done.store(true, Ordering::Relaxed)
                            },
                            20000);
        // Set the outputs to turn off at 5 seconds
        session.set_timeout(&empty,
                            disable_outputs,
                            5000);
        // Set the outputs to turn on at 5 seconds
        session.set_timeout(&empty,
                            enable_outputs,
                            10000);
        // Finish initializing the backend
        session.backend.init().expect("Backend could not initalize");
        // Now that the outputs are registered add a callback per frame.
        // We don't wrap this because it's largely unnecessarily
        unsafe {
            add_frame_callbacks();
        }
        while ! done.load(Ordering::Relaxed) {
            match session.dispatch_event_loop() {
                0 => {}
                err_code => {
                    println!("Error: {:?}", err_code);
                    break;
                }
            }
        }
        // TODO Ensure that this all cleaned up properly in RAII
    }

}

fn disable_outputs(_: &()) {
    let mut outputs = wlroots::output::OUTPUTS.try_lock()
        .expect("Output lock was already acquired");
    for mut output in &mut *outputs {
        output.disable()
    }
}

fn enable_outputs(_: &()) {
    let mut outputs = wlroots::output::OUTPUTS.try_lock()
    .expect("Output lock was already acquired");
    for mut output in &mut *outputs {
        output.enable()
    }
}

/*
NOTE: This is the only unsafe part of the program.

This draws directly to the screen, but the majority of the unsafe part is
unexposed machinery. We don't wrap this well, because in a real program
we will probably not need to do this.
*/
extern crate wayland_sys;
use wlroots::utils::wl_listener;
use wayland_sys::server;

// For graphical functions
mod gl {
    include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
}
struct State {
    /// The color on the screen.
    color: [f32; 3],
    dec: i32,
    /// How long since the last frame was rendered.
    last_frame: Instant
}

impl State {
    unsafe fn new() -> Self {
        State {
            color: [1.0, 0.0, 0.0],
            dec: 0,
            last_frame: Instant::now()
        }
    }
}

// This is so wl_container_of works.
// repr(C) means the struct packing in deterministic.

#[repr(C)]
struct OutputWrapper {
    state: *mut State,
    output: wl_listener
}

unsafe fn add_frame_callbacks() {
    // We store the wl_listener in a struct, and grab it again
    // using the magic of wl_container_of.
    let mut output_frame_listener =wl_listener::new(draw_frame);
    // Keep a raw pointer to make sure wl_container_of works.
    //let mut output_raw = Box::into_raw(output_frame_listener);
    let mut state = Box::new(State::new());
    let mut state_raw = Box::into_raw(state);
    let mut output_wrapper = Box::new(OutputWrapper {
        state: state_raw,
        output: output_frame_listener as _
    });
    let outputs = wlroots::output::OUTPUTS.try_lock()
        .expect("Output lock was already acquired");
    for output in &*outputs {
        wlroots::utils::wl_signal_add(&mut (*output.inner).events.frame,
                                      &mut output_wrapper.output as &mut _);
    }
    ::std::mem::forget(output_wrapper);
}

unsafe extern "C" fn draw_frame(listener: *mut server::wl_listener,
                                data: *mut c_void) {
    // SUPER unsafe
    let output_wrapper = wl_container_of!(listener,
                                          OutputWrapper,
                                          output) as *mut OutputWrapper;
    let state = &mut *(*output_wrapper).state;
    let now = Instant::now();
    let delta = now.duration_since(state.last_frame);
    let seconds_delta= delta.as_secs();
    let nano_delta = delta.subsec_nanos() as u64;
    let ms = (seconds_delta * 1000) + nano_delta / 1000000;
    let inc = (state.dec + 1) % 3;
    state.color[inc as usize] += ms as f32 / 2000.0;
    state.color[state.dec as usize] -= ms as f32 / 2000.0;

    if state.color[state.dec as usize] < 0.0 {
        state.color[inc as usize] = 1.0;
        state.color[state.dec as usize] = 0.0;
        state.dec = inc;
    }
    state.last_frame = now;
    gl::ClearColor(state.color[0], state.color[1], state.color[2], 1.0);
    gl::Clear(gl::COLOR_BUFFER_BIT);

}
*/
<commit_msg>Safe simple example now works<commit_after>#[macro_use] extern crate wlroots;

use std::ptr::null_mut;
use std::env;
use std::time::Instant;
use std::os::raw::{c_void, c_int};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Mutex;

use wlroots::compositor::{Compositor};
use wlroots::output::{Output};
use wlroots::manager::{DefaultInputHandler, OutputManagerHandler};
use wlroots::wlroots_sys::{gl, wlr_input_device, wlr_output, wlr_output_make_current, wlr_output_swap_buffers};

struct OutputHandler {
    color: [f32; 3],
    dec: usize,
    last_frame: Instant
}

impl OutputManagerHandler for OutputHandler {
    fn output_frame(&mut self, output: Output) {
        let now = Instant::now();
        let delta = now.duration_since(self.last_frame);
        let seconds_delta= delta.as_secs();
        let nano_delta = delta.subsec_nanos() as u64;
        let ms = (seconds_delta * 1000) + nano_delta / 1000000;
        let inc = (self.dec + 1) % 3;
        self.color[inc as usize] += ms as f32 / 2000.0;
        self.color[self.dec as usize] -= ms as f32 / 2000.0;

        if self.color[self.dec as usize] < 0.0 {
            self.color[inc as usize] = 1.0;
            self.color[self.dec as usize] = 0.0;
            self.dec = inc;
        }
        self.last_frame = now;
        // NOTE gl functions will probably always be unsafe.
        // NOTE wlr_output_* functions will be wrapped eventually.
        unsafe {
            wlr_output_make_current(output.to_ptr());
            gl::ClearColor(self.color[0], self.color[1], self.color[2], 1.0);
            gl::Clear(gl::COLOR_BUFFER_BIT);
            wlr_output_swap_buffers(output.to_ptr());
        }
    }
}

fn main() {
    let dummy = 0;
    let input_manager = DefaultInputHandler::new();
    let output_manager = OutputHandler {
        color: [0.0, 0.0, 0.0],
        dec: 0,
        last_frame: Instant::now()
    };
    let mut compositor = Compositor::new(Box::new(input_manager),
                                         Box::new(output_manager));
    compositor.run();
}
<|endoftext|>


<commit_before>extern crate tinyrsh;

use std::collections::HashMap;
use std::net::{TcpListener, TcpStream};
use std::io::{Read, Write};
use std::os::unix::io::{RawFd, AsRawFd};
use tinyrsh::select as select;
use tinyrsh::select::FdSet;
use std::process::{Command, Stdio};

fn greet_client(mut stream: &TcpStream) {
    let remote = stream.peer_addr().unwrap();
    println!("connected: {}", remote);

    match stream.write(b"hello") {
        Err(e) => println!("{}", e),
        Ok(n) => println!("wrote {} bytes", n),
    };
}

fn debug_fdset(fdset: &FdSet) {
    let maxfds = select::FD_SETSIZE;
    for i in 0 .. maxfds {
        if fdset.contains(i) {
            println!("contains {}", i);
        }
    }
}

fn read_child<T: Read>(readt: &mut T) {
    let mut buf = [0; 10];
    let n = readt.read(&mut buf).expect("read_child");
    println!("{:?} ({} bytes) `{}'", buf, n, String::from_utf8_lossy(&buf[..n]));
}

fn forward_to_remotes<T: Read, S>(child_out: &mut T, clients: &HashMap<S, TcpStream>) -> ()
    where S : std::cmp::Eq, S : std::hash::Hash
{
    let mut buf = [0; 10];
    let n = child_out.read(&mut buf).expect("read_child");
    assert!(n != 0); //TODO eof
    if clients.is_empty() {
        println!("Warning: child output but no remote connected");
        println!("{:?} ({} bytes) `{}'", buf, n, String::from_utf8_lossy(&buf[..n]));
    }
    for mut remote in clients.values(){
        //println!("forwarding to {}", remote.peer_addr().unwrap());
        let written = remote.write(&buf[..n]).expect("remote write");
        assert_eq!(n, written);
    }
}

fn copy_to<T: Read, U: Write>(from: &mut T, to: &mut U) -> bool {
    let mut buf = [0; 10];
    let n = from.read(&mut buf).expect("copy_to read");
    //println!("copy_to read {:?} ({} bytes) `{}'", buf, n, String::from_utf8_lossy(&buf[..n]));
    let written = to.write(&buf[..n]).expect("copy_to write");
    to.flush();
    assert_eq!(n, written);

    n != 0
}

fn main() {
    println!("Hello, world!");

    let child = Command::new("../py-ptysh/ptysh.py")
            //.arg("-a")
            .stdin(Stdio::piped())
            .stdout(Stdio::piped())
            .stderr(Stdio::piped())
            .spawn()
            .expect("failed to execute process");
    println!("spawned child with pid {}", child.id());

    let mut child_stdin  = child.stdin.unwrap();
    let mut child_stdout = child.stdout.unwrap();
    let mut child_stderr = child.stderr.unwrap();
    // stderr == stdout? no, but py-ptysh copies everything to std out
    assert!(child_stdout.as_raw_fd() != child_stderr.as_raw_fd());

    // TODO linebuffered? how is child output buffered at all?

    let listener = TcpListener::bind("127.0.0.1:6699").unwrap();

    let mut all_fdset = FdSet::new();
    let srv_fd = listener.as_raw_fd(); // not consumed

    //high fd for select() call
    let mut high_fd = 0;

    for fd in [srv_fd, child_stdout.as_raw_fd(), child_stderr.as_raw_fd()].iter() {
        println!("inserting fd {}", fd);
        all_fdset.insert(*fd);
        high_fd = std::cmp::max(high_fd, *fd);
    };

    let mut clients: HashMap<RawFd, TcpStream> = HashMap::new(); //could also use FromRawFd

    fn add_client(all_fdset: &mut FdSet, clients: &mut HashMap<RawFd, TcpStream>, stream: TcpStream) -> RawFd {
        let stream_fd: RawFd = stream.as_raw_fd(); //not consume
        println!("inserted fd {}", stream_fd);
        clients.insert(stream_fd, stream);
        all_fdset.insert(stream_fd);
        stream_fd
    };
    fn del_client(all_fdset: &mut FdSet, clients: &mut HashMap<RawFd, TcpStream>, stream_fd: RawFd) {
        assert!(clients.contains_key(&stream_fd));
        //let stream = clients.get(&stream_fd);
        println!("removing fd {}", stream_fd);
        assert!(all_fdset.contains(stream_fd));
        all_fdset.remove(stream_fd);
        assert!(clients.contains_key(&stream_fd));
        clients.remove(&stream_fd);
    };

   println!("select-looping");
   loop {
       let mut fdset = all_fdset.clone();
       let res = select::select(high_fd + 1, Some(&mut fdset), None, None, None);
       assert!(res > 0);
       println!("selected returned {}", res);
       debug_fdset(&fdset);

       let mut accept_new = false;

       let mut handled_fds = 0;
       for i in 0 .. high_fd + 1 {
           if fdset.contains(i) {
               if i == srv_fd {
                   println!("need to accept new connection");
                   accept_new = true;
                   //TODO move code?
               } else if i == child_stdout.as_raw_fd() {
                   println!("child fd {} (stdout) got active", i);
                   forward_to_remotes(&mut child_stdout, &clients);
               } else if i == child_stderr.as_raw_fd() {
                   println!("child fd {} (stderr) got active", i);
                   read_child(&mut child_stderr);
               } else {
                   assert!(clients.contains_key(&i));
                   let cont = {
                       //let ref stream = clients[&i];
                       let stream: &mut TcpStream= clients.get_mut(&i).unwrap();
                       //read_client(stream)
                       copy_to(stream, &mut child_stdin)
                   };
                   if !cont {
                       del_client(&mut all_fdset, &mut clients, i);
                   };
               }
               handled_fds += 1;
           }
       }
       assert_eq!(handled_fds, res);

       //accept new connection
       if accept_new {
           match listener.accept() {
               Err(e) => println!("couldn't get client: {:?}", e),
               Ok((mut stream, addr)) => {
                   println!("new client: {:?}", addr);
                   greet_client(&mut stream);
                   high_fd = std::cmp::max(high_fd, add_client(&mut all_fdset, &mut clients, stream));
                   println!("new high fd: {}", high_fd);
               }
           }
       }
    }
}
<commit_msg>preparing to handle child eof<commit_after>extern crate tinyrsh;

use std::collections::HashMap;
use std::net::{TcpListener, TcpStream};
use std::io::{Read, Write};
use std::os::unix::io::{RawFd, AsRawFd};
use tinyrsh::select as select;
use tinyrsh::select::FdSet;
use std::process::{Command, Stdio};

fn greet_client(mut stream: &TcpStream) {
    let remote = stream.peer_addr().unwrap();
    println!("connected: {}", remote);

    match stream.write(b"hello\n") {
        Err(e) => println!("{}", e),
        Ok(n) => println!("wrote {} bytes", n),
    };
}

fn debug_fdset(fdset: &FdSet) {
    let maxfds = select::FD_SETSIZE;
    for i in 0 .. maxfds {
        if fdset.contains(i) {
            println!("contains {}", i);
        }
    }
}

fn read_child<T: Read>(readt: &mut T) {
    let mut buf = [0; 10];
    let n = readt.read(&mut buf).expect("read_child");
    println!("{:?} ({} bytes) `{}'", buf, n, String::from_utf8_lossy(&buf[..n]));
}

fn forward_to_remotes<T: Read, S>(child_out: &mut T, clients: &HashMap<S, TcpStream>) -> bool
    where S : std::cmp::Eq, S : std::hash::Hash
{
    let mut buf = [0; 10];
    let n = child_out.read(&mut buf).expect("read_child");
    let child_eof = (n == 0);
    if clients.is_empty() {
        println!("Warning: child output but no remote connected");
        println!("{:?} ({} bytes) `{}'", buf, n, String::from_utf8_lossy(&buf[..n]));
    }
    for mut remote in clients.values(){
        //println!("forwarding to {}", remote.peer_addr().unwrap());
        let written = remote.write(&buf[..n]).expect("remote write");
        assert_eq!(n, written);
    }
    child_eof
}

fn copy_to<T: Read, U: Write>(from: &mut T, to: &mut U) -> bool {
    let mut buf = [0; 10];
    let n = from.read(&mut buf).expect("copy_to read");
    //println!("copy_to read {:?} ({} bytes) `{}'", buf, n, String::from_utf8_lossy(&buf[..n]));
    let written = to.write(&buf[..n]).expect("copy_to write");
    to.flush();
    assert_eq!(n, written);

    n != 0
}

fn spawn_child(cmd: &str) -> std::process::Child {
    //TODO, if I want to respawn the child, I either need to reuse the pipes or always get
    //everything out of the child struct
    Command::new(cmd)
            .stdin(Stdio::piped())
            .stdout(Stdio::piped())
            .stderr(Stdio::piped())
            .spawn()
            .expect("failed to execute process")
}

fn main() {
    println!("Hello, world!");

    let mut child = spawn_child("../py-ptysh/ptysh.py");
    println!("spawned child with pid {}", child.id());

    let mut child_stdin  = child.stdin.unwrap();
    let mut child_stdout = child.stdout.unwrap();
    let mut child_stderr = child.stderr.unwrap();
    // stderr == stdout? no, but py-ptysh copies everything to std out
    assert!(child_stdout.as_raw_fd() != child_stderr.as_raw_fd());

    // TODO linebuffered? how is child output buffered at all?

    let listener = TcpListener::bind("127.0.0.1:6699").unwrap();

    let mut all_fdset = FdSet::new();
    let srv_fd = listener.as_raw_fd(); // not consumed

    //high fd for select() call
    let mut high_fd = 0;

    for fd in [srv_fd, child_stdout.as_raw_fd(), child_stderr.as_raw_fd()].iter() {
        println!("inserting fd {}", fd);
        all_fdset.insert(*fd);
        high_fd = std::cmp::max(high_fd, *fd);
    };

    let mut clients: HashMap<RawFd, TcpStream> = HashMap::new(); //could also use FromRawFd

    fn add_client(all_fdset: &mut FdSet, clients: &mut HashMap<RawFd, TcpStream>, stream: TcpStream) -> RawFd {
        let stream_fd: RawFd = stream.as_raw_fd(); //not consume
        println!("inserted fd {}", stream_fd);
        clients.insert(stream_fd, stream);
        all_fdset.insert(stream_fd);
        stream_fd
    };
    fn del_client(all_fdset: &mut FdSet, clients: &mut HashMap<RawFd, TcpStream>, stream_fd: RawFd) {
        assert!(clients.contains_key(&stream_fd));
        //let stream = clients.get(&stream_fd);
        println!("removing fd {}", stream_fd);
        assert!(all_fdset.contains(stream_fd));
        all_fdset.remove(stream_fd);
        assert!(clients.contains_key(&stream_fd));
        clients.remove(&stream_fd);
    };

   println!("select-looping");
   loop {
       let mut fdset = all_fdset.clone();
       let res = select::select(high_fd + 1, Some(&mut fdset), None, None, None);
       assert!(res > 0);
       println!("selected returned {}", res);
       debug_fdset(&fdset);

       let mut accept_new = false;

       let mut handled_fds = 0;
       for i in 0 .. high_fd + 1 {
           if fdset.contains(i) {
               if i == srv_fd {
                   println!("need to accept new connection");
                   accept_new = true;
                   //TODO move code?
               } else if i == child_stdout.as_raw_fd() {
                   println!("child fd {} (stdout) got active", i);
                   let child_eof = forward_to_remotes(&mut child_stdout, &clients);
                   if child_eof {
                       println!("!!!!!!! child exited. pipe will break now");
                       //println!("exit code: {}", child.wait().expect("child unexpected state"));
                       //ahh, ownership!
                   }
                   assert!(!child_eof);
               } else if i == child_stderr.as_raw_fd() {
                   println!("child fd {} (stderr) got active", i);
                   read_child(&mut child_stderr);
               } else {
                   assert!(clients.contains_key(&i));
                   let cont = {
                       //let ref stream = clients[&i];
                       let stream: &mut TcpStream= clients.get_mut(&i).unwrap();
                       //read_client(stream)
                       copy_to(stream, &mut child_stdin)
                   };
                   if !cont {
                       del_client(&mut all_fdset, &mut clients, i);
                   };
               }
               handled_fds += 1;
           }
       }
       assert_eq!(handled_fds, res);

       //accept new connection
       if accept_new {
           match listener.accept() {
               Err(e) => println!("couldn't get client: {:?}", e),
               Ok((mut stream, addr)) => {
                   println!("new client: {:?}", addr);
                   greet_client(&mut stream);
                   high_fd = std::cmp::max(high_fd, add_client(&mut all_fdset, &mut clients, stream));
                   println!("new high fd: {}", high_fd);
               }
           }
       }
    }
}
<|endoftext|>


<commit_before>use ::ast::*;
use ::ast::ExprNode::*;
use super::*;
use super::parser_combinators::{Parser,parser};

#[test]
fn test_basic_ident() {
    assert_eq!(
        parser(expr).parse("ident"),
        Ok((Name(NameNode { name: "ident".to_string() }), ""))
        );
    assert_eq!(
        parser(expr).parse("a"),
        Ok((Name(NameNode { name: "a".to_string() }), ""))
        );
    assert_eq!(
        parser(expr).parse("ident_With\\special!Chars:~-+"),
        Ok((Name(NameNode { name: "ident_With\\special!Chars:~-+".to_string() }), ""))
        );
}

#[test]
fn test_basic_sexpr() {
    assert_eq!(
        parser(expr).parse("(ident arg1 arg2)"),
        Ok((SExpr(SExprNode {
            operator: NameNode { name: "ident".to_string() },
            operands: vec![
                Name(NameNode { name: "arg1".to_string() }),
                Name(NameNode { name: "arg2".to_string() })
            ]
        }), ""))
        );
}

#[test]
fn test_lex_sint_pos() {
    assert_eq!(
        parser(number).parse("1234"),
        Ok((NumNode::IntConst(IntNode { value: 1234isize }), ""))
        );
    assert_eq!(
        parser(number).parse("#d1234"),
        Ok((NumNode::IntConst(IntNode { value: 1234isize }), ""))
        );
    assert_eq!(
        parser(number).parse("#D1234"),
        Ok((NumNode::IntConst(IntNode { value: 1234isize }), ""))
        );
}

#[test]
fn test_lex_sint_neg() {
    assert_eq!(
        parser(number).parse("-1234"),
        Ok((NumNode::IntConst(IntNode { value: -1234isize }), ""))
        );
}

#[test]
fn test_lex_sint_hex() {
    assert_eq!(
        parser(number).parse("#x0ff"),
        Ok((NumNode::IntConst(IntNode { value: 0x0ffisize }), ""))
        );
    assert_eq!(
        parser(number).parse("#X0FF"),
        Ok((NumNode::IntConst(IntNode { value: 0x0ffisize }), ""))
        );
}
/* // Currently unsupported
#[test]
fn test_parse_sint_bin_upper() {
    assert_eq!(
        parser(number).parse("0B01"),
        Ok((NumNode::IntConst(IntNode { value: 0b01isize }), ""))
        );
    assert_eq!(
        parser(number).parse("0b01"),
        Ok((NumNode::IntConst(IntNode { value: 0b01isize }), ""))
        );
}*/

#[test]
fn test_lex_uint() {
    assert_eq!(
        parser(number).parse("1234u"),
        Ok((NumNode::UIntConst(UIntNode { value: 1234usize }), ""))
        );
    assert_eq!(
        parser(number).parse("4321U"),
        Ok((NumNode::UIntConst(UIntNode { value: 4321usize }), ""))
        );
}

#[test]
fn test_lex_uint_hex() {
    assert_eq!(
        parser(number).parse("#x0ffu"),
        Ok((NumNode::UIntConst(UIntNode { value: 0x0ffusize }), ""))
        );
    assert_eq!(
        parser(number).parse("#X0FFu"),
        Ok((NumNode::UIntConst(UIntNode { value: 0x0ffusize }), ""))
        );
}

#[test]
fn test_lex_float() {
    assert_eq!(
        parser(number).parse("1.0"),
        Ok((NumNode::FloatConst(FloatNode { value: 1.0f64 }), ""))
        );/* // Unsupported
    assert_eq!(
        parser(number).parse("1f").unwrap(),
        (NumNode::FloatConst(FloatNode { value: 1.0f64 }), "")
        );
    assert_eq!(
        parser(number).parse("22.2222").unwrap(),
        (NumNode::FloatConst(FloatNode { value: 22.2222f64 }), "")
        );
    assert_eq!(
        parser(number).parse("22.2222f").unwrap(),
        (NumNode::FloatConst(FloatNode { value: 22.2222f64 }), "")
        );*/
}

#[test]
fn test_lex_bool() {
    assert_eq!(
        parser(bool_const).parse("#t"),
        Ok((BoolNode { value: true}, ""))
        );
    assert_eq!(
        parser(bool_const).parse("#T"),
        Ok((BoolNode { value: true}, ""))
        );
    assert_eq!(
        parser(bool_const).parse("true"),
        Ok((BoolNode { value: true}, ""))
        );
    assert_eq!(
        parser(bool_const).parse("#f"),
        Ok((BoolNode { value: false}, ""))
        );
    assert_eq!(
        parser(bool_const).parse("#F"),
        Ok((BoolNode { value: false}, ""))
        );
    assert_eq!(
        parser(bool_const).parse("false"),
        Ok((BoolNode { value: false}, ""))
        );
}

#[test]
fn test_lex_char() {
    assert_eq!(
        parser(character).parse("#\\c"),
        Ok((CharNode { value: 'c'}, ""))
        );
    assert_eq!(
        parser(character).parse("#\\A"),
        Ok((CharNode { value: 'A'}, ""))
        );
    assert_eq!(
        parser(character).parse("#\\tab"),
        Ok((CharNode { value: '\t'}, ""))
        );
    assert_eq!(
        parser(character).parse("#\\newline"),
        Ok((CharNode { value: '\n'}, ""))
        );
    assert_eq!(
        parser(character).parse("#\\nul"),
        Ok((CharNode { value: '\u{0000}' }, ""))
        );
    assert_eq!(
        parser(character).parse("#\\backspace"),
        Ok((CharNode { value: '\u{0008}' }, ""))
        );
    assert_eq!(
        parser(character).parse("#\\vtab"),
        Ok((CharNode { value: '\u{000B}' }, ""))
        );
    assert_eq!(
        parser(character).parse("#\\page"),
        Ok((CharNode { value: '\u{000C}' }, ""))
        );
    assert_eq!(
        parser(character).parse("#\\return"),
        Ok((CharNode { value: '\u{000D}' }, ""))
        );
    assert_eq!(
        parser(character).parse("#\\esc"),
        Ok((CharNode { value: '\u{001B}' }, ""))
        );
    assert_eq!(
        parser(character).parse("#\\delete"),
        Ok((CharNode { value: '\u{007F}' }, ""))
        );
    assert_eq!(
        parser(character).parse("#\\alarm"),
        Ok((CharNode { value: '\u{0007}' }, ""))
        );
    assert_eq!(
        parser(character).parse("#\\linefeed"),
        Ok((CharNode { value: '\n'}, ""))
        );
    assert_eq!(
        parser(character).parse("#\\space"),
        Ok((CharNode { value: ' '}, ""))
        );
    assert_eq!(
        parser(character).parse("#\\x0020"),
        Ok((CharNode { value: ' '}, ""))
        );
    assert_eq!(
        parser(character).parse("#\\x001B"),
        Ok((CharNode { value: '\u{001B}' }, ""))
        );
}

#[test]
fn test_lex_string() {
    assert_eq!(
        parser(string_const).parse("\"a string\""),
        Ok((StringNode { value: "a string".to_string() }, ""))
    );
    assert_eq!(
        parser(string_const).parse("\"a string with a\\ttab\""),
        Ok((StringNode { value: "a string with a\ttab".to_string() },""))
    );
    assert_eq!(
        parser(string_const).parse("\"a string with an \\\"escaped\\\" quote\""),
        Ok((StringNode { value: "a string with an \"escaped\" quote".to_string() },""))
    );
    assert_eq!(
        parser(string_const).parse("\"the\\\\worst string ever\\\"\""),
        Ok((StringNode { value: "the\\worst string ever\"".to_string() }, ""))
    );
}
<commit_msg>Add tests for line comments<commit_after>use ::ast::*;
use ::ast::ExprNode::*;
use super::*;
use super::parser_combinators::{Parser,parser};

#[test]
fn test_line_comment() {
    assert_eq!(parser(line_comment).parse(";this is a fake line comment\n"),
        Ok(((),"")));
}

#[test]
fn test_line_comment_ignore() {
    assert_eq!(parser(expr).parse(
r#";this is a fake line comment
ident"#),
        Ok((Name(NameNode { name: "ident" }), ""))
        )
}

#[test]
fn test_basic_ident() {
    assert_eq!(
        parser(expr).parse("ident"),
        Ok((Name(NameNode { name: "ident".to_string() }), ""))
        );
    assert_eq!(
        parser(expr).parse("a"),
        Ok((Name(NameNode { name: "a".to_string() }), ""))
        );
    assert_eq!(
        parser(expr).parse("ident_With\\special!Chars:~-+"),
        Ok((Name(NameNode { name: "ident_With\\special!Chars:~-+".to_string() }), ""))
        );
}

#[test]
fn test_basic_sexpr() {
    assert_eq!(
        parser(expr).parse("(ident arg1 arg2)"),
        Ok((SExpr(SExprNode {
            operator: NameNode { name: "ident".to_string() },
            operands: vec![
                Name(NameNode { name: "arg1".to_string() }),
                Name(NameNode { name: "arg2".to_string() })
            ]
        }), ""))
        );
}

#[test]
fn test_lex_sint_pos() {
    assert_eq!(
        parser(number).parse("1234"),
        Ok((NumNode::IntConst(IntNode { value: 1234isize }), ""))
        );
    assert_eq!(
        parser(number).parse("#d1234"),
        Ok((NumNode::IntConst(IntNode { value: 1234isize }), ""))
        );
    assert_eq!(
        parser(number).parse("#D1234"),
        Ok((NumNode::IntConst(IntNode { value: 1234isize }), ""))
        );
}

#[test]
fn test_lex_sint_neg() {
    assert_eq!(
        parser(number).parse("-1234"),
        Ok((NumNode::IntConst(IntNode { value: -1234isize }), ""))
        );
}

#[test]
fn test_lex_sint_hex() {
    assert_eq!(
        parser(number).parse("#x0ff"),
        Ok((NumNode::IntConst(IntNode { value: 0x0ffisize }), ""))
        );
    assert_eq!(
        parser(number).parse("#X0FF"),
        Ok((NumNode::IntConst(IntNode { value: 0x0ffisize }), ""))
        );
}
/* // Currently unsupported
#[test]
fn test_parse_sint_bin_upper() {
    assert_eq!(
        parser(number).parse("0B01"),
        Ok((NumNode::IntConst(IntNode { value: 0b01isize }), ""))
        );
    assert_eq!(
        parser(number).parse("0b01"),
        Ok((NumNode::IntConst(IntNode { value: 0b01isize }), ""))
        );
}*/

#[test]
fn test_lex_uint() {
    assert_eq!(
        parser(number).parse("1234u"),
        Ok((NumNode::UIntConst(UIntNode { value: 1234usize }), ""))
        );
    assert_eq!(
        parser(number).parse("4321U"),
        Ok((NumNode::UIntConst(UIntNode { value: 4321usize }), ""))
        );
}

#[test]
fn test_lex_uint_hex() {
    assert_eq!(
        parser(number).parse("#x0ffu"),
        Ok((NumNode::UIntConst(UIntNode { value: 0x0ffusize }), ""))
        );
    assert_eq!(
        parser(number).parse("#X0FFu"),
        Ok((NumNode::UIntConst(UIntNode { value: 0x0ffusize }), ""))
        );
}

#[test]
fn test_lex_float() {
    assert_eq!(
        parser(number).parse("1.0"),
        Ok((NumNode::FloatConst(FloatNode { value: 1.0f64 }), ""))
        );/* // Unsupported
    assert_eq!(
        parser(number).parse("1f").unwrap(),
        (NumNode::FloatConst(FloatNode { value: 1.0f64 }), "")
        );
    assert_eq!(
        parser(number).parse("22.2222").unwrap(),
        (NumNode::FloatConst(FloatNode { value: 22.2222f64 }), "")
        );
    assert_eq!(
        parser(number).parse("22.2222f").unwrap(),
        (NumNode::FloatConst(FloatNode { value: 22.2222f64 }), "")
        );*/
}

#[test]
fn test_lex_bool() {
    assert_eq!(
        parser(bool_const).parse("#t"),
        Ok((BoolNode { value: true}, ""))
        );
    assert_eq!(
        parser(bool_const).parse("#T"),
        Ok((BoolNode { value: true}, ""))
        );
    assert_eq!(
        parser(bool_const).parse("true"),
        Ok((BoolNode { value: true}, ""))
        );
    assert_eq!(
        parser(bool_const).parse("#f"),
        Ok((BoolNode { value: false}, ""))
        );
    assert_eq!(
        parser(bool_const).parse("#F"),
        Ok((BoolNode { value: false}, ""))
        );
    assert_eq!(
        parser(bool_const).parse("false"),
        Ok((BoolNode { value: false}, ""))
        );
}

#[test]
fn test_lex_char() {
    assert_eq!(
        parser(character).parse("#\\c"),
        Ok((CharNode { value: 'c'}, ""))
        );
    assert_eq!(
        parser(character).parse("#\\A"),
        Ok((CharNode { value: 'A'}, ""))
        );
    assert_eq!(
        parser(character).parse("#\\tab"),
        Ok((CharNode { value: '\t'}, ""))
        );
    assert_eq!(
        parser(character).parse("#\\newline"),
        Ok((CharNode { value: '\n'}, ""))
        );
    assert_eq!(
        parser(character).parse("#\\nul"),
        Ok((CharNode { value: '\u{0000}' }, ""))
        );
    assert_eq!(
        parser(character).parse("#\\backspace"),
        Ok((CharNode { value: '\u{0008}' }, ""))
        );
    assert_eq!(
        parser(character).parse("#\\vtab"),
        Ok((CharNode { value: '\u{000B}' }, ""))
        );
    assert_eq!(
        parser(character).parse("#\\page"),
        Ok((CharNode { value: '\u{000C}' }, ""))
        );
    assert_eq!(
        parser(character).parse("#\\return"),
        Ok((CharNode { value: '\u{000D}' }, ""))
        );
    assert_eq!(
        parser(character).parse("#\\esc"),
        Ok((CharNode { value: '\u{001B}' }, ""))
        );
    assert_eq!(
        parser(character).parse("#\\delete"),
        Ok((CharNode { value: '\u{007F}' }, ""))
        );
    assert_eq!(
        parser(character).parse("#\\alarm"),
        Ok((CharNode { value: '\u{0007}' }, ""))
        );
    assert_eq!(
        parser(character).parse("#\\linefeed"),
        Ok((CharNode { value: '\n'}, ""))
        );
    assert_eq!(
        parser(character).parse("#\\space"),
        Ok((CharNode { value: ' '}, ""))
        );
    assert_eq!(
        parser(character).parse("#\\x0020"),
        Ok((CharNode { value: ' '}, ""))
        );
    assert_eq!(
        parser(character).parse("#\\x001B"),
        Ok((CharNode { value: '\u{001B}' }, ""))
        );
}

#[test]
fn test_lex_string() {
    assert_eq!(
        parser(string_const).parse("\"a string\""),
        Ok((StringNode { value: "a string".to_string() }, ""))
    );
    assert_eq!(
        parser(string_const).parse("\"a string with a\\ttab\""),
        Ok((StringNode { value: "a string with a\ttab".to_string() },""))
    );
    assert_eq!(
        parser(string_const).parse("\"a string with an \\\"escaped\\\" quote\""),
        Ok((StringNode { value: "a string with an \"escaped\" quote".to_string() },""))
    );
    assert_eq!(
        parser(string_const).parse("\"the\\\\worst string ever\\\"\""),
        Ok((StringNode { value: "the\\worst string ever\"".to_string() }, ""))
    );
}
<|endoftext|>


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

#![feature(globs, macro_rules, phase, thread_local, link_args)]

#![allow(experimental, non_camel_case_types)]
#![deny(unused_imports, unused_variables, unused_mut)]

#![feature(phase)]
#[phase(plugin, link)]
extern crate log;
#[phase(plugin)]
extern crate "plugins" as servo_plugins;

extern crate servo;
extern crate compositing;

extern crate azure;
extern crate geom;
extern crate gfx;
extern crate gleam;
extern crate glfw;
extern crate glfw_app;
extern crate js;
extern crate layers;
extern crate png;
extern crate script;

extern crate "net" as servo_net;
extern crate "msg" as servo_msg;
extern crate "util" as servo_util;
extern crate style;
extern crate stb_image;

extern crate green;
extern crate native;
extern crate rustrt;
extern crate libc;
extern crate "url" as std_url;

#[cfg(target_os="macos")]
extern crate cgl;
#[cfg(target_os="macos")]
extern crate cocoa;
#[cfg(target_os="macos")]
extern crate core_graphics;
#[cfg(target_os="macos")]
extern crate core_text;

// Must come first.
pub mod macros;

pub mod browser;
pub mod browser_host;
pub mod command_line;
pub mod cookie;
pub mod core;
pub mod drag_data;
pub mod eutil;
pub mod frame;
pub mod interfaces;
pub mod print_settings;
pub mod process_message;
pub mod render_handler;
pub mod request;
pub mod request_context;
pub mod response;
pub mod stream;
pub mod string;
pub mod string_list;
pub mod string_map;
pub mod string_multimap;
pub mod stubs;
pub mod switches;
pub mod task;
pub mod types;
pub mod urlrequest;
pub mod v8;
pub mod values;
pub mod window;
pub mod wrappers;
pub mod xml_reader;
pub mod zip_reader;
<commit_msg>auto merge of #4446 : Ms2ger/servo/green, r=metajack<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![feature(globs, macro_rules, phase, thread_local, link_args)]

#![allow(experimental, non_camel_case_types)]
#![deny(unused_imports, unused_variables, unused_mut)]

#![feature(phase)]
#[phase(plugin, link)]
extern crate log;
#[phase(plugin)]
extern crate "plugins" as servo_plugins;

extern crate servo;
extern crate compositing;

extern crate azure;
extern crate geom;
extern crate gfx;
extern crate gleam;
extern crate glfw;
extern crate glfw_app;
extern crate js;
extern crate layers;
extern crate png;
extern crate script;

extern crate "net" as servo_net;
extern crate "msg" as servo_msg;
extern crate "util" as servo_util;
extern crate style;
extern crate stb_image;

extern crate native;
extern crate rustrt;
extern crate libc;
extern crate "url" as std_url;

#[cfg(target_os="macos")]
extern crate cgl;
#[cfg(target_os="macos")]
extern crate cocoa;
#[cfg(target_os="macos")]
extern crate core_graphics;
#[cfg(target_os="macos")]
extern crate core_text;

// Must come first.
pub mod macros;

pub mod browser;
pub mod browser_host;
pub mod command_line;
pub mod cookie;
pub mod core;
pub mod drag_data;
pub mod eutil;
pub mod frame;
pub mod interfaces;
pub mod print_settings;
pub mod process_message;
pub mod render_handler;
pub mod request;
pub mod request_context;
pub mod response;
pub mod stream;
pub mod string;
pub mod string_list;
pub mod string_map;
pub mod string_multimap;
pub mod stubs;
pub mod switches;
pub mod task;
pub mod types;
pub mod urlrequest;
pub mod v8;
pub mod values;
pub mod window;
pub mod wrappers;
pub mod xml_reader;
pub mod zip_reader;
<|endoftext|>


<commit_before>// vim: tw=80
//! Integration tests for mock!{}

use mockall_derive::*;

// Semiautomatic style mocking with associated types
mod associated_types_mock {
    use super::*;

    mock! {
        MyIter {}
        trait Iterator {
            type Item=u32;

            fn next(&mut self) -> Option<u32>;
        }
    }

    #[test]
    fn t() {
        let mut mock = MockMyIter::default();
        mock.expect_next()
            .returning(|_| Some(5));
        assert_eq!(5, mock.next().unwrap());
    }
}

/// Mock a struct whose definition is inaccessible
mod external_struct {
    use super::*;

    // A struct with a definition like this:
    // struct ExternalStruct {
    //     _x: i16
    // }
    // impl ExternalStruct {
    //     fn foo(&self, _x: u32) -> u32 {
    //         42
    //     }
    // }
    // Could be mocked like this:
    mock!{
        ExternalStruct {
            fn foo(&self, x: u32) -> u32;
        }
    }

    #[test]
    fn t() {
        let mut mock = MockExternalStruct::default();
        mock.expect_foo()
            .returning(|x| x + 1);
        assert_eq!(6, mock.foo(5));
    }
}

/// Use mock! to mock a generic struct
mod external_generic_struct {
    use super::*;

    // A struct with a definition like this:
    // pub struct ExtGenericStruct<T: Clone> {
    //     _x: i16
    // }
    // impl<T: Clone> ExtGenericStruct<T> {
    //     fn foo(&self, _x: T) -> T {
    //         42
    //     }
    // }
    // Could be mocked like this:
    mock!{
        pub ExtGenericStruct<T: Clone + 'static> {
            fn foo(&self, x: T) -> T;
        }
    }

    #[test]
    fn t() {
        let mut mock = MockExtGenericStruct::<u32>::default();
        mock.expect_foo()
            .returning(|x| x.clone());
        assert_eq!(5, mock.foo(5));
    }
}

mod external_struct_with_trait {
    use super::*;

    trait Bar {
        fn bar(&self, _x: u32) -> u32;
    }

    // A struct with a definition like this:
    // struct ExternalStruct {
    //     _x: i16
    // }
    // impl ExternalStruct {
    //     fn foo(&self, _x: u32) -> u32 {
    //         42
    //     }
    // }
    // impl Bar for ExternalStruct {
    //     fn bar(&self, _x: u32) -> u32 {
    //         42
    //     }
    // }
    //
    // Could be mocked like this:
    mock!{
        ExternalStruct {
            fn foo(&self, x: u32) -> u32;
        }
        trait Bar {
            fn bar(&self, _x: u32) -> u32;
        }
    }

    #[test]
    fn t() {
        let mut mock = MockExternalStruct::default();
        mock.expect_foo()
            .returning(|x| x + 1);
        mock.expect_bar()
            .returning(|x| x - 1);
        assert_eq!(6, mock.foo(5));
        assert_eq!(4, mock.bar(5));
    }
}

/// Use mock! to mock a generic struct
mod generic_struct_with_generic_trait {
    use super::*;

    trait Foo<T: 'static> {
        fn foo(&self, x: T) -> T;
    }
    mock! {
        ExternalStruct<T: 'static, Z: 'static> {}
        trait Foo<T: 'static> {
            fn foo(&self, x: T) -> T;
        }
    }

    #[test]
    fn t() {
        let mut mock = MockExternalStruct::<u32, u64>::default();
        mock.expect_foo()
            .returning(|x| x);
        assert_eq!(5u32, mock.foo(5u32));
    }
}

mod inherited_trait {
    use super::*;

    trait A {
        fn foo(&self);
    }

    trait B: A {
        fn bar(&self);
    }

    mock!{
        B {}
        trait A {
            fn foo(&self);
        }
        trait B {
            fn bar(&self);
        }
    }

    #[test]
    fn t() {
        let mut mock = MockB::default();
        mock.expect_foo().returning(|_| ());
        mock.expect_bar().returning(|_| ());
        mock.foo();
        mock.bar();
    }
}
<commit_msg>Add a test for mock! on multiple traits<commit_after>// vim: tw=80
//! Integration tests for mock!{}

use mockall_derive::*;

// Semiautomatic style mocking with associated types
mod associated_types_mock {
    use super::*;

    mock! {
        MyIter {}
        trait Iterator {
            type Item=u32;

            fn next(&mut self) -> Option<u32>;
        }
    }

    #[test]
    fn t() {
        let mut mock = MockMyIter::default();
        mock.expect_next()
            .returning(|_| Some(5));
        assert_eq!(5, mock.next().unwrap());
    }
}

/// Mock a struct whose definition is inaccessible
mod external_struct {
    use super::*;

    // A struct with a definition like this:
    // struct ExternalStruct {
    //     _x: i16
    // }
    // impl ExternalStruct {
    //     fn foo(&self, _x: u32) -> u32 {
    //         42
    //     }
    // }
    // Could be mocked like this:
    mock!{
        ExternalStruct {
            fn foo(&self, x: u32) -> u32;
        }
    }

    #[test]
    fn t() {
        let mut mock = MockExternalStruct::default();
        mock.expect_foo()
            .returning(|x| x + 1);
        assert_eq!(6, mock.foo(5));
    }
}

/// Use mock! to mock a generic struct
mod external_generic_struct {
    use super::*;

    // A struct with a definition like this:
    // pub struct ExtGenericStruct<T: Clone> {
    //     _x: i16
    // }
    // impl<T: Clone> ExtGenericStruct<T> {
    //     fn foo(&self, _x: T) -> T {
    //         42
    //     }
    // }
    // Could be mocked like this:
    mock!{
        pub ExtGenericStruct<T: Clone + 'static> {
            fn foo(&self, x: T) -> T;
        }
    }

    #[test]
    fn t() {
        let mut mock = MockExtGenericStruct::<u32>::default();
        mock.expect_foo()
            .returning(|x| x.clone());
        assert_eq!(5, mock.foo(5));
    }
}

mod external_struct_with_trait {
    use super::*;

    trait Bar {
        fn bar(&self, _x: u32) -> u32;
    }

    // A struct with a definition like this:
    // struct ExternalStruct {
    //     _x: i16
    // }
    // impl ExternalStruct {
    //     fn foo(&self, _x: u32) -> u32 {
    //         42
    //     }
    // }
    // impl Bar for ExternalStruct {
    //     fn bar(&self, _x: u32) -> u32 {
    //         42
    //     }
    // }
    //
    // Could be mocked like this:
    mock!{
        ExternalStruct {
            fn foo(&self, x: u32) -> u32;
        }
        trait Bar {
            fn bar(&self, _x: u32) -> u32;
        }
    }

    #[test]
    fn t() {
        let mut mock = MockExternalStruct::default();
        mock.expect_foo()
            .returning(|x| x + 1);
        mock.expect_bar()
            .returning(|x| x - 1);
        assert_eq!(6, mock.foo(5));
        assert_eq!(4, mock.bar(5));
    }
}

/// Use mock! to mock a generic struct
mod generic_struct_with_generic_trait {
    use super::*;

    trait Foo<T: 'static> {
        fn foo(&self, x: T) -> T;
    }
    mock! {
        ExternalStruct<T: 'static, Z: 'static> {}
        trait Foo<T: 'static> {
            fn foo(&self, x: T) -> T;
        }
    }

    #[test]
    fn t() {
        let mut mock = MockExternalStruct::<u32, u64>::default();
        mock.expect_foo()
            .returning(|x| x);
        assert_eq!(5u32, mock.foo(5u32));
    }
}

mod inherited_trait {
    use super::*;

    trait A {
        fn foo(&self);
    }

    trait B: A {
        fn bar(&self);
    }

    mock!{
        B {}
        trait A {
            fn foo(&self);
        }
        trait B {
            fn bar(&self);
        }
    }

    #[test]
    fn t() {
        let mut mock = MockB::default();
        mock.expect_foo().returning(|_| ());
        mock.expect_bar().returning(|_| ());
        mock.foo();
        mock.bar();
    }
}

#[allow(unused)]
mod multi_trait {
    use super::*;

    trait A {}
    trait B {}
    mock!{
        MultiTrait {}
        trait A  {}
        trait B  {}
    }

    #[test]
    fn t() {
        fn foo<T: A + B>(_t: T) {}

        let mock = MockMultiTrait::default();
        foo(mock);
    }
}
<|endoftext|>


<commit_before>static EPOCH_LEN: int = 146097;
static MONTHDAY: [int, ..12] = [
    0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
];

/// Convert an ISO 8601 date to a chronological Julian day.
pub fn to_cjd(year: int, month: int, day: int) -> int {
    let y = year - 2000;
    let mut a = y % 400;
    let mut b = y / 400;
    if a < 0 {
        a += 400;
        b -= 1;
    }
    let mut leap = 1 + a / 4 - a / 100;
    if month <= 2 && (a % 4) == 0 && ((a % 100) != 0 || a == 0) {
        leap -= 1;
    }
    146097 * b + 365 * a + MONTHDAY[(month - 1) as uint] + day - 1 + leap
}

/// Convert a chronological Julian day to an ISO 8601 date.
pub fn from_cjd(cjd: int) -> (int, int, int) {
    let mut t1 = cjd / EPOCH_LEN;
    let mut d = cjd % EPOCH_LEN;
    if d < 0 {
        t1 -= 1;
        d += EPOCH_LEN;
    }
    let y = t1 * 400 + 2000;

    let t2 = (d - 1) / 36524;
    let d = (d - 1) % 36524;
    let y = y + t2 * 100;

    let t3 = (d + 1) / 1461;
    let d = (d + 1) % 1461;
    let y = y + t3 * 4;

    let t4 = (d - 1) / 365;
    let d = (d - 1) % 365;
    let y = y + t4;

    let mut m = d / 29 + 1;
    if m > 12 || (m > 1 && d < MONTHDAY[(m - 1) as uint]) {
        m -= 1;
    }

    let mut d = d - MONTHDAY[(m - 1) as uint] + 1;
    if t4 == 0 && (t3 != 0 || t2 == 0) && m <= 2 {
        d += 1;
        if d == 32 {
            m = 2;
            d = 1;
        }
    }

    (y, m, d)
}

#[test]
fn cjd_point() {
    fn test(cjd: int, y: int, m: int, d: int) {
        let out_cjd = to_cjd(y, m, d);
        if out_cjd != cjd {
            fail!("{:04d}-{:02d}-{:02d}: expected {}, got {}",
                  y, m, d, cjd, out_cjd);
        }

        let (y2, m2, d2) = from_cjd(cjd);
        if y != y2 || m != m2 || d != d2 {
            fail!("{}: expected {:04d}-{:02d}-{:02d}, got {:04d}-{:02d}-{:02d}",
                  cjd, y, m, d, y2, m2, d2);
        }
    }

    test(0, 2000, 1, 1);
    test(1, 2000, 1, 2);
    test(-1, 1999, 12, 31);
    test(146097, 2400, 1, 1);
    test(-146097, 1600, 1, 1);
}

#[test]
fn cjd_range() {
    static MONTHS: [int, ..12] = [
        31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
    ];

    fn test_range(start: int, end: int) {
        let mut y = start;
        let mut m = 1;
        let mut d = 1;
        let mut last_cjd = to_cjd(y, m, d) - 1;
        while y < end {
            let cjd = to_cjd(y, m, d);
            if cjd != last_cjd + 1 {
                fail!("Nonconsecutive date.");
            }
            last_cjd = cjd;
            let (y2, m2, d2) = from_cjd(cjd);
            if y != y2 || m != m2 || d != d2 {
                fail!("Bad conversion: {:04d}-{:02d}-{:02d} to {} to {:04d}-{:02d}-{:02d}",
                      y, m, d, cjd, y2, m2, d2);
            }
            d += 1;
            if d > MONTHS[(m - 1) as uint] {
                let is_leap = m == 2 && d == 29 && (y % 4) == 0 &&
                              ((y % 100) != 0 || (y % 400) == 0);
                if !is_leap {
                    m += 1;
                    d = 1;
                    if m >= 13 {
                        m = 1;
                        y += 1;
                    }
                }
            }
        }
    }

    test_range(1596, 2404);
}
<commit_msg>Simplify calendrical conversion functions<commit_after>use std::num::div_rem;
use div_mod::div_mod;

static EPOCH_LEN: int = 146097;
static MONTHDAY: [int, ..12] = [
    0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
];

/// Convert an ISO 8601 date to a chronological Julian day.
pub fn to_cjd(year: int, month: int, day: int) -> int {
    let y = year - 2000;
    let (b, a) = div_mod(y, 400);
    let mut leap = 1 + a / 4 - a / 100;
    if month <= 2 && (a % 4) == 0 && ((a % 100) != 0 || a == 0) {
        leap -= 1;
    }
    146097 * b + 365 * a + MONTHDAY[(month - 1) as uint] + day - 1 + leap
}

/// Convert a chronological Julian day to an ISO 8601 date.
pub fn from_cjd(cjd: int) -> (int, int, int) {
    let (t1, d) = div_mod(cjd, EPOCH_LEN);
    let (t2, d) = div_rem(d - 1, 36524);
    let (t3, d) = div_rem(d + 1, 1461);
    let (t4, d) = div_rem(d - 1, 365);
    let y = 2000 + t1 * 400 + t2 * 100 + t3 * 4 + t4;

    let mut m = d / 29 + 1;
    if m > 12 || (m > 1 && d < MONTHDAY[(m - 1) as uint]) {
        m -= 1;
    }

    let mut d = d - MONTHDAY[(m - 1) as uint] + 1;
    if t4 == 0 && (t3 != 0 || t2 == 0) && m <= 2 {
        d += 1;
        if d == 32 {
            m = 2;
            d = 1;
        }
    }

    (y, m, d)
}

#[test]
fn cjd_point() {
    fn test(cjd: int, y: int, m: int, d: int) {
        let out_cjd = to_cjd(y, m, d);
        if out_cjd != cjd {
            fail!("{:04d}-{:02d}-{:02d}: expected {}, got {}",
                  y, m, d, cjd, out_cjd);
        }

        let (y2, m2, d2) = from_cjd(cjd);
        if y != y2 || m != m2 || d != d2 {
            fail!("{}: expected {:04d}-{:02d}-{:02d}, got {:04d}-{:02d}-{:02d}",
                  cjd, y, m, d, y2, m2, d2);
        }
    }

    test(0, 2000, 1, 1);
    test(1, 2000, 1, 2);
    test(-1, 1999, 12, 31);
    test(146097, 2400, 1, 1);
    test(-146097, 1600, 1, 1);
}

#[test]
fn cjd_range() {
    static MONTHS: [int, ..12] = [
        31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
    ];

    fn test_range(start: int, end: int) {
        let mut y = start;
        let mut m = 1;
        let mut d = 1;
        let mut last_cjd = to_cjd(y, m, d) - 1;
        while y < end {
            let cjd = to_cjd(y, m, d);
            if cjd != last_cjd + 1 {
                fail!("Nonconsecutive date.");
            }
            last_cjd = cjd;
            let (y2, m2, d2) = from_cjd(cjd);
            if y != y2 || m != m2 || d != d2 {
                fail!("Bad conversion: {:04d}-{:02d}-{:02d} to {} to {:04d}-{:02d}-{:02d}",
                      y, m, d, cjd, y2, m2, d2);
            }
            d += 1;
            if d > MONTHS[(m - 1) as uint] {
                let is_leap = m == 2 && d == 29 && (y % 4) == 0 &&
                              ((y % 100) != 0 || (y % 400) == 0);
                if !is_leap {
                    m += 1;
                    d = 1;
                    if m >= 13 {
                        m = 1;
                        y += 1;
                    }
                }
            }
        }
    }

    test_range(1596, 2404);
}
<|endoftext|>


<commit_before>use bot::LalafellBot;
use discord::model::{Event, ChannelId, UserId, Channel, ServerId, Member};
use database::models::AutoReply;
use filters::Filter;
use error::*;

use lalafell::listeners::ReceivesEvents;

use diesel::prelude::*;

use chrono::Utc;

use std::sync::{Arc, Mutex};
use std::collections::HashMap;

pub struct AutoReplyListener {
  bot: Arc<LalafellBot>,
  last_sends: Mutex<HashMap<(UserId, ChannelId), i64>>
}

impl AutoReplyListener {
  pub fn new(bot: Arc<LalafellBot>) -> AutoReplyListener {
    AutoReplyListener {
      bot: bot,
      last_sends: Mutex::default()
    }
  }
}

enum UserIdOrMember {
  UserId(UserId),
  Member(Member)
}

impl ReceivesEvents for AutoReplyListener {
  fn receive(&self, event: &Event) {
    let current_user = try_or!(self.bot.discord.get_current_user(), return);
    let replies: Option<(Result<Vec<AutoReply>>, UserIdOrMember, ServerId)> = ::bot::CONNECTION.with(|c| {
      use database::schema::auto_replies::dsl;
      match *event {
        Event::ServerMemberAdd(ref server_id, ref member) if member.user.id != current_user.id => {
          Some((
            dsl::auto_replies
              .filter(dsl::server_id.eq(server_id.0.to_string())
                .and(dsl::on_join.eq(true)))
              .load(c)
              .chain_err(|| "could not load auto_replies"),
            UserIdOrMember::Member(member.clone()),
            *server_id
          ))
        }
        Event::MessageCreate(ref m) if m.author.id != current_user.id => {
          Some((
            dsl::auto_replies
              .filter(dsl::channel_id.eq(m.channel_id.0.to_string())
                .and(dsl::on_join.eq(false)))
              .load(c)
              .chain_err(|| "could not load auto_replies"),
            UserIdOrMember::UserId(m.author.id),
            match self.bot.discord.get_channel(m.channel_id) {
              Ok(Channel::Public(c)) => c.server_id,
              Ok(_) => {
                warn!("wrong type of channel for auto reply");
                return None;
              }
              Err(e) => {
                warn!("could not get channel for auto reply: {}", e);
                return None;
              }
            }
          ))
        }
        _ => None
      }
    });
    let (replies, user, server) = some_or!(replies, return);
    let live_server = {
      let state_opt = self.bot.state.read().unwrap();
      let state = state_opt.as_ref().unwrap();
      let s = state.servers().iter().find(|s| s.id == server);
      match s {
        Some(s) => s.clone(),
        None => {
          warn!("could not find server for auto reply: {}", server);
          return;
        }
      }
    };
    let member = match user {
      UserIdOrMember::Member(m) => m,
      UserIdOrMember::UserId(u) => match live_server.members.iter().find(|m| m.user.id == u) {
        Some(m) => m.clone(),
        None => {
          warn!("could not find member for auto reply");
          return;
        }
      }
    };
    let roles = live_server.roles;
    let mut last_sends = self.last_sends.lock().unwrap();
    for reply in try_or!(replies, return) {
      if let Some(ref filters_string) = reply.filters {
        match filters_string.split(' ').map(Filter::parse).collect::<Option<Vec<_>>>() {
          Some(filters) => if !filters.iter().all(|f| f.matches(&member, &roles)) {
            continue;
          },
          None => warn!("invalid filters: `{}`", filters_string)
        }
      }
      let last_send = last_sends.entry((member.user.id, ChannelId(*reply.channel_id))).or_insert(0);
      if *last_send + reply.delay as i64 >= Utc::now().timestamp() {
        continue;
      }
      self.bot.discord.send_embed(ChannelId(*reply.channel_id), "", |e| e.description(&reply.message.replace("{mention}", &member.user.mention().to_string()))).ok();
      *last_send = Utc::now().timestamp()
    }
  }
}
<commit_msg>fix: don't check based on channel, check based on reply ID<commit_after>use bot::LalafellBot;
use discord::model::{Event, ChannelId, UserId, Channel, ServerId, Member};
use database::models::AutoReply;
use filters::Filter;
use error::*;

use lalafell::listeners::ReceivesEvents;

use diesel::prelude::*;

use chrono::Utc;

use std::sync::{Arc, Mutex};
use std::collections::HashMap;

pub struct AutoReplyListener {
  bot: Arc<LalafellBot>,
  last_sends: Mutex<HashMap<(UserId, i32), i64>>
}

impl AutoReplyListener {
  pub fn new(bot: Arc<LalafellBot>) -> AutoReplyListener {
    AutoReplyListener {
      bot: bot,
      last_sends: Mutex::default()
    }
  }
}

enum UserIdOrMember {
  UserId(UserId),
  Member(Member)
}

impl ReceivesEvents for AutoReplyListener {
  fn receive(&self, event: &Event) {
    let current_user = try_or!(self.bot.discord.get_current_user(), return);
    let replies: Option<(Result<Vec<AutoReply>>, UserIdOrMember, ServerId)> = ::bot::CONNECTION.with(|c| {
      use database::schema::auto_replies::dsl;
      match *event {
        Event::ServerMemberAdd(ref server_id, ref member) if member.user.id != current_user.id => {
          Some((
            dsl::auto_replies
              .filter(dsl::server_id.eq(server_id.0.to_string())
                .and(dsl::on_join.eq(true)))
              .load(c)
              .chain_err(|| "could not load auto_replies"),
            UserIdOrMember::Member(member.clone()),
            *server_id
          ))
        }
        Event::MessageCreate(ref m) if m.author.id != current_user.id => {
          Some((
            dsl::auto_replies
              .filter(dsl::channel_id.eq(m.channel_id.0.to_string())
                .and(dsl::on_join.eq(false)))
              .load(c)
              .chain_err(|| "could not load auto_replies"),
            UserIdOrMember::UserId(m.author.id),
            match self.bot.discord.get_channel(m.channel_id) {
              Ok(Channel::Public(c)) => c.server_id,
              Ok(_) => {
                warn!("wrong type of channel for auto reply");
                return None;
              }
              Err(e) => {
                warn!("could not get channel for auto reply: {}", e);
                return None;
              }
            }
          ))
        }
        _ => None
      }
    });
    let (replies, user, server) = some_or!(replies, return);
    let live_server = {
      let state_opt = self.bot.state.read().unwrap();
      let state = state_opt.as_ref().unwrap();
      let s = state.servers().iter().find(|s| s.id == server);
      match s {
        Some(s) => s.clone(),
        None => {
          warn!("could not find server for auto reply: {}", server);
          return;
        }
      }
    };
    let member = match user {
      UserIdOrMember::Member(m) => m,
      UserIdOrMember::UserId(u) => match live_server.members.iter().find(|m| m.user.id == u) {
        Some(m) => m.clone(),
        None => {
          warn!("could not find member for auto reply");
          return;
        }
      }
    };
    let roles = live_server.roles;
    let mut last_sends = self.last_sends.lock().unwrap();
    for reply in try_or!(replies, return) {
      if let Some(ref filters_string) = reply.filters {
        match filters_string.split(' ').map(Filter::parse).collect::<Option<Vec<_>>>() {
          Some(filters) => if !filters.iter().all(|f| f.matches(&member, &roles)) {
            continue;
          },
          None => warn!("invalid filters: `{}`", filters_string)
        }
      }
      let last_send = last_sends.entry((member.user.id, reply.id)).or_insert(0);
      if *last_send + reply.delay as i64 >= Utc::now().timestamp() {
        continue;
      }
      self.bot.discord.send_embed(ChannelId(*reply.channel_id), "", |e| e.description(&reply.message.replace("{mention}", &member.user.mention().to_string()))).ok();
      *last_send = Utc::now().timestamp()
    }
  }
}
<|endoftext|>


<commit_before>// This tests that the size of Option<Box<i32>> is the same as *const i32.
fn option_box_deref() -> i32 {
    let val = Some(Box::new(42));
    unsafe {
        let ptr: *const i32 = std::mem::transmute::<Option<Box<i32>>, *const i32>(val);
        *ptr
    }
}

fn main() {
    assert_eq!(option_box_deref(), 42);
}
<commit_msg>remove memory leak from run-pass test<commit_after>// This tests that the size of Option<Box<i32>> is the same as *const i32.
fn option_box_deref() -> i32 {
    let val = Some(Box::new(42));
    unsafe {
        let ptr: *const i32 = std::mem::transmute::<Option<Box<i32>>, *const i32>(val);
        let ret = *ptr;
        // unleak memory
        std::mem::transmute::<*const i32, Option<Box<i32>>>(ptr);
        ret
    }
}

fn main() {
    assert_eq!(option_box_deref(), 42);
}
<|endoftext|>