<commit_before>use ber;
use ber::error::ASN1Error as Error;

use std::io;
use std::io::Write;

use byteorder::BigEndian;
use byteorder::WriteBytesExt;

use ber::common::{self, Tag};

pub struct Encoder<W>
{
    buf: W,
}

impl<W: io::Write> Encoder<W>
{
    pub fn from_writer(wtr: W) -> Encoder<io::BufWriter<W>>
    {
        Encoder::from_writer_raw(io::BufWriter::new(wtr))
    }

    pub fn from_writer_raw(wtr: W) -> Encoder<W>
    {
        Encoder
        {
            buf: wtr,
        }
    }

    pub fn flush(&mut self) -> ber::Result<()>
    {
        try!(self.buf.flush());

        Ok(())
    }

    pub fn encode(&mut self, tag: &common::Tag) -> ber::Result<()>
    {
        try!(write_type(tag._type, &mut self.buf));
        try!(write_length(tag._length, &mut self.buf));
        try!(write_value(&tag._value, &mut self.buf));

        Ok(())
    }
}

fn write(tag: &common::Tag, mut w: &mut Write) -> ber::Result<()>
{
    try!(write_type(tag._type, w));
    try!(write_length(tag._length, w));
    try!(write_value(&tag._value, w));

    Ok(())
}

fn write_type(tagtype: common::Type, mut w: &mut Write) -> ber::Result<()>
{
    let class_number = match tagtype.class
    {
        common::Class::Universal(_) => common::ClassNumber::Universal,
        common::Class::Application(_) => common::ClassNumber::Application,
        common::Class::ContextSpecific(_) => common::ClassNumber::ContextSpecific,
        common::Class::Private(_) => common::ClassNumber::Private,
    };

    let mut extended_tag: Option<Vec<u8>> = None;

    let type_byte =
            // First two bits: Class
            (class_number as u8) << 6 |
            // Bit 6: Primitive/Constructed
            (tagtype.structure as u8) << 5 |
            // Bit 5-1: Tag Number
            match tagtype.class
            {
                // tag will never be bigger than 30 so this is ok
                common::Class::Universal(tag) => (tag as u8),
                common::Class::Application(tag) |
                common::Class::ContextSpecific(tag) |
                common::Class::Private(tag) =>
                {
                    if tag > 30
                    {
                        let mut tagbytes: Vec<u8> = Vec::new();

                        let mut tag = tag;
                        while tag > 0
                        {
                            let mut byte = (tag & 0x7F) as u8;

                            tag >>= 7;

                            tagbytes.push(byte);
                        }

                        extended_tag = Some(tagbytes);

                        // This means we need to set the 5 tag bits to 11111, so 31 or 0x1F
                        31
                    }
                    else
                    {
                        extended_tag = None;
                        (tag as u8)
                    }
                },
            }; // let type_byte

    try!(w.write_u8(type_byte));

    let mut written = 1;

    if let Some(mut ext_bytes) = extended_tag
    {
        for _ in 0..ext_bytes.len()-1
        {
            let mut byte = ext_bytes.pop().unwrap();

            // Set the first bit
            byte |= 0x80;

            w.write_u8(byte);
        }

        let byte = ext_bytes.pop().unwrap();
        w.write_u8(byte);
    }

    Ok(())
}

// Yes I know you could overflow the length in theory. But, do you have 2^64 bytes of memory?
fn write_length(mut length: u64, mut w: &mut Write) -> ber::Result<()>
{
    // Short form
    if length < 128
    {
        try!(w.write_u8(length as u8));

        Ok(())
    }
    // Long form
    else
    {
        let mut count = 0u8;
        let mut len = length;
        while {count += 1; len >>= 8; len > 0 }{}

        try!(w.write_u8(count | 0x80));
        w.write_uint::<BigEndian>(length, count as usize);

        Ok(())
    }
}

fn write_value(payload: &common::Payload, mut w: &mut Write) -> ber::Result<()>
{
    match *payload
    {
        common::Payload::Primitive(ref value) =>
        {
            try!(w.write_all(value));
            Ok(())
        },
        common::Payload::Constructed(ref tags) =>
        {
            for tag in tags
            {
                try!(write(tag, w));
            }
            Ok(())
        }
    }
}

#[cfg(test)]
mod test
{
    use super::*;
    use ber::common;
    use std::io::Cursor;

    use byteorder::WriteBytesExt;
    use byteorder::BigEndian;

    #[test]
    fn encode_simple_tag()
    {
        let mut payload: Vec<u8> = Vec::new();
        payload.write_i16::<BigEndian>(1616);

        let class = common::Class::Universal(common::UniversalTypes::Integer);
        let pl = common::Payload::Primitive(payload);

        let tag = common::construct(class, pl);

        let mut buf = Vec::<u8>::new();
        super::write(&tag, &mut buf).unwrap();

        println!("{:?}", buf);

        assert!(buf == vec![0x2, 0x2, 0x06, 0x50]);
    }

    #[test]
    fn encode_constructed_tag()
    {
        let child =
        {
            let class = common::Class::ContextSpecific(0);
            let pl = common::Payload::Primitive("Hello World!".to_string().into_bytes());

            common::construct(class, pl)
        };

        println!("{:?}", child);

        let parent =
        {
            let class = common::Class::Universal(common::UniversalTypes::Sequence);
            let pl = common::Payload::Constructed(vec![child]);

            common::construct(class, pl)
        };

        println!("{:?}", parent);

        let mut buf = Vec::<u8>::new();
        super::write(&parent, &mut buf);

        println!("{:?}", buf);

        assert!(buf == vec![48, 14, 128, 12, 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33])
    }

    #[test]
    fn encode_extended_type_tags()
    {

        let tag = {
            let class = common::Class::ContextSpecific(1000);
            let pl = common::Payload::Primitive("second".to_string().into_bytes());

            common::construct(class, pl)
        };

        let mut buf = Vec::<u8>::new();
        super::write(&tag, &mut buf);

        println!("{:?}", buf);

        assert!(buf == vec![0x9F,0x87,0x68,0x06,0x73,0x65,0x63,0x6F,0x6E,0x64]);
    }

    #[test]
    fn encode_long_length_tags()
    {
        let name =
        {
            let class = common::Class::ContextSpecific(0);
            let pl = common::Payload::Primitive("JustALongTag".to_string().into_bytes());

            common::construct(class, pl)
        };

        let value =
        {
            let class = common::Class::ContextSpecific(1);
            let pl = common::Payload::Primitive("JustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTag".to_string().into_bytes());

            common::construct(class, pl)
        };

        let seq =
        {
            let class = common::Class::Universal(common::UniversalTypes::Sequence);
            let pl = common::Payload::Constructed(vec![name, value]);

            common::construct(class, pl)
        };

        let mut buf = Vec::<u8>::new();
        super::write(&seq, &mut buf);

        println!("{:?}", buf);
        assert!(buf == vec![
            0x30, 0x82, 0x01, 0x01,
            0x80, 0x0C, 0x4A, 0x75,
            0x73, 0x74, 0x41, 0x4C,
            0x6F, 0x6E, 0x67, 0x54,
            0x61, 0x67, 0x81, 0x81,
            0xF0, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67,
        ]);
    }
}
<commit_msg>Add function to extract underlying reader<commit_after>use ber;
use ber::error::ASN1Error as Error;

use std::io;
use std::io::Write;

use byteorder::BigEndian;
use byteorder::WriteBytesExt;

use ber::common::{self, Tag};

pub struct Encoder<W>
{
    buf: W,
}

impl<W: io::Write> Encoder<W>
{
    pub fn from_writer(wtr: W) -> Encoder<io::BufWriter<W>>
    {
        Encoder::from_writer_raw(io::BufWriter::new(wtr))
    }

    pub fn from_writer_raw(wtr: W) -> Encoder<W>
    {
        Encoder
        {
            buf: wtr,
        }
    }

    pub fn flush(&mut self) -> ber::Result<()>
    {
        try!(self.buf.flush());

        Ok(())
    }

    pub fn encode(&mut self, tag: &common::Tag) -> ber::Result<()>
    {
        try!(write_type(tag._type, &mut self.buf));
        try!(write_length(tag._length, &mut self.buf));
        try!(write_value(&tag._value, &mut self.buf));

        Ok(())
    }

    pub fn into_writer(self) -> W
    {
        self.buf
    }
}

fn write(tag: &common::Tag, mut w: &mut Write) -> ber::Result<()>
{
    try!(write_type(tag._type, w));
    try!(write_length(tag._length, w));
    try!(write_value(&tag._value, w));

    Ok(())
}

fn write_type(tagtype: common::Type, mut w: &mut Write) -> ber::Result<()>
{
    let class_number = match tagtype.class
    {
        common::Class::Universal(_) => common::ClassNumber::Universal,
        common::Class::Application(_) => common::ClassNumber::Application,
        common::Class::ContextSpecific(_) => common::ClassNumber::ContextSpecific,
        common::Class::Private(_) => common::ClassNumber::Private,
    };

    let mut extended_tag: Option<Vec<u8>> = None;

    let type_byte =
            // First two bits: Class
            (class_number as u8) << 6 |
            // Bit 6: Primitive/Constructed
            (tagtype.structure as u8) << 5 |
            // Bit 5-1: Tag Number
            match tagtype.class
            {
                // tag will never be bigger than 30 so this is ok
                common::Class::Universal(tag) => (tag as u8),
                common::Class::Application(tag) |
                common::Class::ContextSpecific(tag) |
                common::Class::Private(tag) =>
                {
                    if tag > 30
                    {
                        let mut tagbytes: Vec<u8> = Vec::new();

                        let mut tag = tag;
                        while tag > 0
                        {
                            let mut byte = (tag & 0x7F) as u8;

                            tag >>= 7;

                            tagbytes.push(byte);
                        }

                        extended_tag = Some(tagbytes);

                        // This means we need to set the 5 tag bits to 11111, so 31 or 0x1F
                        31
                    }
                    else
                    {
                        extended_tag = None;
                        (tag as u8)
                    }
                },
            }; // let type_byte

    try!(w.write_u8(type_byte));

    let mut written = 1;

    if let Some(mut ext_bytes) = extended_tag
    {
        for _ in 0..ext_bytes.len()-1
        {
            let mut byte = ext_bytes.pop().unwrap();

            // Set the first bit
            byte |= 0x80;

            w.write_u8(byte);
        }

        let byte = ext_bytes.pop().unwrap();
        w.write_u8(byte);
    }

    Ok(())
}

