<commit_before>// Copyright 2017 The rust-url developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!

This crate provides wrappers and convenience functions to make rust-url
and Serde work hand in hand.

The supported types are:

* `url::Url`

# How do I use a data type with a `Url` member with Serde?

Use the serde attributes `deserialize_with` and `serialize_with`.

```
#[derive(serde::Serialize, serde::Deserialize)]
struct MyStruct {
    #[serde(serialize_with = "serialize")]
    url: Url,
}
```

# How do I encode a `Url` value with `serde_json::to_string`?

Use the `Ser` wrapper.

```
serde_json::to_string(&Ser::new(&url))
```

# How do I decode a `Url` value with `serde_json::parse`?

Use the `De` wrapper.

```
serde_json::from_str(r"http:://www.rust-lang.org").map(De::into_inner)
```

# How do I send `Url` values as part of an IPC channel?

Use the `Serde` wrapper. It implements `Deref` and `DerefMut` for convenience.

```
ipc::channel::<Serde<Url>>()
```
*/

#![deny(missing_docs)]
#![deny(unsafe_code)]

extern crate serde;
#[cfg(test)] #[macro_use] extern crate serde_derive;
#[cfg(test)] extern crate serde_json;
extern crate url;

use serde::{Deserialize, Serialize, Serializer, Deserializer};
use std::cmp::PartialEq;
use std::error::Error;
use std::fmt;
use std::io::Write;
use std::ops::{Deref, DerefMut};
use std::str;
use url::{Url, Host};

/// Serialises `value` with a given serializer.
///
/// This is useful to serialize `rust-url` types used in structure fields or
/// tuple members with `#[serde(serialize_with = "url_serde::serialize")]`.
pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
    where S: Serializer, for<'a> Ser<'a, T>: Serialize
{
    Ser::new(value).serialize(serializer)
}

/// A wrapper to serialize `rust-url` types.
///
/// This is useful with functions such as `serde_json::to_string`.
///
/// Values of this type can only be passed to the `serde::Serialize` trait.
#[derive(Debug)]
pub struct Ser<'a, T: 'a>(&'a T);

impl<'a, T> Ser<'a, T> where Ser<'a, T>: Serialize {
    /// Returns a new `Ser` wrapper.
    #[inline(always)]
    pub fn new(value: &'a T) -> Self {
        Ser(value)
    }
}

/// Serializes this URL into a `serde` stream.
impl<'a> Serialize for Ser<'a, Url> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        serializer.serialize_str(self.0.as_str())
    }
}

/// Serializes this Option<URL> into a `serde` stream.
impl<'a> Serialize for Ser<'a, Option<Url>> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        if let Some(url) = self.0.as_ref() {
            serializer.serialize_some(url.as_str())
        } else {
            serializer.serialize_none()
        }
    }
}

impl<'a, String> Serialize for Ser<'a, Host<String>> where String: AsRef<str> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        match *self.0 {
            Host::Domain(ref s) => serializer.serialize_str(s.as_ref()),
            Host::Ipv4(_) | Host::Ipv6(_) => {
                // max("101.102.103.104".len(),
                //     "[1000:1002:1003:1004:1005:1006:101.102.103.104]".len())
                const MAX_LEN: usize = 47;
                let mut buffer = [0; MAX_LEN];
                serializer.serialize_str(display_into_buffer(&self.0, &mut buffer))
            }
        }
    }
}

/// Like .to_string(), but doesn’t allocate memory for a `String`.
///
/// Panics if `buffer` is too small.
fn display_into_buffer<'a, T: fmt::Display>(value: &T, buffer: &'a mut [u8]) -> &'a str {
    let remaining_len;
    {
        let mut remaining = &mut *buffer;
        write!(remaining, "{}", value).unwrap();
        remaining_len = remaining.len()
    }
    let written_len = buffer.len() - remaining_len;
    let written = &buffer[..written_len];

    // write! only provides std::fmt::Formatter to Display implementations,
    // which has methods write_str and write_char but no method to write arbitrary bytes.
    // Therefore, `written` is well-formed in UTF-8.
    #[allow(unsafe_code)]
    unsafe {
        str::from_utf8_unchecked(written)
    }
}

/// Deserialises a `T` value with a given deserializer.
///
/// This is useful to deserialize Url types used in structure fields or
/// tuple members with `#[serde(deserialize_with = "url_serde::deserialize")]`.
pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error>
    where D: Deserializer<'de>, De<T>: Deserialize<'de>
{
    De::deserialize(deserializer).map(De::into_inner)
}

/// A wrapper to deserialize `rust-url` types.
///
/// This is useful with functions such as `serde_json::from_str`.
///
/// Values of this type can only be obtained through
/// the `serde::Deserialize` trait.
#[derive(Debug)]
pub struct De<T>(T);

impl<'de, T> De<T> where De<T>: serde::Deserialize<'de> {
    /// Consumes this wrapper, returning the deserialized value.
    #[inline(always)]
    pub fn into_inner(self) -> T {
        self.0
    }
}

/// Deserializes this URL from a `serde` stream.
impl<'de> Deserialize<'de> for De<Url> {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
        let string_representation: String = Deserialize::deserialize(deserializer)?;
        Url::parse(&string_representation).map(De).map_err(|err| {
            serde::de::Error::custom(err.description())
        })
    }
}

/// Deserializes this Option<URL> from a `serde` stream.
impl<'de> Deserialize<'de> for De<Option<Url>> {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
        let option_representation: Option<String> = Deserialize::deserialize(deserializer)?;
        if let Some(s) = option_representation {
            return Url::parse(&s)
                .map(Some)
                .map(De)
                .map_err(|err| {serde::de::Error::custom(err.description())});
        }
        Ok(De(None))

    }
}

impl<'de> Deserialize<'de> for De<Host> {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
        let string_representation: String = Deserialize::deserialize(deserializer)?;
        Host::parse(&string_representation).map(De).map_err(|err| {
            serde::de::Error::custom(err.description())
        })
    }
}

/// A convenience wrapper to be used as a type parameter, for example when
/// a `Vec<T>` or an `HashMap<K, V>` need to be passed to serde.
#[derive(Clone, Eq, Hash, PartialEq)]
pub struct Serde<T>(pub T);

/// A convenience type alias for Serde<Url>.
pub type SerdeUrl = Serde<Url>;

impl<'de, T> Serde<T>
where De<T>: Deserialize<'de>, for<'a> Ser<'a, T>: Serialize
{
    /// Consumes this wrapper, returning the inner value.
    #[inline(always)]
    pub fn into_inner(self) -> T {
        self.0
    }
}

impl<'de, T> fmt::Debug for Serde<T>
where T: fmt::Debug, De<T>: Deserialize<'de>, for<'a> Ser<'a, T>: Serialize
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        self.0.fmt(formatter)
    }
}

impl<'de, T> Deref for Serde<T>
where De<T>: Deserialize<'de>, for<'a> Ser<'a, T>: Serialize
{
    type Target = T;

    fn deref(&self) -> &T {
        &self.0
    }
}

impl<'de, T> DerefMut for Serde<T>
where De<T>: Deserialize<'de>, for<'a> Ser<'a, T>: Serialize
{
    fn deref_mut(&mut self) -> &mut T {
        &mut self.0
    }
}

impl<'de, T: PartialEq> PartialEq<T> for Serde<T>
where De<T>: Deserialize<'de>, for<'a> Ser<'a, T>: Serialize
{
    fn eq(&self, other: &T) -> bool {
        self.0 == *other
    }
}

impl<'de, T> Deserialize<'de> for Serde<T>
where De<T>: Deserialize<'de>, for<'a> Ser<'a, T>: Serialize
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where D: Deserializer<'de>
    {
        De::deserialize(deserializer).map(De::into_inner).map(Serde)
    }
}

impl<'de, T> Serialize for Serde<T>
where De<T>: Deserialize<'de>, for<'a> Ser<'a, T>: Serialize
{
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        Ser(&self.0).serialize(serializer)
    }
}

#[test]
fn test_ser_de_url() {
    let url = Url::parse("http://www.test.com/foo/bar?$param=bazz").unwrap();
    let s = serde_json::to_string(&Ser::new(&url)).unwrap();
    let new_url: Url = serde_json::from_str(&s).map(De::into_inner).unwrap();
    assert_eq!(url, new_url);
}

