<commit_before>#![cfg(feature = "serde")]

extern crate serde;
use self::serde::de::{
    Deserialize, DeserializeSeed, Deserializer, EnumAccess, Error, Unexpected, VariantAccess,
    Visitor,
};
use self::serde::ser::{Serialize, Serializer};

use {Level, LevelFilter, LOG_LEVEL_NAMES};

use std::fmt;
use std::str::{self, FromStr};

// The Deserialize impls are handwritten to be case insensitive using FromStr.

impl Serialize for Level {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match *self {
            Level::Error => serializer.serialize_unit_variant("Level", 0, "ERROR"),
            Level::Warn => serializer.serialize_unit_variant("Level", 1, "WARN"),
            Level::Info => serializer.serialize_unit_variant("Level", 2, "INFO"),
            Level::Debug => serializer.serialize_unit_variant("Level", 3, "DEBUG"),
            Level::Trace => serializer.serialize_unit_variant("Level", 4, "TRACE"),
        }
    }
}

impl<'de> Deserialize<'de> for Level {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct LevelIdentifier;

        impl<'de> Visitor<'de> for LevelIdentifier {
            type Value = Level;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("log level")
            }

            fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
            where
                E: Error,
            {
                // Case insensitive.
                FromStr::from_str(s).map_err(|_| Error::unknown_variant(s, &LOG_LEVEL_NAMES[1..]))
            }

            fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
            where
                E: Error,
            {
                let variant = str::from_utf8(value)
                    .map_err(|_| Error::invalid_value(Unexpected::Bytes(value), &self))?;

                self.visit_str(variant)
            }

            fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
            where
                E: Error,
            {
                let variant: &str = LOG_LEVEL_NAMES[1..]
                    .get(v as usize)
                    .ok_or_else(|| Error::invalid_value(Unexpected::Unsigned(v), &self))?;

                self.visit_str(variant)
            }
        }

        impl<'de> DeserializeSeed<'de> for LevelIdentifier {
            type Value = Level;

            fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
            where
                D: Deserializer<'de>,
            {
                deserializer.deserialize_identifier(LevelIdentifier)
            }
        }

        struct LevelEnum;

        impl<'de> Visitor<'de> for LevelEnum {
            type Value = Level;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("log level")
            }

            fn visit_enum<A>(self, value: A) -> Result<Self::Value, A::Error>
            where
                A: EnumAccess<'de>,
            {
                let (level, variant) = value.variant_seed(LevelIdentifier)?;
                // Every variant is a unit variant.
                variant.unit_variant()?;
                Ok(level)
            }
        }

        deserializer.deserialize_enum("Level", &LOG_LEVEL_NAMES[1..], LevelEnum)
    }
}

impl Serialize for LevelFilter {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match *self {
            LevelFilter::Off => serializer.serialize_unit_variant("LevelFilter", 0, "OFF"),
            LevelFilter::Error => serializer.serialize_unit_variant("LevelFilter", 1, "ERROR"),
            LevelFilter::Warn => serializer.serialize_unit_variant("LevelFilter", 2, "WARN"),
            LevelFilter::Info => serializer.serialize_unit_variant("LevelFilter", 3, "INFO"),
            LevelFilter::Debug => serializer.serialize_unit_variant("LevelFilter", 4, "DEBUG"),
            LevelFilter::Trace => serializer.serialize_unit_variant("LevelFilter", 5, "TRACE"),
        }
    }
}

impl<'de> Deserialize<'de> for LevelFilter {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct LevelFilterIdentifier;

        impl<'de> Visitor<'de> for LevelFilterIdentifier {
            type Value = LevelFilter;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("log level filter")
            }

            fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
            where
                E: Error,
            {
                // Case insensitive.
                FromStr::from_str(s).map_err(|_| Error::unknown_variant(s, &LOG_LEVEL_NAMES))
            }

            fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
            where
                E: Error,
            {
                let variant = str::from_utf8(value)
                    .map_err(|_| Error::invalid_value(Unexpected::Bytes(value), &self))?;

                self.visit_str(variant)
            }

            fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
            where
                E: Error,
            {
                let variant: &str = LOG_LEVEL_NAMES
                    .get(v as usize)
                    .ok_or_else(|| Error::invalid_value(Unexpected::Unsigned(v), &self))?;

                self.visit_str(variant)
            }
        }

        impl<'de> DeserializeSeed<'de> for LevelFilterIdentifier {
            type Value = LevelFilter;

            fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
            where
                D: Deserializer<'de>,
            {
                deserializer.deserialize_identifier(LevelFilterIdentifier)
            }
        }

        struct LevelFilterEnum;

        impl<'de> Visitor<'de> for LevelFilterEnum {
            type Value = LevelFilter;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("log level filter")
            }

            fn visit_enum<A>(self, value: A) -> Result<Self::Value, A::Error>
            where
                A: EnumAccess<'de>,
            {
                let (level_filter, variant) = value.variant_seed(LevelFilterIdentifier)?;
                // Every variant is a unit variant.
                variant.unit_variant()?;
                Ok(level_filter)
            }
        }

        deserializer.deserialize_enum("LevelFilter", &LOG_LEVEL_NAMES, LevelFilterEnum)
    }
}

#[cfg(test)]
mod tests {
    extern crate serde_test;
    use self::serde_test::{assert_de_tokens, assert_de_tokens_error, assert_tokens, Token};

    use {Level, LevelFilter};

    fn level_token(variant: &'static str) -> Token {
        Token::UnitVariant {
            name: "Level",
            variant: variant,
        }
    }

    fn level_bytes_tokens(variant: &'static [u8]) -> [Token; 3] {
        [
            Token::Enum { name: "Level" },
            Token::Bytes(variant),
            Token::Unit,
        ]
    }

    fn level_filter_token(variant: &'static str) -> Token {
        Token::UnitVariant {
            name: "LevelFilter",
            variant: variant,
        }
    }

    fn level_filter_bytes_tokens(variant: &'static [u8]) -> [Token; 3] {
        [
            Token::Enum {
                name: "LevelFilter",
            },
            Token::Bytes(variant),
            Token::Unit,
        ]
    }

    #[test]
    fn test_level_ser_de() {
        let cases = [
            (Level::Error, [level_token("ERROR")]),
            (Level::Warn, [level_token("WARN")]),
            (Level::Info, [level_token("INFO")]),
            (Level::Debug, [level_token("DEBUG")]),
            (Level::Trace, [level_token("TRACE")]),
        ];

        for &(s, expected) in &cases {
            assert_tokens(&s, &expected);
        }
    }

    #[test]
    fn test_level_case_insensitive() {
        let cases = [
            (Level::Error, [level_token("error")]),
            (Level::Warn, [level_token("warn")]),
            (Level::Info, [level_token("info")]),
            (Level::Debug, [level_token("debug")]),
            (Level::Trace, [level_token("trace")]),
        ];

        for &(s, expected) in &cases {
            assert_de_tokens(&s, &expected);
        }
    }

    #[test]
    fn test_level_de_bytes() {
        let cases = [
            (Level::Error, level_bytes_tokens(b"ERROR")),
            (Level::Warn, level_bytes_tokens(b"WARN")),
            (Level::Info, level_bytes_tokens(b"INFO")),
            (Level::Debug, level_bytes_tokens(b"DEBUG")),
            (Level::Trace, level_bytes_tokens(b"TRACE")),
        ];

        for &(value, tokens) in &cases {
            assert_de_tokens(&value, &tokens);
        }
    }

    #[test]
    fn test_level_de_error() {
        let msg = "unknown variant `errorx`, expected one of \
                   `ERROR`, `WARN`, `INFO`, `DEBUG`, `TRACE`";
        assert_de_tokens_error::<Level>(&[level_token("errorx")], msg);
    }

    #[test]
    fn test_level_filter_ser_de() {
        let cases = [
            (LevelFilter::Off, [level_filter_token("OFF")]),
            (LevelFilter::Error, [level_filter_token("ERROR")]),
            (LevelFilter::Warn, [level_filter_token("WARN")]),
            (LevelFilter::Info, [level_filter_token("INFO")]),
            (LevelFilter::Debug, [level_filter_token("DEBUG")]),
            (LevelFilter::Trace, [level_filter_token("TRACE")]),
        ];

        for &(s, expected) in &cases {
            assert_tokens(&s, &expected);
        }
    }

    #[test]
    fn test_level_filter_case_insensitive() {
        let cases = [
            (LevelFilter::Off, [level_filter_token("off")]),
            (LevelFilter::Error, [level_filter_token("error")]),
            (LevelFilter::Warn, [level_filter_token("warn")]),
            (LevelFilter::Info, [level_filter_token("info")]),
            (LevelFilter::Debug, [level_filter_token("debug")]),
            (LevelFilter::Trace, [level_filter_token("trace")]),
        ];

        for &(s, expected) in &cases {
            assert_de_tokens(&s, &expected);
        }
    }

    #[test]
    fn test_level_filter_de_bytes() {
        let cases = [
            (LevelFilter::Off, level_filter_bytes_tokens(b"OFF")),
            (LevelFilter::Error, level_filter_bytes_tokens(b"ERROR")),
            (LevelFilter::Warn, level_filter_bytes_tokens(b"WARN")),
            (LevelFilter::Info, level_filter_bytes_tokens(b"INFO")),
            (LevelFilter::Debug, level_filter_bytes_tokens(b"DEBUG")),
            (LevelFilter::Trace, level_filter_bytes_tokens(b"TRACE")),
        ];

        for &(value, tokens) in &cases {
            assert_de_tokens(&value, &tokens);
        }
    }

    #[test]
    fn test_level_filter_de_error() {
        let msg = "unknown variant `errorx`, expected one of \
                   `OFF`, `ERROR`, `WARN`, `INFO`, `DEBUG`, `TRACE`";
        assert_de_tokens_error::<LevelFilter>(&[level_filter_token("errorx")], msg);
    }
}
<commit_msg>Made the variants deserialize as u32 because that's the type that is given when serializing. Added tests<commit_after>#![cfg(feature = "serde")]

extern crate serde;
use self::serde::de::{
    Deserialize, DeserializeSeed, Deserializer, EnumAccess, Error, Unexpected, VariantAccess,
    Visitor,
};
use self::serde::ser::{Serialize, Serializer};

use {Level, LevelFilter, LOG_LEVEL_NAMES};

use std::fmt;
use std::str::{self, FromStr};

// The Deserialize impls are handwritten to be case insensitive using FromStr.

impl Serialize for Level {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match *self {
            Level::Error => serializer.serialize_unit_variant("Level", 0, "ERROR"),
            Level::Warn => serializer.serialize_unit_variant("Level", 1, "WARN"),
            Level::Info => serializer.serialize_unit_variant("Level", 2, "INFO"),
            Level::Debug => serializer.serialize_unit_variant("Level", 3, "DEBUG"),
            Level::Trace => serializer.serialize_unit_variant("Level", 4, "TRACE"),
        }
    }
}

impl<'de> Deserialize<'de> for Level {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct LevelIdentifier;

        impl<'de> Visitor<'de> for LevelIdentifier {
            type Value = Level;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("log level")
            }

            fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
            where
                E: Error,
            {
                // Case insensitive.
                FromStr::from_str(s).map_err(|_| Error::unknown_variant(s, &LOG_LEVEL_NAMES[1..]))
            }

            fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
            where
                E: Error,
            {
                let variant = str::from_utf8(value)
                    .map_err(|_| Error::invalid_value(Unexpected::Bytes(value), &self))?;

                self.visit_str(variant)
            }

            fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
            where
                E: Error,
            {
                let variant = LOG_LEVEL_NAMES[1..]
                    .get(v as usize)
                    .ok_or_else(|| Error::invalid_value(Unexpected::Unsigned(v as u64), &self))?;

                self.visit_str(variant)
            }
        }

        impl<'de> DeserializeSeed<'de> for LevelIdentifier {
            type Value = Level;

            fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
            where
                D: Deserializer<'de>,
            {
                deserializer.deserialize_identifier(LevelIdentifier)
            }
        }

        struct LevelEnum;

        impl<'de> Visitor<'de> for LevelEnum {
            type Value = Level;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("log level")
            }

            fn visit_enum<A>(self, value: A) -> Result<Self::Value, A::Error>
            where
                A: EnumAccess<'de>,
            {
                let (level, variant) = value.variant_seed(LevelIdentifier)?;
                // Every variant is a unit variant.
                variant.unit_variant()?;
                Ok(level)
            }
        }

        deserializer.deserialize_enum("Level", &LOG_LEVEL_NAMES[1..], LevelEnum)
    }
}