// Yes I know you could overflow the length in theory. But, do you have 2^64 bytes of memory?
fn write_length(mut length: u64, mut w: &mut Write) -> ber::Result<()>
{
    // Short form
    if length < 128
    {
        try!(w.write_u8(length as u8));

        Ok(())
    }
    // Long form
    else
    {
        let mut count = 0u8;
        let mut len = length;
        while {count += 1; len >>= 8; len > 0 }{}

        try!(w.write_u8(count | 0x80));
        w.write_uint::<BigEndian>(length, count as usize);

        Ok(())
    }
}

fn write_value(payload: &common::Payload, mut w: &mut Write) -> ber::Result<()>
{
    match *payload
    {
        common::Payload::Primitive(ref value) =>
        {
            try!(w.write_all(value));
            Ok(())
        },
        common::Payload::Constructed(ref tags) =>
        {
            for tag in tags
            {
                try!(write(tag, w));
            }
            Ok(())
        }
    }
}

#[cfg(test)]
mod test
{
    use super::*;
    use ber::common;
    use std::io::Cursor;

    use byteorder::WriteBytesExt;
    use byteorder::BigEndian;

    #[test]
    fn encode_simple_tag()
    {
        let mut payload: Vec<u8> = Vec::new();
        payload.write_i16::<BigEndian>(1616);

        let class = common::Class::Universal(common::UniversalTypes::Integer);
        let pl = common::Payload::Primitive(payload);

        let tag = common::construct(class, pl);

        let mut buf = Vec::<u8>::new();
        super::write(&tag, &mut buf).unwrap();

        println!("{:?}", buf);

        assert!(buf == vec![0x2, 0x2, 0x06, 0x50]);
    }

    #[test]
    fn encode_constructed_tag()
    {
        let child =
        {
            let class = common::Class::ContextSpecific(0);
            let pl = common::Payload::Primitive("Hello World!".to_string().into_bytes());

            common::construct(class, pl)
        };

        println!("{:?}", child);

        let parent =
        {
            let class = common::Class::Universal(common::UniversalTypes::Sequence);
            let pl = common::Payload::Constructed(vec![child]);

            common::construct(class, pl)
        };

        println!("{:?}", parent);

        let mut buf = Vec::<u8>::new();
        super::write(&parent, &mut buf);

        println!("{:?}", buf);

        assert!(buf == vec![48, 14, 128, 12, 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33])
    }

    #[test]
    fn encode_extended_type_tags()
    {

        let tag = {
            let class = common::Class::ContextSpecific(1000);
            let pl = common::Payload::Primitive("second".to_string().into_bytes());

            common::construct(class, pl)
        };

        let mut buf = Vec::<u8>::new();
        super::write(&tag, &mut buf);

        println!("{:?}", buf);

        assert!(buf == vec![0x9F,0x87,0x68,0x06,0x73,0x65,0x63,0x6F,0x6E,0x64]);
    }

    #[test]
    fn encode_long_length_tags()
    {
        let name =
        {
            let class = common::Class::ContextSpecific(0);
            let pl = common::Payload::Primitive("JustALongTag".to_string().into_bytes());

            common::construct(class, pl)
        };

        let value =
        {
            let class = common::Class::ContextSpecific(1);
            let pl = common::Payload::Primitive("JustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTag".to_string().into_bytes());

            common::construct(class, pl)
        };

        let seq =
        {
            let class = common::Class::Universal(common::UniversalTypes::Sequence);
            let pl = common::Payload::Constructed(vec![name, value]);

            common::construct(class, pl)
        };

        let mut buf = Vec::<u8>::new();
        super::write(&seq, &mut buf);

        println!("{:?}", buf);
        assert!(buf == vec![
            0x30, 0x82, 0x01, 0x01,
            0x80, 0x0C, 0x4A, 0x75,
            0x73, 0x74, 0x41, 0x4C,
            0x6F, 0x6E, 0x67, 0x54,
            0x61, 0x67, 0x81, 0x81,
            0xF0, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67,
        ]);
    }
}
<|endoftext|>


<commit_before>extern crate pirate;
use pirate::{Matches, Match, Vars, matches, usage, vars};
use std::env;

fn main() {
  let options = vec![
    "#File-preserving commands",
    "g/get-value#Given a key or comma separated list of keys, retrieve the values for those keys. If multiple keys are \
      specified and any one of them fails to retrieve a value, the whole command will fail with an error message.:",
    "/has-value#Given a key or comma separated list of keys, print \"true\" if the key has a value and \"false\" if \
      the key doesn't have child keys. Optionally use the --set-true and --set-false flags to change what values are \
      printed instead of \"true\" and \"false\".:",
    "c/get-children#Given a key or comma separated list of keys, retrieve each key's set of child keys. If multiple \
      keys are specified and any one of them fails to retrieve a child keys, the whole command will fail with an error \
      message.:",
    "/has-children#Given a key or comma separated list of keys, print \"true\" if the key has child keys and \"false\" \
      if the key doesn't have child keys. Optionally use the --set-true and --set-false flags to change what values \
      are printed instead of \"true\" and \"false\".:",
    "#File-modifying commands",
    "s/set-value#Given a comma separated list of key followed by value followed by type, set the key's value to the \
      specified value. For instance: \"foo.bar,hello,basic-string,baz.qux,82374,int\" will set the key \"foo.bar\" to \
      a basic string value of \"hello\" and the key \"baz.qux\" to an integer value of 82374. If multiple keys are \
      specified and any one of them fails to set a value, the whole command will fail with an error message.:",
    "#Options.",
    "h/help#Show this screen.",
    "/set-true#For commands that print \"true\" or \"false\", this will change what value is printed for \"true\", \
      i.e. --set-true=1 will cause tomlkit to print \"1\" for \"true\" instead of \"true\".:",
    "/set-false#For commands that print \"true\" or \"false\", this will change what value is printed for \"false\", \
      i.e. --set-false=0 will cause tomlkit to print \"0\" for \"false\" instead of \"false\".:",
  ];

  let mut vars: Vars = match vars("tomlkit", &options) {
    Ok(v) => v,
    Err(e) => panic!("There was an error parsing argument definitions: {}", e)
  };

  let args: Vec<String> = env::args().collect();
  let matches: Matches = match matches(&args, &mut vars) {
    Ok(m) => m,
    Err(e) => {
      println!("Error: {}", e);
      usage(&vars);
      return;
    }
  };

  if matches.has_match("help") {
    usage(&vars);
    return;
  }

  // Switch statement
  if matches.has_match("get-value") {
    println!("You requested get-value: {}", matches.get("get-value").unwrap());
  } else if matches.has_match("has-value") {
    println!("You requested has-value: {}", matches.get("has-value").unwrap());
  } else if matches.has_match("get-children") {
    println!("You requested get-children: {}", matches.get("get-children").unwrap());
  } else if matches.has_match("has-children") {
    println!("You requested has-children: {}", matches.get("has-children").unwrap());
  } else if matches.has_match("set-value") {
    println!("You requested set-value: {}", matches.get("set-value").unwrap());
  } else if matches.has_match("set-true") {
    println!("You requested set-true: {}", matches.get("set-true").unwrap());
  } else if matches.has_match("set-false") {
    println!("You requested set-false: {}", matches.get("set-false").unwrap());
  } else {
    // No command specified print usage
    usage(&vars);
  }
}
<commit_msg>Added a print-doc command, added and implemnted a file argument since pirate doesn't have positional arguments. Implemented the get_file function. Added all other stub methods.<commit_after>extern crate pirate;
extern crate tomllib;
use std::fs::File;
use std::env;
use std::io::{Read, BufReader, Error};
use pirate::{Matches, Match, Vars, matches, usage, vars};
use tomllib::TOMLParser;
use tomllib::types::ParseResult;