#[test]
fn test_derive_deserialize_with_for_url() {
    #[derive(Deserialize, Debug, Eq, PartialEq)]
    struct Test {
        #[serde(deserialize_with = "deserialize", rename = "_url_")]
        url: Url
    }

    let url_str = "http://www.test.com/foo/bar?$param=bazz";

    let expected = Test {
        url: Url::parse(url_str).unwrap()
    };
    let json_string = format!(r#"{{"_url_": "{}"}}"#, url_str);
    let got: Test = serde_json::from_str(&json_string).unwrap();
    assert_eq!(expected, got);

}

#[test]
fn test_derive_deserialize_with_for_option_url() {
    #[derive(Deserialize, Debug, Eq, PartialEq)]
    struct Test {
        #[serde(deserialize_with = "deserialize", rename = "_url_")]
        url: Option<Url>
    }

    let url_str = "http://www.test.com/foo/bar?$param=bazz";

    let expected = Test {
        url: Some(Url::parse(url_str).unwrap())
    };
    let json_string = format!(r#"{{"_url_": "{}"}}"#, url_str);
    let got: Test = serde_json::from_str(&json_string).unwrap();
    assert_eq!(expected, got);

    let expected = Test {
        url: None
    };
    let json_string = r#"{"_url_": null}"#;
    let got: Test = serde_json::from_str(&json_string).unwrap();
    assert_eq!(expected, got);
}

#[test]
fn test_derive_serialize_with_for_url() {
    #[derive(Serialize, Debug, Eq, PartialEq)]
    struct Test {
        #[serde(serialize_with = "serialize", rename = "_url_")]
        url: Url
    }

    let url_str = "http://www.test.com/foo/bar?$param=bazz";

    let expected = format!(r#"{{"_url_":"{}"}}"#, url_str);
    let input = Test {url: Url::parse(url_str).unwrap()};
    let got = serde_json::to_string(&input).unwrap();
    assert_eq!(expected, got);
}

#[test]
fn test_derive_serialize_with_for_option_url() {
    #[derive(Serialize, Debug, Eq, PartialEq)]
    struct Test {
        #[serde(serialize_with = "serialize", rename = "_url_")]
        url: Option<Url>
    }

    let url_str = "http://www.test.com/foo/bar?$param=bazz";

    let expected = format!(r#"{{"_url_":"{}"}}"#, url_str);
    let input = Test {url: Some(Url::parse(url_str).unwrap())};
    let got = serde_json::to_string(&input).unwrap();
    assert_eq!(expected, got);

    let expected = format!(r#"{{"_url_":null}}"#);
    let input = Test {url: None};
    let got = serde_json::to_string(&input).unwrap();
    assert_eq!(expected, got);
}

#[test]
fn test_derive_with_for_url() {
    #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
    struct Test {
        #[serde(with = "self", rename = "_url_")]
        url: Url
    }

    let url_str = "http://www.test.com/foo/bar?$param=bazz";
    let json_string = format!(r#"{{"_url_":"{}"}}"#, url_str);

    // test deserialization
    let expected = Test {
        url: Url::parse(url_str).unwrap()
    };
    let got: Test = serde_json::from_str(&json_string).unwrap();
    assert_eq!(expected, got);

    // test serialization
    let input = Test {url: Url::parse(url_str).unwrap()};
    let got = serde_json::to_string(&input).unwrap();
    assert_eq!(json_string, got);
}

#[test]
fn test_host() {
    for host in &[
        Host::Domain("foo.com".to_owned()),
        Host::Ipv4("127.0.0.1".parse().unwrap()),
        Host::Ipv6("::1".parse().unwrap()),
    ] {
        let json = serde_json::to_string(&Ser(host)).unwrap();
        let de: De<Host> = serde_json::from_str(&json).unwrap();
        assert_eq!(de.into_inner(), *host)
    }
}
<commit_msg>Auto merge of #502 - bestouff:patch-1, r=jdm<commit_after>// Copyright 2017 The rust-url developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!

This crate provides wrappers and convenience functions to make rust-url
and Serde work hand in hand.

The supported types are:

* `url::Url`

# How do I use a data type with a `Url` member with Serde?

Use the serde attributes `deserialize_with` and `serialize_with`.

```
#[derive(serde::Serialize, serde::Deserialize)]
struct MyStruct {
    #[serde(serialize_with = "serialize")]
    url: Url,
}
```

# How do I use a data type with an unnamed `Url` member with serde?

Same problem, same solution.

```
#[derive(serde::Serialize, serde::Deserialize)]
enum MyEnum {
    A(#[serde(with = "url_serde")] Url, OtherType),
}
```

# How do I encode a `Url` value with `serde_json::to_string`?

Use the `Ser` wrapper.

```
serde_json::to_string(&Ser::new(&url))
```

# How do I decode a `Url` value with `serde_json::parse`?

Use the `De` wrapper.

```
serde_json::from_str(r"http:://www.rust-lang.org").map(De::into_inner)
```

# How do I send `Url` values as part of an IPC channel?

Use the `Serde` wrapper. It implements `Deref` and `DerefMut` for convenience.

```
ipc::channel::<Serde<Url>>()
```
*/

#![deny(missing_docs)]
#![deny(unsafe_code)]

extern crate serde;
#[cfg(test)] #[macro_use] extern crate serde_derive;
#[cfg(test)] extern crate serde_json;
extern crate url;

use serde::{Deserialize, Serialize, Serializer, Deserializer};
use std::cmp::PartialEq;
use std::error::Error;
use std::fmt;
use std::io::Write;
use std::ops::{Deref, DerefMut};
use std::str;
use url::{Url, Host};

/// Serialises `value` with a given serializer.
///
/// This is useful to serialize `rust-url` types used in structure fields or
/// tuple members with `#[serde(serialize_with = "url_serde::serialize")]`.
pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
    where S: Serializer, for<'a> Ser<'a, T>: Serialize
{
    Ser::new(value).serialize(serializer)
}

/// A wrapper to serialize `rust-url` types.
///
/// This is useful with functions such as `serde_json::to_string`.
///
/// Values of this type can only be passed to the `serde::Serialize` trait.
#[derive(Debug)]
pub struct Ser<'a, T: 'a>(&'a T);

impl<'a, T> Ser<'a, T> where Ser<'a, T>: Serialize {
    /// Returns a new `Ser` wrapper.
    #[inline(always)]
    pub fn new(value: &'a T) -> Self {
        Ser(value)
    }
}

/// Serializes this URL into a `serde` stream.
impl<'a> Serialize for Ser<'a, Url> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        serializer.serialize_str(self.0.as_str())
    }
}

/// Serializes this Option<URL> into a `serde` stream.
impl<'a> Serialize for Ser<'a, Option<Url>> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        if let Some(url) = self.0.as_ref() {
            serializer.serialize_some(url.as_str())
        } else {
            serializer.serialize_none()
        }
    }
}

impl<'a, String> Serialize for Ser<'a, Host<String>> where String: AsRef<str> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        match *self.0 {
            Host::Domain(ref s) => serializer.serialize_str(s.as_ref()),
            Host::Ipv4(_) | Host::Ipv6(_) => {
                // max("101.102.103.104".len(),
                //     "[1000:1002:1003:1004:1005:1006:101.102.103.104]".len())
                const MAX_LEN: usize = 47;
                let mut buffer = [0; MAX_LEN];
                serializer.serialize_str(display_into_buffer(&self.0, &mut buffer))
            }
        }
    }
}

/// Like .to_string(), but doesn’t allocate memory for a `String`.
///
/// Panics if `buffer` is too small.
fn display_into_buffer<'a, T: fmt::Display>(value: &T, buffer: &'a mut [u8]) -> &'a str {
    let remaining_len;
    {
        let mut remaining = &mut *buffer;
        write!(remaining, "{}", value).unwrap();
        remaining_len = remaining.len()
    }
    let written_len = buffer.len() - remaining_len;
    let written = &buffer[..written_len];

    // write! only provides std::fmt::Formatter to Display implementations,
    // which has methods write_str and write_char but no method to write arbitrary bytes.
    // Therefore, `written` is well-formed in UTF-8.
    #[allow(unsafe_code)]
    unsafe {
        str::from_utf8_unchecked(written)
    }
}

/// Deserialises a `T` value with a given deserializer.
///
/// This is useful to deserialize Url types used in structure fields or
/// tuple members with `#[serde(deserialize_with = "url_serde::deserialize")]`.
pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error>
    where D: Deserializer<'de>, De<T>: Deserialize<'de>
{
    De::deserialize(deserializer).map(De::into_inner)
}

/// A wrapper to deserialize `rust-url` types.
///
/// This is useful with functions such as `serde_json::from_str`.
///
/// Values of this type can only be obtained through
/// the `serde::Deserialize` trait.
#[derive(Debug)]
pub struct De<T>(T);

impl<'de, T> De<T> where De<T>: serde::Deserialize<'de> {
    /// Consumes this wrapper, returning the deserialized value.
    #[inline(always)]
    pub fn into_inner(self) -> T {
        self.0
    }
}

/// Deserializes this URL from a `serde` stream.
impl<'de> Deserialize<'de> for De<Url> {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
        let string_representation: String = Deserialize::deserialize(deserializer)?;
        Url::parse(&string_representation).map(De).map_err(|err| {
            serde::de::Error::custom(err.description())
        })
    }
}

/// Deserializes this Option<URL> from a `serde` stream.
impl<'de> Deserialize<'de> for De<Option<Url>> {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
        let option_representation: Option<String> = Deserialize::deserialize(deserializer)?;
        if let Some(s) = option_representation {
            return Url::parse(&s)
                .map(Some)
                .map(De)
                .map_err(|err| {serde::de::Error::custom(err.description())});
        }
        Ok(De(None))

    }
}

impl<'de> Deserialize<'de> for De<Host> {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
        let string_representation: String = Deserialize::deserialize(deserializer)?;
        Host::parse(&string_representation).map(De).map_err(|err| {
            serde::de::Error::custom(err.description())
        })
    }
}

/// A convenience wrapper to be used as a type parameter, for example when
/// a `Vec<T>` or an `HashMap<K, V>` need to be passed to serde.
#[derive(Clone, Eq, Hash, PartialEq)]
pub struct Serde<T>(pub T);

/// A convenience type alias for Serde<Url>.
pub type SerdeUrl = Serde<Url>;

impl<'de, T> Serde<T>
where De<T>: Deserialize<'de>, for<'a> Ser<'a, T>: Serialize
{
    /// Consumes this wrapper, returning the inner value.
    #[inline(always)]
    pub fn into_inner(self) -> T {
        self.0
    }
}

impl<'de, T> fmt::Debug for Serde<T>
where T: fmt::Debug, De<T>: Deserialize<'de>, for<'a> Ser<'a, T>: Serialize
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        self.0.fmt(formatter)
    }
}

impl<'de, T> Deref for Serde<T>
where De<T>: Deserialize<'de>, for<'a> Ser<'a, T>: Serialize
{
    type Target = T;

    fn deref(&self) -> &T {
        &self.0
    }
}

impl<'de, T> DerefMut for Serde<T>
where De<T>: Deserialize<'de>, for<'a> Ser<'a, T>: Serialize
{
    fn deref_mut(&mut self) -> &mut T {
        &mut self.0
    }
}

impl<'de, T: PartialEq> PartialEq<T> for Serde<T>
where De<T>: Deserialize<'de>, for<'a> Ser<'a, T>: Serialize
{
    fn eq(&self, other: &T) -> bool {
        self.0 == *other
    }
}

impl<'de, T> Deserialize<'de> for Serde<T>
where De<T>: Deserialize<'de>, for<'a> Ser<'a, T>: Serialize
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where D: Deserializer<'de>
    {
        De::deserialize(deserializer).map(De::into_inner).map(Serde)
    }
}

impl<'de, T> Serialize for Serde<T>
where De<T>: Deserialize<'de>, for<'a> Ser<'a, T>: Serialize
{
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        Ser(&self.0).serialize(serializer)
    }
}

#[test]
fn test_ser_de_url() {
    let url = Url::parse("http://www.test.com/foo/bar?$param=bazz").unwrap();
    let s = serde_json::to_string(&Ser::new(&url)).unwrap();
    let new_url: Url = serde_json::from_str(&s).map(De::into_inner).unwrap();
    assert_eq!(url, new_url);
}