impl Serialize for LevelFilter {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match *self {
            LevelFilter::Off => serializer.serialize_unit_variant("LevelFilter", 0, "OFF"),
            LevelFilter::Error => serializer.serialize_unit_variant("LevelFilter", 1, "ERROR"),
            LevelFilter::Warn => serializer.serialize_unit_variant("LevelFilter", 2, "WARN"),
            LevelFilter::Info => serializer.serialize_unit_variant("LevelFilter", 3, "INFO"),
            LevelFilter::Debug => serializer.serialize_unit_variant("LevelFilter", 4, "DEBUG"),
            LevelFilter::Trace => serializer.serialize_unit_variant("LevelFilter", 5, "TRACE"),
        }
    }
}

impl<'de> Deserialize<'de> for LevelFilter {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct LevelFilterIdentifier;

        impl<'de> Visitor<'de> for LevelFilterIdentifier {
            type Value = LevelFilter;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("log level filter")
            }

            fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
            where
                E: Error,
            {
                // Case insensitive.
                FromStr::from_str(s).map_err(|_| Error::unknown_variant(s, &LOG_LEVEL_NAMES))
            }

            fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
            where
                E: Error,
            {
                let variant = str::from_utf8(value)
                    .map_err(|_| Error::invalid_value(Unexpected::Bytes(value), &self))?;

                self.visit_str(variant)
            }

            fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
            where
                E: Error,
            {
                let variant = LOG_LEVEL_NAMES
                    .get(v as usize)
                    .ok_or_else(|| Error::invalid_value(Unexpected::Unsigned(v as u64), &self))?;

                self.visit_str(variant)
            }
        }

        impl<'de> DeserializeSeed<'de> for LevelFilterIdentifier {
            type Value = LevelFilter;

            fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
            where
                D: Deserializer<'de>,
            {
                deserializer.deserialize_identifier(LevelFilterIdentifier)
            }
        }

        struct LevelFilterEnum;

        impl<'de> Visitor<'de> for LevelFilterEnum {
            type Value = LevelFilter;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("log level filter")
            }

            fn visit_enum<A>(self, value: A) -> Result<Self::Value, A::Error>
            where
                A: EnumAccess<'de>,
            {
                let (level_filter, variant) = value.variant_seed(LevelFilterIdentifier)?;
                // Every variant is a unit variant.
                variant.unit_variant()?;
                Ok(level_filter)
            }
        }

        deserializer.deserialize_enum("LevelFilter", &LOG_LEVEL_NAMES, LevelFilterEnum)
    }
}

#[cfg(test)]
mod tests {
    extern crate serde_test;
    use self::serde_test::{assert_de_tokens, assert_de_tokens_error, assert_tokens, Token};

    use {Level, LevelFilter};

    fn level_token(variant: &'static str) -> Token {
        Token::UnitVariant {
            name: "Level",
            variant: variant,
        }
    }

    fn level_bytes_tokens(variant: &'static [u8]) -> [Token; 3] {
        [
            Token::Enum { name: "Level" },
            Token::Bytes(variant),
            Token::Unit,
        ]
    }

    fn level_variant_tokens(variant: u32) -> [Token; 3] {
        [
            Token::Enum { name: "Level" },
            Token::U32(variant),
            Token::Unit,
        ]
    }

    fn level_filter_token(variant: &'static str) -> Token {
        Token::UnitVariant {
            name: "LevelFilter",
            variant: variant,
        }
    }

    fn level_filter_bytes_tokens(variant: &'static [u8]) -> [Token; 3] {
        [
            Token::Enum {
                name: "LevelFilter",
            },
            Token::Bytes(variant),
            Token::Unit,
        ]
    }

    fn level_filter_variant_tokens(variant: u32) -> [Token; 3] {
        [
            Token::Enum {
                name: "LevelFilter",
            },
            Token::U32(variant),
            Token::Unit,
        ]
    }

    #[test]
    fn test_level_ser_de() {
        let cases = [
            (Level::Error, [level_token("ERROR")]),
            (Level::Warn, [level_token("WARN")]),
            (Level::Info, [level_token("INFO")]),
            (Level::Debug, [level_token("DEBUG")]),
            (Level::Trace, [level_token("TRACE")]),
        ];

        for &(s, expected) in &cases {
            assert_tokens(&s, &expected);
        }
    }

    #[test]
    fn test_level_case_insensitive() {
        let cases = [
            (Level::Error, [level_token("error")]),
            (Level::Warn, [level_token("warn")]),
            (Level::Info, [level_token("info")]),
            (Level::Debug, [level_token("debug")]),
            (Level::Trace, [level_token("trace")]),
        ];

        for &(s, expected) in &cases {
            assert_de_tokens(&s, &expected);
        }
    }

    #[test]
    fn test_level_de_bytes() {
        let cases = [
            (Level::Error, level_bytes_tokens(b"ERROR")),
            (Level::Warn, level_bytes_tokens(b"WARN")),
            (Level::Info, level_bytes_tokens(b"INFO")),
            (Level::Debug, level_bytes_tokens(b"DEBUG")),
            (Level::Trace, level_bytes_tokens(b"TRACE")),
        ];

        for &(value, tokens) in &cases {
            assert_de_tokens(&value, &tokens);
        }
    }

    #[test]
    fn test_level_de_variant_index() {
        let cases = [
            (Level::Error, level_variant_tokens(0)),
            (Level::Warn, level_variant_tokens(1)),
            (Level::Info, level_variant_tokens(2)),
            (Level::Debug, level_variant_tokens(3)),
            (Level::Trace, level_variant_tokens(4)),
        ];

        for &(value, tokens) in &cases {
            assert_de_tokens(&value, &tokens);
        }
    }

    #[test]
    fn test_level_de_error() {
        let msg = "unknown variant `errorx`, expected one of \
                   `ERROR`, `WARN`, `INFO`, `DEBUG`, `TRACE`";
        assert_de_tokens_error::<Level>(&[level_token("errorx")], msg);
    }

    #[test]
    fn test_level_filter_ser_de() {
        let cases = [
            (LevelFilter::Off, [level_filter_token("OFF")]),
            (LevelFilter::Error, [level_filter_token("ERROR")]),
            (LevelFilter::Warn, [level_filter_token("WARN")]),
            (LevelFilter::Info, [level_filter_token("INFO")]),
            (LevelFilter::Debug, [level_filter_token("DEBUG")]),
            (LevelFilter::Trace, [level_filter_token("TRACE")]),
        ];

        for &(s, expected) in &cases {
            assert_tokens(&s, &expected);
        }
    }

    #[test]
    fn test_level_filter_case_insensitive() {
        let cases = [
            (LevelFilter::Off, [level_filter_token("off")]),
            (LevelFilter::Error, [level_filter_token("error")]),
            (LevelFilter::Warn, [level_filter_token("warn")]),
            (LevelFilter::Info, [level_filter_token("info")]),
            (LevelFilter::Debug, [level_filter_token("debug")]),
            (LevelFilter::Trace, [level_filter_token("trace")]),
        ];

        for &(s, expected) in &cases {
            assert_de_tokens(&s, &expected);
        }
    }

    #[test]
    fn test_level_filter_de_bytes() {
        let cases = [
            (LevelFilter::Off, level_filter_bytes_tokens(b"OFF")),
            (LevelFilter::Error, level_filter_bytes_tokens(b"ERROR")),
            (LevelFilter::Warn, level_filter_bytes_tokens(b"WARN")),
            (LevelFilter::Info, level_filter_bytes_tokens(b"INFO")),
            (LevelFilter::Debug, level_filter_bytes_tokens(b"DEBUG")),
            (LevelFilter::Trace, level_filter_bytes_tokens(b"TRACE")),
        ];

        for &(value, tokens) in &cases {
            assert_de_tokens(&value, &tokens);
        }
    }

    #[test]
    fn test_level_filter_de_variant_index() {
        let cases = [
            (LevelFilter::Off, level_filter_variant_tokens(0)),
            (LevelFilter::Error, level_filter_variant_tokens(1)),
            (LevelFilter::Warn, level_filter_variant_tokens(2)),
            (LevelFilter::Info, level_filter_variant_tokens(3)),
            (LevelFilter::Debug, level_filter_variant_tokens(4)),
            (LevelFilter::Trace, level_filter_variant_tokens(5)),
        ];

        for &(value, tokens) in &cases {
            assert_de_tokens(&value, &tokens);
        }
    }

    #[test]
    fn test_level_filter_de_error() {
        let msg = "unknown variant `errorx`, expected one of \
                   `OFF`, `ERROR`, `WARN`, `INFO`, `DEBUG`, `TRACE`";
        assert_de_tokens_error::<LevelFilter>(&[level_filter_token("errorx")], msg);
    }
}
<|endoftext|>


<commit_before>// xfail-test FIXME #6257

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

use std::cmp::{Less,Equal,Greater};

#[deriving(TotalEq,TotalOrd)]
struct A<'self> {
    x: &'self int
}

fn main() {
    let a = A { x: &1 }, b = A { x: &2 };

    assert!(a.equals(&a));
    assert!(b.equals(&b));

    assert_eq!(a.cmp(&a), Equal);
    assert_eq!(b.cmp(&b), Equal);

    assert_eq!(a.cmp(&b), Less);
    assert_eq!(b.cmp(&a), Greater);
}
<commit_msg>Use updated local declaration syntax.<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::cmp::{Less,Equal,Greater};

#[deriving(TotalEq,TotalOrd)]
struct A<'self> {
    x: &'self int
}
fn main() {
    let (a, b) = (A { x: &1 }, A { x: &2 });

    assert!(a.equals(&a));
    assert!(b.equals(&b));

    assert_eq!(a.cmp(&a), Equal);
    assert_eq!(b.cmp(&b), Equal);

    assert_eq!(a.cmp(&b), Less);
    assert_eq!(b.cmp(&a), Greater);
}
<|endoftext|>


<commit_before>use std::cmp::Ordering;
use std::collections::{HashMap, HashSet};

pub fn largest_number(nums: Vec<i32>) -> String {
    let mut cache: HashMap<u8, Vec<Vec<u8>>> = HashMap::new();
    for n in nums {
        let this = n.to_string();
        let bs = this.into_bytes();

        let this_value = cache.entry(bs[0]).or_insert(Vec::new());
        this_value.push(bs.clone());
    }

    //dbg!(&cache);

    let mut result: Vec<u8> = vec![];
    for i in 48..58 {
        if let Some(this_) = cache.get_mut(&(48 + 57 - i as u8)) {
            this_.sort_by(compare);
            this_.reverse();
            for v in this_ {
                result.append(v);
            }
        }
    }

    //dbg!(&result);
    if result[0] == 48 as u8 {
        String::from("0")
    } else {
        String::from_utf8(result).unwrap()
    }
}

//give up
fn compare(a: &Vec<u8>, b: &Vec<u8>) -> Ordering {
    let mut ind = 0;
    let (lan_a, lan_b) = (a.len(), b.len());
    while ind != lan_a && ind != lan_b {
        if a[ind] > b[ind] {
            return Ordering::Greater;
        } else if b[ind] > a[ind] {
            return Ordering::Less;
        }

        ind += 1;
    }

    if ind < lan_a {
        while ind < lan_a {
            if a[ind] > a[ind - 1] {
                return Ordering::Greater;
            } else if a[ind] < a[ind - 1] {
                return Ordering::Less;
            }
            ind += 1;
        }
        return Ordering::Equal;
    } else if ind < lan_b {
        while ind < lan_b {
            if b[ind] > b[ind - 1] {
                return Ordering::Less;
            } else if b[ind] < b[ind - 1] {
                return Ordering::Greater;
            }
            ind += 1;
        }
        return Ordering::Equal;
    } else {
        return Ordering::Equal;
    }
}