fn main() {
  let options = vec![
    "Required arguments",
    "f/file#The path to the TOML document to parse and manipulate.:",
    "#File-preserving commands",
    "g/get-value#Given a key or comma separated list of keys, retrieve the values for those keys. If multiple keys are \
      specified and any one of them fails to retrieve a value, the whole command will fail with an error message.:",
    "/has-value#Given a key or comma separated list of keys, print \"true\" if the key has a value and \"false\" if \
      the key doesn't have child keys. Optionally use the --set-true and --set-false flags to change what values are \
      printed instead of \"true\" and \"false\".:",
    "c/get-children#Given a key or comma separated list of keys, retrieve each key's set of child keys. If multiple \
      keys are specified and any one of them fails to retrieve a child keys, the whole command will fail with an error \
      message.:",
    "/has-children#Given a key or comma separated list of keys, print \"true\" if the key has child keys and \"false\" \
      if the key doesn't have child keys. Optionally use the --set-true and --set-false flags to change what values \
      are printed instead of \"true\" and \"false\".:",
    "#File-modifying commands",
    "s/set-value#Given a comma separated list of key followed by value followed by type, set the key's value to the \
      specified value. For instance: \"foo.bar,hello,basic-string,baz.qux,82374,int\" will set the key \"foo.bar\" to \
      a basic string value of \"hello\" and the key \"baz.qux\" to an integer value of 82374. If multiple keys are \
      specified and any one of them fails to set a value, the whole command will fail with an error message.:",
    "#Pre-command Options.",
    "h/help#Show this screen.",
    "/set-true#For commands that print \"true\" or \"false\", this will change what value is printed for \"true\", \
      i.e. --set-true=1 will cause tomlkit to print \"1\" for \"true\" instead of \"true\".:",
    "/set-false#For commands that print \"true\" or \"false\", this will change what value is printed for \"false\", \
      i.e. --set-false=0 will cause tomlkit to print \"0\" for \"false\" instead of \"false\".:",
    "#Post-command Options.",
    "/print-doc#Print out the resultant TOML document after all requested changes have been made.",
  ];

  let mut vars: Vars = match vars("tomlkit", &options) {
    Ok(v) => v,
    Err(e) => panic!("There was an error parsing argument definitions: {}", e)
  };

  let args: Vec<String> = env::args().collect();
  let matches: Matches = match matches(&args, &mut vars) {
    Ok(m) => m,
    Err(e) => {
      println!("Error: {}", e);
      usage(&vars);
      return;
    }
  };

  if matches.has_match("help") {
    usage(&vars);
    return;
  }
  let mut true_val = &"true".to_string();
  let mut false_val = &"false".to_string();
  let mut output: String = "".to_string();

  // The file we're operating on
  let mut file = String::new();
  if matches.has_match("file") {
    if let Some(f) = matches.get("file") {
      match get_file(f, &mut file) {
        Err(err) => {
          println!("Error: Unable to read file: \"{}\". Reason: {}", f, err);
          return;
        },
        _ => ()
      }
    } else {
      println!("Error: A required argument is missing for f/file.");
      usage(&vars);
    }
  } else

  // Pre-command options
  if matches.has_match("set-true") {
    if let Some(t) = matches.get("set-true") {
      true_val = t;
    } else {
      println!("Error: A required argument is missing for set-true.");
      usage(&vars);
    }
  } else if matches.has_match("set-false") {
    if let Some(f) = matches.get("set-false") {
      false_val = f;
    } else {
      println!("Error: A required argument is missing for set-false.");
      usage(&vars);
    }
  }

  // Commands only one command allowed per invocation for this version
  if matches.has_match("get-value") {
    if let Some(k) = matches.get("get-value") {
      output = get_value(k);
    } else {
      println!("Error: A required argument is missing for g/get-value.");
      usage(&vars);
    }
  } else if matches.has_match("has-value") {
    if let Some(k) = matches.get("has-value") {
      output = has_value(k, true_val, false_val);
    } else {
      println!("Error: A required argument is missing for has-value.");
      usage(&vars);
    }
  } else if matches.has_match("get-children") {
    if let Some(v) = matches.get("get-children") {
      output = get_children(v);
    } else {
      println!("Error: A required argument is missing for c/get-children.");
      usage(&vars);
    }
  } else if matches.has_match("has-children") {
    if let Some(k) = matches.get("has-children") {
      output = has_children(k, true_val, false_val);
    } else {
      println!("Error: A required argument is missing for has-children.");
      usage(&vars);
    }
  } else if matches.has_match("set-value") {
    if let Some(kv) = matches.get("set-value") {
      output = set_value(kv);
    } else {
      println!("Error: A required argument is missing for s/set-value.");
      usage(&vars);
    }
  } else {
    // No command specified print usage
    usage(&vars);
    return;
  }

  // Post-command options
  if matches.has_match("print-doc") {
    print_doc(&output);
  }
}

fn get_file(file_path: &String, out_file: &mut String) -> Result<usize, Error> {
  match File::open(file_path) {
    Ok(file) => {
      let mut contents = BufReader::new(&file);
      match contents.read_to_string(out_file) {
        Ok(bytes) => return Ok(bytes),
        Err(err) => return Err(err),
      }
    },
    Err(err) => return Err(err),
  }
}

fn get_value(key: &String) -> String {
  unimplemented!();
}

fn has_value(key: &String, true_val: &String, false_val: &String) -> String {
  unimplemented!();
}

fn get_children(key: &String) -> String {
  unimplemented!();
}

fn has_children(key: &String, true_val: &String, false_val: &String) -> String {
  unimplemented!();
}

fn set_value(key: &String) -> String {
  unimplemented!();
}

fn print_doc(doc: &String) {
  unimplemented!();
}
<|endoftext|>


<commit_before>use std::io::{BufRead, Seek, SeekFrom};

use types::Result;
use utils::{ReadExt, ByteOrder, ByteOrderReadExt};

pub struct TiffReader<R: BufRead + Seek> {
    source: R
}

impl<R: BufRead + Seek> TiffReader<R> {
    pub fn new(source: R) -> TiffReader<R> {
        TiffReader {
            source: source
        }
    }

    pub fn ifds(&mut self) -> Result<Ifds<R>> {
        let mut bom = [0u8; 2];
        try_if_eof!(std, self.source.read_exact(&mut bom), "while reading byte order mark");

        let byte_order = match &bom {
            b"II" => ByteOrder::Little,
            b"MM" => ByteOrder::Big,
            _ => return Err(invalid_format!("invalid TIFF BOM: {:?}", bom))
        };

        let magic = try_if_eof!(
            self.source.read_u16(byte_order),
            "when reading magic number"
        );
        if magic != 42 {
            return Err(invalid_format!("invalid TIFF magic number: {}", magic));
        }

        Ok(Ifds {
            source: &mut self.source,
            byte_order: byte_order,
            next_ifd_offset: 4,
        })
    }
}

pub struct Ifds<'a, R: BufRead + Seek + 'a> {
    source: &'a mut R,
    byte_order: ByteOrder,
    next_ifd_offset: u32,
}

impl<'a, R: BufRead + Seek> Iterator for Ifds<'a, R> {
    type Item = Result<Ifd<'a, R>>;

    fn next(&mut self) -> Option<Result<Ifd<'a, R>>> {
        match self.read_ifd() {
            Err(e) => Some(Err(e)),
            Ok(Some(value)) => Some(Ok(value)),
            Ok(None) => None,
        }
    }
}

impl<'a, R: BufRead + Seek> Ifds<'a, R> {
    fn read_ifd(&mut self) -> Result<Option<Ifd<'a, R>>> {
        if self.next_ifd_offset == 0 {
            return Ok(None);
        }

        let next_ifd_size = try_if_eof!(
            self.source.read_u16(self.byte_order), "when reading number of entries in an IFD"
        ) as u32;
        if next_ifd_size == 0 {
            return Err(invalid_format!("number of entries in an IFD is zero"));
        }

        // compute the offset of the next IFD offset
        let next_ifd_offset_offset = self.next_ifd_offset + 2 + next_ifd_size * 12;

        try_if_eof!(std,
            self.source.seek(SeekFrom::Start(next_ifd_offset_offset as u64)),
            "when seeking to the next IFD offset"
        );

        let current_ifd_offset = self.next_ifd_offset;
        self.next_ifd_offset = try_if_eof!(
            self.source.read_u16(self.byte_order), "when reading the next IFD offset"
        ) as u32;

        try!(self.source.seek(SeekFrom::Start(current_ifd_offset as u64)));

        // now we're at the first IFD entry
        Ok(Some(Ifd(self.source, self.byte_order)))
    }
}

pub struct Ifd<'a, R: BufRead + Seek + 'a>(&'a mut R, ByteOrder);
<commit_msg>More implementation in TIFF reader<commit_after>use std::io::{Read, BufRead, Seek, SeekFrom};
use std::cell::{RefCell, Cell};
use std::marker::PhantomData;

use types::Result;
use utils::{ReadExt, ByteOrder, ByteOrderReadExt};

pub struct TiffReader<R: BufRead + Seek> {
    source: R
}

impl<R: BufRead + Seek> TiffReader<R> {
    pub fn new(source: R) -> TiffReader<R> {
        TiffReader {
            source: source
        }
    }

    pub fn ifds(mut self) -> Result<LazyIfds<R>> {
        let mut bom = [0u8; 2];
        try_if_eof!(std, self.source.read_exact(&mut bom), "while reading byte order mark");

        let byte_order = match &bom {
            b"II" => ByteOrder::Little,
            b"MM" => ByteOrder::Big,
            _ => return Err(invalid_format!("invalid TIFF BOM: {:?}", bom))
        };

        let magic = try_if_eof!(
            self.source.read_u16(byte_order),
            "when reading TIFF magic number"
        );
        if magic != 42 {
            return Err(invalid_format!("invalid TIFF magic number: {}", magic));
        }

        Ok(LazyIfds {
            source: RefCell::new(self.source),
            byte_order: byte_order,
            next_ifd_offset: Cell::new(4),
        })
    }
}

pub struct LazyIfds<R: BufRead + Seek> {
    source: RefCell<R>,
    byte_order: ByteOrder,
    next_ifd_offset: Cell<u64>,
}

impl<'a, R: BufRead + Seek> IntoIterator for &'a LazyIfds<R> {
    type Item = Result<Ifd<'a, R>>;
    type IntoIter = Ifds<'a, R>;

    fn into_iter(self) -> Ifds<'a, R> {
        Ifds(self)
    }
}

pub struct Ifds<'a, R: BufRead + Seek + 'a>(&'a LazyIfds<R>);

impl<'a, R: BufRead + Seek + 'a> Iterator for Ifds<'a, R> {
    type Item = Result<Ifd<'a, R>>;

    fn next(&mut self) -> Option<Result<Ifd<'a, R>>> {
        match self.read_ifd() {
            Err(e) => Some(Err(e)),
            Ok(Some(value)) => Some(Ok(value)),
            Ok(None) => None,
        }
    }
}