#[test]
fn test_derive_deserialize_with_for_url() {
    #[derive(Deserialize, Debug, Eq, PartialEq)]
    struct Test {
        #[serde(deserialize_with = "deserialize", rename = "_url_")]
        url: Url
    }

    let url_str = "http://www.test.com/foo/bar?$param=bazz";

    let expected = Test {
        url: Url::parse(url_str).unwrap()
    };
    let json_string = format!(r#"{{"_url_": "{}"}}"#, url_str);
    let got: Test = serde_json::from_str(&json_string).unwrap();
    assert_eq!(expected, got);

}

#[test]
fn test_derive_deserialize_with_for_option_url() {
    #[derive(Deserialize, Debug, Eq, PartialEq)]
    struct Test {
        #[serde(deserialize_with = "deserialize", rename = "_url_")]
        url: Option<Url>
    }

    let url_str = "http://www.test.com/foo/bar?$param=bazz";

    let expected = Test {
        url: Some(Url::parse(url_str).unwrap())
    };
    let json_string = format!(r#"{{"_url_": "{}"}}"#, url_str);
    let got: Test = serde_json::from_str(&json_string).unwrap();
    assert_eq!(expected, got);

    let expected = Test {
        url: None
    };
    let json_string = r#"{"_url_": null}"#;
    let got: Test = serde_json::from_str(&json_string).unwrap();
    assert_eq!(expected, got);
}

#[test]
fn test_derive_serialize_with_for_url() {
    #[derive(Serialize, Debug, Eq, PartialEq)]
    struct Test {
        #[serde(serialize_with = "serialize", rename = "_url_")]
        url: Url
    }

    let url_str = "http://www.test.com/foo/bar?$param=bazz";

    let expected = format!(r#"{{"_url_":"{}"}}"#, url_str);
    let input = Test {url: Url::parse(url_str).unwrap()};
    let got = serde_json::to_string(&input).unwrap();
    assert_eq!(expected, got);
}

#[test]
fn test_derive_serialize_with_for_option_url() {
    #[derive(Serialize, Debug, Eq, PartialEq)]
    struct Test {
        #[serde(serialize_with = "serialize", rename = "_url_")]
        url: Option<Url>
    }

    let url_str = "http://www.test.com/foo/bar?$param=bazz";

    let expected = format!(r#"{{"_url_":"{}"}}"#, url_str);
    let input = Test {url: Some(Url::parse(url_str).unwrap())};
    let got = serde_json::to_string(&input).unwrap();
    assert_eq!(expected, got);

    let expected = format!(r#"{{"_url_":null}}"#);
    let input = Test {url: None};
    let got = serde_json::to_string(&input).unwrap();
    assert_eq!(expected, got);
}

#[test]
fn test_derive_with_for_url() {
    #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
    struct Test {
        #[serde(with = "self", rename = "_url_")]
        url: Url
    }

    let url_str = "http://www.test.com/foo/bar?$param=bazz";
    let json_string = format!(r#"{{"_url_":"{}"}}"#, url_str);

    // test deserialization
    let expected = Test {
        url: Url::parse(url_str).unwrap()
    };
    let got: Test = serde_json::from_str(&json_string).unwrap();
    assert_eq!(expected, got);

    // test serialization
    let input = Test {url: Url::parse(url_str).unwrap()};
    let got = serde_json::to_string(&input).unwrap();
    assert_eq!(json_string, got);
}

#[test]
fn test_host() {
    for host in &[
        Host::Domain("foo.com".to_owned()),
        Host::Ipv4("127.0.0.1".parse().unwrap()),
        Host::Ipv6("::1".parse().unwrap()),
    ] {
        let json = serde_json::to_string(&Ser(host)).unwrap();
        let de: De<Host> = serde_json::from_str(&json).unwrap();
        assert_eq!(de.into_inner(), *host)
    }
}
<|endoftext|>


<commit_before>use ascii_char::{AsciiChar, ToAsciiChar};

// I would like to require C: AsciiExt, but it's not in core.

/// Terminals use [caret notation](https://en.wikipedia.org/wiki/Caret_notation)
/// to display some typed control codes, such as ^D for EOT and ^Z for SUB.
///
/// This function returns the caret notation letter for control codes,
/// or `None` for printable characters.
///
/// # Examples
/// ```
/// # use ascii::{AsciiChar, caret_encode};
/// assert_eq!(caret_encode(b'\0'), Some(AsciiChar::At));
/// assert_eq!(caret_encode(AsciiChar::DEL), Some(AsciiChar::Question));
/// assert_eq!(caret_encode(b'E'), None);
/// assert_eq!(caret_encode(b'\n'), Some(AsciiChar::J));
/// ```
pub fn caret_encode<C:Copy+Into<u8>>(c: C) -> Option<AsciiChar> {
    // The formula is explained in the Wikipedia article.
    let c = c.into() ^ 0b0100_0000;
    unsafe{ if c >= b'?'  &&  c <= b'_' {
        Some(c.to_ascii_char_unchecked())
    } else {
        None
    }}
}

/// Returns the conrol code represented by a [caret notation](https://en.wikipedia.org/wiki/Caret_notation)
/// letter, or `None` if the letter is not used in caret notation.
///
/// This function is the inverse of `caret_encode()`.
///
/// # Examples
///
/// Basic usage:
/// ```
/// # use ascii::{AsciiChar, caret_decode};
/// assert_eq!(caret_decode(b'?'), Some(AsciiChar::DEL));
/// assert_eq!(caret_decode(AsciiChar::C), Some(AsciiChar::EOT));
/// assert_eq!(caret_decode('\0'), None);
/// ```
///
/// Symmetry:
/// ```
/// # use ascii::{AsciiChar, caret_encode, caret_decode};
/// assert_eq!(caret_encode(AsciiCHar::US).flat_map(caret_decode),  Some(AsciiChar::US));
/// assert_eq!(caret_decode('@').flat_map(caret_encode), Some(AsciiChar::At));
/// ```
pub fn caret_decode<C:Copy+Into<u8>>(c: C) -> Option<AsciiChar> {
    // The formula is explained in the Wikipedia article.
    unsafe {match c.into() {
        b'?'...b'_' => Some(AsciiChar::from_unchecked(c.into() ^ 0b0100_0000)),
        _ => None,
    }}
}
<commit_msg>Fix documentation of `caret_decode`<commit_after>use ascii_char::{AsciiChar, ToAsciiChar};

// I would like to require C: AsciiExt, but it's not in core.

/// Terminals use [caret notation](https://en.wikipedia.org/wiki/Caret_notation)
/// to display some typed control codes, such as ^D for EOT and ^Z for SUB.
///
/// This function returns the caret notation letter for control codes,
/// or `None` for printable characters.
///
/// # Examples
/// ```
/// # use ascii::{AsciiChar, caret_encode};
/// assert_eq!(caret_encode(b'\0'), Some(AsciiChar::At));
/// assert_eq!(caret_encode(AsciiChar::DEL), Some(AsciiChar::Question));
/// assert_eq!(caret_encode(b'E'), None);
/// assert_eq!(caret_encode(b'\n'), Some(AsciiChar::J));
/// ```
pub fn caret_encode<C:Copy+Into<u8>>(c: C) -> Option<AsciiChar> {
    // The formula is explained in the Wikipedia article.
    let c = c.into() ^ 0b0100_0000;
    unsafe{ if c >= b'?'  &&  c <= b'_' {
        Some(c.to_ascii_char_unchecked())
    } else {
        None
    }}
}

/// Returns the control code represented by a [caret notation](https://en.wikipedia.org/wiki/Caret_notation)
/// letter, or `None` if the letter is not used in caret notation.
///
/// This function is the inverse of `caret_encode()`.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// # use ascii::{AsciiChar, caret_decode};
/// assert_eq!(caret_decode(b'?'), Some(AsciiChar::DEL));
/// assert_eq!(caret_decode(AsciiChar::C), Some(AsciiChar::EOT));
/// assert_eq!(caret_decode('\0'), None);
/// ```
///
/// Symmetry:
///
/// ```
/// # use ascii::{AsciiChar, caret_encode, caret_decode};
/// assert_eq!(caret_encode(AsciiCHar::US).flat_map(caret_decode),  Some(AsciiChar::US));
/// assert_eq!(caret_decode('@').flat_map(caret_encode), Some(AsciiChar::At));
/// ```
pub fn caret_decode<C:Copy+Into<u8>>(c: C) -> Option<AsciiChar> {
    // The formula is explained in the Wikipedia article.
    unsafe {match c.into() {
        b'?'...b'_' => Some(AsciiChar::from_unchecked(c.into() ^ 0b0100_0000)),
        _ => None,
    }}
}
<|endoftext|>


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

pub type Id = u32;

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Bounds {
    x: i32,
    y: i32,
    width: i32,
    height: i32,
}
impl Bounds {
    pub fn intersects(&self, other: &Self) -> bool {
        ((self.x - other.x).abs() * 2 < (self.width + other.width)) &&
            ((self.y - other.y).abs() * 2 < (self.height + other.height))
    }
    pub fn contains(&self, other: &Self) -> bool {
        other.x - other.width / 2 >= self.x - self.width / 2 &&
            other.y - other.height / 2 >= self.y - self.height / 2 &&
            other.x + other.width / 2 <= self.x + self.width / 2 &&
            other.y + other.height / 2 <= self.y + self.height / 2
    }
}

pub struct World {
    width: i32,
    height: i32,
    entities: HashMap<Id, Bounds>,
}

impl World {
    pub fn new(width: i32, height: i32) -> Self {
        World {
            width,
            height,
            entities: HashMap::new(),
        }
    }
    pub fn insert(&mut self, id: Id, bounds: Bounds) -> Option<Bounds> {
        assert!(
            bounds.x + bounds.width / 2 > 0 && bounds.y + bounds.height / 2 > 0 &&
                bounds.x - bounds.width / 2 < self.width &&
                bounds.y - bounds.height / 2 < self.height
        );
        self.entities.insert(id, bounds)
    }
    pub fn remove(&mut self, id: Id) -> Option<Bounds> {
        self.entities.remove(&id)
    }
    pub fn query_intersects<T>(&self, bounds: &Bounds, mut cb: T)
    where
        T: FnMut(Id, &Bounds),
    {
        for (id, entity) in &self.entities {
            if entity.intersects(bounds) {
                cb(*id, entity);
            }
        }
    }
    pub fn query_contains<T>(&self, bounds: &Bounds, mut cb: T)
        where
            T: FnMut(Id, &Bounds),
    {
        for (id, entity) in &self.entities {
            if entity.contains(bounds) {
                cb(*id, entity);
            }
        }
    }
}

#[test]
fn intersects() {
    let a = Bounds {
        x: 0,
        y: 0,
        width: 10,
        height: 10,
    };
    let b = Bounds {
        x: 5,
        y: 5,
        width: 10,
        height: 10,
    };
    assert!(a.intersects(&b));
}

#[test]
fn doesnt_intersect() {
    let a = Bounds {
        x: 0,
        y: 0,
        width: 10,
        height: 10,
    };
    let b = Bounds {
        x: 50,
        y: 50,
        width: 10,
        height: 10,
    };
    assert!(!a.intersects(&b));
}

#[test]
fn doesnt_intersect_edge() {
    let a = Bounds {
        x: 0,
        y: 0,
        width: 10,
        height: 10,
    };
    let b = Bounds {
        x: 15,
        y: 0,
        width: 10,
        height: 10,
    };
    assert!(!a.intersects(&b));
}

#[test]
fn contains() {
    let a = Bounds {
        x: 0,
        y: 0,
        width: 100,
        height: 100,
    };
    let b = Bounds {
        x: 2,
        y: 2,
        width: 10,
        height: 10,
    };
    assert!(a.contains(&b));
}

#[test]
fn doesnt_contain() {
    let a = Bounds {
        x: 0,
        y: 0,
        width: 10,
        height: 10,
    };
    let b = Bounds {
        x: 50,
        y: 50,
        width: 10,
        height: 10,
    };
    assert!(!a.contains(&b));
}

#[test]
fn doesnt_contain_when_intersecting() {
    let a = Bounds {
        x: 0,
        y: 0,
        width: 10,
        height: 10,
    };
    let b = Bounds {
        x: 5,
        y: 5,
        width: 10,
        height: 10,
    };
    assert!(!a.contains(&b));
}

#[test]
fn contains_edge() {
    let a = Bounds {
        x: 0,
        y: 0,
        width: 10,
        height: 10,
    };
    let b = Bounds {
        x: 10,
        y: 10,
        width: 0,
        height: 0,
    };
    assert!(!a.contains(&b));
}

#[test]
fn contains_self() {
    let a = Bounds {
        x: 0,
        y: 0,
        width: 10,
        height: 10,
    };
    assert!(a.contains(&a));
}

#[test]
fn init() {
    World::new(1000, 1000);
}

#[test]
fn insert_new() {
    let mut world = World::new(1000, 1000);
    let bounds = Bounds {
        x: 0,
        y: 0,
        width: 10,
        height: 10,
    };
    let old = world.insert(1, bounds);
    assert!(old.is_none());
}

#[test]
#[should_panic]
fn insert_too_low() {
    let mut world = World::new(1000, 1000);
    let bounds = Bounds {
        x: -10,
        y: -10,
        width: 1,
        height: 1,
    };
    world.insert(1, bounds);
}

#[test]
#[should_panic]
fn insert_too_low_edge() {
    let mut world = World::new(1000, 1000);
    let bounds = Bounds {
        x: -10,
        y: 0,
        width: 5,
        height: 5,
    };
    world.insert(1, bounds);
}

#[test]
#[should_panic]
fn insert_too_high() {
    let mut world = World::new(1000, 1000);
    let bounds = Bounds {
        x: 2000,
        y: 2000,
        width: 1,
        height: 1,
    };
    world.insert(1, bounds);
}

#[test]
#[should_panic]
fn insert_too_high_edge() {
    let mut world = World::new(1000, 1000);
    let bounds = Bounds {
        x: 0,
        y: 1010,
        width: 1,
        height: 5,
    };
    world.insert(1, bounds);
}

#[test]
fn insert_existing() {
    let mut world = World::new(1000, 1000);
    let id = 1;
    let bounds_a = Bounds {
        x: 0,
        y: 0,
        width: 10,
        height: 10,
    };
    let old = world.insert(id, bounds_a.clone());
    assert!(old.is_none());
    let bounds_b = Bounds {
        x: 1,
        y: 1,
        width: 10,
        height: 10,
    };
    let old = world.insert(id, bounds_b);
    assert_eq!(bounds_a, old.unwrap())
}

#[test]
fn remove() {
    let mut world = World::new(1000, 1000);
    let id = 1;
    let bounds = Bounds {
        x: 0,
        y: 0,
        width: 10,
        height: 10,
    };
    world.insert(id, bounds.clone());
    let removed_bounds = world.remove(id);
    assert_eq!(bounds, removed_bounds.unwrap());
    let old = world.insert(id, bounds);
    assert!(old.is_none());
}

#[test]
fn remove_nonexistant() {
    let mut world = World::new(1000, 1000);
    let bounds = Bounds {
        x: 0,
        y: 0,
        width: 10,
        height: 10,
    };
    world.insert(1, bounds);
    let removed = world.remove(2);
    assert!(removed.is_none())
}

#[test]
fn remove_empty() {
    let mut world = World::new(1000, 1000);
    let removed = world.remove(1);
    assert!(removed.is_none())
}

#[test]
fn remove_twice() {
    let mut world = World::new(1000, 1000);
    let id = 1;
    let bounds = Bounds {
        x: 0,
        y: 0,
        width: 10,
        height: 10,
    };
    world.insert(id, bounds.clone());
    let removed = world.remove(id);
    assert_eq!(bounds, removed.unwrap());
    let removed = world.remove(id);
    assert!(removed.is_none());
}

#[test]
fn no_collisions() {
    let mut world = World::new(1000, 1000);
    let id = 1;
    let bounds_a = Bounds {
        x: 0,
        y: 0,
        width: 10,
        height: 10,
    };
    world.insert(id, bounds_a.clone());
    let bounds_b = Bounds {
        x: 40,
        y: 40,
        width: 10,
        height: 10,
    };
    world.query_intersects(&bounds_b, |_, _| panic!());
}

#[test]
fn one_collision() {
    let mut world = World::new(1000, 1000);
    let id = 1;
    let bounds_a = Bounds {
        x: 0,
        y: 0,
        width: 10,
        height: 10,
    };
    world.insert(id, bounds_a.clone());
    let bounds_b = Bounds {
        x: 5,
        y: 5,
        width: 10,
        height: 10,
    };
    let mut collisions = Vec::new();
    world.query_intersects(
        &bounds_b,
        |id, bounds| collisions.push((id, bounds.clone())),
    );
    assert_eq!(1, collisions.len());
    let &(coll_id, ref coll_bounds) = collisions.first().unwrap();
    assert_eq!(id, coll_id);
    assert_eq!(bounds_a, *coll_bounds);
}

#[test]
fn multiple_collision() {
    let mut world = World::new(1000, 1000);
    let id_a = 1;
    let bounds_a = Bounds {
        x: 0,
        y: 0,
        width: 10,
        height: 10,
    };
    world.insert(id_a, bounds_a.clone());
    let id_b = 2;
    let bounds_b = Bounds {
        x: 0,
        y: 0,
        width: 10,
        height: 10,
    };
    world.insert(id_b, bounds_b.clone());
    let bounds_c = Bounds {
        x: 5,
        y: 5,
        width: 10,
        height: 10,
    };
    let mut collisions = Vec::new();
    world.query_intersects(
        &bounds_c,
        |id, bounds| collisions.push((id, bounds.clone())),
    );
    assert_eq!(2, collisions.len());
    let (coll_id, ref coll_bounds) = collisions[0];
    let first_is_a = id_a == coll_id;
    if first_is_a {
        assert_eq!(id_a, coll_id);
        assert_eq!(bounds_a, *coll_bounds);
    } else {
        assert_eq!(id_b, coll_id);
        assert_eq!(bounds_b, *coll_bounds);
    }
    let (coll_id, ref coll_bounds) = collisions[1];
    if first_is_a {
        assert_eq!(id_b, coll_id);
        assert_eq!(bounds_b, *coll_bounds);
    } else {
        assert_eq!(id_a, coll_id);
        assert_eq!(bounds_a, *coll_bounds);
    }
}

<commit_msg>Core: Add containing collision check<commit_after>use std::collections::HashMap;

pub type Id = u32;

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Bounds {
    x: i32,
    y: i32,
    width: i32,
    height: i32,
}
impl Bounds {
    pub fn intersects(&self, other: &Self) -> bool {
        ((self.x - other.x).abs() * 2 < (self.width + other.width)) &&
            ((self.y - other.y).abs() * 2 < (self.height + other.height))
    }
    pub fn contains(&self, other: &Self) -> bool {
        other.x - other.width / 2 >= self.x - self.width / 2 &&
            other.y - other.height / 2 >= self.y - self.height / 2 &&
            other.x + other.width / 2 <= self.x + self.width / 2 &&
            other.y + other.height / 2 <= self.y + self.height / 2
    }
}

pub struct World {
    width: i32,
    height: i32,
    entities: HashMap<Id, Bounds>,
}

impl World {
    pub fn new(width: i32, height: i32) -> Self {
        World {
            width,
            height,
            entities: HashMap::new(),
        }
    }
    pub fn insert(&mut self, id: Id, bounds: Bounds) -> Option<Bounds> {
        assert!(
            bounds.x + bounds.width / 2 > 0 && bounds.y + bounds.height / 2 > 0 &&
                bounds.x - bounds.width / 2 < self.width &&
                bounds.y - bounds.height / 2 < self.height
        );
        self.entities.insert(id, bounds)
    }
    pub fn remove(&mut self, id: Id) -> Option<Bounds> {
        self.entities.remove(&id)
    }
    pub fn query_intersects<T>(&self, bounds: &Bounds, mut cb: T)
    where
        T: FnMut(Id, &Bounds),
    {
        for (id, entity) in &self.entities {
            if entity.intersects(bounds) {
                cb(*id, entity);
            }
        }
    }
    pub fn query_contains<T>(&self, bounds: &Bounds, mut cb: T)
        where
            T: FnMut(Id, &Bounds),
    {
        for (id, entity) in &self.entities {
            if entity.contains(bounds) {
                cb(*id, entity);
            }
        }
    }
}

#[test]
fn intersects() {
    let a = Bounds {
        x: 0,
        y: 0,
        width: 10,
        height: 10,
    };
    let b = Bounds {
        x: 5,
        y: 5,
        width: 10,
        height: 10,
    };
    assert!(a.intersects(&b));
}

#[test]
fn doesnt_intersect() {
    let a = Bounds {
        x: 0,
        y: 0,
        width: 10,
        height: 10,
    };
    let b = Bounds {
        x: 50,
        y: 50,
        width: 10,
        height: 10,
    };
    assert!(!a.intersects(&b));
}

#[test]
fn doesnt_intersect_edge() {
    let a = Bounds {
        x: 0,
        y: 0,
        width: 10,
        height: 10,
    };
    let b = Bounds {
        x: 15,
        y: 0,
        width: 10,
        height: 10,
    };
    assert!(!a.intersects(&b));
}

#[test]
fn contains() {
    let a = Bounds {
        x: 0,
        y: 0,
        width: 100,
        height: 100,
    };
    let b = Bounds {
        x: 2,
        y: 2,
        width: 10,
        height: 10,
    };
    assert!(a.contains(&b));
}

#[test]
fn doesnt_contain() {
    let a = Bounds {
        x: 0,
        y: 0,
        width: 10,
        height: 10,
    };
    let b = Bounds {
        x: 50,
        y: 50,
        width: 10,
        height: 10,
    };
    assert!(!a.contains(&b));
}

#[test]
fn doesnt_contain_when_intersecting() {
    let a = Bounds {
        x: 0,
        y: 0,
        width: 10,
        height: 10,
    };
    let b = Bounds {
        x: 5,
        y: 5,
        width: 10,
        height: 10,
    };
    assert!(!a.contains(&b));
}

#[test]
fn contains_edge() {
    let a = Bounds {
        x: 0,
        y: 0,
        width: 10,
        height: 10,
    };
    let b = Bounds {
        x: 10,
        y: 10,
        width: 0,
        height: 0,
    };
    assert!(!a.contains(&b));
}

#[test]
fn contains_self() {
    let a = Bounds {
        x: 0,
        y: 0,
        width: 10,
        height: 10,
    };
    assert!(a.contains(&a));
}

#[test]
fn init() {
    World::new(1000, 1000);
}

#[test]
fn insert_new() {
    let mut world = World::new(1000, 1000);
    let bounds = Bounds {
        x: 0,
        y: 0,
        width: 10,
        height: 10,
    };
    let old = world.insert(1, bounds);
    assert!(old.is_none());
}

#[test]
#[should_panic]
fn insert_too_low() {
    let mut world = World::new(1000, 1000);
    let bounds = Bounds {
        x: -10,
        y: -10,
        width: 1,
        height: 1,
    };
    world.insert(1, bounds);
}

#[test]
#[should_panic]
fn insert_too_low_edge() {
    let mut world = World::new(1000, 1000);
    let bounds = Bounds {
        x: -10,
        y: 0,
        width: 5,
        height: 5,
    };
    world.insert(1, bounds);
}

#[test]
#[should_panic]
fn insert_too_high() {
    let mut world = World::new(1000, 1000);
    let bounds = Bounds {
        x: 2000,
        y: 2000,
        width: 1,
        height: 1,
    };
    world.insert(1, bounds);
}

#[test]
#[should_panic]
fn insert_too_high_edge() {
    let mut world = World::new(1000, 1000);
    let bounds = Bounds {
        x: 0,
        y: 1010,
        width: 1,
        height: 5,
    };
    world.insert(1, bounds);
}

#[test]
fn insert_existing() {
    let mut world = World::new(1000, 1000);
    let id = 1;
    let bounds_a = Bounds {
        x: 0,
        y: 0,
        width: 10,
        height: 10,
    };
    let old = world.insert(id, bounds_a.clone());
    assert!(old.is_none());
    let bounds_b = Bounds {
        x: 1,
        y: 1,
        width: 10,
        height: 10,
    };
    let old = world.insert(id, bounds_b);
    assert_eq!(bounds_a, old.unwrap())
}

#[test]
fn remove() {
    let mut world = World::new(1000, 1000);
    let id = 1;
    let bounds = Bounds {
        x: 0,
        y: 0,
        width: 10,
        height: 10,
    };
    world.insert(id, bounds.clone());
    let removed_bounds = world.remove(id);
    assert_eq!(bounds, removed_bounds.unwrap());
    let old = world.insert(id, bounds);
    assert!(old.is_none());
}

#[test]
fn remove_nonexistant() {
    let mut world = World::new(1000, 1000);
    let bounds = Bounds {
        x: 0,
        y: 0,
        width: 10,
        height: 10,
    };
    world.insert(1, bounds);
    let removed = world.remove(2);
    assert!(removed.is_none())
}

#[test]
fn remove_empty() {
    let mut world = World::new(1000, 1000);
    let removed = world.remove(1);
    assert!(removed.is_none())
}

#[test]
fn remove_twice() {
    let mut world = World::new(1000, 1000);
    let id = 1;
    let bounds = Bounds {
        x: 0,
        y: 0,
        width: 10,
        height: 10,
    };
    world.insert(id, bounds.clone());
    let removed = world.remove(id);
    assert_eq!(bounds, removed.unwrap());
    let removed = world.remove(id);
    assert!(removed.is_none());
}

#[test]
fn no_collisions() {
    let mut world = World::new(1000, 1000);
    let id = 1;
    let bounds_a = Bounds {
        x: 0,
        y: 0,
        width: 10,
        height: 10,
    };
    world.insert(id, bounds_a.clone());
    let bounds_b = Bounds {
        x: 40,
        y: 40,
        width: 10,
        height: 10,
    };
    world.query_intersects(&bounds_b, |_, _| panic!());
}

#[test]
fn one_collision() {
    let mut world = World::new(1000, 1000);
    let id = 1;
    let bounds_a = Bounds {
        x: 0,
        y: 0,
        width: 10,
        height: 10,
    };
    world.insert(id, bounds_a.clone());
    let bounds_b = Bounds {
        x: 5,
        y: 5,
        width: 10,
        height: 10,
    };
    let mut collisions = Vec::new();
    world.query_intersects(
        &bounds_b,
        |id, bounds| collisions.push((id, bounds.clone())),
    );
    assert_eq!(1, collisions.len());
    let &(coll_id, ref coll_bounds) = collisions.first().unwrap();
    assert_eq!(id, coll_id);
    assert_eq!(bounds_a, *coll_bounds);
}

#[test]
fn multiple_collision() {
    let mut world = World::new(1000, 1000);
    let id_a = 1;
    let bounds_a = Bounds {
        x: 0,
        y: 0,
        width: 10,
        height: 10,
    };
    world.insert(id_a, bounds_a.clone());
    let id_b = 2;
    let bounds_b = Bounds {
        x: 0,
        y: 0,
        width: 10,
        height: 10,
    };
    world.insert(id_b, bounds_b.clone());
    let bounds_c = Bounds {
        x: 5,
        y: 5,
        width: 10,
        height: 10,
    };
    let mut collisions = Vec::new();
    world.query_intersects(
        &bounds_c,
        |id, bounds| collisions.push((id, bounds.clone())),
    );
    assert_eq!(2, collisions.len());
    let (coll_id, ref coll_bounds) = collisions[0];
    let first_is_a = id_a == coll_id;
    if first_is_a {
        assert_eq!(id_a, coll_id);
        assert_eq!(bounds_a, *coll_bounds);
    } else {
        assert_eq!(id_b, coll_id);
        assert_eq!(bounds_b, *coll_bounds);
    }
    let (coll_id, ref coll_bounds) = collisions[1];
    if first_is_a {
        assert_eq!(id_b, coll_id);
        assert_eq!(bounds_b, *coll_bounds);
    } else {
        assert_eq!(id_a, coll_id);
        assert_eq!(bounds_a, *coll_bounds);
    }
}

#[test]
fn no_containing() {
    let mut world = World::new(1000, 1000);
    let id = 1;
    let bounds_a = Bounds {
        x: 0,
        y: 0,
        width: 10,
        height: 10,
    };
    world.insert(id, bounds_a.clone());
    let bounds_b = Bounds {
        x: 40,
        y: 40,
        width: 10,
        height: 10,
    };
    world.query_contains(&bounds_b, |_, _| panic!());
}

#[test]
fn one_containing() {
    let mut world = World::new(1000, 1000);
    let id = 1;
    let bounds_a = Bounds {
        x: 0,
        y: 0,
        width: 10,
        height: 10,
    };
    world.insert(id, bounds_a.clone());
    let bounds_b = Bounds {
        x: 2,
        y: 2,
        width: 3,
        height: 3,
    };
    let mut containing = Vec::new();
    world.query_contains(
        &bounds_b,
        |id, bounds| containing.push((id, bounds.clone())),
    );
    assert_eq!(1, containing.len());
    let &(coll_id, ref coll_bounds) = containing.first().unwrap();
    assert_eq!(id, coll_id);
    assert_eq!(bounds_a, *coll_bounds);
}

#[test]
fn multiple_containing() {
    let mut world = World::new(1000, 1000);
    let id_a = 1;
    let bounds_a = Bounds {
        x: 4,
        y: 4,
        width: 100,
        height: 100,
    };
    world.insert(id_a, bounds_a.clone());
    let id_b = 2;
    let bounds_b = Bounds {
        x: 6,
        y: 6,
        width: 2,
        height: 2,
    };
    world.insert(id_b, bounds_b.clone());
    let bounds_c = Bounds {
        x: 5,
        y: 5,
        width: 1,
        height: 1,
    };
    let mut containing = Vec::new();
    world.query_contains(
        &bounds_c,
        |id, bounds| containing.push((id, bounds.clone())),
    );
    assert_eq!(2, containing.len());
    let (coll_id, ref coll_bounds) = containing[0];
    let first_is_a = id_a == coll_id;
    if first_is_a {
        assert_eq!(id_a, coll_id);
        assert_eq!(bounds_a, *coll_bounds);
    } else {
        assert_eq!(id_b, coll_id);
        assert_eq!(bounds_b, *coll_bounds);
    }
    let (coll_id, ref coll_bounds) = containing[1];
    if first_is_a {
        assert_eq!(id_b, coll_id);
        assert_eq!(bounds_b, *coll_bounds);
    } else {
        assert_eq!(id_a, coll_id);
        assert_eq!(bounds_a, *coll_bounds);
    }
}

<|endoftext|>


<commit_before>/// Wrapper around the afl-fuzz binary

use libc;
use std::env;
use std::ffi::CString;
use std::path::PathBuf;

extern "C" {
    // `main` function with afl-fuzz.c
    fn afl_fuzz_main(argc: libc::c_int,
                     argv: *const *const libc::c_char) -> libc::c_int;
}

fn call_afl_fuzz_main(args: Vec<CString>) -> Result<(), libc::c_int> {
    assert!(!args.is_empty());

    // `main` functions in C expect an array of pointers to the arguments
    let args_ptrs = args.iter()
                        .map(|arg| arg.as_ptr())
                        .collect::<Vec<_>>();

    let ret = unsafe {
        afl_fuzz_main(args_ptrs.len() as libc::c_int,
                      args_ptrs.as_ptr())
    };

    match ret {
        0 => Ok(()),
        n => Err(n),
    }
}

// TODO: use builder pattern
pub struct AflFuzzConfig {
    pub in_dir: PathBuf,
    pub out_dir: PathBuf,
    pub target: PathBuf,
}

impl AflFuzzConfig {
    fn into_args(self) -> Vec<CString> {
        let mut args = vec![];

        // -i
        args.push("-i");
        args.push(self.in_dir.to_str().unwrap());

        // -o
        args.push("-o");
        args.push(self.out_dir.to_str().unwrap());

        // target
        args.push(self.target.to_str().unwrap());

        // Convert args from `str`s to `CString`s
        args.into_iter()
            .map(|s| CString::new(s).unwrap())
            .collect()
    }
}

pub fn afl_fuzz_env() -> Result<(), libc::c_int> {
    let args = env::args();

    // don't include anything before 'afl-fuzz' or 'cargo-afl-fuzz'
    let mut args = args.skip_while(|a| !a.ends_with("afl-fuzz"))
                       .map(|arg| CString::new(arg).unwrap())
                       .collect::<Vec<_>>();
    assert!(!args.is_empty(), "Error generating afl-fuzz arguments");

    args[0] = CString::new("afl-fuzz").unwrap();

    call_afl_fuzz_main(args)
}

pub fn afl_fuzz(config: AflFuzzConfig) -> Result<(), libc::c_int> {
    let mut args = vec![];

    // Fake the first argument
    let arg0 = CString::new("afl-fuzz").unwrap();
    args.push(arg0);

    args.extend(config.into_args());

    call_afl_fuzz_main(args)
}

/// FIXME: figure out a way to make it not run indefinitely
#[test]
fn testsomething() {
    let config = AflFuzzConfig {
        in_dir: ".".into(),
        out_dir: "testout".into(),
        target: "../target/debug/examples/hello".into(),
    };
    afl_fuzz(config);
}
<commit_msg>argv should be a null-terminated array.<commit_after>/// Wrapper around the afl-fuzz binary

use libc;
use std::env;
use std::ffi::CString;
use std::path::PathBuf;
use std::ptr;

extern "C" {
    // `main` function with afl-fuzz.c
    fn afl_fuzz_main(argc: libc::c_int,
                     argv: *const *const libc::c_char) -> libc::c_int;
}

fn call_afl_fuzz_main(args: Vec<CString>) -> Result<(), libc::c_int> {
    assert!(!args.is_empty());
    // `main` functions in C expect an array of pointers to the arguments
    let mut args_ptrs = args.iter()
                        .map(|arg| arg.as_ptr())
                        .collect::<Vec<_>>();
    let argc = args_ptrs.len() as libc::c_int;
    // argv is a null-terminated array
    // http://stackoverflow.com/a/11020198
    args_ptrs.push(ptr::null());
    let ret = unsafe {
        afl_fuzz_main(argc, args_ptrs.as_ptr())
    };

    match ret {
        0 => Ok(()),
        n => Err(n),
    }
}

// TODO: use builder pattern
pub struct AflFuzzConfig {
    pub in_dir: PathBuf,
    pub out_dir: PathBuf,
    pub target: PathBuf,
}

impl AflFuzzConfig {
    fn into_args(self) -> Vec<CString> {
        let mut args = vec![];

        // -i
        args.push("-i");
        args.push(self.in_dir.to_str().unwrap());

        // -o
        args.push("-o");
        args.push(self.out_dir.to_str().unwrap());

        // target
        args.push(self.target.to_str().unwrap());

        // Convert args from `str`s to `CString`s
        args.into_iter()
            .map(|s| CString::new(s).unwrap())
            .collect()
    }
}

pub fn afl_fuzz_env() -> Result<(), libc::c_int> {
    let args = env::args();

    // don't include anything before 'afl-fuzz' or 'cargo-afl-fuzz'
    let mut args = args.skip_while(|a| !a.ends_with("afl-fuzz"))
                       .map(|arg| CString::new(arg).unwrap())
                       .collect::<Vec<_>>();
    assert!(!args.is_empty(), "Error generating afl-fuzz arguments");

    args[0] = CString::new("afl-fuzz").unwrap();

    call_afl_fuzz_main(args)
}

pub fn afl_fuzz(config: AflFuzzConfig) -> Result<(), libc::c_int> {
    let mut args = vec![];

    // Fake the first argument
    let arg0 = CString::new("afl-fuzz").unwrap();
    args.push(arg0);

    args.extend(config.into_args());

    call_afl_fuzz_main(args)
}

/// FIXME: figure out a way to make it not run indefinitely
#[test]
fn testsomething() {
    let config = AflFuzzConfig {
        in_dir: ".".into(),
        out_dir: "testout".into(),
        target: "../target/debug/examples/hello".into(),
    };
    afl_fuzz(config);
}
<|endoftext|>


<commit_before>extern crate winapi;
extern crate kernel32;
extern crate user32;
extern crate shell32;
extern crate libc;

use winapi::windef::{HWND, HMENU, HICON, HBRUSH, HBITMAP};
use winapi::winnt::{LPCWSTR};
use winapi::minwindef::{UINT, DWORD, WPARAM, LPARAM, LRESULT, HINSTANCE};
use winapi::winuser::{WNDCLASSW, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT};
use std::os::windows::ffi::OsStrExt;
use std::ffi::OsStr;

fn to_wstring(str : &str) -> Vec<u16> {
    OsStr::new(str).encode_wide().chain(Some(0).into_iter()).collect()
}

static mut hwnd : HWND = 0 as HWND;
static mut hmenu: HMENU = 0 as HMENU;

struct WinApp {
}

pub unsafe extern "system" fn window_proc(h_wnd :HWND,
	                                        msg :UINT,
                                          w_param :WPARAM,
                                          l_param :LPARAM) -> LRESULT
{
    if msg == winapi::winuser::WM_USER + 1 {
        println!("Got callback message! {}", l_param);
        // if l_param as UINT == winapi::winuser::WM_LBUTTONUP {
        //     println!("Posting quit message! {}", l_param);
        //     user32::PostQuitMessage(0);
        // }
        if l_param as UINT == winapi::winuser::WM_LBUTTONUP  {
            let mut p = winapi::POINT {
                x: 0,
                y: 0
            };
            if user32::GetCursorPos(&mut p as *mut winapi::POINT) == 0 {
                println!("Wrong position!");
                return 1;
            }
            println!("showing menu!");
            user32::SetForegroundWindow(hwnd);
            user32::TrackPopupMenu(hmenu, 0, p.x, p.y, (winapi::TPM_BOTTOMALIGN | winapi::TPM_LEFTALIGN) as i32, hwnd, std::ptr::null_mut());
        }
    }
    if msg == winapi::winuser::WM_DESTROY {
        user32::PostQuitMessage(0);
    }
    return user32::DefWindowProcW(h_wnd, msg, w_param, l_param);
}

fn main() {
    // Create window

    let class_name = to_wstring("my_window");
    let instance;
    unsafe {
        instance = kernel32::GetModuleHandleA(std::ptr::null_mut());
    };
    let wnd;
    unsafe {
        wnd = WNDCLASSW {
            style: 0,
            lpfnWndProc: Some(window_proc),
            cbClsExtra: 0,
            cbWndExtra: 0,
            hInstance: 0 as HINSTANCE,
            hIcon: user32::LoadIconW(0 as HINSTANCE, winapi::winuser::IDI_APPLICATION),
            hCursor: user32::LoadCursorW(0 as HINSTANCE, winapi::winuser::IDI_APPLICATION),
            hbrBackground: 16 as HBRUSH,
            lpszMenuName: 0 as LPCWSTR,
            lpszClassName: class_name.as_ptr(),
        };
    }
    unsafe {
        user32::RegisterClassW(&wnd);
        hwnd = user32::CreateWindowExW(0,
                                       class_name.as_ptr(),
                                       to_wstring("rust_systray_window").as_ptr(),
                                       WS_OVERLAPPEDWINDOW,
                                       CW_USEDEFAULT,
                                       0,
                                       CW_USEDEFAULT,
                                       0,
                                       0 as HWND,
                                       0 as HMENU,
                                       0 as HINSTANCE,
                                       std::ptr::null_mut());
        println!("Got window! {:?}", hwnd as u32);
        println!("Error? {}", kernel32::GetLastError());
    }

    // Create and add icon

    let icon;
    unsafe {
        icon = user32::LoadImageA(instance,
                                  std::mem::transmute(0x1 as isize),
                                  winapi::IMAGE_ICON,
                                  64,
                                  64,
                                  0) as HICON;
    }
    println!("Got icon! {:?}", icon as u32);
    let a : [i8; 64] = [0; 64];
    let mut b : [i8; 128] = [0; 128];
    let g : [i8; 256] = [0; 256];
    let guid = winapi::GUID {
        Data1: 0 as winapi::c_ulong,
        Data2: 0 as winapi::c_ushort,
        Data3: 0 as winapi::c_ushort,
        Data4: [0; 8]
    };
    unsafe {
        let mut nid_add = winapi::shellapi::NOTIFYICONDATAA {
            cbSize: std::mem::size_of::<winapi::shellapi::NOTIFYICONDATAA>() as DWORD,
            hWnd: hwnd,
            uID: 0x1 as UINT,
            uFlags: winapi::NIF_MESSAGE,
            uCallbackMessage: winapi::WM_USER + 1,
            hIcon: 0 as HICON,
            szTip: b,
            dwState: 0 as DWORD,
            dwStateMask: 0 as DWORD,
            szInfo: g,
            uTimeout: 0 as UINT,
            szInfoTitle: a,
            dwInfoFlags: 0 as UINT,
            guidItem: guid,
            hBalloonIcon: 0 as HICON
        };
        println!("Adding icon! {}", shell32::Shell_NotifyIconA(winapi::NIM_ADD,
                                                               &mut nid_add as *mut winapi::shellapi::NOTIFYICONDATAA));
    }
    unsafe {
        let mut nid = winapi::shellapi::NOTIFYICONDATAA {
            cbSize: std::mem::size_of::<winapi::shellapi::NOTIFYICONDATAA>() as DWORD,
            hWnd: hwnd,
            uID: 0x1 as UINT,
            uFlags: winapi::NIF_ICON,
            uCallbackMessage: 0 as UINT,
            hIcon: icon,
            szTip: b,
            dwState: 0 as DWORD,
            dwStateMask: 0 as DWORD,
            szInfo: g,
            uTimeout: 0 as UINT,
            szInfoTitle: a,
            dwInfoFlags: 0 as UINT,
            guidItem: guid,
            hBalloonIcon: 0 as HICON
        };
        println!("Setting icon! {}", shell32::Shell_NotifyIconA(winapi::NIM_MODIFY,
                                                                &mut nid as *mut winapi::shellapi::NOTIFYICONDATAA));
    }

    // Add Tooltip
    // Gross way to convert String to [i8; 128]
    // TODO: Clean up conversion, test for length so we don't panic at runtime
    let t = "Test Tip".to_string();
    let tt = t.as_bytes();
    for i in 0..tt.len() {
        b[i] = tt[i].clone() as i8;
    }
    unsafe {
        let mut nid_tip = winapi::shellapi::NOTIFYICONDATAA {
            cbSize: std::mem::size_of::<winapi::shellapi::NOTIFYICONDATAA>() as DWORD,
            hWnd: hwnd,
            uID: 0x1 as UINT,
            uFlags: winapi::NIF_TIP,
            uCallbackMessage: 0 as UINT,
            hIcon: 0 as HICON,
            szTip: b,
            dwState: 0 as DWORD,
            dwStateMask: 0 as DWORD,
            szInfo: g,
            uTimeout: 0 as UINT,
            szInfoTitle: a,
            dwInfoFlags: 0 as UINT,
            guidItem: guid,
            hBalloonIcon: 0 as HICON
        };
        println!("Setting tip! {}", shell32::Shell_NotifyIconA(winapi::NIM_MODIFY,
                                                               &mut nid_tip as *mut winapi::shellapi::NOTIFYICONDATAA));
    }

    // Add Menu
    let m;
    unsafe {
        hmenu = user32::CreatePopupMenu();
        m = winapi::MENUINFO {
            cbSize: std::mem::size_of::<winapi::MENUINFO>() as DWORD,
            fMask: winapi::MIM_APPLYTOSUBMENUS | winapi::MIM_STYLE,
            dwStyle: winapi::MNS_NOTIFYBYPOS,
            cyMax: 0 as UINT,
            hbrBack: 0 as HBRUSH,
            dwContextHelpID: 0 as DWORD,
            dwMenuData: 0 as winapi::ULONG_PTR
        };
        println!("Created menu! {}", user32::SetMenuInfo(hmenu, &m as *const winapi::MENUINFO));
    }

    // Add Menu Item
    unsafe {
        let idx : u32 = 1;
        let mut st = to_wstring("Quit");
        let item = winapi::MENUITEMINFOW {
            cbSize: std::mem::size_of::<winapi::MENUITEMINFOW>() as UINT,
            fMask: (winapi::MIIM_FTYPE | winapi::MIIM_STRING | winapi::MIIM_DATA | winapi::MIIM_STATE),
            fType: winapi::MFT_STRING,
            fState: 0 as UINT,
            wID: 0 as UINT,
            hSubMenu: 0 as HMENU,
            hbmpChecked: 0 as HBITMAP,
            hbmpUnchecked: 0 as HBITMAP,
            dwItemData: idx as u64,
            dwTypeData: st.as_mut_ptr(),
            cch: 10,
            hbmpItem: 0 as HBITMAP
        };
        user32::InsertMenuItemW(hmenu, 0, 1, &item as *const winapi::MENUITEMINFOW);
    }

    // Run message loop

    let mut msg = winapi::winuser::MSG {
        hwnd: 0 as HWND,
        message: 0 as UINT,
        wParam: 0 as WPARAM,
        lParam: 0 as LPARAM,
        time: 0 as DWORD,
        pt: winapi::windef::POINT { x: 0, y: 0, },
    };
    loop {
        unsafe {
            user32::GetMessageW(&mut msg, 0 as HWND, 0, 0);
        }
        if msg.message == winapi::winuser::WM_QUIT {
            break;
        }
        unsafe {
            user32::TranslateMessage(&mut msg);
            user32::DispatchMessageW(&mut msg);
        }
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<commit_msg>chore: Clean up windows code some<commit_after>extern crate winapi;
extern crate kernel32;
extern crate user32;
extern crate shell32;
extern crate libc;

use winapi::windef::{HWND, HMENU, HICON, HBRUSH, HBITMAP};
use winapi::winnt::{LPCWSTR};
use winapi::minwindef::{UINT, DWORD, WPARAM, LPARAM, LRESULT, HINSTANCE};
use winapi::winuser::{WNDCLASSW, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT};
use std::os::windows::ffi::OsStrExt;
use std::ffi::OsStr;

fn to_wstring(str : &str) -> Vec<u16> {
    OsStr::new(str).encode_wide().chain(Some(0).into_iter()).collect()
}

static mut instance : HINSTANCE = 0 as HINSTANCE;
static mut hwnd : HWND = 0 as HWND;
static mut hmenu: HMENU = 0 as HMENU;

pub unsafe extern "system" fn window_proc(h_wnd :HWND,
	                                        msg :UINT,
                                          w_param :WPARAM,
                                          l_param :LPARAM) -> LRESULT
{
    if msg == winapi::winuser::WM_USER + 1 {
        println!("Got callback message! {}", l_param);
        // if l_param as UINT == winapi::winuser::WM_LBUTTONUP {
        //     println!("Posting quit message! {}", l_param);
        //     user32::PostQuitMessage(0);
        // }
        if l_param as UINT == winapi::winuser::WM_LBUTTONUP  {
            let mut p = winapi::POINT {
                x: 0,
                y: 0
            };
            if user32::GetCursorPos(&mut p as *mut winapi::POINT) == 0 {
                return 1;
            }
            user32::SetForegroundWindow(hwnd);
            user32::TrackPopupMenu(hmenu, 0, p.x, p.y, (winapi::TPM_BOTTOMALIGN | winapi::TPM_LEFTALIGN) as i32, hwnd, std::ptr::null_mut());
        }
    }
    if msg == winapi::winuser::WM_DESTROY {
        user32::PostQuitMessage(0);
    }
    return user32::DefWindowProcW(h_wnd, msg, w_param, l_param);
}

fn get_nid_struct() -> winapi::shellapi::NOTIFYICONDATAA {
    let a : [i8; 64] = [0; 64];
    let mut b : [i8; 128] = [0; 128];
    let g : [i8; 256] = [0; 256];
    let guid = winapi::GUID {
        Data1: 0 as winapi::c_ulong,
        Data2: 0 as winapi::c_ushort,
        Data3: 0 as winapi::c_ushort,
        Data4: [0; 8]
    };
    unsafe {
        winapi::shellapi::NOTIFYICONDATAA {
            cbSize: std::mem::size_of::<winapi::shellapi::NOTIFYICONDATAA>() as DWORD,
            hWnd: hwnd,
            uID: 0x1 as UINT,
            uFlags: 0 as UINT,
            uCallbackMessage: 0 as UINT,
            hIcon: 0 as HICON,
            szTip: b,
            dwState: 0 as DWORD,
            dwStateMask: 0 as DWORD,
            szInfo: g,
            uTimeout: 0 as UINT,
            szInfoTitle: a,
            dwInfoFlags: 0 as UINT,
            guidItem: guid,
            hBalloonIcon: 0 as HICON
        }
    }
}

fn create_window() {
    let class_name = to_wstring("my_window");
    unsafe {
        instance = kernel32::GetModuleHandleA(std::ptr::null_mut());
    };
    let wnd;
    unsafe {
        wnd = WNDCLASSW {
            style: 0,
            lpfnWndProc: Some(window_proc),
            cbClsExtra: 0,
            cbWndExtra: 0,
            hInstance: 0 as HINSTANCE,
            hIcon: user32::LoadIconW(0 as HINSTANCE, winapi::winuser::IDI_APPLICATION),
            hCursor: user32::LoadCursorW(0 as HINSTANCE, winapi::winuser::IDI_APPLICATION),
            hbrBackground: 16 as HBRUSH,
            lpszMenuName: 0 as LPCWSTR,
            lpszClassName: class_name.as_ptr(),
        };
        user32::RegisterClassW(&wnd);
        hwnd = user32::CreateWindowExW(0,
                                       class_name.as_ptr(),
                                       to_wstring("rust_systray_window").as_ptr(),
                                       WS_OVERLAPPEDWINDOW,
                                       CW_USEDEFAULT,
                                       0,
                                       CW_USEDEFAULT,
                                       0,
                                       0 as HWND,
                                       0 as HMENU,
                                       0 as HINSTANCE,
                                       std::ptr::null_mut());
        println!("Got window! {:?}", hwnd as u32);
        println!("Error? {}", kernel32::GetLastError());
        let mut nid = get_nid_struct();
        nid.uID = 0x1;
        nid.uFlags = winapi::NIF_MESSAGE;
        nid.uCallbackMessage = winapi::WM_USER + 1;
        println!("Adding icon! {}", shell32::Shell_NotifyIconA(winapi::NIM_ADD,
                                                               &mut nid as *mut winapi::shellapi::NOTIFYICONDATAA));
        // Setup menu
        let m;
        hmenu = user32::CreatePopupMenu();
        m = winapi::MENUINFO {
            cbSize: std::mem::size_of::<winapi::MENUINFO>() as DWORD,
            fMask: winapi::MIM_APPLYTOSUBMENUS | winapi::MIM_STYLE,
            dwStyle: winapi::MNS_NOTIFYBYPOS,
            cyMax: 0 as UINT,
            hbrBack: 0 as HBRUSH,
            dwContextHelpID: 0 as DWORD,
            dwMenuData: 0 as winapi::ULONG_PTR
        };
        println!("Created menu! {}", user32::SetMenuInfo(hmenu, &m as *const winapi::MENUINFO));
    }
}

fn set_icon(icon: HICON) {
    unsafe {
        let mut nid = get_nid_struct();
        nid.uFlags = winapi::NIF_ICON;
        nid.hIcon = icon;
        println!("Setting icon! {}", shell32::Shell_NotifyIconA(winapi::NIM_MODIFY,
                                                                &mut nid as *mut winapi::shellapi::NOTIFYICONDATAA));

    }
}

fn set_icon_from_resource() {
    let icon;
    unsafe {
        icon = user32::LoadImageA(instance,
                                  std::mem::transmute(0x1 as isize),
                                  winapi::IMAGE_ICON,
                                  64,
                                  64,
                                  0) as HICON;
    }
    set_icon(icon);
}

fn set_icon_from_file() {
}

fn setup_menu() {
    unsafe {
    }
}

fn set_tooltip(tooltip: &String) {
    // Add Tooltip
    // Gross way to convert String to [i8; 128]
    // TODO: Clean up conversion, test for length so we don't panic at runtime
    let tt = tooltip.as_bytes().clone();
    let mut nid = get_nid_struct();
    for i in 0..tt.len() {
        nid.szTip[i] = tt[i] as i8;
    }
    nid.uFlags = winapi::NIF_TIP;
    unsafe {
        println!("Setting tip! {}", shell32::Shell_NotifyIconA(winapi::NIM_MODIFY,
                                                               &mut nid as *mut winapi::shellapi::NOTIFYICONDATAA));
    }
}

fn add_menu_item(item_name: &String) {
    let idx : u32 = 1;
    let mut st = to_wstring(item_name);
    let item = winapi::MENUITEMINFOW {
        cbSize: std::mem::size_of::<winapi::MENUITEMINFOW>() as UINT,
        fMask: (winapi::MIIM_FTYPE | winapi::MIIM_STRING | winapi::MIIM_DATA | winapi::MIIM_STATE),
        fType: winapi::MFT_STRING,
        fState: 0 as UINT,
        wID: 0 as UINT,
        hSubMenu: 0 as HMENU,
        hbmpChecked: 0 as HBITMAP,
        hbmpUnchecked: 0 as HBITMAP,
        dwItemData: idx as u64,
        dwTypeData: st.as_mut_ptr(),
        cch: item_name.len() * 2, // 16 bit characters
        hbmpItem: 0 as HBITMAP
    };
    unsafe {
        user32::InsertMenuItemW(hmenu, 0, 1, &item as *const winapi::MENUITEMINFOW);
    }
}

fn run_loop() {
    // Run message loop
    let mut msg = winapi::winuser::MSG {
        hwnd: 0 as HWND,
        message: 0 as UINT,
        wParam: 0 as WPARAM,
        lParam: 0 as LPARAM,
        time: 0 as DWORD,
        pt: winapi::windef::POINT { x: 0, y: 0, },
    };
    loop {
        unsafe {
            user32::GetMessageW(&mut msg, 0 as HWND, 0, 0);
        }
        if msg.message == winapi::winuser::WM_QUIT {
            break;
        }
        unsafe {
            user32::TranslateMessage(&mut msg);
            user32::DispatchMessageW(&mut msg);
        }
    }
}

fn main() {
    create_window();
    setup_menu();
    set_tooltip(&"Whatever".to_string());
    add_menu_item(&"Something".to_string());
    run_loop();
}
<|endoftext|>


<commit_before>use error::{CliError, Usage, UsageKind};
use super::Command;

extern crate chrono;
extern crate regex;
extern crate toml;

use self::chrono::NaiveTime;
use self::regex::Regex;

use error::{CannotHappenError, ConfigError, ConfigErrorKind};
use lib::config;
use std::collections::BTreeMap;
use std::str::FromStr;

pub struct Config {
    param: Option<String>,
    value: Option<String>,
}

impl Command for Config {
    fn validation(&self) -> bool { true }

    fn usage(&self) -> Usage {
        return Usage::new(UsageKind::Config);
    }

    fn main(&self) -> Result<(), CliError> {
        let (param, value) = match (self.param.clone(), self.value.clone()) {
            (Some(p), Some(v)) => (p, v),
            _                  => return Err(From::from(self.usage())),
        };
        let (param, value) = (param.trim(), value.trim());

        let (first, second) = match param {
            p @ "sweep.period" | p @ "sweep.time" | p @ "burn.after" => {
                let params = p.split('.').collect::<Vec<_>>();
                (params[0], params[1])
            },
            _ => return Err(From::from(ConfigError::new(ConfigErrorKind::InvalidParam))),
        };

        // validate value
        let value = match param {
            "sweep.period" => {
                match value {
                    "daily" | "weekly" => value.to_string(),
                    _                  => return Err(From::from(ConfigError::new(ConfigErrorKind::SweepPeriod))),
                }
            },
            "sweep.time" => {
                match NaiveTime::from_str(format!("{}:00", value).as_ref()) {
                    Ok(_)  => value.to_string(),
                    // should set Err(e) to Error::cause()
                    Err(_) => return Err(From::from(ConfigError::new(ConfigErrorKind::SweepTime))),
                }
            },
            "burn.after" => {
                let re = try!(Regex::new(r"(?P<num>\d+)\s*(?P<unit>days?|weeks?)"));
                let (num, value) = match re.captures(value.as_ref()).map(|caps| (caps.name("num"), caps.name("unit"))) {
                    Some((Some(num), Some(unit))) => (num, format!("{} {}", num, unit)),
                    _                             => return Err(From::from(ConfigError::new(ConfigErrorKind::BurnAfter)))
                };
                // should set Err(e) to Error::cause()
                try!(num.parse::<u32>());

                value
            },
            _ => return Err(From::from(CannotHappenError)),
        };

        let config     = try!(config::Config::read());
        let mut config = match toml::decode::<BTreeMap<String, BTreeMap<String, String>>>(config) {
            Some(decoded) => decoded,
            None          => return Err(From::from(ConfigError::new(ConfigErrorKind::Something))),
        };

        config
            .get_mut(first)
            .map(|c| c.insert(second.to_string(), value));

        let new_config = toml::encode_str(&config);
        println!("{}", new_config);

        //try!(create_config_file(new_config));

        Ok(())
    }
}

impl Config {
    pub fn new(param: Option<String>, value: Option<String>) -> Config {
        Config { param: param, value: value }
    }
}
<commit_msg>[Fix] Release comment-out<commit_after>use error::{CliError, Usage, UsageKind};
use super::Command;

extern crate chrono;
extern crate regex;
extern crate toml;

use self::chrono::NaiveTime;
use self::regex::Regex;

use error::{CannotHappenError, ConfigError, ConfigErrorKind};
use lib::config;
use lib::setting;
use std::collections::BTreeMap;
use std::str::FromStr;

pub struct Config {
    param: Option<String>,
    value: Option<String>,
}

impl Command for Config {
    fn validation(&self) -> bool { true }

    fn usage(&self) -> Usage {
        return Usage::new(UsageKind::Config);
    }

    fn main(&self) -> Result<(), CliError> {
        let (param, value) = match (self.param.clone(), self.value.clone()) {
            (Some(p), Some(v)) => (p, v),
            _                  => return Err(From::from(self.usage())),
        };
        let (param, value) = (param.trim(), value.trim());

        let (first, second) = match param {
            p @ "sweep.period" | p @ "sweep.time" | p @ "burn.after" => {
                let params = p.split('.').collect::<Vec<_>>();
                (params[0], params[1])
            },
            _ => return Err(From::from(ConfigError::new(ConfigErrorKind::InvalidParam))),
        };

        // validate value
        let value = match param {
            "sweep.period" => {
                match value {
                    "daily" | "weekly" => value.to_string(),
                    _                  => return Err(From::from(ConfigError::new(ConfigErrorKind::SweepPeriod))),
                }
            },
            "sweep.time" => {
                match NaiveTime::from_str(format!("{}:00", value).as_ref()) {
                    Ok(_)  => value.to_string(),
                    // should set Err(e) to Error::cause()
                    Err(_) => return Err(From::from(ConfigError::new(ConfigErrorKind::SweepTime))),
                }
            },
            "burn.after" => {
                let re = try!(Regex::new(r"(?P<num>\d+)\s*(?P<unit>days?|weeks?)"));
                let (num, value) = match re.captures(value.as_ref()).map(|caps| (caps.name("num"), caps.name("unit"))) {
                    Some((Some(num), Some(unit))) => (num, format!("{} {}", num, unit)),
                    _                             => return Err(From::from(ConfigError::new(ConfigErrorKind::BurnAfter)))
                };
                // should set Err(e) to Error::cause()
                try!(num.parse::<u32>());

                value
            },
            _ => return Err(From::from(CannotHappenError)),
        };

        let config     = try!(config::Config::read());
        let mut config = match toml::decode::<BTreeMap<String, BTreeMap<String, String>>>(config) {
            Some(decoded) => decoded,
            None          => return Err(From::from(ConfigError::new(ConfigErrorKind::Something))),
        };

        config
            .get_mut(first)
            .map(|c| c.insert(second.to_string(), value));

        let new_config = toml::encode_str(&config);

        try!(setting::create_config_file(new_config));

        Ok(())
    }
}

impl Config {
    pub fn new(param: Option<String>, value: Option<String>) -> Config {
        Config { param: param, value: value }
    }
}
<|endoftext|>