fn compare_two<'x>(a: &'x Vec<u8>, b: &'x Vec<u8>) -> (bool, &'x Vec<u8>) {
    let mut ind = 0;
    let (lan_a, lan_b) = (a.len(), b.len());
    while ind != lan_a && ind != lan_b {
        if a[ind] > b[ind] {
            return (true, a);
        } else if b[ind] > a[ind] {
            return (false, b);
        }

        ind += 1;
    }

    if ind < lan_a {
        while ind < lan_a {
            if a[ind] > a[ind - 1] {
                return (true, a);
            } else if a[ind] < a[ind - 1] {
                return (false, b);
            }
            ind += 1;
        }
        return (true, a);
    } else if ind < lan_b {
        while ind < lan_b {
            if b[ind] > b[ind - 1] {
                return (false, b);
            } else if b[ind] < b[ind - 1] {
                return (true, a);
            }
            ind += 1;
        }
        return (false, b);
    } else {
        return (true, a);
    }
}

fn which_bit(a: String, b: String) {
    let a_ = a.into_bytes();
    let b_ = b.into_bytes();

    let len = a_.len();

    for i in 0..len {
        if a_[i] != b_[i] {
            println!("bit: {}, is: {}", i, a_[i] as char);
        }
    }
}

fn main() {
    //let a = String::from("123").into_bytes();
    //let b = String::from("123").into_bytes();
    //dbg!(compare_two(&a, &b));

    dbg!(largest_number(vec![12, 23])); //=> 2312
    dbg!(largest_number(vec![10, 2])); //=> 210
    dbg!(largest_number(vec![3, 30, 34, 5, 9])); //=> 9534330
    dbg!(largest_number(vec![0, 0])); //=> 0

    dbg!(largest_number(vec![
        4704, 6306, 9385, 7536, 3462, 4798, 5422, 5529, 8070, 6241, 9094, 7846, 663, 6221, 216,
        6758, 8353, 3650, 3836, 8183, 3516, 5909, 6744, 1548, 5712, 2281, 3664, 7100, 6698, 7321,
        4980, 8937, 3163, 5784, 3298, 9890, 1090, 7605, 1380, 1147, 1495, 3699, 9448, 5208, 9456,
        3846, 3567, 6856, 2000, 3575, 7205, 2697, 5972, 7471, 1763, 1143, 1417, 6038, 2313, 6554,
        9026, 8107, 9827, 7982, 9685, 3905, 8939, 1048, 282, 7423, 6327, 2970, 4453, 5460, 3399,
        9533, 914, 3932, 192, 3084, 6806, 273, 4283, 2060, 5682, 2, 2362, 4812, 7032, 810, 2465,
        6511, 213, 2362, 3021, 2745, 3636, 6265, 1518, 8398
    ])); // => 98909827968595339456944893859149094902689398937839883538183810810780707982784676057536747174237321720571007032685668066758674466986636554651163276306626562416221603859725909578457125682552954605422520849804812479847044453428339323905384638363699366436503636357535673516346233993298316330843021297028227452732697246523622362231322812216213206020001921763154815181495141713801147114310901048

    // assert_eq!(largest_number(vec![
    //     4704, 6306, 9385, 7536, 3462, 4798, 5422, 5529, 8070, 6241, 9094, 7846, 663, 6221, 216,
    //     6758, 8353, 3650, 3836, 8183, 3516, 5909, 6744, 1548, 5712, 2281, 3664, 7100, 6698, 7321,
    //     4980, 8937, 3163, 5784, 3298, 9890, 1090, 7605, 1380, 1147, 1495, 3699, 9448, 5208, 9456,
    //     3846, 3567, 6856, 2000, 3575, 7205, 2697, 5972, 7471, 1763, 1143, 1417, 6038, 2313, 6554,
    //     9026, 8107, 9827, 7982, 9685, 3905, 8939, 1048, 282, 7423, 6327, 2970, 4453, 5460, 3399,
    //     9533, 914, 3932, 192, 3084, 6806, 273, 4283, 2060, 5682, 2, 2362, 4812, 7032, 810, 2465,
    //     6511, 213, 2362, 3021, 2745, 3636, 6265, 1518, 8398
    // ]), String::from("98909827968595339456944893859149094902689398937839883538183810810780707982784676057536747174237321720571007032685668066758674466986636554651163276306626562416221603859725909578457125682552954605422520849804812479847044453428339323905384638363699366436503636357535673516346233993298316330843021297028227452732697246523622362231322812216213206020001921763154815181495141713801147114310901048"));

    let mut a = vec![824, 938, 1399, 5607, 6973, 5703, 9609, 4398, 8247];
    dbg!(largest_number(a));

    a = vec![2, 2281];
    dbg!(largest_number(a));

    // which_bit(String::from("98909827968595339456944893859149094902689398937839883538183810810780707982784676057536747174237321720571007032685668066758674466986636554651163276306626562416221603859725909578457125682552954605422520849804812479847044453428339323905384638363699366436503636357535673516346233993298316330843021297028227452732697246523622362231322812216213206020001921763154815181495141713801147114310901048"),
    //           String::from("98909827968595339456944893859149094902689398937839883538183810781080707982784676057536747174237321720571007032685668066758674466986636554651163276306626562416221603859725909578457125682552954605422520849804812479847044453428339323905384638363699366436503636357535673516346233993298316330843021297028227452732697246523622362231322812216213206020001921763154815181495141713801147114310901048"));
}
<commit_msg>finish new<commit_after>use std::cmp::Ordering;
use std::collections::{HashMap, HashSet};

pub fn largest_number(nums: Vec<i32>) -> String {
    let mut cache: HashMap<u8, Vec<Vec<u8>>> = HashMap::new();
    for n in nums {
        let this = n.to_string();
        let bs = this.into_bytes();

        let this_value = cache.entry(bs[0]).or_insert(Vec::new());
        this_value.push(bs.clone());
    }

    //dbg!(&cache);

    let mut result: Vec<u8> = vec![];
    for i in 48..58 {
        if let Some(this_) = cache.get_mut(&(48 + 57 - i as u8)) {
            //this_.sort_by(compare);
            this_.sort_by(compare);
            this_.reverse();
            for v in this_ {
                result.append(v);
            }
        }
    }

    //dbg!(&result);
    if result[0] == 48 as u8 {
        String::from("0")
    } else {
        String::from_utf8(result).unwrap()
    }
}

fn compare_stupid(a: &Vec<u8>, b: &Vec<u8>) -> Ordering {
    let mut first = a.clone();
    first.append(&mut (b.clone()));
    let mut second = b.clone();
    second.append(&mut (a.clone()));

    let first_num = String::from_utf8(first).unwrap();
    let second_num = String::from_utf8(second).unwrap();

    if first_num > second_num {
        return Ordering::Greater;
    } else if first_num < second_num {
        return Ordering::Less;
    }

    return Ordering::Equal;
}

//give up
fn compare(a: &Vec<u8>, b: &Vec<u8>) -> Ordering {
    let mut ind = 0;
    let (lan_a, lan_b) = (a.len(), b.len());
    while ind != lan_a && ind != lan_b {
        if a[ind] > b[ind] {
            return Ordering::Greater;
        } else if b[ind] > a[ind] {
            return Ordering::Less;
        }

        ind += 1;
    }

    if ind < lan_a {
        while ind < lan_a {
            if a[ind] > a[ind - 1] {
                return Ordering::Greater;
            } else if a[ind] < a[ind - 1] {
                return Ordering::Less;
            }
            ind += 1;
        }
        return Ordering::Equal;
    } else if ind < lan_b {
        while ind < lan_b {
            if b[ind] > b[ind - 1] {
                return Ordering::Less;
            } else if b[ind] < b[ind - 1] {
                return Ordering::Greater;
            }
            ind += 1;
        }
        return Ordering::Equal;
    } else {
        return Ordering::Equal;
    }
}

fn compare_two<'x>(a: &'x Vec<u8>, b: &'x Vec<u8>) -> (bool, &'x Vec<u8>) {
    let mut ind = 0;
    let (lan_a, lan_b) = (a.len(), b.len());
    while ind != lan_a && ind != lan_b {
        if a[ind] > b[ind] {
            return (true, a);
        } else if b[ind] > a[ind] {
            return (false, b);
        }

        ind += 1;
    }

    if ind < lan_a {
        while ind < lan_a {
            if a[ind] > a[ind - 1] {
                return (true, a);
            } else if a[ind] < a[ind - 1] {
                return (false, b);
            }
            ind += 1;
        }
        return (true, a);
    } else if ind < lan_b {
        while ind < lan_b {
            if b[ind] > b[ind - 1] {
                return (false, b);
            } else if b[ind] < b[ind - 1] {
                return (true, a);
            }
            ind += 1;
        }
        return (false, b);
    } else {
        return (true, a);
    }
}

fn which_bit(a: String, b: String) {
    let a_ = a.into_bytes();
    let b_ = b.into_bytes();

    let len = a_.len();

    for i in 0..len {
        if a_[i] != b_[i] {
            println!("bit: {}, is: {}", i, a_[i] as char);
        }
    }
}