impl<'a, R: BufRead + Seek> Ifds<'a, R> {
    fn read_ifd(&mut self) -> Result<Option<Ifd<'a, R>>> {
        let next_ifd_offset = self.0.next_ifd_offset.get();

        // next ifd offset is only zero in the last entry of a TIFF document
        if next_ifd_offset == 0 {
            return Ok(None);
        }

        // seek to the beginning of the next IFD
        try_if_eof!(std,
            self.0.source.borrow_mut().seek(SeekFrom::Start(next_ifd_offset as u64)),
            "when seeking to the beginning of the next IFD"
        );
        let current_ifd_offset = next_ifd_offset;

        // read the length of this IFD
        let next_ifd_size = try_if_eof!(
            self.0.source.borrow_mut().read_u16(self.0.byte_order), "when reading number of entries in an IFD"
        );
        // it is an error for an IFD to be empty
        if next_ifd_size == 0 {
            return Err(invalid_format!("number of entries in an IFD is zero"));
        }

        // compute the offset of the next IFD offset and seek to it
        let next_ifd_offset_offset = current_ifd_offset + 2 + next_ifd_size as u64 * 12;
        try_if_eof!(std,
            self.0.source.borrow_mut().seek(SeekFrom::Start(next_ifd_offset_offset as u64)),
            "when seeking to the next IFD offset"
        );

        // read and update the next IFD offset for further calls to `next()`
        self.0.next_ifd_offset.set(try_if_eof!(
            self.0.source.borrow_mut().read_u16(self.0.byte_order), "when reading the next IFD offset"
        ) as u64);

        Ok(Some(Ifd {
            ifds: self.0,
            ifd_offset: current_ifd_offset,
            current_entry: 0,
            total_entries: next_ifd_size,
        }))
    }
}

pub struct Ifd<'a, R: BufRead + Seek + 'a> {
    ifds: &'a LazyIfds<R>,
    ifd_offset: u64,
    current_entry: u16,
    total_entries: u16,
}

impl<'a, R: BufRead + Seek + 'a> Iterator for Ifd<'a, R> {
    type Item = Result<Entry<'a, R>>;

    fn next(&mut self) -> Option<Result<Entry<'a, R>>> {
        if self.current_entry == self.total_entries {
            None
        } else {
            Some(self.read_entry())
        }
    }
}

impl<'a, R: BufRead + Seek + 'a> Ifd<'a, R> {
    fn read_entry(&mut self) -> Result<Entry<'a, R>> {
        let mut source = self.ifds.source.borrow_mut();

        // seek to the beginning of the next entry (ifd offset + 2 + next_entry * 12)
        try!(source.seek(SeekFrom::Start(self.ifd_offset + 2 + self.current_entry as u64 * 12)));

        let tag = try_if_eof!(
            source.read_u16(self.ifds.byte_order), "when reading TIFF IFD entry tag"
        );

        let entry_type = try_if_eof!(
            source.read_u16(self.ifds.byte_order), "when reading TIFF IFD entry type"
        );

        let count = try_if_eof!(
            source.read_u32(self.ifds.byte_order), "when reading TIFF IFD entry data count"
        );

        let offset = try_if_eof!(
            source.read_u32(self.ifds.byte_order), "when reading TIFF IFD offset value"
        );

        self.current_entry += 1;

        Ok(Entry {
            ifds: self.ifds,
            tag: tag,
            entry_type: EntryType::Byte,
            count: 0,
            offset: offset,
        })
    }
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum EntryType {
    Byte,
    Ascii,
    Short,
    Long,
    Rational,
    SignedByte,
    Undefined,
    SignedShort,
    SignedLong,
    SignedRational,
    Float,
    Double,
    Unknown(u16),
}

impl From<u16> for EntryType {
    fn from(n: u16) -> EntryType {
        match n {
            1  => EntryType::Byte,
            2  => EntryType::Ascii,
            3  => EntryType::Short,
            4  => EntryType::Long,
            5  => EntryType::Rational,
            6  => EntryType::SignedByte,
            7  => EntryType::Undefined,
            8  => EntryType::SignedShort,
            9  => EntryType::SignedLong,
            10 => EntryType::SignedRational,
            11 => EntryType::Float,
            12 => EntryType::Double,
            n  => EntryType::Unknown(n),
        }
    }
}

impl EntryType {
    pub fn size(self) -> Option<u8> {
        match self {
            EntryType::Byte           => Some(1),
            EntryType::Ascii          => Some(1),
            EntryType::Short          => Some(2),
            EntryType::Long           => Some(4),
            EntryType::Rational       => Some(8),
            EntryType::SignedByte     => Some(1),
            EntryType::Undefined      => Some(1),
            EntryType::SignedShort    => Some(2),
            EntryType::SignedLong     => Some(4),
            EntryType::SignedRational => Some(4),
            EntryType::Float          => Some(4),
            EntryType::Double         => Some(8),
            EntryType::Unknown(n)     => None,
        }
    }
}

pub struct Entry<'a, R: BufRead + Seek + 'a> {
    ifds: &'a LazyIfds<R>,
    tag: u16,
    entry_type: EntryType,
    count: u32,
    offset: u32,
}

impl<'a, R: BufRead + Seek + 'a> Entry<'a, R> {
    #[inline]
    pub fn tag(&self) -> u16 {
        self.tag
    }

    #[inline]
    pub fn entry_type(&self) -> EntryType {
        self.entry_type
    }

    #[inline]
    pub fn count(&self) -> u32 {
        self.count
    }

    #[inline]
    pub fn values<T: EntryTypeRepr>(&self) -> Option<EntryValues<'a, T, R>> {
        if self.entry_type == T::entry_type() {
            Some(EntryValues {
                ifds: self.ifds,
                entry_type: self.entry_type,
                count: self.count,
                offset: self.offset,
                _entry_type_repr: PhantomData,
            })
        } else {
            None
        }
    }

    #[inline]
    pub fn values_vec<T: EntryTypeRepr>(&self) -> Option<Result<Vec<T::Repr>>> {
        unimplemented!()
    }
}

pub mod entry_types {
    use std::io::Read;

    use byteorder;

    use super::{EntryType, EntryTypeRepr};
    use utils::{ByteOrder, ByteOrderReadExt};
    use types::Result;

    macro_rules! gen_entry_types {
        ($($tpe:ident, $repr:ty, |$source:pat, $byte_order:pat| $read:expr);+) => {
            $(
                pub enum $tpe {}

                impl EntryTypeRepr for $tpe {
                    type Repr = $repr;

                    #[inline]
                    fn entry_type() -> EntryType {
                        EntryType::$tpe
                    }

                    fn read_from<R: Read>($source: &mut R, $byte_order: ByteOrder) -> Result<$repr> {
                        $read.map_err(From::from)
                    }
                }
            )+
        }
    }

    gen_entry_types! {
        Byte, u8,
            |source, _| byteorder::ReadBytesExt::read_u8(source);
        Ascii, String, |source, _| {
            let mut s = String::new();
            loop {
                let mut b = try!(byteorder::ReadBytesExt::read_u8(source));
                if b == 0 { break; }
                s.push(b as char);
            }
            Ok::<String, byteorder::Error>(s)
        };
        Short, u16, |source, byte_order| source.read_u16(byte_order);
        Long, u32, |source, byte_order| source.read_u32(byte_order);
        Rational, (u32, u32), |source, byte_order|
            source.read_u32(byte_order)
                .and_then(|n| source.read_u32(byte_order).map(|d| (n, d)));
        SignedByte, i8, |source, _| byteorder::ReadBytesExt::read_i8(source);
        Undefined, u8, |source, _| byteorder::ReadBytesExt::read_u8(source);
        SignedShort, i16, |source, byte_order| source.read_i16(byte_order);
        SignedLong, i32, |source, byte_order| source.read_i32(byte_order);
        SignedRational, (i32, i32), |source, byte_order|
            source.read_i32(byte_order)
                .and_then(|n| source.read_i32(byte_order).map(|d| (n, d)));
        Float, f32, |source, byte_order| source.read_f32(byte_order);
        Double, f64, |source, byte_order| source.read_f64(byte_order)
    }
}

pub trait EntryTypeRepr {
    type Repr;
    fn entry_type() -> EntryType;
    fn read_from<R: Read>(source: &mut R, byte_order: ByteOrder) -> Result<Self::Repr>;
    fn read_many_from<R: Read>(source: &mut R, byte_order: ByteOrder, n: u32, target: Vec<Self::Repr>) -> Result<()>;
}

pub struct EntryValues<'a, T: EntryTypeRepr, R: BufRead + Seek + 'a> {
    ifds: &'a LazyIfds<R>,
    entry_type: EntryType,
    count: u32,
    offset: u32,
    _entry_type_repr: PhantomData<T>,
}

//impl<'a, R: BufRead + Seek + 'a> Iterator for EntryValues<'a, R> {
    //type Item =
//}

<|endoftext|>


<commit_before>#![cfg_attr(feature = "cargo-clippy", allow(forget_copy))]

use super::errors::{Result, Error, ResultExt};
use super::system::System;
use super::window::Window;
use glium::{Blend, Surface, VertexBuffer};
use glium::{DrawParameters, Program};
use glium::Frame;
use glium::index::{NoIndices, PrimitiveType};
use glium::texture::{ClientFormat, RawImage2d, Texture2d};
use idcontain::{IdSlab, Id};
use math::Pnt2f;
use rusttype::{self, Font, FontCollection, Scale, PositionedGlyph, GlyphId, Point as FontPoint};
use std::borrow::Cow;
use std::fs::File;
use std::io::Read;
use std::ops::{Index, IndexMut};
use std::str::Chars as StrChars;
use unicode_normalization::{UnicodeNormalization, Recompositions};

