<commit_before>#[macro_use]
extern crate pest;
#[macro_use]
extern crate pest_derive;

#[cfg(debug_assertions)]
const _GRAMMER: &'static str = include_str!("grammer.pest");

#[derive(Parser)]
#[grammar = "grammer.pest"]
struct TurtleParser;

#[test]
fn rdf_literal_test() {
    parses_to! {
        parser: TurtleParser,
        input: r#""test"@en"#,
        rule: Rule::rdf_literal,
        tokens: [
            rdf_literal(0, 9, [
                string(0, 6, [
                    string_literal_quote(0, 6)
                ]),
                langtag(6, 9)
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: r#""test"^^<http://www.example.com>"#,
        rule: Rule::rdf_literal,
        tokens: [
            rdf_literal(0, 32, [
                string(0, 6, [
                    string_literal_quote(0, 6)
                ]),
                iri(8, 32, [
                    iriref(8, 32)
                ])
            ])
        ]
    };
}

#[test]
fn boolean_literal_test() {
    parses_to! {
        parser: TurtleParser,
        input: "true",
        rule: Rule::boolean_literal,
        tokens: [
            boolean_literal(0, 4)
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: "false",
        rule: Rule::boolean_literal,
        tokens: [
            boolean_literal(0, 5)
        ]
    };
}

#[test]
fn string_test() {
    parses_to! {
        parser: TurtleParser,
        input: r#""test""#,
        rule: Rule::string,
        tokens: [
            string(0, 6, [
                string_literal_quote(0, 6)
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: r#"'test'"#,
        rule: Rule::string,
        tokens: [
            string(0, 6, [
                string_literal_single_quote(0, 6)
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: r#""""test"test""""#,
        rule: Rule::string,
        tokens: [
            string(0, 15, [
                string_literal_long_quote(0, 15)
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: r#"'''test'test'''"#,
        rule: Rule::string,
        tokens: [
            string(0, 15, [
                string_literal_long_single_quote(0, 15)
            ])
        ]
    };
}

#[test]
fn iri_test() {
    parses_to! {
        parser: TurtleParser,
        input: "<http://www.example.com>",
        rule: Rule::iri,
        tokens: [
            iri(0, 24, [
                iriref(0, 24)
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: "foaf:Person",
        rule: Rule::iri,
        tokens: [
            iri(0, 11, [
                prefixed_name(0, 11, [
                    pname_ln(0, 11)
                ])
            ])
        ]
    };
}

#[test]
fn prefixd_name_test() {
    parses_to! {
        parser: TurtleParser,
        input: "foaf:",
        rule: Rule::prefixed_name,
        tokens: [
            prefixed_name(0, 5, [
                pname_ns(0, 5)
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: "foaf:Person",
        rule: Rule::prefixed_name,
        tokens: [
            prefixed_name(0, 11, [
                pname_ln(0, 11)
            ])
        ]
    };
}

#[test]
fn blank_node_test() {
    parses_to! {
        parser: TurtleParser,
        input: "_:blank",
        rule: Rule::blank_node,
        tokens: [
            blank_node(0, 7, [
                blank_node_label(0, 7)
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: "[     ]",
        rule: Rule::blank_node,
        tokens: [
            blank_node(0, 7, [
                anon(0, 7)
            ])
        ]
    };
}
<commit_msg>Add numeric_literal_test, collection_test<commit_after>#[macro_use]
extern crate pest;
#[macro_use]
extern crate pest_derive;

#[cfg(debug_assertions)]
const _GRAMMER: &'static str = include_str!("grammer.pest");

#[derive(Parser)]
#[grammar = "grammer.pest"]
struct TurtleParser;

#[test]
fn collection_test() {
    parses_to! {
        parser: TurtleParser,
        input: "(<http://www.example.com> ([ ]))",
        rule: Rule::collection,
        tokens: [
            collection(0, 32, [
                object(1, 25, [
                    iri(1, 25, [ iriref(1, 25) ])
                ]),
                object(26, 31, [
                    collection(26, 31, [
                        object(27, 30, [ blank_node(27, 30, [ anon(27, 30) ]) ])
                    ])
                ])
            ])
        ]
    };
}

#[test]
fn numeric_literal_test() {
    parses_to! {
        parser: TurtleParser,
        input: "+10",
        rule: Rule::numeric_literal,
        tokens: [
            numeric_literal(0, 3, [
                integer(0, 3)
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: "+1.0",
        rule: Rule::numeric_literal,
        tokens: [
            numeric_literal(0, 4, [
                decimal(0, 4)
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: "+1.0e-9",
        rule: Rule::numeric_literal,
        tokens: [
            numeric_literal(0, 7, [
                double(0, 7)
            ])
        ]
    };
}

#[test]
fn rdf_literal_test() {
    parses_to! {
        parser: TurtleParser,
        input: r#""test"@en"#,
        rule: Rule::rdf_literal,
        tokens: [
            rdf_literal(0, 9, [
                string(0, 6, [
                    string_literal_quote(0, 6)
                ]),
                langtag(6, 9)
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: r#""test"^^<http://www.example.com>"#,
        rule: Rule::rdf_literal,
        tokens: [
            rdf_literal(0, 32, [
                string(0, 6, [
                    string_literal_quote(0, 6)
                ]),
                iri(8, 32, [
                    iriref(8, 32)
                ])
            ])
        ]
    };
}

#[test]
fn boolean_literal_test() {
    parses_to! {
        parser: TurtleParser,
        input: "true",
        rule: Rule::boolean_literal,
        tokens: [
            boolean_literal(0, 4)
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: "false",
        rule: Rule::boolean_literal,
        tokens: [
            boolean_literal(0, 5)
        ]
    };
}

#[test]
fn string_test() {
    parses_to! {
        parser: TurtleParser,
        input: r#""test""#,
        rule: Rule::string,
        tokens: [
            string(0, 6, [
                string_literal_quote(0, 6)
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: r#"'test'"#,
        rule: Rule::string,
        tokens: [
            string(0, 6, [
                string_literal_single_quote(0, 6)
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: r#""""test"test""""#,
        rule: Rule::string,
        tokens: [
            string(0, 15, [
                string_literal_long_quote(0, 15)
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: r#"'''test'test'''"#,
        rule: Rule::string,
        tokens: [
            string(0, 15, [
                string_literal_long_single_quote(0, 15)
            ])
        ]
    };
}

#[test]
fn iri_test() {
    parses_to! {
        parser: TurtleParser,
        input: "<http://www.example.com>",
        rule: Rule::iri,
        tokens: [
            iri(0, 24, [
                iriref(0, 24)
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: "foaf:Person",
        rule: Rule::iri,
        tokens: [
            iri(0, 11, [
                prefixed_name(0, 11, [
                    pname_ln(0, 11)
                ])
            ])
        ]
    };
}

#[test]
fn prefixd_name_test() {
    parses_to! {
        parser: TurtleParser,
        input: "foaf:",
        rule: Rule::prefixed_name,
        tokens: [
            prefixed_name(0, 5, [
                pname_ns(0, 5)
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: "foaf:Person",
        rule: Rule::prefixed_name,
        tokens: [
            prefixed_name(0, 11, [
                pname_ln(0, 11)
            ])
        ]
    };
}

#[test]
fn blank_node_test() {
    parses_to! {
        parser: TurtleParser,
        input: "_:blank",
        rule: Rule::blank_node,
        tokens: [
            blank_node(0, 7, [
                blank_node_label(0, 7)
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: "[     ]",
        rule: Rule::blank_node,
        tokens: [
            blank_node(0, 7, [
                anon(0, 7)
            ])
        ]
    };
}
<|endoftext|>


<commit_before>/// Literal kind.
///
/// E.g. `"foo"`, `42`, `12.34` or `bool`
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum Lit {
    /// A string literal (`"foo"`)
    Str(String, StrStyle),
    /// A byte string (`b"foo"`)
    ByteStr(Vec<u8>),
    /// A byte char (`b'f'`)
    Byte(u8),
    /// A character literal (`'a'`)
    Char(char),
    /// An integer literal (`1`)
    Int(u64, IntTy),
    /// A float literal (`1f64` or `1E10f64` or `1.0E10`)
    Float(String, FloatTy),
    /// A boolean literal
    Bool(bool),
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum StrStyle {
    /// A regular string, like `"foo"`
    Cooked,
    /// A raw string, like `r##"foo"##`
    ///
    /// The uint is the number of `#` symbols used
    Raw(usize),
}

impl From<String> for Lit {
    fn from(input: String) -> Lit {
        Lit::Str(input, StrStyle::Cooked)
    }
}

impl<'a> From<&'a str> for Lit {
    fn from(input: &str) -> Lit {
        Lit::Str(input.into(), StrStyle::Cooked)
    }
}

impl From<Vec<u8>> for Lit {
    fn from(input: Vec<u8>) -> Lit {
        Lit::ByteStr(input)
    }
}

impl<'a> From<&'a [u8]> for Lit {
    fn from(input: &[u8]) -> Lit {
        Lit::ByteStr(input.into())
    }
}

impl From<char> for Lit {
    fn from(input: char) -> Lit {
        Lit::Char(input)
    }
}

impl From<bool> for Lit {
    fn from(input: bool) -> Lit {
        Lit::Bool(input)
    }
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum IntTy {
    Isize,
    I8,
    I16,
    I32,
    I64,
    Usize,
    U8,
    U16,
    U32,
    U64,
    Unsuffixed,
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum FloatTy {
    F32,
    F64,
    Unsuffixed,
}

macro_rules! impl_from_for_lit {
    (Int, [$($rust_type:ty => $syn_type:expr),+]) => {
        $(
            impl From<$rust_type> for Lit {
                fn from(input: $rust_type) -> Lit {
                    Lit::Int(input as u64, $syn_type)
                }
            }
        )+
    };
    (Float, [$($rust_type:ty => $syn_type:expr),+]) => {
        $(
            impl From<$rust_type> for Lit {
                fn from(input: $rust_type) -> Lit {
                    Lit::Float(format!("{}", input), $syn_type)
                }
            }
        )+
    };
}

impl_from_for_lit! {Int, [
    isize => IntTy::Isize,
    i8 => IntTy::I8,
    i16 => IntTy::I16,
    i32 => IntTy::I32,
    i64 => IntTy::I64,
    usize => IntTy::Usize,
    u8 => IntTy::U8,
    u16 => IntTy::U16,
    u32 => IntTy::U32,
    u64 => IntTy::U64
]}

impl_from_for_lit! {Float, [
    f32 => FloatTy::F32,
    f64 => FloatTy::F64
]}

#[cfg(feature = "parsing")]
pub mod parsing {
    use super::*;
    use escape::{cooked_char, cooked_string, raw_string};
    use space::whitespace;
    use nom::IResult;

    named!(pub lit -> Lit, alt!(
        string
        |
        byte_string
        |
        byte
        |
        character
        |
        int => { |(value, ty)| Lit::Int(value, ty) }
    // TODO: Float
        |
        keyword!("true") => { |_| Lit::Bool(true) }
        |
        keyword!("false") => { |_| Lit::Bool(false) }
    ));

    named!(string -> Lit, alt!(
        quoted_string => { |s| Lit::Str(s, StrStyle::Cooked) }
        |
        preceded!(
            punct!("r"),
            raw_string
        ) => { |(s, n)| Lit::Str(s, StrStyle::Raw(n)) }
    ));

    named!(pub quoted_string -> String, delimited!(
        punct!("\""),
        cooked_string,
        tag!("\"")
    ));

    named!(byte_string -> Lit, alt!(
        delimited!(
            punct!("b\""),
            cooked_string,
            tag!("\"")
        ) => { |s: String| Lit::ByteStr(s.into_bytes()) }
        |
        preceded!(
            punct!("br"),
            raw_string
        ) => { |(s, _): (String, _)| Lit::ByteStr(s.into_bytes()) }
    ));

    named!(byte -> Lit, do_parse!(
        punct!("b") >>
        tag!("'") >>
        ch: cooked_char >>
        tag!("'") >>
        (Lit::Byte(ch as u8))
    ));

    named!(character -> Lit, do_parse!(
        punct!("'") >>
        ch: cooked_char >>
        tag!("'") >>
        (Lit::Char(ch))
    ));

    named!(pub int -> (u64, IntTy), tuple!(
        preceded!(
            option!(whitespace),
            digits
        ),
        alt!(
            tag!("isize") => { |_| IntTy::Isize }
            |
            tag!("i8") => { |_| IntTy::I8 }
            |
            tag!("i16") => { |_| IntTy::I16 }
            |
            tag!("i32") => { |_| IntTy::I32 }
            |
            tag!("i64") => { |_| IntTy::I64 }
            |
            tag!("usize") => { |_| IntTy::Usize }
            |
            tag!("u8") => { |_| IntTy::U8 }
            |
            tag!("u16") => { |_| IntTy::U16 }
            |
            tag!("u32") => { |_| IntTy::U32 }
            |
            tag!("u64") => { |_| IntTy::U64 }
            |
            epsilon!() => { |_| IntTy::Unsuffixed }
        )
    ));

    pub fn digits(input: &str) -> IResult<&str, u64> {
        let mut value = 0u64;
        let mut len = 0;
        let mut bytes = input.bytes().peekable();
        while let Some(&b) = bytes.peek() {
            match b {
                b'0'...b'9' => {
                    value = match value.checked_mul(10) {
                        Some(value) => value,
                        None => return IResult::Error,
                    };
                    value = match value.checked_add((b - b'0') as u64) {
                        Some(value) => value,
                        None => return IResult::Error,
                    };
                    bytes.next();
                    len += 1;
                }
                _ => break,
            }
        }
        if len > 0 {
            IResult::Done(&input[len..], value)
        } else {
            IResult::Error
        }
    }
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;
    use quote::{Tokens, ToTokens};
    use std::{ascii, iter};
    use std::fmt::{self, Display};

    impl ToTokens for Lit {
        fn to_tokens(&self, tokens: &mut Tokens) {
            match *self {
                Lit::Str(ref s, StrStyle::Cooked) => s.to_tokens(tokens),
                Lit::Str(ref s, StrStyle::Raw(n)) => {
                    tokens.append(&format!("r{delim}\"{string}\"{delim}",
                        delim = iter::repeat("#").take(n).collect::<String>(),
                        string = s));
                }
                Lit::ByteStr(ref v) => {
                    let mut escaped = "b\"".to_string();
                    for &ch in v.iter() {
                        escaped.extend(ascii::escape_default(ch).map(|c| c as char));
                    }
                    escaped.push('"');
                    tokens.append(&escaped);
                }
                Lit::Byte(b) => tokens.append(&format!("b{:?}", b as char)),
                Lit::Char(ch) => ch.to_tokens(tokens),
                Lit::Int(value, ty) => tokens.append(&format!("{}{}", value, ty)),
                Lit::Float(ref value, ty) => tokens.append(&format!("{}{}", value, ty)),
                Lit::Bool(true) => tokens.append("true"),
                Lit::Bool(false) => tokens.append("false"),
            }
        }
    }

    impl Display for IntTy {
        fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
            match *self {
                IntTy::Isize => formatter.write_str("isize"),
                IntTy::I8 => formatter.write_str("i8"),
                IntTy::I16 => formatter.write_str("i16"),
                IntTy::I32 => formatter.write_str("i32"),
                IntTy::I64 => formatter.write_str("i64"),
                IntTy::Usize => formatter.write_str("usize"),
                IntTy::U8 => formatter.write_str("u8"),
                IntTy::U16 => formatter.write_str("u16"),
                IntTy::U32 => formatter.write_str("u32"),
                IntTy::U64 => formatter.write_str("u64"),
                IntTy::Unsuffixed => Ok(()),
            }
        }
    }

    impl Display for FloatTy {
        fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
            match *self {
                FloatTy::F32 => formatter.write_str("f32"),
                FloatTy::F64 => formatter.write_str("f64"),
                FloatTy::Unsuffixed => Ok(()),
            }
        }
    }
}
<commit_msg>Separate parser to parse boolean literals<commit_after>/// Literal kind.
///
/// E.g. `"foo"`, `42`, `12.34` or `bool`
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum Lit {
    /// A string literal (`"foo"`)
    Str(String, StrStyle),
    /// A byte string (`b"foo"`)
    ByteStr(Vec<u8>),
    /// A byte char (`b'f'`)
    Byte(u8),
    /// A character literal (`'a'`)
    Char(char),
    /// An integer literal (`1`)
    Int(u64, IntTy),
    /// A float literal (`1f64` or `1E10f64` or `1.0E10`)
    Float(String, FloatTy),
    /// A boolean literal
    Bool(bool),
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum StrStyle {
    /// A regular string, like `"foo"`
    Cooked,
    /// A raw string, like `r##"foo"##`
    ///
    /// The uint is the number of `#` symbols used
    Raw(usize),
}

impl From<String> for Lit {
    fn from(input: String) -> Lit {
        Lit::Str(input, StrStyle::Cooked)
    }
}

impl<'a> From<&'a str> for Lit {
    fn from(input: &str) -> Lit {
        Lit::Str(input.into(), StrStyle::Cooked)
    }
}

impl From<Vec<u8>> for Lit {
    fn from(input: Vec<u8>) -> Lit {
        Lit::ByteStr(input)
    }
}

impl<'a> From<&'a [u8]> for Lit {
    fn from(input: &[u8]) -> Lit {
        Lit::ByteStr(input.into())
    }
}

impl From<char> for Lit {
    fn from(input: char) -> Lit {
        Lit::Char(input)
    }
}

impl From<bool> for Lit {
    fn from(input: bool) -> Lit {
        Lit::Bool(input)
    }
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum IntTy {
    Isize,
    I8,
    I16,
    I32,
    I64,
    Usize,
    U8,
    U16,
    U32,
    U64,
    Unsuffixed,
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum FloatTy {
    F32,
    F64,
    Unsuffixed,
}

macro_rules! impl_from_for_lit {
    (Int, [$($rust_type:ty => $syn_type:expr),+]) => {
        $(
            impl From<$rust_type> for Lit {
                fn from(input: $rust_type) -> Lit {
                    Lit::Int(input as u64, $syn_type)
                }
            }
        )+
    };
    (Float, [$($rust_type:ty => $syn_type:expr),+]) => {
        $(
            impl From<$rust_type> for Lit {
                fn from(input: $rust_type) -> Lit {
                    Lit::Float(format!("{}", input), $syn_type)
                }
            }
        )+
    };
}

impl_from_for_lit! {Int, [
    isize => IntTy::Isize,
    i8 => IntTy::I8,
    i16 => IntTy::I16,
    i32 => IntTy::I32,
    i64 => IntTy::I64,
    usize => IntTy::Usize,
    u8 => IntTy::U8,
    u16 => IntTy::U16,
    u32 => IntTy::U32,
    u64 => IntTy::U64
]}

impl_from_for_lit! {Float, [
    f32 => FloatTy::F32,
    f64 => FloatTy::F64
]}

#[cfg(feature = "parsing")]
pub mod parsing {
    use super::*;
    use escape::{cooked_char, cooked_string, raw_string};
    use space::whitespace;
    use nom::IResult;

    named!(pub lit -> Lit, alt!(
        string
        |
        byte_string
        |
        byte
        |
        character
        |
        int => { |(value, ty)| Lit::Int(value, ty) }
    // TODO: Float
        |
        boolean
    ));

    named!(string -> Lit, alt!(
        quoted_string => { |s| Lit::Str(s, StrStyle::Cooked) }
        |
        preceded!(
            punct!("r"),
            raw_string
        ) => { |(s, n)| Lit::Str(s, StrStyle::Raw(n)) }
    ));

    named!(pub quoted_string -> String, delimited!(
        punct!("\""),
        cooked_string,
        tag!("\"")
    ));

    named!(byte_string -> Lit, alt!(
        delimited!(
            punct!("b\""),
            cooked_string,
            tag!("\"")
        ) => { |s: String| Lit::ByteStr(s.into_bytes()) }
        |
        preceded!(
            punct!("br"),
            raw_string
        ) => { |(s, _): (String, _)| Lit::ByteStr(s.into_bytes()) }
    ));

    named!(byte -> Lit, do_parse!(
        punct!("b") >>
        tag!("'") >>
        ch: cooked_char >>
        tag!("'") >>
        (Lit::Byte(ch as u8))
    ));

    named!(character -> Lit, do_parse!(
        punct!("'") >>
        ch: cooked_char >>
        tag!("'") >>
        (Lit::Char(ch))
    ));

    named!(pub int -> (u64, IntTy), tuple!(
        preceded!(
            option!(whitespace),
            digits
        ),
        alt!(
            tag!("isize") => { |_| IntTy::Isize }
            |
            tag!("i8") => { |_| IntTy::I8 }
            |
            tag!("i16") => { |_| IntTy::I16 }
            |
            tag!("i32") => { |_| IntTy::I32 }
            |
            tag!("i64") => { |_| IntTy::I64 }
            |
            tag!("usize") => { |_| IntTy::Usize }
            |
            tag!("u8") => { |_| IntTy::U8 }
            |
            tag!("u16") => { |_| IntTy::U16 }
            |
            tag!("u32") => { |_| IntTy::U32 }
            |
            tag!("u64") => { |_| IntTy::U64 }
            |
            epsilon!() => { |_| IntTy::Unsuffixed }
        )
    ));

    named!(boolean -> Lit, alt!(
        keyword!("true") => { |_| Lit::Bool(true) }
        |
        keyword!("false") => { |_| Lit::Bool(false) }
    ));

    pub fn digits(input: &str) -> IResult<&str, u64> {
        let mut value = 0u64;
        let mut len = 0;
        let mut bytes = input.bytes().peekable();
        while let Some(&b) = bytes.peek() {
            match b {
                b'0'...b'9' => {
                    value = match value.checked_mul(10) {
                        Some(value) => value,
                        None => return IResult::Error,
                    };
                    value = match value.checked_add((b - b'0') as u64) {
                        Some(value) => value,
                        None => return IResult::Error,
                    };
                    bytes.next();
                    len += 1;
                }
                _ => break,
            }
        }
        if len > 0 {
            IResult::Done(&input[len..], value)
        } else {
            IResult::Error
        }
    }
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;
    use quote::{Tokens, ToTokens};
    use std::{ascii, iter};
    use std::fmt::{self, Display};

    impl ToTokens for Lit {
        fn to_tokens(&self, tokens: &mut Tokens) {
            match *self {
                Lit::Str(ref s, StrStyle::Cooked) => s.to_tokens(tokens),
                Lit::Str(ref s, StrStyle::Raw(n)) => {
                    tokens.append(&format!("r{delim}\"{string}\"{delim}",
                        delim = iter::repeat("#").take(n).collect::<String>(),
                        string = s));
                }
                Lit::ByteStr(ref v) => {
                    let mut escaped = "b\"".to_string();
                    for &ch in v.iter() {
                        escaped.extend(ascii::escape_default(ch).map(|c| c as char));
                    }
                    escaped.push('"');
                    tokens.append(&escaped);
                }
                Lit::Byte(b) => tokens.append(&format!("b{:?}", b as char)),
                Lit::Char(ch) => ch.to_tokens(tokens),
                Lit::Int(value, ty) => tokens.append(&format!("{}{}", value, ty)),
                Lit::Float(ref value, ty) => tokens.append(&format!("{}{}", value, ty)),
                Lit::Bool(true) => tokens.append("true"),
                Lit::Bool(false) => tokens.append("false"),
            }
        }
    }

    impl Display for IntTy {
        fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
            match *self {
                IntTy::Isize => formatter.write_str("isize"),
                IntTy::I8 => formatter.write_str("i8"),
                IntTy::I16 => formatter.write_str("i16"),
                IntTy::I32 => formatter.write_str("i32"),
                IntTy::I64 => formatter.write_str("i64"),
                IntTy::Usize => formatter.write_str("usize"),
                IntTy::U8 => formatter.write_str("u8"),
                IntTy::U16 => formatter.write_str("u16"),
                IntTy::U32 => formatter.write_str("u32"),
                IntTy::U64 => formatter.write_str("u64"),
                IntTy::Unsuffixed => Ok(()),
            }
        }
    }

    impl Display for FloatTy {
        fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
            match *self {
                FloatTy::F32 => formatter.write_str("f32"),
                FloatTy::F64 => formatter.write_str("f64"),
                FloatTy::Unsuffixed => Ok(()),
            }
        }
    }
}
<|endoftext|>


<commit_before>use super::{Point, LatLon};
use projection::Projection;
use layer::Layer;

///
/// Represents a map view
///
/// A map uses three coordinate systems:
///
/// * Latitude/longitude
/// * Map coordinates: Map coordinates are in arbitrary units, as defined by the projection.
///   The only constraint on map coordinates is that the X coordinate increases going right
///   and the Y coordinate increases going up.
/// * Display coordinates: Display coordinates are in pixels, with the X coordinate increasing
///   going right and the Y coordinate increasing going down. The origin is located at the
///   upper left corner of the viewport.
///
/// The map's projection converts between latitude/longitude and map coordinates. The map's
/// view projection converts between map coordinates and display coordinates.
///
pub struct Map {
    /// The projection
    projection: Box<Projection>,
    /// The view projection
    view_projection: ViewProjection,
    /// The layers
    layers: Vec<Box<Layer>>,
}

impl Map {
    ///
    /// Creates a new map using a given projection
    ///
    pub fn new<P>(projection: P) -> Map where P: 'static + Projection {
        Map {
            projection: Box::new(projection),
            view_projection: ViewProjection {
                center: Point::origin(),
                zoom: 1f64,
            },
            layers: Vec::new(),
        }
    }

    ///
    /// Sets the projection that this map should use
    ///
    pub fn set_projection<P>(&mut self, projection: P) where P: 'static + Projection {
        self.projection = Box::new(projection)
    }

    ///
    /// Adds a layer to this map. The new layer will be drawn on top of the existing layers.
    ///
    pub fn add_layer<L>(&mut self, layer: L) where L: 'static + Layer {
        self.layers.push(Box::new(layer))
    }

    ///
    /// Removes all layers from this map
    ///
    pub fn clear_layers(&mut self) {
        self.layers.clear()
    }

    ///
    /// Draws this map with its upper left corner at (x, y) with the specified width and height
    ///
    pub fn draw(&self, x: i32, y: i32, width: i32, height: i32) {
        let combined = CombinedProjection::new(self.projection.as_ref(), &self.view_projection, width, height);
        for layer in self.layers.iter() {
            layer.draw(&combined, x, y, width, height);
        }
    }
}

///
/// A linear projection that maps between map coordinates and display coordinates
///
struct ViewProjection {
    /// The location, in map coordinates, where the center of the viewport is located
    center: Point<f64>,
    /// The ratio of the size of a display unit to the size of a map coordinate unit
    zoom: f64,
}

impl ViewProjection {
    /// Projects a point in map coordinates to a point in screen coordinates
    pub fn project(&self, map: &Point<f64>, viewport_width: i32, viewport_height: i32) -> Point<f64> {
        // Calculate the vector from the center point to the map point
        let mut map_vector = map.clone() - self.center.clone();
        // Scale by the zoom ratio
        map_vector = map_vector * self.zoom;
        // Invert Y to make it increase downwards
        map_vector.y *= -1.0;
        // map_vector is now the screen position relative to the center
        // Shift it to make it relative to the corner
        map_vector = map_vector + Point { x: (viewport_width / 2) as f64, y: (viewport_height / 2) as f64 };
        map_vector
    }
    /// Unprojects a point from screen coordinates to a point in map coordinates
    pub fn unproject(&self, screen: &Point<f64>, viewport_width: i32, viewport_height: i32) -> Point<f64> {
        // Shift to make it relative to the center
        let mut map_vector = screen.clone() - Point { x: (viewport_width / 2) as f64, y: (viewport_height / 2) as f64 };
        // Invert Y to make it increase upwards
        map_vector.y *= -1.0;
        // Scale by inverse zoom ratio
        map_vector = map_vector * (1f64 / self.zoom);
        // Make relative to center point
        map_vector = map_vector + self.center.clone();
        map_vector
    }
}

///
/// A Projection implementation for a combination of a Projection and a ViewProjection
///
struct CombinedProjection<'a, 'b> {
    /// The primary projection
    projection: &'a Projection,
    /// The view projection
    view_projection: &'b ViewProjection,
    /// The width of the viewport in pixels
    viewport_width: i32,
    /// The height of the viewport in pixels
    viewport_height: i32,
}

impl<'a, 'b> CombinedProjection<'a, 'b> {
    pub fn new(projection: &'a Projection, view_projection: &'b ViewProjection, viewport_width: i32, viewport_height: i32) -> CombinedProjection<'a, 'b> {
        CombinedProjection {
            projection: projection,
            view_projection: view_projection,
            viewport_width: viewport_width,
            viewport_height: viewport_height,
        }
    }
}

impl<'a, 'b> Projection for CombinedProjection<'a, 'b> {
    fn project(&self, position: &LatLon) -> Point<f64> {
        let map = self.projection.project(position);
        self.view_projection.project(&map, self.viewport_width, self.viewport_height)
    }
    fn unproject(&self, position: &Point<f64>) -> LatLon {
        let map = self.view_projection.unproject(position, self.viewport_width, self.viewport_height);
        self.projection.unproject(&map)
    }
}
<commit_msg>Changed mapping<commit_after>use super::{Point, LatLon};
use projection::Projection;
use layer::Layer;

///
/// Represents a map view
///
/// A map uses three coordinate systems:
///
/// * Latitude/longitude
/// * Map coordinates: Map coordinates are in arbitrary units, as defined by the projection.
///   The only constraint on map coordinates is that the X coordinate increases going right
///   and the Y coordinate increases going up.
/// * Display coordinates: Display coordinates are in pixels, with the X coordinate increasing
///   going right and the Y coordinate increasing going up. The origin is located at the
///   lower left corner of the viewport.
///
/// The map's projection converts between latitude/longitude and map coordinates. The map's
/// view projection converts between map coordinates and display coordinates.
///
pub struct Map {
    /// The projection
    projection: Box<Projection>,
    /// The view projection
    view_projection: ViewProjection,
    /// The layers
    layers: Vec<Box<Layer>>,
}

impl Map {
    ///
    /// Creates a new map using a given projection
    ///
    pub fn new<P>(projection: P) -> Map where P: 'static + Projection {
        Map {
            projection: Box::new(projection),
            view_projection: ViewProjection {
                center: Point::origin(),
                zoom: 1f64,
            },
            layers: Vec::new(),
        }
    }

    ///
    /// Sets the projection that this map should use
    ///
    pub fn set_projection<P>(&mut self, projection: P) where P: 'static + Projection {
        self.projection = Box::new(projection)
    }

    ///
    /// Adds a layer to this map. The new layer will be drawn on top of the existing layers.
    ///
    pub fn add_layer<L>(&mut self, layer: L) where L: 'static + Layer {
        self.layers.push(Box::new(layer))
    }

    ///
    /// Removes all layers from this map
    ///
    pub fn clear_layers(&mut self) {
        self.layers.clear()
    }

    ///
    /// Draws this map with its upper left corner at (x, y) with the specified width and height
    ///
    pub fn draw(&self, x: i32, y: i32, width: i32, height: i32) {
        let combined = CombinedProjection::new(self.projection.as_ref(), &self.view_projection, width, height);
        for layer in self.layers.iter() {
            layer.draw(&combined, x, y, width, height);
        }
    }
}

///
/// A linear projection that maps between map coordinates and display coordinates
///
struct ViewProjection {
    /// The location, in map coordinates, where the center of the viewport is located
    center: Point<f64>,
    /// The ratio of the size of a display unit to the size of a map coordinate unit
    zoom: f64,
}

impl ViewProjection {
    /// Projects a point in map coordinates to a point in screen coordinates
    pub fn project(&self, map: &Point<f64>, viewport_width: i32, viewport_height: i32) -> Point<f64> {
        // Calculate the vector from the center point to the map point
        let mut map_vector = map.clone() - self.center.clone();
        // Scale by the zoom ratio
        map_vector = map_vector * self.zoom;
        // map_vector is now the screen position relative to the center
        // Shift it to make it relative to the corner
        map_vector = map_vector + Point { x: (viewport_width / 2) as f64, y: (viewport_height / 2) as f64 };
        map_vector
    }
    /// Unprojects a point from screen coordinates to a point in map coordinates
    pub fn unproject(&self, screen: &Point<f64>, viewport_width: i32, viewport_height: i32) -> Point<f64> {
        // Shift to make it relative to the center
        let mut map_vector = screen.clone() - Point { x: (viewport_width / 2) as f64, y: (viewport_height / 2) as f64 };
        // Scale by inverse zoom ratio
        map_vector = map_vector * (1f64 / self.zoom);
        // Make relative to center point
        map_vector = map_vector + self.center.clone();
        map_vector
    }
}

///
/// A Projection implementation for a combination of a Projection and a ViewProjection
///
struct CombinedProjection<'a, 'b> {
    /// The primary projection
    projection: &'a Projection,
    /// The view projection
    view_projection: &'b ViewProjection,
    /// The width of the viewport in pixels
    viewport_width: i32,
    /// The height of the viewport in pixels
    viewport_height: i32,
}

impl<'a, 'b> CombinedProjection<'a, 'b> {
    pub fn new(projection: &'a Projection, view_projection: &'b ViewProjection, viewport_width: i32, viewport_height: i32) -> CombinedProjection<'a, 'b> {
        CombinedProjection {
            projection: projection,
            view_projection: view_projection,
            viewport_width: viewport_width,
            viewport_height: viewport_height,
        }
    }
}

impl<'a, 'b> Projection for CombinedProjection<'a, 'b> {
    fn project(&self, position: &LatLon) -> Point<f64> {
        let map = self.projection.project(position);
        self.view_projection.project(&map, self.viewport_width, self.viewport_height)
    }
    fn unproject(&self, position: &Point<f64>) -> LatLon {
        let map = self.view_projection.unproject(position, self.viewport_width, self.viewport_height);
        self.projection.unproject(&map)
    }
}
<|endoftext|>


<commit_before>use super::mpz::{mpz_struct, Mpz, mpz_ptr, mpz_srcptr};
use super::mpf::{Mpf, mpf_srcptr};
use ffi::*;
use libc::{c_double, c_int, c_ulong};
use std::convert::{From, Into};
use std::mem::uninitialized;
use std::fmt;
use std::cmp::Ordering::{self, Greater, Less, Equal};
use std::ops::{Div, DivAssign, Mul, MulAssign, Add, AddAssign, Sub, SubAssign, Neg};

#[repr(C)]
pub struct mpq_struct {
    _mp_num: mpz_struct,
    _mp_den: mpz_struct
}

pub type mpq_srcptr = *const mpq_struct;
pub type mpq_ptr = *mut mpq_struct;

#[link(name = "gmp")]
extern "C" {
    fn __gmpq_init(x: mpq_ptr);
    fn __gmpq_clear(x: mpq_ptr);
    fn __gmpq_set(rop: mpq_ptr, op: mpq_srcptr);
    fn __gmpq_set_z(rop: mpq_ptr, op: mpz_srcptr);
    fn __gmpq_set_ui(rop: mpq_ptr, op1: c_ulong, op2: c_ulong);
    fn __gmpq_set_d(rop: mpq_ptr, op: c_double);
    fn __gmpq_set_f(rop: mpq_ptr, op: mpf_srcptr);
    fn __gmpq_cmp(op1: mpq_srcptr, op2: mpq_srcptr) -> c_int;
    fn __gmpq_cmp_ui(op1: mpq_srcptr, num2: c_ulong, den2: c_ulong) -> c_int;
    fn __gmpq_equal(op1: mpq_srcptr, op2: mpq_srcptr) -> c_int;
    fn __gmpq_add(sum: mpq_ptr, addend1: mpq_srcptr, addend2: mpq_srcptr);
    fn __gmpq_sub(difference: mpq_ptr, minuend: mpq_srcptr, subtrahend: mpq_srcptr);
    fn __gmpq_mul(product: mpq_ptr, multiplier: mpq_srcptr, multiplicand: mpq_srcptr);
    fn __gmpq_div(product: mpq_ptr, multiplier: mpq_srcptr, multiplicand: mpq_srcptr);
    fn __gmpq_neg(negated_operand: mpq_ptr, operand: mpq_srcptr);
    fn __gmpq_abs(rop: mpq_ptr, op: mpq_srcptr);
    fn __gmpq_inv(inverted_number: mpq_ptr, number: mpq_srcptr);
    fn __gmpq_get_num(numerator: mpz_ptr, rational: mpq_srcptr);
    fn __gmpq_get_den(denominator: mpz_ptr, rational: mpq_srcptr);
    fn __gmpq_set_num(rational: mpq_ptr, numerator: mpz_srcptr);
    fn __gmpq_set_den(rational: mpq_ptr, denominator: mpz_srcptr);
    fn __gmpq_canonicalize(rational: mpq_ptr);
    fn __gmpq_get_d(rational: mpq_srcptr) -> c_double;
}

pub struct Mpq {
    mpq: mpq_struct,
}

unsafe impl Send for Mpq { }

impl Drop for Mpq {
    fn drop(&mut self) { unsafe { __gmpq_clear(&mut self.mpq) } }
}

impl Mpq {
    pub unsafe fn inner(&self) -> mpq_srcptr {
        &self.mpq
    }

    pub unsafe fn inner_mut(&mut self) -> mpq_ptr {
        &mut self.mpq
    }

    pub fn new() -> Mpq {
        unsafe {
            let mut mpq = uninitialized();
            __gmpq_init(&mut mpq);
            Mpq { mpq: mpq }
        }
    }

    pub fn ratio(num: &Mpz, den: &Mpz) -> Mpq {
        unsafe {
            let mut res = Mpq::new();
            __gmpq_set_num(&mut res.mpq, num.inner());
            __gmpq_set_den(&mut res.mpq, den.inner());
            res
        }
    }

    pub fn canonicalize(&mut self) {
        unsafe {
            __gmpq_canonicalize(&mut self.mpq);
        }
    }

    pub fn set(&mut self, other: &Mpq) {
        unsafe { __gmpq_set(&mut self.mpq, &other.mpq) }
    }

    pub fn set_z(&mut self, other: &Mpz) {
        unsafe { __gmpq_set_z(&mut self.mpq, other.inner()) }
    }

    pub fn set_d(&mut self, other: f64) {
        unsafe { __gmpq_set_d(&mut self.mpq, other) }
    }

    pub fn set_f(&mut self, other: &Mpf) {
        unsafe { __gmpq_set_f(&mut self.mpq, other.inner()) }
    }

    pub fn get_num(&self) -> Mpz {
        unsafe {
            let mut res = Mpz::new();
            __gmpq_get_num(res.inner_mut(), &self.mpq);
            res
        }
    }

    pub fn get_den(&self) -> Mpz {
        unsafe {
            let mut res = Mpz::new();
            __gmpq_get_den(res.inner_mut(), &self.mpq);
            res
        }
    }

    pub fn abs(&self) -> Mpq {
        unsafe {
            let mut res = Mpq::new();
            __gmpq_abs(&mut res.mpq, &self.mpq);
            res
        }
    }

    pub fn invert(&self) -> Mpq {
        unsafe {
            if self.is_zero() {
                panic!("divide by zero")
            }

            let mut res = Mpq::new();
            __gmpq_inv(&mut res.mpq, &self.mpq);
            res
        }
    }

    pub fn floor(&self) -> Mpz {
        let mut res = Mpz::new();
        unsafe {
            __gmpz_fdiv_q(res.inner_mut(), &self.mpq._mp_num, &self.mpq._mp_den);
        }
        res
    }

    pub fn ceil(&self) -> Mpz {
        let mut res = Mpz::new();
        unsafe {
            __gmpz_cdiv_q(res.inner_mut(), &self.mpq._mp_num, &self.mpq._mp_den);
        }
        res
    }

    pub fn one() -> Mpq {
        let mut res = Mpq::new();
        unsafe { __gmpq_set_ui(&mut res.mpq, 1, 1) }
        res
    }

    pub fn zero() -> Mpq { Mpq::new() }
    pub fn is_zero(&self) -> bool {
        unsafe { __gmpq_cmp_ui(&self.mpq, 0, 1) == 0 }
    }
}

impl Clone for Mpq {
    fn clone(&self) -> Mpq {
        let mut res = Mpq::new();
        res.set(self);
        res
    }
}

impl Eq for Mpq { }
impl PartialEq for Mpq {
    fn eq(&self, other: &Mpq) -> bool {
        unsafe { __gmpq_equal(&self.mpq, &other.mpq) != 0 }
    }
}

impl Ord for Mpq {
    fn cmp(&self, other: &Mpq) -> Ordering {
        let cmp = unsafe { __gmpq_cmp(&self.mpq, &other.mpq) };
        if cmp == 0 {
            Equal
        } else if cmp < 0 {
            Less
        } else {
            Greater
        }
    }
}
impl PartialOrd for Mpq {
    fn partial_cmp(&self, other: &Mpq) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

macro_rules! div_guard {
    (Div, $what: expr) => {
        if $what.is_zero() {
            panic!("divide by zero")
        }
    };
    ($tr: ident, $what: expr) => {}
}

macro_rules! impl_oper {
    ($tr: ident, $meth: ident, $tr_assign: ident, $meth_assign: ident, $fun: ident) => {
        impl $tr<Mpq> for Mpq {
            type Output = Mpq;
            #[inline]
            fn $meth(self, other: Mpq) -> Mpq {
                self.$meth(&other)
            }
        }

        impl<'a> $tr<&'a Mpq> for Mpq {
            type Output = Mpq;
            #[inline]
            fn $meth(mut self, other: &Mpq) -> Mpq {
                self.$meth_assign(other);
                self
            }
        }

        impl<'a> $tr<Mpq> for &'a Mpq {
            type Output = Mpq;
            #[inline]
            fn $meth(self, mut other: Mpq) -> Mpq {
                unsafe {
                    div_guard!($tr, other);
                    $fun(&mut other.mpq, &self.mpq, &other.mpq);
                    other
                }
            }
        }

        impl<'a, 'b> $tr<&'a Mpq> for &'b Mpq {
            type Output = Mpq;
            fn $meth(self, other: &Mpq) -> Mpq {
                unsafe {
                    div_guard!($tr, *other);
                    let mut res = Mpq::new();
                    $fun(&mut res.mpq, &self.mpq, &other.mpq);
                    res
                }
            }
        }

        impl<'a> $tr_assign<Mpq> for Mpq {
            #[inline]
            fn $meth_assign(&mut self, other: Mpq) {
                self.$meth_assign(&other)
            }
        }

        impl<'a> $tr_assign<&'a Mpq> for Mpq {
            #[inline]
            fn $meth_assign(&mut self, other: &Mpq) {
                unsafe {
                    div_guard!($tr, *other);
                    $fun(&mut self.mpq, &self.mpq, &other.mpq)
                }
            }
        }
    }
}

impl_oper!(Add, add, AddAssign, add_assign, __gmpq_add);
impl_oper!(Sub, sub, SubAssign, sub_assign, __gmpq_sub);
impl_oper!(Mul, mul, MulAssign, mul_assign, __gmpq_mul);
impl_oper!(Div, div, DivAssign, div_assign, __gmpq_div);

impl<'b> Neg for &'b Mpq {
    type Output = Mpq;
    fn neg(self) -> Mpq {
        unsafe {
            let mut res = Mpq::new();
            __gmpq_neg(&mut res.mpq, &self.mpq);
            res
        }
    }
}

impl Neg for Mpq {
    type Output = Mpq;
    #[inline]
    fn neg(mut self) -> Mpq {
        unsafe {
            __gmpq_neg(&mut self.mpq, &self.mpq);
            self
        }
    }
}

impl Into<Option<i64>> for Mpq {
    fn into(self) -> Option<i64> {
        panic!("not implemented")
    }
}

impl Into<Option<u64>> for Mpq {
    fn into(self) -> Option<u64> {
        panic!("not implemented")
    }
}

impl Into<f64> for Mpq {
    fn into(self) -> f64 {
        unsafe {
            __gmpq_get_d(&self.mpq) as f64
        }
    }
}

impl From<Mpz> for Mpq {
    fn from(other: Mpz) -> Mpq {
        let mut res = Mpq::new();
        res.set_z(&other);
        res
    }
}

impl From<i64> for Mpq {
    fn from(other: i64) -> Mpq {
        From::<Mpz>::from(From::<i64>::from(other))
    }
}

impl From<i32> for Mpq {
    fn from(other: i32) -> Mpq {
        From::<Mpz>::from(From::<i32>::from(other))
    }
}

impl From<u64> for Mpq {
    fn from(other: u64) -> Mpq {
        From::<Mpz>::from(From::<u64>::from(other))
    }
}

impl From<u32> for Mpq {
    fn from(other: u32) -> Mpq {
        From::<Mpz>::from(From::<u32>::from(other))
    }
}

impl fmt::Debug for Mpq {
    /// Renders as `numer/denom`. If denom=1, renders as numer.
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let numer = self.get_num();
        let denom = self.get_den();

        if denom == From::<i64>::from(1) {
            write!(f, "{}", numer)
        } else {
            write!(f, "{}/{}", numer, denom)
        }
    }
}
<commit_msg>Mpq: Implement FromStr<commit_after>use super::mpz::{mpz_struct, Mpz, mpz_ptr, mpz_srcptr};
use super::mpf::{Mpf, mpf_srcptr};
use ffi::*;
use libc::{c_char, c_double, c_int, c_ulong};
use std::ffi::CString;
use std::str::FromStr;
use std::error::Error;
use std::convert::{From, Into};
use std::mem::uninitialized;
use std::fmt;
use std::cmp::Ordering::{self, Greater, Less, Equal};
use std::ops::{Div, DivAssign, Mul, MulAssign, Add, AddAssign, Sub, SubAssign, Neg};

#[repr(C)]
pub struct mpq_struct {
    _mp_num: mpz_struct,
    _mp_den: mpz_struct
}

pub type mpq_srcptr = *const mpq_struct;
pub type mpq_ptr = *mut mpq_struct;

#[link(name = "gmp")]
extern "C" {
    fn __gmpq_init(x: mpq_ptr);
    fn __gmpq_clear(x: mpq_ptr);
    fn __gmpq_set(rop: mpq_ptr, op: mpq_srcptr);
    fn __gmpq_set_z(rop: mpq_ptr, op: mpz_srcptr);
    fn __gmpq_set_ui(rop: mpq_ptr, op1: c_ulong, op2: c_ulong);
    fn __gmpq_set_d(rop: mpq_ptr, op: c_double);
    fn __gmpq_set_f(rop: mpq_ptr, op: mpf_srcptr);
    fn __gmpq_cmp(op1: mpq_srcptr, op2: mpq_srcptr) -> c_int;
    fn __gmpq_cmp_ui(op1: mpq_srcptr, num2: c_ulong, den2: c_ulong) -> c_int;
    fn __gmpq_equal(op1: mpq_srcptr, op2: mpq_srcptr) -> c_int;
    fn __gmpq_add(sum: mpq_ptr, addend1: mpq_srcptr, addend2: mpq_srcptr);
    fn __gmpq_sub(difference: mpq_ptr, minuend: mpq_srcptr, subtrahend: mpq_srcptr);
    fn __gmpq_mul(product: mpq_ptr, multiplier: mpq_srcptr, multiplicand: mpq_srcptr);
    fn __gmpq_div(product: mpq_ptr, multiplier: mpq_srcptr, multiplicand: mpq_srcptr);
    fn __gmpq_neg(negated_operand: mpq_ptr, operand: mpq_srcptr);
    fn __gmpq_abs(rop: mpq_ptr, op: mpq_srcptr);
    fn __gmpq_inv(inverted_number: mpq_ptr, number: mpq_srcptr);
    fn __gmpq_get_num(numerator: mpz_ptr, rational: mpq_srcptr);
    fn __gmpq_get_den(denominator: mpz_ptr, rational: mpq_srcptr);
    fn __gmpq_set_num(rational: mpq_ptr, numerator: mpz_srcptr);
    fn __gmpq_set_den(rational: mpq_ptr, denominator: mpz_srcptr);
    fn __gmpq_canonicalize(rational: mpq_ptr);
    fn __gmpq_get_d(rational: mpq_srcptr) -> c_double;
    fn __gmpq_set_str(rop: mpq_ptr, str: *const c_char, base: c_int) -> c_int;
}

pub struct Mpq {
    mpq: mpq_struct,
}

unsafe impl Send for Mpq { }

impl Drop for Mpq {
    fn drop(&mut self) { unsafe { __gmpq_clear(&mut self.mpq) } }
}

impl Mpq {
    pub unsafe fn inner(&self) -> mpq_srcptr {
        &self.mpq
    }

    pub unsafe fn inner_mut(&mut self) -> mpq_ptr {
        &mut self.mpq
    }

    pub fn new() -> Mpq {
        unsafe {
            let mut mpq = uninitialized();
            __gmpq_init(&mut mpq);
            Mpq { mpq: mpq }
        }
    }

    pub fn ratio(num: &Mpz, den: &Mpz) -> Mpq {
        unsafe {
            let mut res = Mpq::new();
            __gmpq_set_num(&mut res.mpq, num.inner());
            __gmpq_set_den(&mut res.mpq, den.inner());
            res
        }
    }

    pub fn canonicalize(&mut self) {
        unsafe {
            __gmpq_canonicalize(&mut self.mpq);
        }
    }

    pub fn from_str_radix(s: &str, base: u8) -> Result<Mpq, ParseMpqError> {
        let s = CString::new(s).map_err(|_| ParseMpqError { _priv: () })?;
        let mut res = Mpq::new();
        unsafe {
            assert!(base == 0 || (base >= 2 && base <= 62));
            let r = __gmpq_set_str(&mut res.mpq, s.as_ptr(), base as c_int);
            if r == 0 {
                Ok(res)
            } else {
                Err(ParseMpqError { _priv: () })
            }
        }
    }

    pub fn set(&mut self, other: &Mpq) {
        unsafe { __gmpq_set(&mut self.mpq, &other.mpq) }
    }

    pub fn set_z(&mut self, other: &Mpz) {
        unsafe { __gmpq_set_z(&mut self.mpq, other.inner()) }
    }

    pub fn set_d(&mut self, other: f64) {
        unsafe { __gmpq_set_d(&mut self.mpq, other) }
    }

    pub fn set_f(&mut self, other: &Mpf) {
        unsafe { __gmpq_set_f(&mut self.mpq, other.inner()) }
    }

    pub fn get_num(&self) -> Mpz {
        unsafe {
            let mut res = Mpz::new();
            __gmpq_get_num(res.inner_mut(), &self.mpq);
            res
        }
    }

    pub fn get_den(&self) -> Mpz {
        unsafe {
            let mut res = Mpz::new();
            __gmpq_get_den(res.inner_mut(), &self.mpq);
            res
        }
    }

    pub fn abs(&self) -> Mpq {
        unsafe {
            let mut res = Mpq::new();
            __gmpq_abs(&mut res.mpq, &self.mpq);
            res
        }
    }

    pub fn invert(&self) -> Mpq {
        unsafe {
            if self.is_zero() {
                panic!("divide by zero")
            }

            let mut res = Mpq::new();
            __gmpq_inv(&mut res.mpq, &self.mpq);
            res
        }
    }

    pub fn floor(&self) -> Mpz {
        let mut res = Mpz::new();
        unsafe {
            __gmpz_fdiv_q(res.inner_mut(), &self.mpq._mp_num, &self.mpq._mp_den);
        }
        res
    }

    pub fn ceil(&self) -> Mpz {
        let mut res = Mpz::new();
        unsafe {
            __gmpz_cdiv_q(res.inner_mut(), &self.mpq._mp_num, &self.mpq._mp_den);
        }
        res
    }

    pub fn one() -> Mpq {
        let mut res = Mpq::new();
        unsafe { __gmpq_set_ui(&mut res.mpq, 1, 1) }
        res
    }

    pub fn zero() -> Mpq { Mpq::new() }
    pub fn is_zero(&self) -> bool {
        unsafe { __gmpq_cmp_ui(&self.mpq, 0, 1) == 0 }
    }
}

#[derive(Debug)]
pub struct ParseMpqError {
    _priv: ()
}

impl fmt::Display for ParseMpqError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.description().fmt(f)
    }
}

impl Error for ParseMpqError {
    fn description(&self) -> &'static str {
        "invalid rational number"
    }

    fn cause(&self) -> Option<&'static Error> {
        None
    }
}

impl Clone for Mpq {
    fn clone(&self) -> Mpq {
        let mut res = Mpq::new();
        res.set(self);
        res
    }
}

impl Eq for Mpq { }
impl PartialEq for Mpq {
    fn eq(&self, other: &Mpq) -> bool {
        unsafe { __gmpq_equal(&self.mpq, &other.mpq) != 0 }
    }
}

impl Ord for Mpq {
    fn cmp(&self, other: &Mpq) -> Ordering {
        let cmp = unsafe { __gmpq_cmp(&self.mpq, &other.mpq) };
        if cmp == 0 {
            Equal
        } else if cmp < 0 {
            Less
        } else {
            Greater
        }
    }
}
impl PartialOrd for Mpq {
    fn partial_cmp(&self, other: &Mpq) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

macro_rules! div_guard {
    (Div, $what: expr) => {
        if $what.is_zero() {
            panic!("divide by zero")
        }
    };
    ($tr: ident, $what: expr) => {}
}

macro_rules! impl_oper {
    ($tr: ident, $meth: ident, $tr_assign: ident, $meth_assign: ident, $fun: ident) => {
        impl $tr<Mpq> for Mpq {
            type Output = Mpq;
            #[inline]
            fn $meth(self, other: Mpq) -> Mpq {
                self.$meth(&other)
            }
        }

        impl<'a> $tr<&'a Mpq> for Mpq {
            type Output = Mpq;
            #[inline]
            fn $meth(mut self, other: &Mpq) -> Mpq {
                self.$meth_assign(other);
                self
            }
        }

        impl<'a> $tr<Mpq> for &'a Mpq {
            type Output = Mpq;
            #[inline]
            fn $meth(self, mut other: Mpq) -> Mpq {
                unsafe {
                    div_guard!($tr, other);
                    $fun(&mut other.mpq, &self.mpq, &other.mpq);
                    other
                }
            }
        }

        impl<'a, 'b> $tr<&'a Mpq> for &'b Mpq {
            type Output = Mpq;
            fn $meth(self, other: &Mpq) -> Mpq {
                unsafe {
                    div_guard!($tr, *other);
                    let mut res = Mpq::new();
                    $fun(&mut res.mpq, &self.mpq, &other.mpq);
                    res
                }
            }
        }

        impl<'a> $tr_assign<Mpq> for Mpq {
            #[inline]
            fn $meth_assign(&mut self, other: Mpq) {
                self.$meth_assign(&other)
            }
        }

        impl<'a> $tr_assign<&'a Mpq> for Mpq {
            #[inline]
            fn $meth_assign(&mut self, other: &Mpq) {
                unsafe {
                    div_guard!($tr, *other);
                    $fun(&mut self.mpq, &self.mpq, &other.mpq)
                }
            }
        }
    }
}

impl_oper!(Add, add, AddAssign, add_assign, __gmpq_add);
impl_oper!(Sub, sub, SubAssign, sub_assign, __gmpq_sub);
impl_oper!(Mul, mul, MulAssign, mul_assign, __gmpq_mul);
impl_oper!(Div, div, DivAssign, div_assign, __gmpq_div);

impl<'b> Neg for &'b Mpq {
    type Output = Mpq;
    fn neg(self) -> Mpq {
        unsafe {
            let mut res = Mpq::new();
            __gmpq_neg(&mut res.mpq, &self.mpq);
            res
        }
    }
}

impl Neg for Mpq {
    type Output = Mpq;
    #[inline]
    fn neg(mut self) -> Mpq {
        unsafe {
            __gmpq_neg(&mut self.mpq, &self.mpq);
            self
        }
    }
}

impl Into<Option<i64>> for Mpq {
    fn into(self) -> Option<i64> {
        panic!("not implemented")
    }
}

impl Into<Option<u64>> for Mpq {
    fn into(self) -> Option<u64> {
        panic!("not implemented")
    }
}

impl Into<f64> for Mpq {
    fn into(self) -> f64 {
        unsafe {
            __gmpq_get_d(&self.mpq) as f64
        }
    }
}

impl From<Mpz> for Mpq {
    fn from(other: Mpz) -> Mpq {
        let mut res = Mpq::new();
        res.set_z(&other);
        res
    }
}

impl From<i64> for Mpq {
    fn from(other: i64) -> Mpq {
        From::<Mpz>::from(From::<i64>::from(other))
    }
}

impl From<i32> for Mpq {
    fn from(other: i32) -> Mpq {
        From::<Mpz>::from(From::<i32>::from(other))
    }
}

impl From<u64> for Mpq {
    fn from(other: u64) -> Mpq {
        From::<Mpz>::from(From::<u64>::from(other))
    }
}

impl From<u32> for Mpq {
    fn from(other: u32) -> Mpq {
        From::<Mpz>::from(From::<u32>::from(other))
    }
}

impl FromStr for Mpq {
    type Err = ParseMpqError;
    fn from_str(s: &str) -> Result<Mpq, ParseMpqError> {
        Mpq::from_str_radix(s, 10)
    }
}

impl fmt::Debug for Mpq {
    /// Renders as `numer/denom`. If denom=1, renders as numer.
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let numer = self.get_num();
        let denom = self.get_den();

        if denom == From::<i64>::from(1) {
            write!(f, "{}", numer)
        } else {
            write!(f, "{}/{}", numer, denom)
        }
    }
}
<|endoftext|>


<commit_before>#[allow(dead_code)]
#[allow(unused_variables)]
extern crate mmap;

use std::mem;
use std::ptr;
use std::fs::OpenOptions;
use std::os::unix::fs::OpenOptionsExt;
use mmap::{MemoryMap, MapOption};
use std::os::unix::prelude::AsRawFd;

const BCM2708_PERI_BASE: u32 = 0x20000000;
const GPIO_BASE: u32 = BCM2708_PERI_BASE + 0x200000;
const O_SYNC: u32 = 1052672;
const MAP_SHARED: i32 = 0x0001;
const BLOCK_SIZE: usize = (4*1024);
enum Void {} // void type

struct Bcm2835Peripheral {
    addr_p: u32,
    mem_fd: i32,
    map: *mut Void,
    addr: *mut i32
}

fn main() {
    unsafe {
        let gpio = Bcm2835Peripheral { addr_p: GPIO_BASE, mem_fd: 0, map: mem::uninitialized(), addr: ptr::null_mut()};
        map_peripheral(gpio);
    }
}

fn map_peripheral(foo: Bcm2835Peripheral) {
    let file = OpenOptions::new()
                    .read(true)
                    .write(true)
                    .mode(O_SYNC)
                    .open("/dev/mem")
                    .expect("Unable to open /dev/mem/, Are you root?");

    let map_opts = &[
        MapOption::MapNonStandardFlags(MAP_SHARED),
        MapOption::MapReadable,
        MapOption::MapWritable,
        MapOption::MapFd(file.as_raw_fd())
    ];

    let memmap = MemoryMap::new(BLOCK_SIZE, map_opts).unwrap();

}
<commit_msg>Remove Void Type<commit_after>#[allow(dead_code)]
#[allow(unused_variables)]
extern crate mmap;

use std::mem;
use std::ptr;
use std::fs::OpenOptions;
use std::os::unix::fs::OpenOptionsExt;
use mmap::{MemoryMap, MapOption};
use std::os::unix::prelude::AsRawFd;

const BCM2708_PERI_BASE: u32 = 0x20000000;
const GPIO_BASE: u8 = (BCM2708_PERI_BASE + 0x200000) as u8;
const O_SYNC: u32 = 1052672;
const MAP_SHARED: i32 = 0x0001;
const BLOCK_SIZE: usize = (4*1024);

struct Bcm2835Peripheral {
    addr_p: *const u8,
    mem_fd: i32,
    map: mmap::MemoryMap,
    addr: *mut i32
}

fn main() {
    unsafe {
        let gpio = Bcm2835Peripheral { addr_p: &GPIO_BASE, mem_fd: 0, map: MemoryMap::new(1024, &[]).unwrap(), addr: ptr::null_mut()};
        map_peripheral(gpio);
    }
}

fn map_peripheral(mut foo: Bcm2835Peripheral) {
    let file = OpenOptions::new()
                    .read(true)
                    .write(true)
                    .mode(O_SYNC)
                    .open("/dev/mem")
                    .expect("Unable to open /dev/mem/, Are you root?");

    let map_opts = &[
        MapOption::MapNonStandardFlags(MAP_SHARED),
        MapOption::MapReadable,
        MapOption::MapWritable,
       // MapOption::MapAddr(foo.addr_p),
        MapOption::MapFd(file.as_raw_fd())
    ];

   let mmap = MemoryMap::new(BLOCK_SIZE, map_opts).expect("Unable to MemoryMap");
   foo.map = mmap;
}
<|endoftext|>


<commit_before>use serde::Deserialize;
use serde::Serialize;
use serde_json;
use std::collections::BTreeMap;
use super::Result;

/// represents an general jira error response
#[derive(Deserialize, Debug)]
pub struct Errors {
    #[serde(rename = "errorMessages")]
    pub error_messages: Vec<String>,
    pub errors: BTreeMap<String, String>,
}

/// represents a single jira issue
#[derive(Deserialize, Debug)]
pub struct Issue {
    #[serde(rename = "self")]
    pub self_link: String,
    pub key: String,
    pub id: u64,
    //    pub expand: String,
    pub fields: BTreeMap<String, ::serde_json::Value>,
}

impl Issue {
    /// resolves a typed field from an issues lists of arbitrary fields
    pub fn field<'a, F>(&self, name: &str) -> Option<Result<F>>
    where
        for<'de> F: Deserialize<'de>,
    //where
    //    F: Deserialize<'a>,
    {
        self.fields.get(name).map(|value| {
            let decoded = try!(serde_json::value::from_value::<F>(value.clone()));
            Ok(decoded)
        })
    }

    fn user_field(&self, name: &str) -> Option<Result<User>> {
        self.field::<User>(name)
    }

    fn string_field(&self, name: &str) -> Option<Result<String>> {
        self.field::<String>(name)
    }

    /// user assigned to issue
    pub fn assignee(&self) -> Option<User> {
        self.user_field("assignee").and_then(|value| value.ok())
    }

    /// user that created the issue
    pub fn creator(&self) -> Option<User> {
        self.user_field("creator").and_then(|value| value.ok())
    }

    /// user that reported the issue
    pub fn reporter(&self) -> Option<User> {
        self.user_field("reporter").and_then(|value| value.ok())
    }

    /// the current status of the issue
    pub fn status(&self) -> Option<Status> {
        self.field::<Status>("status").and_then(|value| value.ok())
    }

    /// brief summary of the issue
    pub fn summary(&self) -> Option<String> {
        self.string_field("summary").and_then(|value| value.ok())
    }

    /// description of the issue
    pub fn description(&self) -> Option<String> {
        self.string_field("description").and_then(
            |value| value.ok(),
        )
    }

    /// updated timestamp
    pub fn updated(&self) -> Option<String> {
        self.string_field("updated").and_then(|value| value.ok())
    }

    /// created timestamp
    pub fn created(&self) -> Option<String> {
        self.string_field("created").and_then(|value| value.ok())
    }

    pub fn resolution_date(&self) -> Option<String> {
        self.string_field("resolution_date").and_then(
            |value| value.ok(),
        )
    }

    /// an issue type
    pub fn issue_type(&self) -> Option<IssueType> {
        self.field::<IssueType>("issuetype").and_then(
            |value| value.ok(),
        )
    }

    /// labels associated with the issue
    pub fn labels(&self) -> Vec<String> {
        self.field::<Vec<String>>("labels")
            .and_then(|value| value.ok())
            .unwrap_or(vec![])
    }

    /// list of versions associated with the issue
    pub fn fix_versions(&self) -> Vec<Version> {
        self.field::<Vec<Version>>("fixVersions")
            .and_then(|value| value.ok())
            .unwrap_or(vec![])
    }

    /// priority of the issue
    pub fn priority(&self) -> Option<Priority> {
        self.field::<Priority>("priority").and_then(
            |value| value.ok(),
        )
    }

    /// links to other issues
    pub fn links(&self) -> Option<Result<Vec<IssueLink>>> {
        self.field::<Vec<IssueLink>>("issuelinks") //.and_then(|value| value.ok()).unwrap_or(vec![])
    }

    pub fn project(&self) -> Option<Project> {
        self.field::<Project>("project").and_then(
            |value| value.ok(),
        )
    }

    pub fn resolution(&self) -> Option<Resolution> {
        self.field::<Resolution>("resolution").and_then(
            |value| value.ok(),
        )
    }
}

#[derive(Deserialize, Debug)]
pub struct Project {
    pub id: String,
    pub key: String,
    pub name: String,
}

/// represents link relationship between issues
#[derive(Deserialize, Debug)]
pub struct IssueLink {
    pub id: String,
    #[serde(rename = "self")]
    pub self_link: String,
    #[serde(rename = "outwardIssue")]
    pub outward_issue: Option<Issue>,
    #[serde(rename = "inwardIssue")]
    pub inward_issue: Option<Issue>,
    #[serde(rename = "type")]
    pub link_type: LinkType,
}

/// represents type of issue relation
#[derive(Deserialize, Debug)]
pub struct LinkType {
    pub id: String,
    pub inward: String,
    pub name: String,
    pub outward: String,
    #[serde(rename = "self")]
    pub self_link: String,
}

#[derive(Deserialize, Debug)]
pub struct Version {
    pub archived: bool,
    pub id: String,
    pub name: String,
    pub released: bool,
    #[serde(rename = "self")]
    pub self_link: String,
}

#[derive(Deserialize, Debug)]
pub struct User {
    pub active: bool,
    #[serde(rename = "avatarUrls")]
    pub avatar_urls: BTreeMap<String, String>,
    #[serde(rename = "displayName")]
    pub display_name: String,
    #[serde(rename = "emailAddress")]
    pub email_address: String,
    pub key: String,
    pub name: String,
    #[serde(rename = "self")]
    pub self_link: String,
    #[serde(rename = "timeZone")]
    pub timezone: String,
}

#[derive(Deserialize, Debug)]
pub struct Status {
    pub description: String,
    #[serde(rename = "iconUrl")]
    pub icon_url: String,
    pub id: String,
    pub name: String,
    #[serde(rename = "self")]
    pub self_link: String,
}

#[derive(Deserialize, Debug)]
pub struct Priority {
    pub icon_url: String,
    pub id: String,
    pub name: String,
    #[serde(rename = "self")]
    pub self_link: String,
}

#[derive(Deserialize, Debug)]
pub struct IssueType {
    pub description: String,
    #[serde(rename = "iconUrl")]
    pub icon_url: String,
    pub id: String,
    pub name: String,
    #[serde(rename = "self")]
    pub self_link: String,
    pub subtask: bool,
}

#[derive(Deserialize, Debug)]
pub struct SearchResults {
    pub total: u64,
    #[serde(rename = "maxResults")]
    pub max_results: u64,
    #[serde(rename = "startAt")]
    pub start_at: u64,
    pub expand: String,
    pub issues: Vec<Issue>,
}

#[derive(Deserialize, Debug)]
pub struct TransitionOption {
    pub id: String,
    pub name: String,
    pub to: TransitionTo,
}

#[derive(Deserialize, Debug)]
pub struct TransitionTo {
    pub name: String,
    pub id: String,
}

/// contains list of options an issue can transitions through
#[derive(Deserialize, Debug)]
pub struct TransitionOptions {
    pub transitions: Vec<TransitionOption>,
}

#[derive(Serialize, Debug)]
pub struct TransitionTriggerOptions {
    pub transition: Transition,
    pub fields: BTreeMap<String, ::serde_json::Value>,
}

impl TransitionTriggerOptions {
    /// creates a new instance
    pub fn new<I>(id: I) -> TransitionTriggerOptions
    where
        I: Into<String>,
    {
        TransitionTriggerOptions {
            transition: Transition { id: id.into() },
            fields: BTreeMap::new(),
        }
    }

    pub fn builder<I>(id: I) -> TransitionTriggerOptionsBuilder
    where
        I: Into<String>,
    {
        TransitionTriggerOptionsBuilder::new(id)
    }
}

pub struct TransitionTriggerOptionsBuilder {
    pub transition: Transition,
    pub fields: BTreeMap<String, ::serde_json::Value>,
}

impl TransitionTriggerOptionsBuilder {
    /// creates a new instance
    pub fn new<I>(id: I) -> TransitionTriggerOptionsBuilder
    where
        I: Into<String>,
    {
        TransitionTriggerOptionsBuilder {
            transition: Transition { id: id.into() },
            fields: BTreeMap::new(),
        }
    }

    /// appends a field to update as part of transition
    pub fn field<N, V>(&mut self, name: N, value: V) -> &mut TransitionTriggerOptionsBuilder
    where
        N: Into<String>,
        V: Serialize,
    {
        self.fields.insert(
            name.into(),
            serde_json::to_value(value).expect("Value to serialize"),
        );
        self
    }

    /// updates resolution in transition
    pub fn resolution<R>(&mut self, name: R) -> &mut TransitionTriggerOptionsBuilder
    where
        R: Into<String>,
    {
        self.field("resolution", Resolution { name: name.into() });
        self
    }

    pub fn build(&self) -> TransitionTriggerOptions {
        TransitionTriggerOptions {
            transition: self.transition.clone(),
            fields: self.fields.clone(),
        }
    }
}

#[derive(Serialize, Debug, Deserialize)]
pub struct Resolution {
    name: String,
}

#[derive(Serialize, Clone, Debug)]
pub struct Transition {
    pub id: String,
}
<commit_msg>Change issue id to String<commit_after>use serde::Deserialize;
use serde::Serialize;
use serde_json;
use std::collections::BTreeMap;
use super::Result;

/// represents an general jira error response
#[derive(Deserialize, Debug)]
pub struct Errors {
    #[serde(rename = "errorMessages")]
    pub error_messages: Vec<String>,
    pub errors: BTreeMap<String, String>,
}

/// represents a single jira issue
#[derive(Deserialize, Debug)]
pub struct Issue {
    #[serde(rename = "self")]
    pub self_link: String,
    pub key: String,
    pub id: String,
    //    pub expand: String,
    pub fields: BTreeMap<String, ::serde_json::Value>,
}

impl Issue {
    /// resolves a typed field from an issues lists of arbitrary fields
    pub fn field<'a, F>(&self, name: &str) -> Option<Result<F>>
    where
        for<'de> F: Deserialize<'de>,
    //where
    //    F: Deserialize<'a>,
    {
        self.fields.get(name).map(|value| {
            let decoded = try!(serde_json::value::from_value::<F>(value.clone()));
            Ok(decoded)
        })
    }

    fn user_field(&self, name: &str) -> Option<Result<User>> {
        self.field::<User>(name)
    }

    fn string_field(&self, name: &str) -> Option<Result<String>> {
        self.field::<String>(name)
    }

    /// user assigned to issue
    pub fn assignee(&self) -> Option<User> {
        self.user_field("assignee").and_then(|value| value.ok())
    }

    /// user that created the issue
    pub fn creator(&self) -> Option<User> {
        self.user_field("creator").and_then(|value| value.ok())
    }

    /// user that reported the issue
    pub fn reporter(&self) -> Option<User> {
        self.user_field("reporter").and_then(|value| value.ok())
    }

    /// the current status of the issue
    pub fn status(&self) -> Option<Status> {
        self.field::<Status>("status").and_then(|value| value.ok())
    }

    /// brief summary of the issue
    pub fn summary(&self) -> Option<String> {
        self.string_field("summary").and_then(|value| value.ok())
    }

    /// description of the issue
    pub fn description(&self) -> Option<String> {
        self.string_field("description").and_then(
            |value| value.ok(),
        )
    }

    /// updated timestamp
    pub fn updated(&self) -> Option<String> {
        self.string_field("updated").and_then(|value| value.ok())
    }

    /// created timestamp
    pub fn created(&self) -> Option<String> {
        self.string_field("created").and_then(|value| value.ok())
    }

    pub fn resolution_date(&self) -> Option<String> {
        self.string_field("resolution_date").and_then(
            |value| value.ok(),
        )
    }

    /// an issue type
    pub fn issue_type(&self) -> Option<IssueType> {
        self.field::<IssueType>("issuetype").and_then(
            |value| value.ok(),
        )
    }

    /// labels associated with the issue
    pub fn labels(&self) -> Vec<String> {
        self.field::<Vec<String>>("labels")
            .and_then(|value| value.ok())
            .unwrap_or(vec![])
    }

    /// list of versions associated with the issue
    pub fn fix_versions(&self) -> Vec<Version> {
        self.field::<Vec<Version>>("fixVersions")
            .and_then(|value| value.ok())
            .unwrap_or(vec![])
    }

    /// priority of the issue
    pub fn priority(&self) -> Option<Priority> {
        self.field::<Priority>("priority").and_then(
            |value| value.ok(),
        )
    }

    /// links to other issues
    pub fn links(&self) -> Option<Result<Vec<IssueLink>>> {
        self.field::<Vec<IssueLink>>("issuelinks") //.and_then(|value| value.ok()).unwrap_or(vec![])
    }

    pub fn project(&self) -> Option<Project> {
        self.field::<Project>("project").and_then(
            |value| value.ok(),
        )
    }

    pub fn resolution(&self) -> Option<Resolution> {
        self.field::<Resolution>("resolution").and_then(
            |value| value.ok(),
        )
    }
}

#[derive(Deserialize, Debug)]
pub struct Project {
    pub id: String,
    pub key: String,
    pub name: String,
}

/// represents link relationship between issues
#[derive(Deserialize, Debug)]
pub struct IssueLink {
    pub id: String,
    #[serde(rename = "self")]
    pub self_link: String,
    #[serde(rename = "outwardIssue")]
    pub outward_issue: Option<Issue>,
    #[serde(rename = "inwardIssue")]
    pub inward_issue: Option<Issue>,
    #[serde(rename = "type")]
    pub link_type: LinkType,
}

/// represents type of issue relation
#[derive(Deserialize, Debug)]
pub struct LinkType {
    pub id: String,
    pub inward: String,
    pub name: String,
    pub outward: String,
    #[serde(rename = "self")]
    pub self_link: String,
}

#[derive(Deserialize, Debug)]
pub struct Version {
    pub archived: bool,
    pub id: String,
    pub name: String,
    pub released: bool,
    #[serde(rename = "self")]
    pub self_link: String,
}

#[derive(Deserialize, Debug)]
pub struct User {
    pub active: bool,
    #[serde(rename = "avatarUrls")]
    pub avatar_urls: BTreeMap<String, String>,
    #[serde(rename = "displayName")]
    pub display_name: String,
    #[serde(rename = "emailAddress")]
    pub email_address: String,
    pub key: String,
    pub name: String,
    #[serde(rename = "self")]
    pub self_link: String,
    #[serde(rename = "timeZone")]
    pub timezone: String,
}

#[derive(Deserialize, Debug)]
pub struct Status {
    pub description: String,
    #[serde(rename = "iconUrl")]
    pub icon_url: String,
    pub id: String,
    pub name: String,
    #[serde(rename = "self")]
    pub self_link: String,
}

#[derive(Deserialize, Debug)]
pub struct Priority {
    pub icon_url: String,
    pub id: String,
    pub name: String,
    #[serde(rename = "self")]
    pub self_link: String,
}

#[derive(Deserialize, Debug)]
pub struct IssueType {
    pub description: String,
    #[serde(rename = "iconUrl")]
    pub icon_url: String,
    pub id: String,
    pub name: String,
    #[serde(rename = "self")]
    pub self_link: String,
    pub subtask: bool,
}

#[derive(Deserialize, Debug)]
pub struct SearchResults {
    pub total: u64,
    #[serde(rename = "maxResults")]
    pub max_results: u64,
    #[serde(rename = "startAt")]
    pub start_at: u64,
    pub expand: String,
    pub issues: Vec<Issue>,
}

#[derive(Deserialize, Debug)]
pub struct TransitionOption {
    pub id: String,
    pub name: String,
    pub to: TransitionTo,
}

#[derive(Deserialize, Debug)]
pub struct TransitionTo {
    pub name: String,
    pub id: String,
}

/// contains list of options an issue can transitions through
#[derive(Deserialize, Debug)]
pub struct TransitionOptions {
    pub transitions: Vec<TransitionOption>,
}

#[derive(Serialize, Debug)]
pub struct TransitionTriggerOptions {
    pub transition: Transition,
    pub fields: BTreeMap<String, ::serde_json::Value>,
}

impl TransitionTriggerOptions {
    /// creates a new instance
    pub fn new<I>(id: I) -> TransitionTriggerOptions
    where
        I: Into<String>,
    {
        TransitionTriggerOptions {
            transition: Transition { id: id.into() },
            fields: BTreeMap::new(),
        }
    }

    pub fn builder<I>(id: I) -> TransitionTriggerOptionsBuilder
    where
        I: Into<String>,
    {
        TransitionTriggerOptionsBuilder::new(id)
    }
}

pub struct TransitionTriggerOptionsBuilder {
    pub transition: Transition,
    pub fields: BTreeMap<String, ::serde_json::Value>,
}

impl TransitionTriggerOptionsBuilder {
    /// creates a new instance
    pub fn new<I>(id: I) -> TransitionTriggerOptionsBuilder
    where
        I: Into<String>,
    {
        TransitionTriggerOptionsBuilder {
            transition: Transition { id: id.into() },
            fields: BTreeMap::new(),
        }
    }

    /// appends a field to update as part of transition
    pub fn field<N, V>(&mut self, name: N, value: V) -> &mut TransitionTriggerOptionsBuilder
    where
        N: Into<String>,
        V: Serialize,
    {
        self.fields.insert(
            name.into(),
            serde_json::to_value(value).expect("Value to serialize"),
        );
        self
    }

    /// updates resolution in transition
    pub fn resolution<R>(&mut self, name: R) -> &mut TransitionTriggerOptionsBuilder
    where
        R: Into<String>,
    {
        self.field("resolution", Resolution { name: name.into() });
        self
    }

    pub fn build(&self) -> TransitionTriggerOptions {
        TransitionTriggerOptions {
            transition: self.transition.clone(),
            fields: self.fields.clone(),
        }
    }
}

#[derive(Serialize, Debug, Deserialize)]
pub struct Resolution {
    name: String,
}

#[derive(Serialize, Clone, Debug)]
pub struct Transition {
    pub id: String,
}
<|endoftext|>