fn main() {
    dbg!(largest_number(vec![12, 23])); //=> 2312
    dbg!(largest_number(vec![10, 2])); //=> 210
    dbg!(largest_number(vec![3, 30, 34, 5, 9])); //=> 9534330
    dbg!(largest_number(vec![0, 0])); //=> 0

    let mut a = vec![824, 938, 1399, 5607, 6973, 5703, 9609, 4398, 8247];
    dbg!(largest_number(a));

    a = vec![2, 2281];
    dbg!(largest_number(a));
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::error;
use std::fmt;
use std::mem;

use {Value, Table};

#[cfg(feature = "rustc-serialize")] mod rustc_serialize;
#[cfg(feature = "serde")] mod serde;

/// A structure to transform Rust values into TOML values.
///
/// This encoder implements the serialization `Encoder` interface, allowing
/// `Encodable` rust types to be fed into the encoder. The output of this
/// encoder is a TOML `Table` structure. The resulting TOML can be stringified
/// if necessary.
///
/// # Example
///
/// ```
/// extern crate rustc_serialize;
/// extern crate toml;
///
/// # fn main() {
/// use toml::{Encoder, Value};
/// use rustc_serialize::Encodable;
///
/// #[derive(RustcEncodable)]
/// struct MyStruct { foo: isize, bar: String }
/// let my_struct = MyStruct { foo: 4, bar: "hello!".to_string() };
///
/// let mut e = Encoder::new();
/// my_struct.encode(&mut e).unwrap();
///
/// assert_eq!(e.toml.get(&"foo".to_string()), Some(&Value::Integer(4)))
/// # }
/// ```
pub struct Encoder {
    /// Output TOML that is emitted. The current version of this encoder forces
    /// the top-level representation of a structure to be a table.
    ///
    /// This field can be used to extract the return value after feeding a value
    /// into this `Encoder`.
    pub toml: Table,
    state: State,
}

/// Enumeration of errors which can occur while encoding a rust value into a
/// TOML value.
#[allow(missing_copy_implementations)]
#[derive(Debug)]
pub enum Error {
    /// Indication that a key was needed when a value was emitted, but no key
    /// was previously emitted.
    NeedsKey,
    /// Indication that a key was emitted, but not value was emitted.
    NoValue,
    /// Indicates that a map key was attempted to be emitted at an invalid
    /// location.
    InvalidMapKeyLocation,
    /// Indicates that a type other than a string was attempted to be used as a
    /// map key type.
    InvalidMapKeyType,
}

#[derive(PartialEq)]
enum State {
    Start,
    NextKey(String),
    NextArray(Vec<Value>),
    NextMapKey,
}

impl Encoder {
    /// Constructs a new encoder which will emit to the given output stream.
    pub fn new() -> Encoder {
        Encoder { state: State::Start, toml: BTreeMap::new() }
    }

    fn emit_value(&mut self, v: Value) -> Result<(), Error> {
        match mem::replace(&mut self.state, State::Start) {
            State::NextKey(key) => { self.toml.insert(key, v); Ok(()) }
            State::NextArray(mut vec) => {
                // TODO: validate types
                vec.push(v);
                self.state = State::NextArray(vec);
                Ok(())
            }
            State::NextMapKey => {
                match v {
                    Value::String(s) => { self.state = State::NextKey(s); Ok(()) }
                    _ => Err(Error::InvalidMapKeyType)
                }
            }
            _ => Err(Error::NeedsKey)
        }
    }

    fn emit_none(&mut self) -> Result<(), Error> {
        match mem::replace(&mut self.state, State::Start) {
            State::Start => unreachable!(),
            State::NextKey(_) => Ok(()),
            State::NextArray(..) => panic!("how to encode None in an array?"),
            State::NextMapKey => Err(Error::InvalidMapKeyLocation),
        }
    }

    fn seq<F>(&mut self, f: F) -> Result<(), Error>
        where F: FnOnce(&mut Encoder) -> Result<(), Error>
    {
        let old = mem::replace(&mut self.state, State::NextArray(Vec::new()));
        try!(f(self));
        match mem::replace(&mut self.state, old) {
            State::NextArray(v) => self.emit_value(Value::Array(v)),
            _ => unreachable!(),
        }
    }

    fn table<F>(&mut self, f: F) -> Result<(), Error>
        where F: FnOnce(&mut Encoder) -> Result<(), Error>
    {
        match mem::replace(&mut self.state, State::Start) {
            State::NextKey(key) => {
                let mut nested = Encoder::new();
                try!(f(&mut nested));
                self.toml.insert(key, Value::Table(nested.toml));
                Ok(())
            }
            State::NextArray(mut arr) => {
                let mut nested = Encoder::new();
                try!(f(&mut nested));
                arr.push(Value::Table(nested.toml));
                self.state = State::NextArray(arr);
                Ok(())
            }
            State::Start => f(self),
            State::NextMapKey => Err(Error::InvalidMapKeyLocation),
        }
    }

    fn table_key<F>(&mut self, f: F) -> Result<(), Error>
        where F: FnOnce(&mut Encoder) -> Result<(), Error>
    {
        match mem::replace(&mut self.state, State::NextMapKey) {
            State::Start => {}
            _ => return Err(Error::InvalidMapKeyLocation),
        }
        try!(f(self));
        match self.state {
            State::NextKey(_) => Ok(()),
            _ => Err(Error::InvalidMapKeyLocation),
        }
    }
}

/// Encodes an encodable value into a TOML value.
///
/// This function expects the type given to represent a TOML table in some form.
/// If encoding encounters an error, then this function will fail the task.
#[cfg(feature = "rustc-serialize")]
pub fn encode<T: ::rustc_serialize::Encodable>(t: &T) -> Value {
    let mut e = Encoder::new();
    t.encode(&mut e).unwrap();
    Value::Table(e.toml)
}

/// Encodes an encodable value into a TOML value.
///
/// This function expects the type given to represent a TOML table in some form.
/// If encoding encounters an error, then this function will fail the task.
#[cfg(all(not(feature = "rustc-serialize"), feature = "serde"))]
pub fn encode<T: ::serde::Serialize>(t: &T) -> Value {
    let mut e = Encoder::new();
    t.serialize(&mut e).unwrap();
    Value::Table(e.toml)
}

/// Encodes an encodable value into a TOML string.
///
/// This function expects the type given to represent a TOML table in some form.
/// If encoding encounters an error, then this function will fail the task.
#[cfg(feature = "rustc-serialize")]
pub fn encode_str<T: ::rustc_serialize::Encodable>(t: &T) -> String {
    encode(t).to_string()
}

/// Encodes an encodable value into a TOML string.
///
/// This function expects the type given to represent a TOML table in some form.
/// If encoding encounters an error, then this function will fail the task.
#[cfg(all(not(feature = "rustc-serialize"), feature = "serde"))]
pub fn encode_str<T: ::serde::Serialize>(t: &T) -> String {
    encode(t).to_string()
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::NeedsKey => write!(f, "need a key to encode"),
            Error::NoValue => write!(f, "not value to emit for a previous key"),
            Error::InvalidMapKeyLocation => write!(f, "a map cannot be emitted \
                                                       at this location"),
            Error::InvalidMapKeyType => write!(f, "only strings can be used as \
                                                   key types"),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str { "TOML encoding error" }
}
<commit_msg>Fixed typo<commit_after>use std::collections::BTreeMap;
use std::error;
use std::fmt;
use std::mem;

use {Value, Table};

#[cfg(feature = "rustc-serialize")] mod rustc_serialize;
#[cfg(feature = "serde")] mod serde;

/// A structure to transform Rust values into TOML values.
///
/// This encoder implements the serialization `Encoder` interface, allowing
/// `Encodable` rust types to be fed into the encoder. The output of this
/// encoder is a TOML `Table` structure. The resulting TOML can be stringified
/// if necessary.
///
/// # Example
///
/// ```
/// extern crate rustc_serialize;
/// extern crate toml;
///
/// # fn main() {
/// use toml::{Encoder, Value};
/// use rustc_serialize::Encodable;
///
/// #[derive(RustcEncodable)]
/// struct MyStruct { foo: isize, bar: String }
/// let my_struct = MyStruct { foo: 4, bar: "hello!".to_string() };
///
/// let mut e = Encoder::new();
/// my_struct.encode(&mut e).unwrap();
///
/// assert_eq!(e.toml.get(&"foo".to_string()), Some(&Value::Integer(4)))
/// # }
/// ```
pub struct Encoder {
    /// Output TOML that is emitted. The current version of this encoder forces
    /// the top-level representation of a structure to be a table.
    ///
    /// This field can be used to extract the return value after feeding a value
    /// into this `Encoder`.
    pub toml: Table,
    state: State,
}

/// Enumeration of errors which can occur while encoding a rust value into a
/// TOML value.
#[allow(missing_copy_implementations)]
#[derive(Debug)]
pub enum Error {
    /// Indication that a key was needed when a value was emitted, but no key
    /// was previously emitted.
    NeedsKey,
    /// Indication that a key was emitted, but not value was emitted.
    NoValue,
    /// Indicates that a map key was attempted to be emitted at an invalid
    /// location.
    InvalidMapKeyLocation,
    /// Indicates that a type other than a string was attempted to be used as a
    /// map key type.
    InvalidMapKeyType,
}

#[derive(PartialEq)]
enum State {
    Start,
    NextKey(String),
    NextArray(Vec<Value>),
    NextMapKey,
}

impl Encoder {
    /// Constructs a new encoder which will emit to the given output stream.
    pub fn new() -> Encoder {
        Encoder { state: State::Start, toml: BTreeMap::new() }
    }

    fn emit_value(&mut self, v: Value) -> Result<(), Error> {
        match mem::replace(&mut self.state, State::Start) {
            State::NextKey(key) => { self.toml.insert(key, v); Ok(()) }
            State::NextArray(mut vec) => {
                // TODO: validate types
                vec.push(v);
                self.state = State::NextArray(vec);
                Ok(())
            }
            State::NextMapKey => {
                match v {
                    Value::String(s) => { self.state = State::NextKey(s); Ok(()) }
                    _ => Err(Error::InvalidMapKeyType)
                }
            }
            _ => Err(Error::NeedsKey)
        }
    }

    fn emit_none(&mut self) -> Result<(), Error> {
        match mem::replace(&mut self.state, State::Start) {
            State::Start => unreachable!(),
            State::NextKey(_) => Ok(()),
            State::NextArray(..) => panic!("how to encode None in an array?"),
            State::NextMapKey => Err(Error::InvalidMapKeyLocation),
        }
    }

    fn seq<F>(&mut self, f: F) -> Result<(), Error>
        where F: FnOnce(&mut Encoder) -> Result<(), Error>
    {
        let old = mem::replace(&mut self.state, State::NextArray(Vec::new()));
        try!(f(self));
        match mem::replace(&mut self.state, old) {
            State::NextArray(v) => self.emit_value(Value::Array(v)),
            _ => unreachable!(),
        }
    }

    fn table<F>(&mut self, f: F) -> Result<(), Error>
        where F: FnOnce(&mut Encoder) -> Result<(), Error>
    {
        match mem::replace(&mut self.state, State::Start) {
            State::NextKey(key) => {
                let mut nested = Encoder::new();
                try!(f(&mut nested));
                self.toml.insert(key, Value::Table(nested.toml));
                Ok(())
            }
            State::NextArray(mut arr) => {
                let mut nested = Encoder::new();
                try!(f(&mut nested));
                arr.push(Value::Table(nested.toml));
                self.state = State::NextArray(arr);
                Ok(())
            }
            State::Start => f(self),
            State::NextMapKey => Err(Error::InvalidMapKeyLocation),
        }
    }

    fn table_key<F>(&mut self, f: F) -> Result<(), Error>
        where F: FnOnce(&mut Encoder) -> Result<(), Error>
    {
        match mem::replace(&mut self.state, State::NextMapKey) {
            State::Start => {}
            _ => return Err(Error::InvalidMapKeyLocation),
        }
        try!(f(self));
        match self.state {
            State::NextKey(_) => Ok(()),
            _ => Err(Error::InvalidMapKeyLocation),
        }
    }
}

/// Encodes an encodable value into a TOML value.
///
/// This function expects the type given to represent a TOML table in some form.
/// If encoding encounters an error, then this function will fail the task.
#[cfg(feature = "rustc-serialize")]
pub fn encode<T: ::rustc_serialize::Encodable>(t: &T) -> Value {
    let mut e = Encoder::new();
    t.encode(&mut e).unwrap();
    Value::Table(e.toml)
}

/// Encodes an encodable value into a TOML value.
///
/// This function expects the type given to represent a TOML table in some form.
/// If encoding encounters an error, then this function will fail the task.
#[cfg(all(not(feature = "rustc-serialize"), feature = "serde"))]
pub fn encode<T: ::serde::Serialize>(t: &T) -> Value {
    let mut e = Encoder::new();
    t.serialize(&mut e).unwrap();
    Value::Table(e.toml)
}

/// Encodes an encodable value into a TOML string.
///
/// This function expects the type given to represent a TOML table in some form.
/// If encoding encounters an error, then this function will fail the task.
#[cfg(feature = "rustc-serialize")]
pub fn encode_str<T: ::rustc_serialize::Encodable>(t: &T) -> String {
    encode(t).to_string()
}

/// Encodes an encodable value into a TOML string.
///
/// This function expects the type given to represent a TOML table in some form.
/// If encoding encounters an error, then this function will fail the task.
#[cfg(all(not(feature = "rustc-serialize"), feature = "serde"))]
pub fn encode_str<T: ::serde::Serialize>(t: &T) -> String {
    encode(t).to_string()
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::NeedsKey => write!(f, "need a key to encode"),
            Error::NoValue => write!(f, "no value to emit for a previous key"),
            Error::InvalidMapKeyLocation => write!(f, "a map cannot be emitted \
                                                       at this location"),
            Error::InvalidMapKeyType => write!(f, "only strings can be used as \
                                                   key types"),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str { "TOML encoding error" }
}
<|endoftext|>


<commit_before>use jsrs_common::ast::*;
use jsrs_common::ast::BinOp::*;
use jsrs_common::types::coerce::{AsBool,AsNumber};
use jsrs_common::types::js_var::{JsVar, JsType};
use jsrs_common::types::js_var::JsType::*;

macro_rules! b { ($e: expr) => { $e.as_bool() } }

macro_rules! n { ($e: expr) => { $e.as_number() } }
macro_rules! ni64 { ($e: expr) => { $e.as_number() as i64 } }
macro_rules! nu64 { ($e: expr) => { $e.as_number() as u64 } }
macro_rules! ni32 { ($e: expr) => { $e.as_number() as i32 } }
macro_rules! nu32 { ($e: expr) => { $e.as_number() as u32 } }

pub fn eval_binop(op: &BinOp, val1: JsVar, val2: JsVar) -> JsType {
    match *op {
        And => JsBool(b!(val1) && b!(val2)),
        Or  => JsBool(b!(val1) || b!(val2)),

        Ge  => JsBool(b!(val1) >= b!(val2)),
        Gt  => JsBool(b!(val1) >  b!(val2)),
        Le  => JsBool(b!(val1) <= b!(val2)),
        Lt  => JsBool(b!(val1) <  b!(val2)),

        // TODO: equality?
        Neq => JsBool(b!(val1) != b!(val2)),
        Eql => JsBool(b!(val1) == b!(val2)),

        EqlStrict => JsBool(val1.t == val2.t),
        NeqStrict => JsBool(val1.t != val2.t),

        BitOr  => JsNum((ni64!(val1) | ni64!(val2)) as f64),
        BitXor => JsNum((ni64!(val1) ^ ni64!(val2)) as f64),
        BitAnd => JsNum((ni64!(val1) & ni64!(val2)) as f64),

        // TODO: Rust panics on shift overflow, and I don't want this.
        ShiftLeft          => JsNum(0.0),
        ShiftRight         => JsNum(0.0),
        ShiftRightUnsigned => JsNum(0.0),
        //ShiftLeft          => JsNum((ni32!(val1) << ni32!(val2)) as f64),
        //ShiftRight         => JsNum((ni32!(val1) >> ni32!(val2)) as f64),
        //ShiftRightUnsigned => JsNum((nu32!(val1) >> ni32!(val2)) as f64),

        Minus => JsNum(n!(val1) - n!(val2)),
        Plus  => JsNum(n!(val1) + n!(val2)),
        Slash => JsNum(n!(val1) / n!(val2)),
        Star  => JsNum(n!(val1) * n!(val2)),
        Mod   => JsNum(n!(val1) % n!(val2)),
        //Exponentiation => JsNum(val1.as_number() ** val2.as_number()),
        _ => panic!()
    }
}
<commit_msg>Impl Exponent<commit_after>use jsrs_common::ast::*;
use jsrs_common::ast::BinOp::*;
use jsrs_common::types::coerce::{AsBool,AsNumber};
use jsrs_common::types::js_var::{JsVar, JsType};
use jsrs_common::types::js_var::JsType::*;

macro_rules! b { ($e: expr) => { $e.as_bool() } }

macro_rules! n { ($e: expr) => { $e.as_number() } }
macro_rules! ni64 { ($e: expr) => { $e.as_number() as i64 } }
macro_rules! nu64 { ($e: expr) => { $e.as_number() as u64 } }
macro_rules! ni32 { ($e: expr) => { $e.as_number() as i32 } }
macro_rules! nu32 { ($e: expr) => { $e.as_number() as u32 } }

pub fn eval_binop(op: &BinOp, val1: JsVar, val2: JsVar) -> JsType {
    match *op {
        And => JsBool(b!(val1) && b!(val2)),
        Or  => JsBool(b!(val1) || b!(val2)),

        Ge  => JsBool(b!(val1) >= b!(val2)),
        Gt  => JsBool(b!(val1) >  b!(val2)),
        Le  => JsBool(b!(val1) <= b!(val2)),
        Lt  => JsBool(b!(val1) <  b!(val2)),

        // TODO: equality?
        Neq => JsBool(b!(val1) != b!(val2)),
        Eql => JsBool(b!(val1) == b!(val2)),

        EqlStrict => JsBool(val1.t == val2.t),
        NeqStrict => JsBool(val1.t != val2.t),

        BitOr  => JsNum((ni64!(val1) | ni64!(val2)) as f64),
        BitXor => JsNum((ni64!(val1) ^ ni64!(val2)) as f64),
        BitAnd => JsNum((ni64!(val1) & ni64!(val2)) as f64),

        // TODO: Rust panics on shift overflow, and I don't want this.
        ShiftLeft          => JsNum(0.0),
        ShiftRight         => JsNum(0.0),
        ShiftRightUnsigned => JsNum(0.0),
        //ShiftLeft          => JsNum((ni32!(val1) << ni32!(val2)) as f64),
        //ShiftRight         => JsNum((ni32!(val1) >> ni32!(val2)) as f64),
        //ShiftRightUnsigned => JsNum((nu32!(val1) >> ni32!(val2)) as f64),

        Minus => JsNum(n!(val1) - n!(val2)),
        Plus  => JsNum(n!(val1) + n!(val2)),
        Slash => JsNum(n!(val1) / n!(val2)),
        Star  => JsNum(n!(val1) * n!(val2)),
        Mod   => JsNum(n!(val1) % n!(val2)),
        Exponent   => JsNum(n!(val1) % n!(val2)),
    }
}
<|endoftext|>


<commit_before>use dimensions::Dimensions;

/// A trait that indicates whether or not a widget
/// builder is positionable.
pub trait Shapeable: Sized {
    fn get_dim(&self) -> Dimensions;
    fn dim(self, dim: Dimensions) -> Self;
    fn dimensions(self, width: f64, height: f64) -> Self {
        self.dim([width, height])
    }
    fn width(self, width: f64) -> Self {
        let size = self.get_dim();
        self.dim([width, size[1]])
    }
    fn height(self, height: f64) -> Self {
        let size = self.get_dim();
        self.dim([size[0], height])
    }
}

/// Size property.
#[derive(Copy, Clone)]
pub struct Size(pub Dimensions);

/*
impl<T> Shapeable for T
    where
        (Size, T): Pair<Data = Size, Object = T> + SetAt + GetFrom
{
    #[inline]
    fn dimensions(self, width: f64, height: f64) -> Self {
        self.set(Size([width, height]))
    }
    #[inline]
    fn dim(self, dim: ::dimensions::Dimensions) -> Self {
        self.set(Size(dim))
    }
    #[inline]
    fn width(self, width: f64) -> Self {
        let Size(size) = self.get();
        self.set(Size([width, size[1]]))
    }
    #[inline]
    fn height(self, height: f64) -> Self {
        let Size(size) = self.get();
        self.set(Size([size[0], height]))
    }
}
*/
<commit_msg>Deleted some old code<commit_after>use dimensions::Dimensions;

/// A trait that indicates whether or not a widget
/// builder is positionable.
pub trait Shapeable: Sized {
    fn get_dim(&self) -> Dimensions;
    fn dim(self, dim: Dimensions) -> Self;
    fn dimensions(self, width: f64, height: f64) -> Self {
        self.dim([width, height])
    }
    fn width(self, width: f64) -> Self {
        let size = self.get_dim();
        self.dim([width, size[1]])
    }
    fn height(self, height: f64) -> Self {
        let size = self.get_dim();
        self.dim([size[0], height])
    }
}

/// Size property.
#[derive(Copy, Clone)]
pub struct Size(pub Dimensions);
<|endoftext|>


<commit_before>use std::marker::PhantomData;
use std::collections::hash_map::{HashMap, Entry};
use std::borrow::BorrowMut;
use gl;
use gl::types::*;
use context::{AContext, ContextOf};
use renderbuffer::{Renderbuffer, RenderbufferTarget};
use texture::{Texture, TextureType, ImageTargetType,
              Texture2d, Tx2dImageTarget};
use types::{BufferBits, GLError, GLFramebufferError};

pub struct Framebuffer {
    gl_id: GLuint
}

impl Framebuffer {
    pub unsafe fn from_gl(id: GLuint) -> Self {
        Framebuffer { gl_id: id }
    }

    pub fn gl_id(&self) -> GLuint {
        self.gl_id
    }
}

impl Drop for Framebuffer {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteFramebuffers(1, &self.gl_id as *const GLuint);
        }
    }
}