/// A handle to a piece of text created with a `TextRenderer`.
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct TextId(Id<Text>);

/// Handles rendering of debug text to `OpenGL`.
pub struct TextRenderer {
    font: Font<'static>,
    slab: IdSlab<Text>,
    program: Program,
    draw_params: DrawParameters<'static>,
    pixel_buffer: Vec<u16>,
}

impl TextRenderer {
    pub fn new(window: &Window) -> Result<Self> {
        let mut font_bytes = Vec::with_capacity(1024 * 1024); // 1MB
        File::open(FONT_PATH)
            .and_then(|mut file| file.read_to_end(&mut font_bytes))
            .chain_err(|| format!("Failed to read font at {:?}.", FONT_PATH))?;
        Ok(TextRenderer {
            font: FontCollection::from_bytes(font_bytes)
                .font_at(0)
                .ok_or_else(|| format!("No fonts in {:?}.", FONT_PATH))?,
            slab: IdSlab::with_capacity(16),
            program: Program::from_source(window.facade(), VERTEX_SRC, FRAGMENT_SRC, None).unwrap(),
            draw_params: DrawParameters {
                blend: Blend::alpha_blending(),
                ..DrawParameters::default()
            },
            pixel_buffer: Vec::new(),
        })
    }

    pub fn insert(&mut self, win: &Window, text: &str, pos: Pnt2f, padding: u32) -> TextId {
        debug!("Creating text...");
        let (width, height) = self.rasterise(text, padding).unwrap();
        let texture = Texture2d::new(
            win.facade(),
            RawImage2d {
                data: Cow::Borrowed(&self.pixel_buffer),
                width,
                height,
                format: ClientFormat::U8U8,
            },
        ).unwrap();
        let (w, h) = (
            width as f32 / win.width() as f32 * 2.0,
            height as f32 / win.height() as f32 * 2.0,
        );
        let (x, y) = (pos.x * 2.0 - 1.0, 1.0 - pos.y * 2.0 - h);
        let text = Text {
            buffer: VertexBuffer::immutable(
                win.facade(),
                &[
                    vertex(x, y, 0.0, 1.0),
                    vertex(x, y + h, 0.0, 0.0),
                    vertex(x + w, y, 1.0, 1.0),
                    vertex(x + w, y + h, 1.0, 0.0),
                ],
            ).unwrap(),
            texture: texture,
            visible: true,
        };
        let id = self.slab.insert(text);
        debug!("Created text {:?}.", id);
        TextId(id)
    }

    pub fn remove(&mut self, id: TextId) -> bool {
        debug!("Removed text {:?}.", id.0);
        self.slab.remove(id.0).is_some()
    }

    pub fn text(&self, id: TextId) -> Option<&Text> {
        self.slab.get(id.0)
    }

    pub fn text_mut(&mut self, id: TextId) -> Option<&mut Text> {
        self.slab.get_mut(id.0)
    }

    pub fn render(&self, frame: &mut Frame) -> Result<()> {
        for text in &self.slab {
            if !text.visible {
                continue;
            }
            let uniforms =
                uniform! {
                    u_tex: &text.texture,
                };
            frame
                .draw(
                    &text.buffer,
                    NoIndices(PrimitiveType::TriangleStrip),
                    &self.program,
                    &uniforms,
                    &self.draw_params,
                )
                .unwrap();
        }
        Ok(())
    }

    fn rasterise(&mut self, text: &str, padding: u32) -> Result<(u32, u32)> {
        debug!("Rasterising text {:?}...", text);
        let scale = Scale::uniform(POINT_SIZE);
        let (width, height) = LayoutIter::new(&self.font, scale, !0, text)
            .filter_map(|glyph| glyph.pixel_bounding_box())
            .map(|bb| (bb.max.x, bb.max.y))
            .fold((0, 0), |left, right| {
                (left.0.max(right.0), left.1.max(right.1))
            });
        let (width, height) = (width as u32 + padding * 2, height as u32 + padding * 2);
        debug!("Computed dimensions {}x{}...", width, height);

        let pixel_buffer = &mut self.pixel_buffer;
        pixel_buffer.clear();
        pixel_buffer.resize((width * height) as usize, 0x00_80);
        debug!("Resized buffer to {}...", pixel_buffer.len());
        for glyph in LayoutIter::new(&self.font, scale, width, text) {
            if let Some(bb) = glyph.pixel_bounding_box() {
                let offset_x = (bb.min.x + padding as i32) as u32;
                let offset_y = (bb.min.y + padding as i32) as u32;
                glyph.draw(|mut x, mut y, alpha| {
                    x += offset_x;
                    y += offset_y;
                    if x < width && y < height {
                        let scale = (alpha * 256.0) as u32;
                        let one_minus_scale = 256 - scale;

                        let pixel = &mut pixel_buffer[(y * width + x) as usize];

                        let new_alpha = scale * 255 / 256;

                        let red = (*pixel >> 8) as u32 * one_minus_scale + 0xff * scale;
                        let alpha = (*pixel & 0xff) as u32 * one_minus_scale + new_alpha * scale;

                        *pixel = (red | (alpha >> 8)) as u16;
                    }
                });
            }
        }
        Ok((width, height))
    }
}

struct LayoutIter<'a> {
    font: &'a Font<'static>,
    scale: Scale,
    width: u32,
    advance_height: f32,
    caret: FontPoint<f32>,
    last_glyph_id: Option<GlyphId>,
    chars: Recompositions<StrChars<'a>>,
}

impl<'a> LayoutIter<'a> {
    fn new(font: &'a Font<'static>, scale: Scale, width: u32, text: &'a str) -> Self {
        let v_metrics = font.v_metrics(scale);

        LayoutIter {
            font,
            scale,
            width,
            advance_height: v_metrics.ascent - v_metrics.descent + v_metrics.line_gap,
            caret: rusttype::point(0.0, v_metrics.ascent),
            last_glyph_id: None,
            chars: text.nfc(),
        }
    }
}

impl<'a> Iterator for LayoutIter<'a> {
    type Item = PositionedGlyph<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        for c in &mut self.chars {
            if c.is_control() {
                match c {
                    '\n' => {
                        self.caret = rusttype::point(0.0, self.caret.y + self.advance_height);
                        self.last_glyph_id = None;
                    }
                    _ => {}
                }
                continue;
            }
            let base_glyph = if let Some(glyph) = self.font.glyph(c) {
                glyph
            } else {
                continue;
            };
            if let Some(id) = self.last_glyph_id.take() {
                self.caret.x += self.font.pair_kerning(self.scale, id, base_glyph.id());
            }
            self.last_glyph_id = Some(base_glyph.id());
            let mut glyph = base_glyph.scaled(self.scale).positioned(self.caret);
            if let Some(bb) = glyph.pixel_bounding_box() {
                if bb.max.x as u32 > self.width {
                    self.caret = rusttype::point(0.0, self.caret.y + self.advance_height);
                    glyph = glyph.into_unpositioned().positioned(self.caret);
                    self.last_glyph_id = None;
                }
            }
            self.caret.x += glyph.unpositioned().h_metrics().advance_width;
            return Some(glyph);
        }
        None
    }
}

impl Index<TextId> for TextRenderer {
    type Output = Text;
    fn index(&self, id: TextId) -> &Text {
        self.text(id).expect("invalid text id")
    }
}

impl IndexMut<TextId> for TextRenderer {
    fn index_mut(&mut self, id: TextId) -> &mut Text {
        self.text_mut(id).expect("invalid text id")
    }
}

impl<'context> System<'context> for TextRenderer {
    type Dependencies = &'context Window;
    type Error = Error;

    fn create(window: &Window) -> Result<Self> {
        Self::new(window)
    }

    fn destroy(self, _window: &Window) -> Result<()> {
        if !self.slab.is_empty() {
            error!("Text leaked, {} instances.", self.slab.len());
        }
        Ok(())
    }

    fn debug_name() -> &'static str {
        "text_renderer"
    }
}

pub struct Text {
    texture: Texture2d,
    buffer: VertexBuffer<TextVertex>,
    visible: bool,
}

impl Text {
    pub fn set_visible(&mut self, visible: bool) {
        self.visible = visible;
    }
}

/// Hard-coded path to the TTF file to use for rendering debug text.
const FONT_PATH: &str = "assets/ttf/OpenSans-Regular.ttf";

/// Hard-coded font size.
const POINT_SIZE: f32 = 24.0;

const VERTEX_SRC: &str = r#"
    #version 140
    in vec2 a_pos;
    in vec2 a_uv;
    out vec2 v_uv;
    void main() {
        v_uv = a_uv;
        gl_Position = vec4(a_pos, 0.0, 1.0);
    }
"#;

const FRAGMENT_SRC: &str = r#"
    #version 140
    uniform sampler2D u_tex;
    in vec2 v_uv;
    out vec4 color;
    void main() {
        vec4 tex_color = texture(u_tex, v_uv);
        color = vec4(tex_color.g, tex_color.g, tex_color.g, tex_color.r);
    }
"#;

#[repr(C)]
#[derive(Copy, Clone)]
struct TextVertex {
    a_pos: [f32; 2],
    a_uv: [f32; 2],
}

implement_vertex!(TextVertex, a_pos, a_uv);

fn vertex(x: f32, y: f32, u: f32, v: f32) -> TextVertex {
    TextVertex {
        a_pos: [x, y],
        a_uv: [u, v],
    }
}
<commit_msg>text: reorder methods a bit for consistency<commit_after>#![cfg_attr(feature = "cargo-clippy", allow(forget_copy))]

use super::errors::{Result, Error, ResultExt};
use super::system::System;
use super::window::Window;
use glium::{Blend, Surface, VertexBuffer};
use glium::{DrawParameters, Program};
use glium::Frame;
use glium::index::{NoIndices, PrimitiveType};
use glium::texture::{ClientFormat, RawImage2d, Texture2d};
use idcontain::{IdSlab, Id};
use math::Pnt2f;
use rusttype::{self, Font, FontCollection, Scale, PositionedGlyph, GlyphId, Point as FontPoint};
use std::borrow::Cow;
use std::fs::File;
use std::io::Read;
use std::ops::{Index, IndexMut};
use std::str::Chars as StrChars;
use unicode_normalization::{UnicodeNormalization, Recompositions};

/// A handle to a piece of text created with a `TextRenderer`.
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct TextId(Id<Text>);

/// Handles rendering of debug text to `OpenGL`.
pub struct TextRenderer {
    font: Font<'static>,
    slab: IdSlab<Text>,
    program: Program,
    draw_params: DrawParameters<'static>,
    pixel_buffer: Vec<u16>,
}

impl TextRenderer {
    pub fn insert(&mut self, win: &Window, text: &str, pos: Pnt2f, padding: u32) -> TextId {
        debug!("Creating text...");
        let (width, height) = self.rasterise(text, padding).unwrap();
        let texture = Texture2d::new(
            win.facade(),
            RawImage2d {
                data: Cow::Borrowed(&self.pixel_buffer),
                width,
                height,
                format: ClientFormat::U8U8,
            },
        ).unwrap();
        let (w, h) = (
            width as f32 / win.width() as f32 * 2.0,
            height as f32 / win.height() as f32 * 2.0,
        );
        let (x, y) = (pos.x * 2.0 - 1.0, 1.0 - pos.y * 2.0 - h);
        let text = Text {
            buffer: VertexBuffer::immutable(
                win.facade(),
                &[
                    vertex(x, y, 0.0, 1.0),
                    vertex(x, y + h, 0.0, 0.0),
                    vertex(x + w, y, 1.0, 1.0),
                    vertex(x + w, y + h, 1.0, 0.0),
                ],
            ).unwrap(),
            texture: texture,
            visible: true,
        };
        let id = self.slab.insert(text);
        debug!("Created text {:?}.", id);
        TextId(id)
    }

    pub fn remove(&mut self, id: TextId) -> bool {
        debug!("Removed text {:?}.", id.0);
        self.slab.remove(id.0).is_some()
    }

    pub fn text(&self, id: TextId) -> Option<&Text> {
        self.slab.get(id.0)
    }

    pub fn text_mut(&mut self, id: TextId) -> Option<&mut Text> {
        self.slab.get_mut(id.0)
    }

    pub fn render(&self, frame: &mut Frame) -> Result<()> {
        for text in &self.slab {
            if !text.visible {
                continue;
            }
            let uniforms =
                uniform! {
                    u_tex: &text.texture,
                };
            frame
                .draw(
                    &text.buffer,
                    NoIndices(PrimitiveType::TriangleStrip),
                    &self.program,
                    &uniforms,
                    &self.draw_params,
                )
                .unwrap();
        }
        Ok(())
    }

    fn rasterise(&mut self, text: &str, padding: u32) -> Result<(u32, u32)> {
        debug!("Rasterising text {:?}...", text);
        let scale = Scale::uniform(POINT_SIZE);
        let (width, height) = LayoutIter::new(&self.font, scale, !0, text)
            .filter_map(|glyph| glyph.pixel_bounding_box())
            .map(|bb| (bb.max.x, bb.max.y))
            .fold((0, 0), |left, right| {
                (left.0.max(right.0), left.1.max(right.1))
            });
        let (width, height) = (width as u32 + padding * 2, height as u32 + padding * 2);
        debug!("Computed dimensions {}x{}...", width, height);

        let pixel_buffer = &mut self.pixel_buffer;
        pixel_buffer.clear();
        pixel_buffer.resize((width * height) as usize, 0x00_80);
        debug!("Resized buffer to {}...", pixel_buffer.len());
        for glyph in LayoutIter::new(&self.font, scale, width, text) {
            if let Some(bb) = glyph.pixel_bounding_box() {
                let offset_x = (bb.min.x + padding as i32) as u32;
                let offset_y = (bb.min.y + padding as i32) as u32;
                glyph.draw(|mut x, mut y, alpha| {
                    x += offset_x;
                    y += offset_y;
                    if x < width && y < height {
                        let scale = (alpha * 256.0) as u32;
                        let one_minus_scale = 256 - scale;

                        let pixel = &mut pixel_buffer[(y * width + x) as usize];

                        let new_alpha = scale * 255 / 256;

                        let red = (*pixel >> 8) as u32 * one_minus_scale + 0xff * scale;
                        let alpha = (*pixel & 0xff) as u32 * one_minus_scale + new_alpha * scale;

                        *pixel = (red | (alpha >> 8)) as u16;
                    }
                });
            }
        }
        Ok((width, height))
    }
}

impl<'a> Iterator for LayoutIter<'a> {
    type Item = PositionedGlyph<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        for c in &mut self.chars {
            if c.is_control() {
                match c {
                    '\n' => {
                        self.caret = rusttype::point(0.0, self.caret.y + self.advance_height);
                        self.last_glyph_id = None;
                    }
                    _ => {}
                }
                continue;
            }
            let base_glyph = if let Some(glyph) = self.font.glyph(c) {
                glyph
            } else {
                continue;
            };
            if let Some(id) = self.last_glyph_id.take() {
                self.caret.x += self.font.pair_kerning(self.scale, id, base_glyph.id());
            }
            self.last_glyph_id = Some(base_glyph.id());
            let mut glyph = base_glyph.scaled(self.scale).positioned(self.caret);
            if let Some(bb) = glyph.pixel_bounding_box() {
                if bb.max.x as u32 > self.width {
                    self.caret = rusttype::point(0.0, self.caret.y + self.advance_height);
                    glyph = glyph.into_unpositioned().positioned(self.caret);
                    self.last_glyph_id = None;
                }
            }
            self.caret.x += glyph.unpositioned().h_metrics().advance_width;
            return Some(glyph);
        }
        None
    }
}

impl Index<TextId> for TextRenderer {
    type Output = Text;
    fn index(&self, id: TextId) -> &Text {
        self.text(id).expect("invalid text id")
    }
}

impl IndexMut<TextId> for TextRenderer {
    fn index_mut(&mut self, id: TextId) -> &mut Text {
        self.text_mut(id).expect("invalid text id")
    }
}

impl<'context> System<'context> for TextRenderer {
    type Dependencies = &'context Window;
    type Error = Error;

    fn create(window: &Window) -> Result<Self> {
        let mut font_bytes = Vec::with_capacity(1024 * 1024); // 1MB
        File::open(FONT_PATH)
            .and_then(|mut file| file.read_to_end(&mut font_bytes))
            .chain_err(|| format!("Failed to read font at {:?}.", FONT_PATH))?;
        Ok(TextRenderer {
            font: FontCollection::from_bytes(font_bytes)
                .font_at(0)
                .ok_or_else(|| format!("No fonts in {:?}.", FONT_PATH))?,
            slab: IdSlab::with_capacity(16),
            program: Program::from_source(window.facade(), VERTEX_SRC, FRAGMENT_SRC, None).unwrap(),
            draw_params: DrawParameters {
                blend: Blend::alpha_blending(),
                ..DrawParameters::default()
            },
            pixel_buffer: Vec::new(),
        })
    }

    fn destroy(self, _window: &Window) -> Result<()> {
        if !self.slab.is_empty() {
            error!("Text leaked, {} instances.", self.slab.len());
        }
        Ok(())
    }

    fn debug_name() -> &'static str {
        "text_renderer"
    }
}

pub struct Text {
    texture: Texture2d,
    buffer: VertexBuffer<TextVertex>,
    visible: bool,
}

impl Text {
    pub fn set_visible(&mut self, visible: bool) {
        self.visible = visible;
    }
}

struct LayoutIter<'a> {
    font: &'a Font<'static>,
    scale: Scale,
    width: u32,
    advance_height: f32,
    caret: FontPoint<f32>,
    last_glyph_id: Option<GlyphId>,
    chars: Recompositions<StrChars<'a>>,
}

impl<'a> LayoutIter<'a> {
    fn new(font: &'a Font<'static>, scale: Scale, width: u32, text: &'a str) -> Self {
        let v_metrics = font.v_metrics(scale);

        LayoutIter {
            font,
            scale,
            width,
            advance_height: v_metrics.ascent - v_metrics.descent + v_metrics.line_gap,
            caret: rusttype::point(0.0, v_metrics.ascent),
            last_glyph_id: None,
            chars: text.nfc(),
        }
    }
}

/// Hard-coded path to the TTF file to use for rendering debug text.
const FONT_PATH: &str = "assets/ttf/OpenSans-Regular.ttf";

/// Hard-coded font size.
const POINT_SIZE: f32 = 24.0;

const VERTEX_SRC: &str = r#"
    #version 140
    in vec2 a_pos;
    in vec2 a_uv;
    out vec2 v_uv;
    void main() {
        v_uv = a_uv;
        gl_Position = vec4(a_pos, 0.0, 1.0);
    }
"#;

const FRAGMENT_SRC: &str = r#"
    #version 140
    uniform sampler2D u_tex;
    in vec2 v_uv;
    out vec4 color;
    void main() {
        vec4 tex_color = texture(u_tex, v_uv);
        color = vec4(tex_color.g, tex_color.g, tex_color.g, tex_color.r);
    }