pub unsafe trait ContextFramebufferExt {
    unsafe fn gen_framebuffer(&self) -> Framebuffer {
        let mut id : GLuint = 0;

        gl::GenFramebuffers(1, &mut id as *mut GLuint);
        dbg_gl_sanity_check! {
            GLError::InvalidValue => "`n` is negative",
            _ => "Unknown error"
        }

        Framebuffer {
            gl_id: id
        }
    }

    fn check_framebuffer_status(&self, gl_fbo: &FramebufferBinding)
        -> Option<GLFramebufferError>
    {
        unsafe {
            match gl::CheckFramebufferStatus(gl_fbo.target().gl_enum()) {
                gl::FRAMEBUFFER_INCOMPLETE_ATTACHMENT => {
                    Some(GLFramebufferError::IncompleteAttachment)
                },
                // gl::FRAMEBUFFER_INCOMPLETE_DIMENSIONS => {
                //     Some(GLFramebufferError::IncompleteDimensions)
                // },
                gl::FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT => {
                    Some(GLFramebufferError::IncompleteMissingAttachment)
                },
                gl::FRAMEBUFFER_UNSUPPORTED => {
                    Some(GLFramebufferError::Unsupported)
                },
                _ => { None }
            }
        }
    }

    fn framebuffer_renderbuffer(&self,
                                gl_fbo: &mut FramebufferBinding,
                                attachment: FramebufferAttachment,
                                renderbuffer: &mut Renderbuffer)
    {
        let renderbuffer_target = RenderbufferTarget::Renderbuffer;
        unsafe {
            gl::FramebufferRenderbuffer(gl_fbo.target().gl_enum(),
                                        attachment.gl_enum(),
                                        renderbuffer_target.gl_enum(),
                                        renderbuffer.gl_id());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`, `attachment` is not a valid attachment point, or `renderbuffer` is not `GL_RENDERBUFFER` and `renderbuffer` is not 0",
                GLError::InvalidOperation => "Framebuffer 0 is bound, or `renderbuffer` is neither 0 nor the name of an existing renderbuffer object",
                _ => "Unknown error"
            }
        }
    }

    fn framebuffer_texture_2d<I, T>(&self,
                                    gl_fbo: &mut FramebufferBinding,
                                    attachment: FramebufferAttachment,
                                    tex_target: I,
                                    texture: &mut Texture<T>,
                                    level: i32)
        where I: Into<T::ImageTargetType>,
              T: TextureType,
    {
        debug_assert!(level == 0);

        unsafe {
            gl::FramebufferTexture2D(gl_fbo.target().gl_enum(),
                                     attachment.gl_enum(),
                                     tex_target.into().gl_enum(),
                                     texture.gl_id(),
                                     level as GLint);
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`, `attachment` is not an accepted attachment point, or `textarget` is not an accepted texture target and texture is not 0",
                GLError::InvalidValue => "`level` is not 0 and `texture` is not 0",
                GLError::InvalidOperation => "Framebuffer object 0 is bound, `texture` is neither 0 nor the name of an existing texture object, or `textarget` is not a valid target for `texture`",
                _ => "Unknown error"
            }
        }
    }

    // TODO: Think about this function signature harder (and all draw calls).
    // Should this require a &mut FramebufferBinding, to prevent a
    // no-op glClear(), and for (future) multi-threaded safety?
    fn clear(&self, buffers: BufferBits) {
        unsafe {
            gl::Clear(buffers.bits());
            dbg_gl_sanity_check! {
                GLError::InvalidValue => "`mask` includes a bit other than an allowed value",
                _ => "Unkown error"
            }
        }
    }
}

unsafe impl<B, F, P, R, T> ContextFramebufferExt for ContextOf<B, F, P, R, T> {

}

unsafe impl<'a, B, F, P, R, T> ContextFramebufferExt
    for &'a mut ContextOf<B, F, P, R, T>
{

}