"#;

#[repr(C)]
#[derive(Copy, Clone)]
struct TextVertex {
    a_pos: [f32; 2],
    a_uv: [f32; 2],
}

implement_vertex!(TextVertex, a_pos, a_uv);

fn vertex(x: f32, y: f32, u: f32, v: f32) -> TextVertex {
    TextVertex {
        a_pos: [x, y],
        a_uv: [u, v],
    }
}
<|endoftext|>


<commit_before>//! Test Driven Learning Project.
//! Desenvolva TDD e programação com TDD e programação!
//! Módulo novice.
//!
//! The MIT License (MIT)
//!
//! Copyright (c) 2016 Paulo Henrique Rodrigues Pinheiro <paulo@sysincloud.it>
//!
//! Permission is hereby granted, free of charge, to any person obtaining a copy
//! of this software and associated documentation files (the "Software"), to deal
//! in the Software without restriction, including without limitation the rights
//! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//! copies of the Software, and to permit persons to whom the Software is
//! furnished to do so, subject to the following conditions:
//!
//! The above copyright notice and this permission notice shall be included in all
//! copies or substantial portions of the Software.
//!
//! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//! SOFTWARE.

use std::collections::HashSet;

/// A função `negue` deve receber um valor boleano (verdadeiro ou falso) e
/// retornar a negação desse valor.
///
/// # Examples
///
/// ```
/// extern crate rust;
/// assert_eq!(true, rust::problems::negue(false));
/// assert_eq!(false, rust::problems::negue(true));
/// ```
pub fn negue(value:bool) -> bool {
    !value
}

/// A função `diga_ola` deve ser escrita de tal forma que receba como
/// parâmetro um argumento *string*. Deve retornar a *string* "Olá, ", seguida
/// do argumento recebido, mais um ponto final. A *string* recebida deve estar
/// limpa, ou seja, sem caracteres de espaço no começo ou no fim. Se a *string*
/// estiver vazia, retorna apenas "Olá!"
///
/// # Examples
///
/// ```
/// extern crate rust;
///
/// assert_eq!("Olá!", rust::problems::diga_ola(""));
/// assert_eq!("Olá!", rust::problems::diga_ola("    "));
/// assert_eq!("Olá, Paulo.", rust::problems::diga_ola("Paulo"));
/// assert_eq!("Olá, Paulo.", rust::problems::diga_ola("  Paulo  "));
/// assert_eq!("Olá, Paulo Henrique.", rust::problems::diga_ola("  Paulo Henrique  "));
/// ```
pub fn diga_ola(nome:&str) -> String {
    let nome_limpo = nome.trim();

    if "" == nome_limpo {
        return "Olá!".to_string();
    }

    "Olá, ".to_string() + &nome_limpo.to_string() + "."
}

/// A função `lista_numeros_pares` deve receber um parâmetro numérico
/// inteiro que determina quantos números pares devem estar em um array que
/// será o retorno da função.
///
/// Examples
///
/// ```
/// extern crate rust;
///
/// assert_eq!(0, rust::problems::lista_numeros_pares(0).len());
/// assert_eq!(vec![2], rust::problems::lista_numeros_pares(1));
/// assert_eq!(vec![2, 4, 6, 8], rust::problems::lista_numeros_pares(4));
/// assert_eq!(vec![2, 4, 6, 8, 10], rust::problems::lista_numeros_pares(5));
/// assert_eq!(0, rust::problems::lista_numeros_pares(-1).len());
/// ```
pub fn lista_numeros_pares(quantos:i32) -> Vec<i32> {
    (1..quantos+1).map(|x| x*2).collect::<Vec<i32>>()
}

/// A função `lista_multiplos` deve receber dois parâmetros numéricos
/// inteiros e retornar uma lista de números inteiros. O tamanho da lista é
/// determinado pelo primeiro parâmetro, e o número base será o segundo
/// parâmetro.
///
/// Examples
///
/// ```
/// extern crate rust;
///
/// assert_eq!(0, rust::problems::lista_multiplos(0, 10).len());
/// assert_eq!(0, rust::problems::lista_multiplos(-1, 10).len());
/// assert_eq!(vec![-3, -2, -1], rust::problems::lista_multiplos(3, -1));
/// assert_eq!(0, rust::problems::lista_multiplos(3, 0).len());
/// assert_eq!(vec![10, 20, 30], rust::problems::lista_multiplos(3, 10));
/// ```
pub fn lista_multiplos(quantos:i32, base:i32) -> Vec<i32> {
    if base == 0 {
        return vec![];
    }

    let mut response = (1..quantos+1).map(|x| x*base).collect::<Vec<i32>>();

    if base < 1 {
        response.reverse();
    }

    response
}

/// A função `soma` deve receber um *array* de números inteiros, e retornar
/// a sua soma. Se a lista for vazia, deve retornar zero.
///
/// Examples
///
/// ```
/// extern crate rust;
///
/// assert_eq!(0, rust::problems::soma(vec![]));
/// assert_eq!(1, rust::problems::soma(vec![1]));
/// assert_eq!(3, rust::problems::soma(vec![1, 2]));
/// ```
pub fn soma(lista:Vec<i32>) -> i32 {
    lista.iter().fold(0, |result, x| result + x)
}

/// A função `subtracao` deve receber um *array* de números inteiros, e
/// retornar a subtração de todos os elementos em sequência. Por exemplo,
/// subtracao([3,2,1]) deve retornar 0, e subtracao([10,2,3]) deve retornar 5.
/// Se a lista for vazia, deve retornar zero.
///
/// Examples
///
/// ```
/// extern crate rust;
///
/// assert_eq!(0, rust::problems::subtracao(vec![3, 2, 1]));
/// assert_eq!(5, rust::problems::subtracao(vec![10, 2, 3]));
/// assert_eq!(0, rust::problems::subtracao(vec![]));
/// assert_eq!(-1, rust::problems::subtracao(vec![1, 2]));
/// assert_eq!(4, rust::problems::subtracao(vec![-1, -2, -3]));
/// assert_eq!(3, rust::problems::subtracao(vec![9, 3, 2, 1]));
/// ```
pub fn subtracao(lista:Vec<i32>) -> i32 {
    if lista.len() < 1 {
        return 0;
    }

    lista[1..lista.len()].iter().fold(lista[0], |result, x| result - x)
}

/// A função `multiplicação` deve receber um *array* de números inteiros, e
/// retornar o seu produto. Se a lista for vazia, deve retornar zero.
///
/// Examples
///
/// ```
/// extern crate rust;
///
/// assert_eq!(6, rust::problems::multiplicacao(vec![1, 2, 3]));
/// assert_eq!(0, rust::problems::multiplicacao(vec![]));
/// assert_eq!(-8, rust::problems::multiplicacao(vec![-2, 1, 4]));
/// assert_eq!(8, rust::problems::multiplicacao(vec![-2, -1, 4]));
pub fn multiplicacao(lista:Vec<i32>) -> i32 {
    if lista.len() < 1 {
        return 0;
    }

    lista.iter().fold(1, |result, x| result * x)
}

/// A função `divisao` deve receber um *array* de números inteiros, e
/// retornar o resultado da sequência de divisões por cada elemento. Por
/// exemplo, divisão([16, 4, 2]) deve retornar 2, e divisão([100,2,10]) deve
/// retornar 5. Se a lista for vazia, deve retornar zero.
///
/// Examples
///
/// ```
/// extern crate rust;
///
/// assert_eq!(2, rust::problems::divisao(vec![5, 2]));
/// assert_eq!(0, rust::problems::divisao(vec![]));
/// assert_eq!(0, rust::problems::divisao(vec![0]));
/// assert_eq!(2, rust::problems::divisao(vec![16, 4, 2]));
/// assert_eq!(5, rust::problems::divisao(vec![100, 2, 10]));
/// assert_eq!(0, rust::problems::divisao(vec![0, 1]));
/// //assert_eq!(0, rust::problems::divisao(vec![1, 0]));
pub fn divisao(lista:Vec<i32>) ->i32 {
    if lista.len() < 1 {
        return 0;
    }

    lista[1..lista.len()].iter().fold(lista[0], |result, x| result / x)
}

/// A função `maior` deve receber um *array* de números inteiros e retornar
/// qual é o maior deles.
///
/// Examples
///
/// ```
/// extern crate rust;
///
/// assert_eq!(100, rust::problems::maior(vec![0, 1 ,100]));
/// assert_eq!(0, rust::problems::maior(vec![0]));
pub fn maior(lista:Vec<i32>)-> i32 {
    lista.iter().fold(lista[0], |result, x| if *x > result {*x} else {result})
}

/// A função `intersecao` deve receber dois *arrays* contendo números
/// inteiros, e retornar a interseção entre os conjuntos, ou seja, um *array*
/// que contenha apenas os números que estejam contidos nos dois *arrays*
/// passados para a função.
///
/// Examples
///
/// ```
/// assert_eq!(0, rust::problems::intersecao(vec![], vec![]).len());
/// assert_eq!(0, rust::problems::intersecao(vec![1, 2], vec![3, 4]).len());
/// assert_eq!(vec![2], rust::problems::intersecao(vec![1, 2], vec![2, 3]));
pub fn intersecao(a:Vec<i32>, b:Vec<i32>) -> Vec<i32> {
    let _a:HashSet<i32> = a.iter().cloned().collect();
    let _b:HashSet<i32> = b.iter().cloned().collect();

    _a.intersection(&_b).cloned().collect::<Vec<i32>>()
}
<commit_msg>Uitiliza a função de checar se a String está vazia.<commit_after>//! Test Driven Learning Project.
//! Desenvolva TDD e programação com TDD e programação!
//! Módulo novice.
//!
//! The MIT License (MIT)
//!
//! Copyright (c) 2016 Paulo Henrique Rodrigues Pinheiro <paulo@sysincloud.it>
//!
//! Permission is hereby granted, free of charge, to any person obtaining a copy
//! of this software and associated documentation files (the "Software"), to deal
//! in the Software without restriction, including without limitation the rights
//! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//! copies of the Software, and to permit persons to whom the Software is
//! furnished to do so, subject to the following conditions:
//!
//! The above copyright notice and this permission notice shall be included in all
//! copies or substantial portions of the Software.
//!
//! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//! SOFTWARE.

use std::collections::HashSet;

/// A função `negue` deve receber um valor boleano (verdadeiro ou falso) e
/// retornar a negação desse valor.
///
/// # Examples
///
/// ```
/// extern crate rust;
/// assert_eq!(true, rust::problems::negue(false));
/// assert_eq!(false, rust::problems::negue(true));
/// ```
pub fn negue(value:bool) -> bool {
    !value
}

/// A função `diga_ola` deve ser escrita de tal forma que receba como
/// parâmetro um argumento *string*. Deve retornar a *string* "Olá, ", seguida
/// do argumento recebido, mais um ponto final. A *string* recebida deve estar
/// limpa, ou seja, sem caracteres de espaço no começo ou no fim. Se a *string*
/// estiver vazia, retorna apenas "Olá!"
///
/// # Examples
///
/// ```
/// extern crate rust;
///
/// assert_eq!("Olá!", rust::problems::diga_ola(""));
/// assert_eq!("Olá!", rust::problems::diga_ola("    "));
/// assert_eq!("Olá, Paulo.", rust::problems::diga_ola("Paulo"));
/// assert_eq!("Olá, Paulo.", rust::problems::diga_ola("  Paulo  "));
/// assert_eq!("Olá, Paulo Henrique.", rust::problems::diga_ola("  Paulo Henrique  "));
/// ```
pub fn diga_ola(nome:&str) -> String {
    let nome_limpo = nome.trim();

    if nome_limpo.is_empty() {
        return "Olá!".to_string();
    }

    "Olá, ".to_string() + &nome_limpo.to_string() + "."
}

/// A função `lista_numeros_pares` deve receber um parâmetro numérico
/// inteiro que determina quantos números pares devem estar em um array que
/// será o retorno da função.
///
/// Examples
///
/// ```
/// extern crate rust;
///
/// assert_eq!(0, rust::problems::lista_numeros_pares(0).len());
/// assert_eq!(vec![2], rust::problems::lista_numeros_pares(1));
/// assert_eq!(vec![2, 4, 6, 8], rust::problems::lista_numeros_pares(4));
/// assert_eq!(vec![2, 4, 6, 8, 10], rust::problems::lista_numeros_pares(5));
/// assert_eq!(0, rust::problems::lista_numeros_pares(-1).len());
/// ```
pub fn lista_numeros_pares(quantos:i32) -> Vec<i32> {
    (1..quantos+1).map(|x| x*2).collect::<Vec<i32>>()
}

/// A função `lista_multiplos` deve receber dois parâmetros numéricos
/// inteiros e retornar uma lista de números inteiros. O tamanho da lista é
/// determinado pelo primeiro parâmetro, e o número base será o segundo
/// parâmetro.
///
/// Examples
///
/// ```
/// extern crate rust;
///
/// assert_eq!(0, rust::problems::lista_multiplos(0, 10).len());
/// assert_eq!(0, rust::problems::lista_multiplos(-1, 10).len());
/// assert_eq!(vec![-3, -2, -1], rust::problems::lista_multiplos(3, -1));
/// assert_eq!(0, rust::problems::lista_multiplos(3, 0).len());
/// assert_eq!(vec![10, 20, 30], rust::problems::lista_multiplos(3, 10));
/// ```
pub fn lista_multiplos(quantos:i32, base:i32) -> Vec<i32> {
    if base == 0 {
        return vec![];
    }

    let mut response = (1..quantos+1).map(|x| x*base).collect::<Vec<i32>>();

    if base < 1 {
        response.reverse();
    }

    response
}

/// A função `soma` deve receber um *array* de números inteiros, e retornar
/// a sua soma. Se a lista for vazia, deve retornar zero.
///
/// Examples
///
/// ```
/// extern crate rust;
///
/// assert_eq!(0, rust::problems::soma(vec![]));
/// assert_eq!(1, rust::problems::soma(vec![1]));
/// assert_eq!(3, rust::problems::soma(vec![1, 2]));
/// ```
pub fn soma(lista:Vec<i32>) -> i32 {
    lista.iter().fold(0, |result, x| result + x)
}

/// A função `subtracao` deve receber um *array* de números inteiros, e
/// retornar a subtração de todos os elementos em sequência. Por exemplo,
/// subtracao([3,2,1]) deve retornar 0, e subtracao([10,2,3]) deve retornar 5.
/// Se a lista for vazia, deve retornar zero.
///
/// Examples
///
/// ```
/// extern crate rust;
///
/// assert_eq!(0, rust::problems::subtracao(vec![3, 2, 1]));
/// assert_eq!(5, rust::problems::subtracao(vec![10, 2, 3]));
/// assert_eq!(0, rust::problems::subtracao(vec![]));
/// assert_eq!(-1, rust::problems::subtracao(vec![1, 2]));
/// assert_eq!(4, rust::problems::subtracao(vec![-1, -2, -3]));
/// assert_eq!(3, rust::problems::subtracao(vec![9, 3, 2, 1]));
/// ```
pub fn subtracao(lista:Vec<i32>) -> i32 {
    if lista.len() < 1 {
        return 0;
    }

    lista[1..lista.len()].iter().fold(lista[0], |result, x| result - x)
}

/// A função `multiplicação` deve receber um *array* de números inteiros, e
/// retornar o seu produto. Se a lista for vazia, deve retornar zero.
///
/// Examples
///
/// ```
/// extern crate rust;
///
/// assert_eq!(6, rust::problems::multiplicacao(vec![1, 2, 3]));
/// assert_eq!(0, rust::problems::multiplicacao(vec![]));
/// assert_eq!(-8, rust::problems::multiplicacao(vec![-2, 1, 4]));
/// assert_eq!(8, rust::problems::multiplicacao(vec![-2, -1, 4]));
pub fn multiplicacao(lista:Vec<i32>) -> i32 {
    if lista.len() < 1 {
        return 0;
    }

    lista.iter().fold(1, |result, x| result * x)
}

/// A função `divisao` deve receber um *array* de números inteiros, e
/// retornar o resultado da sequência de divisões por cada elemento. Por
/// exemplo, divisão([16, 4, 2]) deve retornar 2, e divisão([100,2,10]) deve
/// retornar 5. Se a lista for vazia, deve retornar zero.
///
/// Examples
///
/// ```
/// extern crate rust;
///
/// assert_eq!(2, rust::problems::divisao(vec![5, 2]));
/// assert_eq!(0, rust::problems::divisao(vec![]));
/// assert_eq!(0, rust::problems::divisao(vec![0]));
/// assert_eq!(2, rust::problems::divisao(vec![16, 4, 2]));
/// assert_eq!(5, rust::problems::divisao(vec![100, 2, 10]));
/// assert_eq!(0, rust::problems::divisao(vec![0, 1]));
/// //assert_eq!(0, rust::problems::divisao(vec![1, 0]));
pub fn divisao(lista:Vec<i32>) ->i32 {
    if lista.len() < 1 {
        return 0;
    }

    lista[1..lista.len()].iter().fold(lista[0], |result, x| result / x)
}

/// A função `maior` deve receber um *array* de números inteiros e retornar
/// qual é o maior deles.
///
/// Examples
///
/// ```
/// extern crate rust;
///
/// assert_eq!(100, rust::problems::maior(vec![0, 1 ,100]));
/// assert_eq!(0, rust::problems::maior(vec![0]));
pub fn maior(lista:Vec<i32>)-> i32 {
    lista.iter().fold(lista[0], |result, x| if *x > result {*x} else {result})
}

/// A função `intersecao` deve receber dois *arrays* contendo números
/// inteiros, e retornar a interseção entre os conjuntos, ou seja, um *array*
/// que contenha apenas os números que estejam contidos nos dois *arrays*
/// passados para a função.
///
/// Examples
///
/// ```
/// assert_eq!(0, rust::problems::intersecao(vec![], vec![]).len());
/// assert_eq!(0, rust::problems::intersecao(vec![1, 2], vec![3, 4]).len());
/// assert_eq!(vec![2], rust::problems::intersecao(vec![1, 2], vec![2, 3]));
pub fn intersecao(a:Vec<i32>, b:Vec<i32>) -> Vec<i32> {
    let _a:HashSet<i32> = a.iter().cloned().collect();
    let _b:HashSet<i32> = b.iter().cloned().collect();

    _a.intersection(&_b).cloned().collect::<Vec<i32>>()
}
<|endoftext|>


<commit_before>
mod todotxt;

fn main () {

        let t = ::todotxt::Todo::create(~"some important task", 1);
        println(t.to_str());
        let x = ::todotxt::Todo::create(~"x some important task", 1);
        println(x.to_str());
}
<commit_msg>naming<commit_after>
mod todotxt;

fn main () {

        let mut tasks = ~[];

        let t = ::todotxt::Task::create(~"some important task", 1);
        println(t.to_str());

        tasks.push(t);
        let x = ::todotxt::Task::create(~"x some important task", 1);
        println(x.to_str());

        tasks.push(x);
}
<|endoftext|>