enum BuilderAttachment<'a> {
    Texture2d(&'a mut Texture2d, i32),
    Renderbuffer(&'a mut Renderbuffer)
}

pub struct FramebufferBuilder<'a, C>
    where C: FramebufferContext
{
    gl: C,
    attachments: HashMap<FramebufferAttachment, BuilderAttachment<'a>>
}

impl<'a, C> FramebufferBuilder<'a, C>
    where C: FramebufferContext
{
    fn new(gl: C) -> Self {
        FramebufferBuilder {
            gl: gl,
            attachments: HashMap::new()
        }
    }

    pub fn texture_2d(mut self,
                      attachment: FramebufferAttachment,
                      texture: &'a mut Texture2d,
                      level: i32)
        -> Self
    {
        let attached = BuilderAttachment::Texture2d(texture, level);
        match self.attachments.entry(attachment) {
            Entry::Occupied(mut e) => { e.insert(attached); },
            Entry::Vacant(e) => { e.insert(attached); }
        };

        self
    }

    pub fn renderbuffer(mut self,
                        attachment: FramebufferAttachment,
                        renderbuffer: &'a mut Renderbuffer)
        -> Self
    {
        let attached = BuilderAttachment::Renderbuffer(renderbuffer);
        match self.attachments.entry(attachment) {
            Entry::Occupied(mut e) => { e.insert(attached); },
            Entry::Vacant(e) => { e.insert(attached); }
        };

        self
    }

    pub fn try_unwrap(self) -> Result<Framebuffer, GLError> {
        let gl = self.gl;
        let mut fbo = unsafe { gl.gen_framebuffer() };
        let fbo_status = {
            let (mut gl_fbo, gl) = gl.bind_framebuffer(&mut fbo);

            for (attachment, attached) in self.attachments.into_iter() {
                match attached {
                    BuilderAttachment::Texture2d(texture, level) => {
                        gl.framebuffer_texture_2d(&mut gl_fbo,
                                                  attachment,
                                                  Tx2dImageTarget::Texture2d,
                                                  texture,
                                                  level);
                    },
                    BuilderAttachment::Renderbuffer(renderbuffer) => {
                        gl.framebuffer_renderbuffer(&mut gl_fbo,
                                                    attachment,
                                                    renderbuffer);
                    }
                }
            }

            gl.check_framebuffer_status(&mut gl_fbo)
        };

        match fbo_status {
            Some(err) => { Err(err.into()) },
            None => { Ok(fbo) }
        }
    }

    pub fn unwrap(self) -> Framebuffer {
        self.try_unwrap().unwrap()
    }
}

pub trait ContextFramebufferBuilderExt: FramebufferContext + Sized {
    fn build_framebuffer<'a>(self) -> FramebufferBuilder<'a, Self>;
}

impl<'b, C: 'b> ContextFramebufferBuilderExt for &'b mut C
    where &'b mut C: FramebufferContext
{
    fn build_framebuffer<'a>(self) -> FramebufferBuilder<'a, &'b mut C> {
        FramebufferBuilder::new(self)
    }
}

gl_enum! {
    pub gl_enum FramebufferTarget {
        Framebuffer as FRAMEBUFFER = gl::FRAMEBUFFER
    }
}

gl_enum! {
    pub gl_enum FramebufferAttachment {
        ColorAttachment0 as COLOR_ATTACHMENT0 = gl::COLOR_ATTACHMENT0,
        DepthAttachment as DEPTH_ATTACHMENT = gl::DEPTH_ATTACHMENT,
        StencilAttachment as STENCIL_ATTACHMENT = gl::STENCIL_ATTACHMENT
    }
}

pub trait FramebufferContext: AContext {
    type Binder: BorrowMut<FramebufferBinder>;
    type Rest: AContext;

    fn split_framebuffer(self) -> (Self::Binder, Self::Rest);

    fn bind_framebuffer<'a>(self, fbo: &'a mut Framebuffer)
        -> (FramebufferBinding<'a>, Self::Rest)
        where Self: Sized
    {
        let (mut binder, rest) = self.split_framebuffer();
        (binder.borrow_mut().bind(fbo), rest)
    }
}

impl<B, F, P, R, T> FramebufferContext for ContextOf<B, F, P, R, T>
    where F: BorrowMut<FramebufferBinder>
{
    type Binder = F;
    type Rest = ContextOf<B, (), P, R, T>;

    fn split_framebuffer(self) -> (Self::Binder, Self::Rest) {
        self.swap_framebuffer(())
    }
}

impl<'a, B, F, P, R, T> FramebufferContext for &'a mut ContextOf<B, F, P, R, T>
    where F: BorrowMut<FramebufferBinder>
{
    type Binder = &'a mut FramebufferBinder;
    type Rest = ContextOf<&'a mut B, (), &'a mut P, &'a mut R, &'a mut T>;

    fn split_framebuffer(self) -> (Self::Binder, Self::Rest) {
        let gl = self.borrowed_mut();
        gl.swap_framebuffer(())
    }
}

pub struct FramebufferBinding<'a> {
    phantom: PhantomData<&'a mut Framebuffer>
}

impl<'a> FramebufferBinding<'a> {
    fn target(&self) -> FramebufferTarget {
        FramebufferTarget::Framebuffer
    }
}

pub struct FramebufferBinder;
impl FramebufferBinder {
    pub unsafe fn current_binding(&mut self) -> FramebufferBinding {
        FramebufferBinding { phantom: PhantomData }
    }

    pub fn bind<'a>(&mut self, fbo: &'a mut Framebuffer)
        -> FramebufferBinding<'a>
    {
        let binding = FramebufferBinding { phantom: PhantomData };
        unsafe {
            gl::BindFramebuffer(binding.target().gl_enum(), fbo.gl_id());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`",
                _ => "Unknown error"
            }
        }
        binding
    }
}
<commit_msg>Add `GLObject` impl for `Framebuffer`<commit_after>use std::marker::PhantomData;
use std::collections::hash_map::{HashMap, Entry};
use std::borrow::BorrowMut;
use gl;
use gl::types::*;
use context::{AContext, ContextOf};
use renderbuffer::{Renderbuffer, RenderbufferTarget};
use texture::{Texture, TextureType, ImageTargetType,
              Texture2d, Tx2dImageTarget};
use types::{BufferBits, GLError, GLObject, GLFramebufferError};

pub struct Framebuffer {
    gl_id: GLuint
}

impl Framebuffer {
    pub unsafe fn from_gl(id: GLuint) -> Self {
        Framebuffer { gl_id: id }
    }

    pub fn gl_id(&self) -> GLuint {
        self.gl_id
    }
}

impl Drop for Framebuffer {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteFramebuffers(1, &self.gl_id as *const GLuint);
        }
    }
}

impl GLObject for Framebuffer {
    type Id = GLuint;

    unsafe fn from_raw(id: Self::Id) -> Self {
        Framebuffer { gl_id: id }
    }

    fn id(&self) -> Self::Id {
        self.gl_id
    }
}

pub unsafe trait ContextFramebufferExt {
    unsafe fn gen_framebuffer(&self) -> Framebuffer {
        let mut id : GLuint = 0;

        gl::GenFramebuffers(1, &mut id as *mut GLuint);
        dbg_gl_sanity_check! {
            GLError::InvalidValue => "`n` is negative",
            _ => "Unknown error"
        }

        Framebuffer {
            gl_id: id
        }
    }

    fn check_framebuffer_status(&self, gl_fbo: &FramebufferBinding)
        -> Option<GLFramebufferError>
    {
        unsafe {
            match gl::CheckFramebufferStatus(gl_fbo.target().gl_enum()) {
                gl::FRAMEBUFFER_INCOMPLETE_ATTACHMENT => {
                    Some(GLFramebufferError::IncompleteAttachment)
                },
                // gl::FRAMEBUFFER_INCOMPLETE_DIMENSIONS => {
                //     Some(GLFramebufferError::IncompleteDimensions)
                // },
                gl::FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT => {
                    Some(GLFramebufferError::IncompleteMissingAttachment)
                },
                gl::FRAMEBUFFER_UNSUPPORTED => {
                    Some(GLFramebufferError::Unsupported)
                },
                _ => { None }
            }
        }
    }

    fn framebuffer_renderbuffer(&self,
                                gl_fbo: &mut FramebufferBinding,
                                attachment: FramebufferAttachment,
                                renderbuffer: &mut Renderbuffer)
    {
        let renderbuffer_target = RenderbufferTarget::Renderbuffer;
        unsafe {
            gl::FramebufferRenderbuffer(gl_fbo.target().gl_enum(),
                                        attachment.gl_enum(),
                                        renderbuffer_target.gl_enum(),
                                        renderbuffer.gl_id());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`, `attachment` is not a valid attachment point, or `renderbuffer` is not `GL_RENDERBUFFER` and `renderbuffer` is not 0",
                GLError::InvalidOperation => "Framebuffer 0 is bound, or `renderbuffer` is neither 0 nor the name of an existing renderbuffer object",
                _ => "Unknown error"
            }
        }
    }

    fn framebuffer_texture_2d<I, T>(&self,
                                    gl_fbo: &mut FramebufferBinding,
                                    attachment: FramebufferAttachment,
                                    tex_target: I,
                                    texture: &mut Texture<T>,
                                    level: i32)
        where I: Into<T::ImageTargetType>,
              T: TextureType,
    {
        debug_assert!(level == 0);

        unsafe {
            gl::FramebufferTexture2D(gl_fbo.target().gl_enum(),
                                     attachment.gl_enum(),
                                     tex_target.into().gl_enum(),
                                     texture.gl_id(),
                                     level as GLint);
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`, `attachment` is not an accepted attachment point, or `textarget` is not an accepted texture target and texture is not 0",
                GLError::InvalidValue => "`level` is not 0 and `texture` is not 0",
                GLError::InvalidOperation => "Framebuffer object 0 is bound, `texture` is neither 0 nor the name of an existing texture object, or `textarget` is not a valid target for `texture`",
                _ => "Unknown error"
            }
        }
    }

    // TODO: Think about this function signature harder (and all draw calls).
    // Should this require a &mut FramebufferBinding, to prevent a
    // no-op glClear(), and for (future) multi-threaded safety?
    fn clear(&self, buffers: BufferBits) {
        unsafe {
            gl::Clear(buffers.bits());
            dbg_gl_sanity_check! {
                GLError::InvalidValue => "`mask` includes a bit other than an allowed value",
                _ => "Unkown error"
            }
        }
    }
}

unsafe impl<B, F, P, R, T> ContextFramebufferExt for ContextOf<B, F, P, R, T> {

}

unsafe impl<'a, B, F, P, R, T> ContextFramebufferExt
    for &'a mut ContextOf<B, F, P, R, T>
{

}

enum BuilderAttachment<'a> {
    Texture2d(&'a mut Texture2d, i32),
    Renderbuffer(&'a mut Renderbuffer)
}

pub struct FramebufferBuilder<'a, C>
    where C: FramebufferContext
{
    gl: C,
    attachments: HashMap<FramebufferAttachment, BuilderAttachment<'a>>
}

impl<'a, C> FramebufferBuilder<'a, C>
    where C: FramebufferContext
{
    fn new(gl: C) -> Self {
        FramebufferBuilder {
            gl: gl,
            attachments: HashMap::new()
        }
    }

    pub fn texture_2d(mut self,
                      attachment: FramebufferAttachment,
                      texture: &'a mut Texture2d,
                      level: i32)
        -> Self
    {
        let attached = BuilderAttachment::Texture2d(texture, level);
        match self.attachments.entry(attachment) {
            Entry::Occupied(mut e) => { e.insert(attached); },
            Entry::Vacant(e) => { e.insert(attached); }
        };

        self
    }

    pub fn renderbuffer(mut self,
                        attachment: FramebufferAttachment,
                        renderbuffer: &'a mut Renderbuffer)
        -> Self
    {
        let attached = BuilderAttachment::Renderbuffer(renderbuffer);
        match self.attachments.entry(attachment) {
            Entry::Occupied(mut e) => { e.insert(attached); },
            Entry::Vacant(e) => { e.insert(attached); }
        };

        self
    }

    pub fn try_unwrap(self) -> Result<Framebuffer, GLError> {
        let gl = self.gl;
        let mut fbo = unsafe { gl.gen_framebuffer() };
        let fbo_status = {
            let (mut gl_fbo, gl) = gl.bind_framebuffer(&mut fbo);

            for (attachment, attached) in self.attachments.into_iter() {
                match attached {
                    BuilderAttachment::Texture2d(texture, level) => {
                        gl.framebuffer_texture_2d(&mut gl_fbo,
                                                  attachment,
                                                  Tx2dImageTarget::Texture2d,
                                                  texture,
                                                  level);
                    },
                    BuilderAttachment::Renderbuffer(renderbuffer) => {
                        gl.framebuffer_renderbuffer(&mut gl_fbo,
                                                    attachment,
                                                    renderbuffer);
                    }
                }
            }

            gl.check_framebuffer_status(&mut gl_fbo)
        };

        match fbo_status {
            Some(err) => { Err(err.into()) },
            None => { Ok(fbo) }
        }
    }

    pub fn unwrap(self) -> Framebuffer {
        self.try_unwrap().unwrap()
    }
}

pub trait ContextFramebufferBuilderExt: FramebufferContext + Sized {
    fn build_framebuffer<'a>(self) -> FramebufferBuilder<'a, Self>;
}

impl<'b, C: 'b> ContextFramebufferBuilderExt for &'b mut C
    where &'b mut C: FramebufferContext
{
    fn build_framebuffer<'a>(self) -> FramebufferBuilder<'a, &'b mut C> {
        FramebufferBuilder::new(self)
    }
}

gl_enum! {
    pub gl_enum FramebufferTarget {
        Framebuffer as FRAMEBUFFER = gl::FRAMEBUFFER
    }
}

gl_enum! {
    pub gl_enum FramebufferAttachment {
        ColorAttachment0 as COLOR_ATTACHMENT0 = gl::COLOR_ATTACHMENT0,
        DepthAttachment as DEPTH_ATTACHMENT = gl::DEPTH_ATTACHMENT,
        StencilAttachment as STENCIL_ATTACHMENT = gl::STENCIL_ATTACHMENT
    }
}

pub trait FramebufferContext: AContext {
    type Binder: BorrowMut<FramebufferBinder>;
    type Rest: AContext;

    fn split_framebuffer(self) -> (Self::Binder, Self::Rest);

    fn bind_framebuffer<'a>(self, fbo: &'a mut Framebuffer)
        -> (FramebufferBinding<'a>, Self::Rest)
        where Self: Sized
    {
        let (mut binder, rest) = self.split_framebuffer();
        (binder.borrow_mut().bind(fbo), rest)
    }
}

impl<B, F, P, R, T> FramebufferContext for ContextOf<B, F, P, R, T>
    where F: BorrowMut<FramebufferBinder>
{
    type Binder = F;
    type Rest = ContextOf<B, (), P, R, T>;

    fn split_framebuffer(self) -> (Self::Binder, Self::Rest) {
        self.swap_framebuffer(())
    }
}

impl<'a, B, F, P, R, T> FramebufferContext for &'a mut ContextOf<B, F, P, R, T>
    where F: BorrowMut<FramebufferBinder>
{
    type Binder = &'a mut FramebufferBinder;
    type Rest = ContextOf<&'a mut B, (), &'a mut P, &'a mut R, &'a mut T>;

    fn split_framebuffer(self) -> (Self::Binder, Self::Rest) {
        let gl = self.borrowed_mut();
        gl.swap_framebuffer(())
    }
}

pub struct FramebufferBinding<'a> {
    phantom: PhantomData<&'a mut Framebuffer>
}

impl<'a> FramebufferBinding<'a> {
    fn target(&self) -> FramebufferTarget {
        FramebufferTarget::Framebuffer
    }
}

pub struct FramebufferBinder;
impl FramebufferBinder {
    pub unsafe fn current_binding(&mut self) -> FramebufferBinding {
        FramebufferBinding { phantom: PhantomData }
    }

    pub fn bind<'a>(&mut self, fbo: &'a mut Framebuffer)
        -> FramebufferBinding<'a>
    {
        let binding = FramebufferBinding { phantom: PhantomData };
        unsafe {
            gl::BindFramebuffer(binding.target().gl_enum(), fbo.gl_id());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`",
                _ => "Unknown error"
            }
        }
        binding
    }
}
<|endoftext|>


<commit_before>use std::marker::PhantomData;
use std::collections::hash_map::{HashMap, Entry};
use std::borrow::BorrowMut;
use gl;
use gl::types::*;
use context::{AContext, ContextOf};
use renderbuffer::{Renderbuffer, RenderbufferTarget};
use texture::{Texture, TextureType, ImageTargetType,
              Texture2d, Tx2dImageTarget};
use types::{BufferBits, GLError, GLFramebufferError};

pub struct Framebuffer {
    gl_id: GLuint
}

impl Framebuffer {
    pub unsafe fn from_gl(id: GLuint) -> Self {
        Framebuffer { gl_id: id }
    }

    pub fn gl_id(&self) -> GLuint {
        self.gl_id
    }
}

impl Drop for Framebuffer {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteFramebuffers(1, &self.gl_id as *const GLuint);
        }
    }
}

enum BuilderAttachment<'a> {
    Texture2d(&'a mut Texture2d, i32),
    Renderbuffer(&'a mut Renderbuffer)
}

pub struct FramebufferBuilder<'a, B, F, P, R, T>
    where   B: 'a,
            F: 'a + BorrowMut<FramebufferBinder>,
            P: 'a,
            R: 'a,
            T: 'a
{
    gl: &'a mut ContextOf<B, F, P, R, T>,
    attachments: HashMap<FramebufferAttachment, BuilderAttachment<'a>>
}

impl<'a, B, F, P, R, T> FramebufferBuilder<'a, B, F, P, R, T>
    where B: 'a,
          F: 'a + BorrowMut<FramebufferBinder>,
          P: 'a,
          R: 'a,
          T: 'a
{
    fn new(gl: &'a mut ContextOf<B, F, P, R, T>) -> Self {
        FramebufferBuilder {
            gl: gl,
            attachments: HashMap::new()
        }
    }

    pub fn texture_2d(mut self,
                      attachment: FramebufferAttachment,
                      texture: &'a mut Texture2d,
                      level: i32)
        -> Self
    {
        let attached = BuilderAttachment::Texture2d(texture, level);
        match self.attachments.entry(attachment) {
            Entry::Occupied(mut e) => { e.insert(attached); },
            Entry::Vacant(e) => { e.insert(attached); }
        };

        self
    }

    pub fn renderbuffer(mut self,
                        attachment: FramebufferAttachment,
                        renderbuffer: &'a mut Renderbuffer)
        -> Self
    {
        let attached = BuilderAttachment::Renderbuffer(renderbuffer);
        match self.attachments.entry(attachment) {
            Entry::Occupied(mut e) => { e.insert(attached); },
            Entry::Vacant(e) => { e.insert(attached); }
        };

        self
    }

    pub fn try_unwrap(self) -> Result<Framebuffer, GLError> {
        let mut fbo = unsafe { self.gl.gen_framebuffer() };
        let fbo_status = {
            let gl = self.gl.borrowed_mut();
            let (mut gl_fbo, _) = gl.bind_framebuffer(&mut fbo);

            for (attachment, attached) in self.attachments.into_iter() {
                match attached {
                    BuilderAttachment::Texture2d(texture, level) => {
                        gl_fbo.texture_2d(attachment,
                                          Tx2dImageTarget::Texture2d,
                                          texture,
                                          level);
                    },
                    BuilderAttachment::Renderbuffer(renderbuffer) => {
                        gl_fbo.renderbuffer(attachment, renderbuffer);
                    }
                }
            }

            gl_fbo.check_framebuffer_status()
        };

        match fbo_status {
            Some(err) => { Err(err.into()) },
            None => { Ok(fbo) }
        }
    }

    pub fn unwrap(self) -> Framebuffer {
        self.try_unwrap().unwrap()
    }
}

impl<B, F, P, R, T> ContextOf<B, F, P, R, T> {
    // TODO: Move this method into `ContextFramebufferExt`
    pub fn build_framebuffer<'a>(&'a mut self)
        -> FramebufferBuilder<'a, B, F, P, R, T>
        where B: 'a,
              F: 'a + BorrowMut<FramebufferBinder>,
              P: 'a,
              R: 'a,
              T: 'a
    {
        FramebufferBuilder::new(self)
    }
}

pub trait ContextFramebufferExt {
    unsafe fn gen_framebuffer(&self) -> Framebuffer;
}

impl<B, F, P, R, T> ContextFramebufferExt for ContextOf<B, F, P, R, T> {
    unsafe fn gen_framebuffer(&self) -> Framebuffer {
        let mut id : GLuint = 0;

        gl::GenFramebuffers(1, &mut id as *mut GLuint);
        dbg_gl_sanity_check! {
            GLError::InvalidValue => "`n` is negative",
            _ => "Unknown error"
        }

        Framebuffer {
            gl_id: id
        }
    }
}

// TODO: Add a macro to reduce this boilerplate
impl<'a, B, F, P, R, T> ContextFramebufferExt
    for &'a mut ContextOf<B, F, P, R, T>
{
    unsafe fn gen_framebuffer(&self) -> Framebuffer {
        (**self).gen_framebuffer()
    }
}

gl_enum! {
    pub gl_enum FramebufferTarget {
        Framebuffer as FRAMEBUFFER = gl::FRAMEBUFFER
    }
}

gl_enum! {
    pub gl_enum FramebufferAttachment {
        ColorAttachment0 as COLOR_ATTACHMENT0 = gl::COLOR_ATTACHMENT0,
        DepthAttachment as DEPTH_ATTACHMENT = gl::DEPTH_ATTACHMENT,
        StencilAttachment as STENCIL_ATTACHMENT = gl::STENCIL_ATTACHMENT
    }
}

pub trait FramebufferContext: AContext {
    type Rest: AContext;

    fn bind_framebuffer<'a>(self, fbo: &'a mut Framebuffer)
        -> (FramebufferBinding<'a>, Self::Rest);
}

impl<B, F, P, R, T> FramebufferContext for ContextOf<B, F, P, R, T>
    where F: BorrowMut<FramebufferBinder>
{
    type Rest = ContextOf<B, (), P, R, T>;

    fn bind_framebuffer<'a>(self, fbo: &'a mut Framebuffer)
        -> (FramebufferBinding<'a>, Self::Rest)
    {
        let (mut fbo_binder, rest) = self.split_framebuffer();
        (fbo_binder.borrow_mut().bind(fbo), rest)
    }
}

impl<'b, B, F, P, R, T> FramebufferContext for &'b mut ContextOf<B, F, P, R, T>
    where F: BorrowMut<FramebufferBinder>
{
    type Rest = ContextOf<&'b mut B, (), &'b mut P, &'b mut R, &'b mut T>;

    fn bind_framebuffer<'a>(self, fbo: &'a mut Framebuffer)
        -> (FramebufferBinding<'a>, Self::Rest)
    {
        let gl = self.mut_into();
        let (framebuffer_binder, rest): (&mut F, _) = gl.split_framebuffer();
        (framebuffer_binder.borrow_mut().bind(fbo), rest)
    }
}

pub struct FramebufferBinding<'a> {
    phantom: PhantomData<&'a mut Framebuffer>
}

impl<'a> FramebufferBinding<'a> {
    fn target(&self) -> FramebufferTarget {
        FramebufferTarget::Framebuffer
    }

    pub fn check_framebuffer_status(&self) -> Option<GLFramebufferError> {
        unsafe {
            match gl::CheckFramebufferStatus(self.target().gl_enum()) {
                gl::FRAMEBUFFER_INCOMPLETE_ATTACHMENT => {
                    Some(GLFramebufferError::IncompleteAttachment)
                },
                // gl::FRAMEBUFFER_INCOMPLETE_DIMENSIONS => {
                //     Some(GLFramebufferError::IncompleteDimensions)
                // },
                gl::FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT => {
                    Some(GLFramebufferError::IncompleteMissingAttachment)
                },
                gl::FRAMEBUFFER_UNSUPPORTED => {
                    Some(GLFramebufferError::Unsupported)
                },
                _ => { None }
            }
        }
    }

    pub fn renderbuffer(&mut self,
                        attachment: FramebufferAttachment,
                        renderbuffer: &mut Renderbuffer)
    {
        let renderbuffer_target = RenderbufferTarget::Renderbuffer;
        unsafe {
            gl::FramebufferRenderbuffer(self.target().gl_enum(),
                                        attachment.gl_enum(),
                                        renderbuffer_target.gl_enum(),
                                        renderbuffer.gl_id());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`, `attachment` is not a valid attachment point, or `renderbuffer` is not `GL_RENDERBUFFER` and `renderbuffer` is not 0",
                GLError::InvalidOperation => "Framebuffer 0 is bound, or `renderbuffer` is neither 0 nor the name of an existing renderbuffer object",
                _ => "Unknown error"
            }
        }
    }

    pub fn texture_2d<T, I>(&mut self,
                            attachment: FramebufferAttachment,
                            tex_target: I,
                            texture: &mut Texture<T>,
                            level: i32)
        where T: TextureType, I: Into<T::ImageTargetType>
    {
        debug_assert!(level == 0);

        unsafe {
            gl::FramebufferTexture2D(self.target().gl_enum(),
                                     attachment.gl_enum(),
                                     tex_target.into().gl_enum(),
                                     texture.gl_id(),
                                     level as GLint);
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`, `attachment` is not an accepted attachment point, or `textarget` is not an accepted texture target and texture is not 0",
                GLError::InvalidValue => "`level` is not 0 and `texture` is not 0",
                GLError::InvalidOperation => "Framebuffer object 0 is bound, `texture` is neither 0 nor the name of an existing texture object, or `textarget` is not a valid target for `texture`",
                _ => "Unknown error"
            }
        }
    }

    pub fn clear(&mut self, buffers: BufferBits) {
        unsafe {
            gl::Clear(buffers.bits());
            dbg_gl_sanity_check! {
                GLError::InvalidValue => "`mask` includes a bit other than an allowed value",
                _ => "Unkown error"
            }
        }
    }
}

pub struct FramebufferBinder;
impl FramebufferBinder {
    pub unsafe fn current_binding(&mut self) -> FramebufferBinding {
        FramebufferBinding { phantom: PhantomData }
    }

    pub fn bind<'a>(&mut self, fbo: &'a mut Framebuffer)
        -> FramebufferBinding<'a>
    {
        let binding = FramebufferBinding { phantom: PhantomData };
        unsafe {
            gl::BindFramebuffer(binding.target().gl_enum(), fbo.gl_id());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`",
                _ => "Unknown error"
            }
        }
        binding
    }
}
<commit_msg>Refactor `FramebufferBuilder` to have one generic parameter<commit_after>use std::marker::PhantomData;
use std::collections::hash_map::{HashMap, Entry};
use std::borrow::BorrowMut;
use gl;
use gl::types::*;
use context::{AContext, ContextOf};
use renderbuffer::{Renderbuffer, RenderbufferTarget};
use texture::{Texture, TextureType, ImageTargetType,
              Texture2d, Tx2dImageTarget};
use types::{BufferBits, GLError, GLFramebufferError};

pub struct Framebuffer {
    gl_id: GLuint
}

impl Framebuffer {
    pub unsafe fn from_gl(id: GLuint) -> Self {
        Framebuffer { gl_id: id }
    }

    pub fn gl_id(&self) -> GLuint {
        self.gl_id
    }
}

impl Drop for Framebuffer {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteFramebuffers(1, &self.gl_id as *const GLuint);
        }
    }
}

enum BuilderAttachment<'a> {
    Texture2d(&'a mut Texture2d, i32),
    Renderbuffer(&'a mut Renderbuffer)
}

pub struct FramebufferBuilder<'a, C>
    where C: FramebufferContext
{
    gl: C,
    attachments: HashMap<FramebufferAttachment, BuilderAttachment<'a>>
}

impl<'a, C> FramebufferBuilder<'a, C>
    where C: FramebufferContext
{
    fn new(gl: C) -> Self {
        FramebufferBuilder {
            gl: gl,
            attachments: HashMap::new()
        }
    }

    pub fn texture_2d(mut self,
                      attachment: FramebufferAttachment,
                      texture: &'a mut Texture2d,
                      level: i32)
        -> Self
    {
        let attached = BuilderAttachment::Texture2d(texture, level);
        match self.attachments.entry(attachment) {
            Entry::Occupied(mut e) => { e.insert(attached); },
            Entry::Vacant(e) => { e.insert(attached); }
        };

        self
    }

    pub fn renderbuffer(mut self,
                        attachment: FramebufferAttachment,
                        renderbuffer: &'a mut Renderbuffer)
        -> Self
    {
        let attached = BuilderAttachment::Renderbuffer(renderbuffer);
        match self.attachments.entry(attachment) {
            Entry::Occupied(mut e) => { e.insert(attached); },
            Entry::Vacant(e) => { e.insert(attached); }
        };

        self
    }

    pub fn try_unwrap(self) -> Result<Framebuffer, GLError> {
        let gl = self.gl;
        let mut fbo = unsafe { gl.gen_framebuffer() };
        let fbo_status = {
            let (mut gl_fbo, _) = gl.bind_framebuffer(&mut fbo);

            for (attachment, attached) in self.attachments.into_iter() {
                match attached {
                    BuilderAttachment::Texture2d(texture, level) => {
                        gl_fbo.texture_2d(attachment,
                                          Tx2dImageTarget::Texture2d,
                                          texture,
                                          level);
                    },
                    BuilderAttachment::Renderbuffer(renderbuffer) => {
                        gl_fbo.renderbuffer(attachment, renderbuffer);
                    }
                }
            }

            gl_fbo.check_framebuffer_status()
        };

        match fbo_status {
            Some(err) => { Err(err.into()) },
            None => { Ok(fbo) }
        }
    }

    pub fn unwrap(self) -> Framebuffer {
        self.try_unwrap().unwrap()
    }
}

impl<B, F, P, R, T> ContextOf<B, F, P, R, T> {
    // TODO: Move this method into `ContextFramebufferExt`
    pub fn build_framebuffer<'a>(&'a mut self)
        -> FramebufferBuilder<'a, &'a mut Self>
        where B: 'a,
              F: 'a + BorrowMut<FramebufferBinder>,
              P: 'a,
              R: 'a,
              T: 'a
    {
        FramebufferBuilder::new(self)
    }
}

pub trait ContextFramebufferExt {
    unsafe fn gen_framebuffer(&self) -> Framebuffer;
}

impl<B, F, P, R, T> ContextFramebufferExt for ContextOf<B, F, P, R, T> {
    unsafe fn gen_framebuffer(&self) -> Framebuffer {
        let mut id : GLuint = 0;

        gl::GenFramebuffers(1, &mut id as *mut GLuint);
        dbg_gl_sanity_check! {
            GLError::InvalidValue => "`n` is negative",
            _ => "Unknown error"
        }

        Framebuffer {
            gl_id: id
        }
    }
}

// TODO: Add a macro to reduce this boilerplate
impl<'a, B, F, P, R, T> ContextFramebufferExt
    for &'a mut ContextOf<B, F, P, R, T>
{
    unsafe fn gen_framebuffer(&self) -> Framebuffer {
        (**self).gen_framebuffer()
    }
}

gl_enum! {
    pub gl_enum FramebufferTarget {
        Framebuffer as FRAMEBUFFER = gl::FRAMEBUFFER
    }
}

gl_enum! {
    pub gl_enum FramebufferAttachment {
        ColorAttachment0 as COLOR_ATTACHMENT0 = gl::COLOR_ATTACHMENT0,
        DepthAttachment as DEPTH_ATTACHMENT = gl::DEPTH_ATTACHMENT,
        StencilAttachment as STENCIL_ATTACHMENT = gl::STENCIL_ATTACHMENT
    }
}

pub trait FramebufferContext: AContext {
    type Rest: AContext;

    fn bind_framebuffer<'a>(self, fbo: &'a mut Framebuffer)
        -> (FramebufferBinding<'a>, Self::Rest);
}

impl<B, F, P, R, T> FramebufferContext for ContextOf<B, F, P, R, T>
    where F: BorrowMut<FramebufferBinder>
{
    type Rest = ContextOf<B, (), P, R, T>;

    fn bind_framebuffer<'a>(self, fbo: &'a mut Framebuffer)
        -> (FramebufferBinding<'a>, Self::Rest)
    {
        let (mut fbo_binder, rest) = self.split_framebuffer();
        (fbo_binder.borrow_mut().bind(fbo), rest)
    }
}

impl<'b, B, F, P, R, T> FramebufferContext for &'b mut ContextOf<B, F, P, R, T>
    where F: BorrowMut<FramebufferBinder>
{
    type Rest = ContextOf<&'b mut B, (), &'b mut P, &'b mut R, &'b mut T>;

    fn bind_framebuffer<'a>(self, fbo: &'a mut Framebuffer)
        -> (FramebufferBinding<'a>, Self::Rest)
    {
        let gl = self.mut_into();
        let (framebuffer_binder, rest): (&mut F, _) = gl.split_framebuffer();
        (framebuffer_binder.borrow_mut().bind(fbo), rest)
    }
}

pub struct FramebufferBinding<'a> {
    phantom: PhantomData<&'a mut Framebuffer>
}

impl<'a> FramebufferBinding<'a> {
    fn target(&self) -> FramebufferTarget {
        FramebufferTarget::Framebuffer
    }

    pub fn check_framebuffer_status(&self) -> Option<GLFramebufferError> {
        unsafe {
            match gl::CheckFramebufferStatus(self.target().gl_enum()) {
                gl::FRAMEBUFFER_INCOMPLETE_ATTACHMENT => {
                    Some(GLFramebufferError::IncompleteAttachment)
                },
                // gl::FRAMEBUFFER_INCOMPLETE_DIMENSIONS => {
                //     Some(GLFramebufferError::IncompleteDimensions)
                // },
                gl::FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT => {
                    Some(GLFramebufferError::IncompleteMissingAttachment)
                },
                gl::FRAMEBUFFER_UNSUPPORTED => {
                    Some(GLFramebufferError::Unsupported)
                },
                _ => { None }
            }
        }
    }

    pub fn renderbuffer(&mut self,
                        attachment: FramebufferAttachment,
                        renderbuffer: &mut Renderbuffer)
    {
        let renderbuffer_target = RenderbufferTarget::Renderbuffer;
        unsafe {
            gl::FramebufferRenderbuffer(self.target().gl_enum(),
                                        attachment.gl_enum(),
                                        renderbuffer_target.gl_enum(),
                                        renderbuffer.gl_id());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`, `attachment` is not a valid attachment point, or `renderbuffer` is not `GL_RENDERBUFFER` and `renderbuffer` is not 0",
                GLError::InvalidOperation => "Framebuffer 0 is bound, or `renderbuffer` is neither 0 nor the name of an existing renderbuffer object",
                _ => "Unknown error"
            }
        }
    }

    pub fn texture_2d<T, I>(&mut self,
                            attachment: FramebufferAttachment,
                            tex_target: I,
                            texture: &mut Texture<T>,
                            level: i32)
        where T: TextureType, I: Into<T::ImageTargetType>
    {
        debug_assert!(level == 0);

        unsafe {
            gl::FramebufferTexture2D(self.target().gl_enum(),
                                     attachment.gl_enum(),
                                     tex_target.into().gl_enum(),
                                     texture.gl_id(),
                                     level as GLint);
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`, `attachment` is not an accepted attachment point, or `textarget` is not an accepted texture target and texture is not 0",
                GLError::InvalidValue => "`level` is not 0 and `texture` is not 0",
                GLError::InvalidOperation => "Framebuffer object 0 is bound, `texture` is neither 0 nor the name of an existing texture object, or `textarget` is not a valid target for `texture`",
                _ => "Unknown error"
            }
        }
    }

    pub fn clear(&mut self, buffers: BufferBits) {
        unsafe {
            gl::Clear(buffers.bits());
            dbg_gl_sanity_check! {
                GLError::InvalidValue => "`mask` includes a bit other than an allowed value",
                _ => "Unkown error"
            }
        }
    }
}

pub struct FramebufferBinder;
impl FramebufferBinder {
    pub unsafe fn current_binding(&mut self) -> FramebufferBinding {
        FramebufferBinding { phantom: PhantomData }
    }

    pub fn bind<'a>(&mut self, fbo: &'a mut Framebuffer)
        -> FramebufferBinding<'a>
    {
        let binding = FramebufferBinding { phantom: PhantomData };
        unsafe {
            gl::BindFramebuffer(binding.target().gl_enum(), fbo.gl_id());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`",
                _ => "Unknown error"
            }
        }
        binding
    }
}
<|endoftext|>