<commit_before>use Request;

use std::io::Read;
use std::error::Error;

/// Request and response transport abstraction.
///
/// The `Transport` trait provides a way to send a `Request` to a server and to receive the
/// corresponding response. A `Transport` implementor is passed to `Request::call` in order to use
/// it to perform that request.
///
/// The most commonly used transport is simple HTTP: If the `reqwest` feature is enabled (it is by
/// default), the reqwest `RequestBuilder` will implement this trait and send the XML-RPC `Request`
/// via HTTP.
///
/// You can implement this trait for your own types if you want to customize how requests are sent.
/// You can modify HTTP headers or wrap requests in a completely different protocol.
pub trait Transport {
    // FIXME replace with `impl Trait` when stable
    /// The response stream returned by `transmit`.
    type Stream: Read;

    /// Transmits an XML-RPC request and returns the server's response.
    ///
    /// The response is returned as a `Self::Stream` - some type implementing the `Read` trait. The
    /// library will read all of the data and parse it as a response. It must be UTF-8 encoded XML,
    /// otherwise the call will fail.
    ///
    /// If a transport error occurs, this should return it as a boxed error - the library will
    /// interpret it as a transport error and return an appropriate `RequestError`.
    fn transmit(self, request: &Request) -> Result<Self::Stream, Box<Error>>;
}

/// Provides helpers for implementing custom `Transport`s using reqwest.
///
/// This module will be disabled if the `reqwest` feature is not enabled.
///
/// The default `Transport` implementation for `RequestBuilder` looks roughly like this:
///
/// ```notrust
/// // serialize request into `body` (a `Vec<u8>`)
///
/// build_headers(builder, body.len());
///
/// // send `body` using `builder`, ensure server returned 200 OK
///
/// check_response(&response)?;
/// ```
///
/// From this, you can build your own custom transports.
#[cfg(feature = "reqwest")]
pub mod http {
    extern crate reqwest;

    use {Request, Transport};
    use self::reqwest::{Client, RequestBuilder, Url, mime};
    use self::reqwest::header::{ContentType, ContentLength, UserAgent};

    use std::error::Error;

    /// Appends all HTTP headers required by the XML-RPC specification to the `RequestBuilder`.
    ///
    /// More specifically, the following headers are set:
    ///
    /// ```notrust
    /// User-Agent: Rust xmlrpc
    /// Content-Type: text/xml; charset=utf-8
    /// Content-Length: $body_len
    /// ```
    pub fn build_headers(builder: &mut RequestBuilder, body_len: u64) {
        builder
            .header(UserAgent::new("Rust xmlrpc"))
            .header(ContentType("text/xml; charset=utf-8".parse().unwrap()))
            .header(ContentLength(body_len));
    }

    /// Checks that a reqwest `Response` contains all headers mandated by the spec.
    ///
    /// This is done by default to ensure compliance.
    pub fn check_response(response: &reqwest::Response) -> Result<(), Box<Error>> {
        // Check response headers
        // "The Content-Type is text/xml. Content-Length must be present and correct."
        if let Some(content) = response.headers().get::<ContentType>() {
            // (we ignore this if the header is missing completely)
            match (content.type_(), content.subtype()) {
                (mime::TEXT, mime::XML) => {},
                (ty, sub) => return Err(
                    format!("expected Content-Type 'text/xml', got '{}/{}'", ty, sub).into()
                ),
            }
        }

        response.headers().get::<ContentLength>()
            .ok_or_else(|| format!("expected Content-Length header, but none was found"))?;

        Ok(())
    }

    /// Use a `RequestBuilder` as the transport.
    ///
    /// The request will be sent as specified in the XML-RPC specification: A default `User-Agent`
    /// will be set, along with the correct `Content-Type` and `Content-Length`.
    impl Transport for RequestBuilder {
        type Stream = reqwest::Response;

        fn transmit(mut self, request: &Request) -> Result<Self::Stream, Box<Error>> {
            // First, build the body XML
            let mut body = Vec::new();
            // This unwrap never panics as we are using `Vec<u8>` as a `Write` implementor,
            // and not doing anything else that could return an `Err` in `write_as_xml()`.
            request.write_as_xml(&mut body).unwrap();

            // Set all required request headers
            // NB: The `Host` header is also required, but reqwest adds it automatically, since
            // HTTP/1.1 requires it.
            build_headers(&mut self, body.len() as u64);

            let response = self
                .body(body)
                .send()?
                .error_for_status()?;

            check_response(&response)?;

            Ok(response)
        }
    }

    /// Convenience implementation for `Url`. Creates a `Client` and performs a `POST` request to
    /// the URL.
    // (this isn't actually that convenient - to parse a URL to have to deal with another layer of
    // errors)
    impl Transport for Url {
        type Stream = reqwest::Response;

        fn transmit(self, request: &Request) -> Result<Self::Stream, Box<Error>> {
            Client::new().post(self).transmit(request)
        }
    }
}

// TODO: integration test - can you usefully implement this trait from outside?
// Also test reported use cases:
// - Cookie support (missing in reqwest!),
// - Custom useragent
// - "XML-RPC wrapped in SCGI over a unix domain socket"
<commit_msg>Remove Transport impl for Url in favor in Request.call_url<commit_after>use Request;

use std::io::Read;
use std::error::Error;

/// Request and response transport abstraction.
///
/// The `Transport` trait provides a way to send a `Request` to a server and to receive the
/// corresponding response. A `Transport` implementor is passed to `Request::call` in order to use
/// it to perform that request.
///
/// The most commonly used transport is simple HTTP: If the `reqwest` feature is enabled (it is by
/// default), the reqwest `RequestBuilder` will implement this trait and send the XML-RPC `Request`
/// via HTTP.
///
/// You can implement this trait for your own types if you want to customize how requests are sent.
/// You can modify HTTP headers or wrap requests in a completely different protocol.
pub trait Transport {
    // FIXME replace with `impl Trait` when stable
    /// The response stream returned by `transmit`.
    type Stream: Read;

    /// Transmits an XML-RPC request and returns the server's response.
    ///
    /// The response is returned as a `Self::Stream` - some type implementing the `Read` trait. The
    /// library will read all of the data and parse it as a response. It must be UTF-8 encoded XML,
    /// otherwise the call will fail.
    ///
    /// If a transport error occurs, this should return it as a boxed error - the library will
    /// interpret it as a transport error and return an appropriate `RequestError`.
    fn transmit(self, request: &Request) -> Result<Self::Stream, Box<Error>>;
}

/// Provides helpers for implementing custom `Transport`s using reqwest.
///
/// This module will be disabled if the `reqwest` feature is not enabled.
///
/// The default `Transport` implementation for `RequestBuilder` looks roughly like this:
///
/// ```notrust
/// // serialize request into `body` (a `Vec<u8>`)
///
/// build_headers(builder, body.len());
///
/// // send `body` using `builder`, ensure server returned 200 OK
///
/// check_response(&response)?;
/// ```
///
/// From this, you can build your own custom transports.
#[cfg(feature = "reqwest")]
pub mod http {
    extern crate reqwest;

    use {Request, Transport};
    use self::reqwest::{RequestBuilder, mime};
    use self::reqwest::header::{ContentType, ContentLength, UserAgent};

    use std::error::Error;

    /// Appends all HTTP headers required by the XML-RPC specification to the `RequestBuilder`.
    ///
    /// More specifically, the following headers are set:
    ///
    /// ```notrust
    /// User-Agent: Rust xmlrpc
    /// Content-Type: text/xml; charset=utf-8
    /// Content-Length: $body_len
    /// ```
    pub fn build_headers(builder: &mut RequestBuilder, body_len: u64) {
        builder
            .header(UserAgent::new("Rust xmlrpc"))
            .header(ContentType("text/xml; charset=utf-8".parse().unwrap()))
            .header(ContentLength(body_len));
    }

    /// Checks that a reqwest `Response` contains all headers mandated by the spec.
    ///
    /// This is done by default to ensure compliance.
    pub fn check_response(response: &reqwest::Response) -> Result<(), Box<Error>> {
        // Check response headers
        // "The Content-Type is text/xml. Content-Length must be present and correct."
        if let Some(content) = response.headers().get::<ContentType>() {
            // (we ignore this if the header is missing completely)
            match (content.type_(), content.subtype()) {
                (mime::TEXT, mime::XML) => {},
                (ty, sub) => return Err(
                    format!("expected Content-Type 'text/xml', got '{}/{}'", ty, sub).into()
                ),
            }
        }

        response.headers().get::<ContentLength>()
            .ok_or_else(|| format!("expected Content-Length header, but none was found"))?;

        Ok(())
    }

    /// Use a `RequestBuilder` as the transport.
    ///
    /// The request will be sent as specified in the XML-RPC specification: A default `User-Agent`
    /// will be set, along with the correct `Content-Type` and `Content-Length`.
    impl Transport for RequestBuilder {
        type Stream = reqwest::Response;

        fn transmit(mut self, request: &Request) -> Result<Self::Stream, Box<Error>> {
            // First, build the body XML
            let mut body = Vec::new();
            // This unwrap never panics as we are using `Vec<u8>` as a `Write` implementor,
            // and not doing anything else that could return an `Err` in `write_as_xml()`.
            request.write_as_xml(&mut body).unwrap();

            // Set all required request headers
            // NB: The `Host` header is also required, but reqwest adds it automatically, since
            // HTTP/1.1 requires it.
            build_headers(&mut self, body.len() as u64);

            let response = self
                .body(body)
                .send()?
                .error_for_status()?;

            check_response(&response)?;

            Ok(response)
        }
    }
}
<|endoftext|>


<commit_before>extern crate time;

use std::fmt;
use std::io;
use std::io::{Error, Write};
use std::cmp::{Ord, Ordering};

pub enum LogLevel {
    ERROR,
    WARN,
    INFO,
    VERBOSE
}

// ERROR > WARN > INFO > VERBOSE
impl Ord for LogLevel {
    fn cmp(&self, other: &Self) -> Ordering {
        match *self {
            LogLevel::ERROR => match *other {
                        LogLevel::ERROR => Ordering::Equal,
                        _ => Ordering::Greater,
                    },
            LogLevel::WARN => match *other {
                        LogLevel::ERROR => Ordering::Less,
                        LogLevel::WARN => Ordering::Equal,
                        _ => Ordering::Greater,
                    },
            LogLevel::INFO => match *other {
                        LogLevel::VERBOSE => Ordering::Greater,
                        LogLevel::INFO => Ordering::Equal,
                        _ => Ordering::Less,
                    },
            LogLevel::VERBOSE => match *other {
                        LogLevel::VERBOSE => Ordering::Equal,
                        _ => Ordering::Less,
                    },
        }
    }
}

impl Eq for LogLevel {}

impl PartialEq for LogLevel {

    fn eq(&self, other: &Self) -> bool {
        self.cmp(other) == Ordering::Equal
    }

    fn ne(&self, other: &Self) -> bool {
        !self.eq(other)
    }

}

impl PartialOrd for LogLevel {

    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }

    fn lt(&self, other: &Self) -> bool {
        self.cmp(other) == Ordering::Less
    }

    fn le(&self, other: &Self) -> bool {
        self.cmp(other) != Ordering::Greater
    }

    fn gt(&self, other: &Self) -> bool {
        self.cmp(other) == Ordering::Greater
    }

    fn ge(&self, other: &Self) -> bool {
        self.cmp(other) != Ordering::Less
    }
}

/// Set global log level here
static LOG_LEVEL: LogLevel = LogLevel::INFO;

/// the log function returning a result
///
/// # Examples
/// '''
/// log(LogLevel::ERROR, format_args!("This is bad!")).unwrap();
/// '''
pub fn log(level: LogLevel, args: fmt::Arguments) -> Result<(), Error> {

    if level < LOG_LEVEL {
        return Ok(());
    }

    let stderr = io::stderr();
    let stdout = io::stdout();

    let mut stderr_lock = stderr.lock();
    let mut stdout_lock = stdout.lock();

    let cur_time = time::now();

    match level {
        LogLevel::ERROR => writeln!(stderr_lock, "[ERROR] {}:{}:{} - {}", cur_time.tm_hour, cur_time.tm_min, cur_time.tm_sec, args),
        LogLevel::WARN => writeln!(stdout_lock, "[WARN] {}:{}:{} - {}", cur_time.tm_hour, cur_time.tm_min, cur_time.tm_sec, args),
        LogLevel::INFO => writeln!(stdout_lock, "[INFO] {}:{}:{} - {}", cur_time.tm_hour, cur_time.tm_min, cur_time.tm_sec, args),
        LogLevel::VERBOSE => writeln!(stdout_lock, "[VERBOSE] {}:{}:{} - {}", cur_time.tm_hour, cur_time.tm_min, cur_time.tm_sec, args),
    }

}

/// a log function ignoring any failure
/// "log something, if possible"
///
/// # Examples
/// '''
/// try_log(LogLevel::ERROR, format_args!("This is bad!"));
/// '''
pub fn try_log(level: LogLevel, args: fmt::Arguments) {
    let _ = log(level, args);
}

// Helper Macro

/// Error Macro
///
/// # Examples
/// '''
/// error!("This is bad!");
/// '''
macro_rules! log_error {
    ($($arg:tt)*) => (::utils::log::try_log(::utils::log::LogLevel::ERROR, format_args!($($arg)*)));
}

/// Warning Macro
///
/// # Examples
/// '''
/// error!("This is maybe bad?!");
/// '''
macro_rules! log_warn {
    ($($arg:tt)*) => (::utils::log::try_log(::utils::log::LogLevel::WARN, format_args!($($arg)*)));
}

/// Info Macro
///
/// # Examples
/// '''
/// error!("This is just to let you know!");
/// '''
macro_rules! log_info {
    ($($arg:tt)*) => (::utils::log::try_log(::utils::log::LogLevel::INFO, format_args!($($arg)*)));
}

/// Verbose Macro
///
/// # Examples
/// '''
/// error!("You must really like spam!");
/// '''
macro_rules! log_verbose {
    ($($arg:tt)*) => (::utils::log::try_log(::utils::log::LogLevel::VERBOSE, format_args!($($arg)*)));
}

#[test]
fn test() {
    log_info!("Test!");
}

//To-Do add a way to check the result automatically
#[test]
fn multi_thread_test() {
    let mut joins = Vec::new();
    for _ in 0..10 {
        joins.push(std::thread::spawn(move || {
            log_info!("No corruption should happen in this ultra-extra-super-long string output even if run in multiple threads.");
        }));
    }
    for handle in joins {
        let _ = handle.join();
    }
}
<commit_msg>util/log: Fix documentation comments<commit_after>extern crate time;

use std::fmt;
use std::io;
use std::io::{Error, Write};
use std::cmp::{Ord, Ordering};

pub enum LogLevel {
    ERROR,
    WARN,
    INFO,
    VERBOSE
}

// ERROR > WARN > INFO > VERBOSE
impl Ord for LogLevel {
    fn cmp(&self, other: &Self) -> Ordering {
        match *self {
            LogLevel::ERROR => match *other {
                        LogLevel::ERROR => Ordering::Equal,
                        _ => Ordering::Greater,
                    },
            LogLevel::WARN => match *other {
                        LogLevel::ERROR => Ordering::Less,
                        LogLevel::WARN => Ordering::Equal,
                        _ => Ordering::Greater,
                    },
            LogLevel::INFO => match *other {
                        LogLevel::VERBOSE => Ordering::Greater,
                        LogLevel::INFO => Ordering::Equal,
                        _ => Ordering::Less,
                    },
            LogLevel::VERBOSE => match *other {
                        LogLevel::VERBOSE => Ordering::Equal,
                        _ => Ordering::Less,
                    },
        }
    }
}

impl Eq for LogLevel {}

impl PartialEq for LogLevel {

    fn eq(&self, other: &Self) -> bool {
        self.cmp(other) == Ordering::Equal
    }

    fn ne(&self, other: &Self) -> bool {
        !self.eq(other)
    }

}

impl PartialOrd for LogLevel {

    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }

    fn lt(&self, other: &Self) -> bool {
        self.cmp(other) == Ordering::Less
    }

    fn le(&self, other: &Self) -> bool {
        self.cmp(other) != Ordering::Greater
    }

    fn gt(&self, other: &Self) -> bool {
        self.cmp(other) == Ordering::Greater
    }

    fn ge(&self, other: &Self) -> bool {
        self.cmp(other) != Ordering::Less
    }
}

/// Set global log level here
static LOG_LEVEL: LogLevel = LogLevel::INFO;

/// the log function returning a result
///
/// # Examples
/// '''
/// log(LogLevel::ERROR, format_args!("This is bad!")).unwrap();
/// '''
pub fn log(level: LogLevel, args: fmt::Arguments) -> Result<(), Error> {

    if level < LOG_LEVEL {
        return Ok(());
    }

    let stderr = io::stderr();
    let stdout = io::stdout();

    let mut stderr_lock = stderr.lock();
    let mut stdout_lock = stdout.lock();

    let cur_time = time::now();

    match level {
        LogLevel::ERROR => writeln!(stderr_lock, "[ERROR] {}:{}:{} - {}", cur_time.tm_hour, cur_time.tm_min, cur_time.tm_sec, args),
        LogLevel::WARN => writeln!(stdout_lock, "[WARN] {}:{}:{} - {}", cur_time.tm_hour, cur_time.tm_min, cur_time.tm_sec, args),
        LogLevel::INFO => writeln!(stdout_lock, "[INFO] {}:{}:{} - {}", cur_time.tm_hour, cur_time.tm_min, cur_time.tm_sec, args),
        LogLevel::VERBOSE => writeln!(stdout_lock, "[VERBOSE] {}:{}:{} - {}", cur_time.tm_hour, cur_time.tm_min, cur_time.tm_sec, args),
    }

}

/// a log function ignoring any failure
/// "log something, if possible"
///
/// # Examples
/// '''
/// try_log(LogLevel::ERROR, format_args!("This is bad!"));
/// '''
pub fn try_log(level: LogLevel, args: fmt::Arguments) {
    let _ = log(level, args);
}

// Helper Macro

/// Error Macro
///
/// # Examples
/// '''
/// error!("This is bad!");
/// '''
macro_rules! log_error {
    ($($arg:tt)*) => (::utils::log::try_log(::utils::log::LogLevel::ERROR, format_args!($($arg)*)));
}

/// Warning Macro
///
/// # Examples
/// '''
/// log_warn!("This is maybe bad?!");
/// '''
macro_rules! log_warn {
    ($($arg:tt)*) => (::utils::log::try_log(::utils::log::LogLevel::WARN, format_args!($($arg)*)));
}

/// Info Macro
///
/// # Examples
/// '''
/// log_info!("This is just to let you know!");
/// '''
macro_rules! log_info {
    ($($arg:tt)*) => (::utils::log::try_log(::utils::log::LogLevel::INFO, format_args!($($arg)*)));
}

/// Verbose Macro
///
/// # Examples
/// '''
/// log_verbose!("You must really like spam!");
/// '''
macro_rules! log_verbose {
    ($($arg:tt)*) => (::utils::log::try_log(::utils::log::LogLevel::VERBOSE, format_args!($($arg)*)));
}

#[test]
fn test() {
    log_info!("Test!");
}

//To-Do add a way to check the result automatically
#[test]
fn multi_thread_test() {
    let mut joins = Vec::new();
    for _ in 0..10 {
        joins.push(std::thread::spawn(move || {
            log_info!("No corruption should happen in this ultra-extra-super-long string output even if run in multiple threads.");
        }));
    }
    for handle in joins {
        let _ = handle.join();
    }
}
<|endoftext|>


<commit_before>//! A set of utilities to help with common use cases that are not required to
//! fully use the library.

mod colour;

mod message_builder;

pub use self::colour::Colour;
pub use self::message_builder::{Content, ContentModifier, MessageBuilder};

// Note: Here for BC purposes.
#[cfg(feature = "builder")]
pub use super::builder;

use base64;
use std::ffi::OsStr;
use std::fs::File;
use std::io::Read;
use std::path::Path;
use internal::prelude::*;
use model::{EmojiId, EmojiIdentifier};
use cache::Cache;
use ::CACHE;

/// Determines if a name is NSFW.
///
/// This checks that the name is either `"nsfw"` or, for names longer than that,
/// is prefixed with `"nsfw"`.
///
/// **Note**: Whether a channel is NSFW is done client-side, as a field for the
/// NSFW-ness of a channel is not sent to clients. Discord's requirements for
/// defining a channel as NSFW can change at any time.
///
/// # Examples
///
/// Check that a channel named `"nsfw"` is in fact NSFW:
///
/// ```rust
/// use serenity::utils;
///
/// assert!(utils::is_nsfw("nsfw"));
/// ```
///
/// Check that a channel named `"cats"` is _not_ NSFW:
///
/// ```rust
/// use serenity::utils;
///
/// assert!(!utils::is_nsfw("cats"));
/// ```
///
/// Check that a channel named `"nsfw-stuff"` _is_ NSFW:
///
/// ```rust
/// use serenity::utils;
///
/// assert!(utils::is_nsfw("nsfw-stuff"));
/// ```
///
/// Channels prefixed with `"nsfw"` but not the hyphen (`'-'`) are _not_
/// considered NSFW:
///
/// ```rust
/// use serenity::utils;
///
/// assert!(!utils::is_nsfw("nsfwstuff"));
/// ```
pub fn is_nsfw(name: &str) -> bool {
    if name.len() == 4 {
        &name[..4] == "nsfw"
    } else if name.len() > 4 {
        &name[..5] == "nsfw-"
    } else {
        false
    }
}

/// Retrieves the "code" part of an invite out of a URL.
///
/// # Examples
///
/// Three formats of [invite][`RichInvite`] codes are supported:
///
/// 1. Retrieving the code from the URL `"https://discord.gg/0cDvIgU2voY8RSYL"`:
///
/// ```rust
/// use serenity::utils;
///
/// let url = "https://discord.gg/0cDvIgU2voY8RSYL";
///
/// assert_eq!(utils::parse_invite(url), "0cDvIgU2voY8RSYL");
/// ```
///
/// 2. Retrieving the code from the URL `"http://discord.gg/0cDvIgU2voY8RSYL"`:
///
/// ```rust
/// use serenity::utils;
///
/// let url = "http://discord.gg/0cDvIgU2voY8RSYL";
///
/// assert_eq!(utils::parse_invite(url), "0cDvIgU2voY8RSYL");
/// ```
///
/// 3. Retrieving the code from the URL `"discord.gg/0cDvIgU2voY8RSYL"`:
///
/// ```rust
/// use serenity::utils;
///
/// let url = "discord.gg/0cDvIgU2voY8RSYL";
///
/// assert_eq!(utils::parse_invite(url), "0cDvIgU2voY8RSYL");
/// ```
///
/// [`RichInvite`]: ../model/struct.RichInvite.html
pub fn parse_invite(code: &str) -> &str {
    if code.starts_with("https://discord.gg/") {
        &code[19..]
    } else if code.starts_with("http://discord.gg/") {
        &code[18..]
    } else if code.starts_with("discord.gg/") {
        &code[11..]
    } else {
        code
    }
}

/// Retreives an Id from a user mention.
///
/// If the mention is invalid, then `None` is returned.
///
/// # Examples
///
/// Retrieving an Id from a valid [`User`] mention:
///
/// ```rust
/// use serenity::utils::parse_username;
///
/// // regular username mention
/// assert_eq!(parse_username("<@114941315417899012>"), Some(114941315417899012));
///
/// // nickname mention
/// assert_eq!(parse_username("<@!114941315417899012>"), Some(114941315417899012));
/// ```
///
/// Asserting that an invalid username or nickname mention returns `None`:
///
/// ```rust
/// use serenity::utils::parse_username;
///
/// assert!(parse_username("<@1149413154aa17899012").is_none());
/// assert!(parse_username("<@!11494131541789a90b1c2").is_none());
/// ```
///
/// [`User`]: ../model/struct.User.html
pub fn parse_username(mention: &str) -> Option<u64> {
    if mention.len() < 4 {
        return None;
    }

    if mention.starts_with("<@!") {
        let len = mention.len() - 1;
        mention[3..len].parse::<u64>().ok()
    } else if mention.starts_with("<@") {
        let len = mention.len() - 1;
        mention[2..len].parse::<u64>().ok()
    } else {
        None
    }
}

/// Retreives an Id from a role mention.
///
/// If the mention is invalid, then `None` is returned.
///
/// # Examples
///
/// Retrieving an Id from a valid [`Role`] mention:
///
/// ```rust
/// use serenity::utils::parse_role;
///
/// assert_eq!(parse_role("<@&136107769680887808>"), Some(136107769680887808));
/// ```
///
/// Asserting that an invalid role mention returns `None`:
///
/// ```rust
/// use serenity::utils::parse_role;
///
/// assert!(parse_role("<@&136107769680887808").is_none());
/// ```
///
/// [`Role`]: ../model/struct.Role.html
pub fn parse_role(mention: &str) -> Option<u64> {
    if mention.len() < 4 {
        return None;
    }

    if mention.starts_with("<@&") && mention.ends_with('>') {
        let len = mention.len() - 1;
        mention[3..len].parse::<u64>().ok()
    } else {
        None
    }
}

/// Retreives an Id from a channel mention.
///
/// If the channel mention is invalid, then `None` is returned.
///
/// # Examples
///
/// Retrieving an Id from a valid [`Channel`] mention:
///
/// ```rust
/// use serenity::utils::parse_channel;
///
/// assert_eq!(parse_channel("<#81384788765712384>"), Some(81384788765712384));
/// ```
///
/// Asserting that an invalid channel mention returns `None`:
///
/// ```rust
/// use serenity::utils::parse_channel;
///
/// assert!(parse_channel("<#!81384788765712384>").is_none());
/// assert!(parse_channel("<#81384788765712384").is_none());
/// ```
///
/// [`Channel`]: ../model/enum.Channel.html
pub fn parse_channel(mention: &str) -> Option<u64> {
    if mention.len() < 4 {
        return None;
    }

    if mention.starts_with("<#") && mention.ends_with('>') {
        let len = mention.len() - 1;
        mention[2..len].parse::<u64>().ok()
    } else {
        None
    }
}

/// Retreives the name and Id from an emoji mention, in the form of an
/// `EmojiIdentifier`.
///
/// If the emoji usage is invalid, then `None` is returned.
///
/// # Examples
///
/// Ensure that a valid [`Emoji`] usage is correctly parsed:
///
/// ```rust
/// use serenity::model::{EmojiId, EmojiIdentifier};
/// use serenity::utils::parse_emoji;
///
/// let expected = EmojiIdentifier {
///     id: EmojiId(302516740095606785),
///     name: "smugAnimeFace".to_owned(),
/// };
///
/// assert_eq!(parse_emoji("<:smugAnimeFace:302516740095606785>").unwrap(), expected);
/// ```
///
/// Asserting that an invalid emoji usage returns `None`:
///
/// ```rust
/// use serenity::utils::parse_emoji;
///
/// assert!(parse_emoji("<:smugAnimeFace:302516740095606785").is_none());
/// ```
///
/// [`Emoji`]: ../model/struct.Emoji.html
pub fn parse_emoji(mention: &str) -> Option<EmojiIdentifier> {
    let len = mention.len();

    if len < 6 || len > 56 {
        return None;
    }

    if mention.starts_with("<:") && mention.ends_with('>') {
        let mut name = String::default();
        let mut id = String::default();

        for (i, x) in mention[2..].chars().enumerate() {
            if x == ':' {
                let from = i + 3;

                for y in mention[from..].chars() {
                    if y == '>' {
                        break;
                    } else {
                        id.push(y);
                    }
                }

                break;
            } else {
                name.push(x);
            }
        }

        match id.parse::<u64>() {
            Ok(x) => Some(EmojiIdentifier {
                name: name,
                id: EmojiId(x),
            }),
            _ => None,
        }
    } else {
        None
    }
}

/// Reads an image from a path and encodes it into base64.
///
/// This can be used for methods like [`EditProfile::avatar`].
///
/// # Examples
///
/// Reads an image located at `./cat.png` into a base64-encoded string:
///
/// ```rust,no_run
/// use serenity::utils;
///
/// let image = utils::read_image("./cat.png").expect("Failed to read image");
/// ```
///
/// [`EditProfile::avatar`]: ../builder/struct.EditProfile.html#method.avatar
pub fn read_image<P: AsRef<Path>>(path: P) -> Result<String> {
    let path = path.as_ref();

    let mut v = Vec::default();
    let mut f = File::open(path)?;
    let _ = f.read_to_end(&mut v);

    let b64 = base64::encode(&v);
    let ext = if path.extension() == Some(OsStr::new("png")) {
        "png"
    } else {
        "jpg"
    };

    Ok(format!("data:image/{};base64,{}", ext, b64))
}

/// Turns a string into a vector of string arguments, splitting by spaces, but
/// parsing content within quotes as one individual argument.
///
/// # Examples
///
/// Parsing two quoted commands:
///
/// ```rust
/// use serenity::utils::parse_quotes;
///
/// let command = r#""this is the first" "this is the second""#;
/// let expected = vec![
///     "this is the first".to_owned(),
///     "this is the second".to_owned()
/// ];
///
/// assert_eq!(parse_quotes(command), expected);
/// ```
///
/// ```rust
/// use serenity::utils::parse_quotes;
///
/// let command = r#""this is a quoted command that doesn't have an ending quotation"#;
/// let expected = vec![
///     "this is a quoted command that doesn't have an ending quotation".to_owned(),
/// ];
///
/// assert_eq!(parse_quotes(command), expected);
/// ```
pub fn parse_quotes(s: &str) -> Vec<String> {
    let mut args = vec![];
    let mut in_string = false;
    let mut escaping = false;
    let mut current_str = String::default();

    for x in s.chars() {
        if in_string {
            if x == '\\' && !escaping {
                escaping = true;
            } else if x == '"' && !escaping {
                if !current_str.is_empty() {
                    args.push(current_str);
                }

                current_str = String::default();
                in_string = false;
            } else {
                current_str.push(x);
                escaping = false;
            }
        } else if x == ' ' {
            if !current_str.is_empty() {
                args.push(current_str.clone());
            }

            current_str = String::default();
        } else if x == '"' {
            if !current_str.is_empty() {
                args.push(current_str.clone());
            }

            in_string = true;
            current_str = String::default();
        } else {
            current_str.push(x);
        }
    }

    if !current_str.is_empty() {
        args.push(current_str);
    }

    args
}

/// Calculates the Id of the shard responsible for a guild, given its Id and
/// total number of shards used.
///
/// # Examples
///
/// Retrieve the Id of the shard for a guild with Id `81384788765712384`, using
/// 17 shards:
///
/// ```rust
/// use serenity::utils;
///
/// assert_eq!(utils::shard_id(81384788765712384, 17), 7);
/// ```
#[inline]
pub fn shard_id(guild_id: u64, shard_count: u64) -> u64 { (guild_id >> 22) % shard_count }

/// A function for doing automatic `read`ing (and the releasing of the guard as well)
/// This is particularly useful if you just want to use the cache for this one time,
/// or don't want to be messing with the `RwLock` directly.
///
/// # Examples
///
/// Return the bot's id
///
/// ```rust,ignore
/// use serenity::utils;
///
/// // assuming that the id is `1234`:
/// assert_eq!(1234, utils::with_cache(|cache| cache.user.id));
/// ```
pub fn with_cache<T, F>(f: F) -> T where F: Fn(&Cache) -> T {
    let cache = CACHE.read().unwrap();
    f(&cache)
}

/// Like [`with_cache`] but as the name says, allows for modifications to be done.
///
/// # Examples
///
/// Return the bot's id, and changes the shard count
///
/// ```rust,ignore
/// use serenity::utils;
///
/// // assuming that the id is `1234`:
/// assert_eq!(1234, utils::with_cache_mut(|cache| { cache.shard_count = 8; cache.user.id }));
/// ```
///
/// [`with_cache`]: #fn.with_cache
pub fn with_cache_mut<T, F>(mut f: F) -> T where F: FnMut(&mut Cache) -> T {
    let mut cache = CACHE.write().unwrap();
    f(&mut cache)
}<commit_msg>Apply rustfmt fixes<commit_after>//! A set of utilities to help with common use cases that are not required to
//! fully use the library.

mod colour;

mod message_builder;

pub use self::colour::Colour;
pub use self::message_builder::{Content, ContentModifier, MessageBuilder};

// Note: Here for BC purposes.
#[cfg(feature = "builder")]
pub use super::builder;

use base64;
use std::ffi::OsStr;
use std::fs::File;
use std::io::Read;
use std::path::Path;
use internal::prelude::*;
use model::{EmojiId, EmojiIdentifier};
use cache::Cache;
use CACHE;

/// Determines if a name is NSFW.
///
/// This checks that the name is either `"nsfw"` or, for names longer than that,
/// is prefixed with `"nsfw"`.
///
/// **Note**: Whether a channel is NSFW is done client-side, as a field for the
/// NSFW-ness of a channel is not sent to clients. Discord's requirements for
/// defining a channel as NSFW can change at any time.
///
/// # Examples
///
/// Check that a channel named `"nsfw"` is in fact NSFW:
///
/// ```rust
/// use serenity::utils;
///
/// assert!(utils::is_nsfw("nsfw"));
/// ```
///
/// Check that a channel named `"cats"` is _not_ NSFW:
///
/// ```rust
/// use serenity::utils;
///
/// assert!(!utils::is_nsfw("cats"));
/// ```
///
/// Check that a channel named `"nsfw-stuff"` _is_ NSFW:
///
/// ```rust
/// use serenity::utils;
///
/// assert!(utils::is_nsfw("nsfw-stuff"));
/// ```
///
/// Channels prefixed with `"nsfw"` but not the hyphen (`'-'`) are _not_
/// considered NSFW:
///
/// ```rust
/// use serenity::utils;
///
/// assert!(!utils::is_nsfw("nsfwstuff"));
/// ```
pub fn is_nsfw(name: &str) -> bool {
    if name.len() == 4 {
        &name[..4] == "nsfw"
    } else if name.len() > 4 {
        &name[..5] == "nsfw-"
    } else {
        false
    }
}

/// Retrieves the "code" part of an invite out of a URL.
///
/// # Examples
///
/// Three formats of [invite][`RichInvite`] codes are supported:
///
/// 1. Retrieving the code from the URL `"https://discord.gg/0cDvIgU2voY8RSYL"`:
///
/// ```rust
/// use serenity::utils;
///
/// let url = "https://discord.gg/0cDvIgU2voY8RSYL";
///
/// assert_eq!(utils::parse_invite(url), "0cDvIgU2voY8RSYL");
/// ```
///
/// 2. Retrieving the code from the URL `"http://discord.gg/0cDvIgU2voY8RSYL"`:
///
/// ```rust
/// use serenity::utils;
///
/// let url = "http://discord.gg/0cDvIgU2voY8RSYL";
///
/// assert_eq!(utils::parse_invite(url), "0cDvIgU2voY8RSYL");
/// ```
///
/// 3. Retrieving the code from the URL `"discord.gg/0cDvIgU2voY8RSYL"`:
///
/// ```rust
/// use serenity::utils;
///
/// let url = "discord.gg/0cDvIgU2voY8RSYL";
///
/// assert_eq!(utils::parse_invite(url), "0cDvIgU2voY8RSYL");
/// ```
///
/// [`RichInvite`]: ../model/struct.RichInvite.html
pub fn parse_invite(code: &str) -> &str {
    if code.starts_with("https://discord.gg/") {
        &code[19..]
    } else if code.starts_with("http://discord.gg/") {
        &code[18..]
    } else if code.starts_with("discord.gg/") {
        &code[11..]
    } else {
        code
    }
}

/// Retreives an Id from a user mention.
///
/// If the mention is invalid, then `None` is returned.
///
/// # Examples
///
/// Retrieving an Id from a valid [`User`] mention:
///
/// ```rust
/// use serenity::utils::parse_username;
///
/// // regular username mention
/// assert_eq!(parse_username("<@114941315417899012>"), Some(114941315417899012));
///
/// // nickname mention
/// assert_eq!(parse_username("<@!114941315417899012>"), Some(114941315417899012));
/// ```
///
/// Asserting that an invalid username or nickname mention returns `None`:
///
/// ```rust
/// use serenity::utils::parse_username;
///
/// assert!(parse_username("<@1149413154aa17899012").is_none());
/// assert!(parse_username("<@!11494131541789a90b1c2").is_none());
/// ```
///
/// [`User`]: ../model/struct.User.html
pub fn parse_username(mention: &str) -> Option<u64> {
    if mention.len() < 4 {
        return None;
    }

    if mention.starts_with("<@!") {
        let len = mention.len() - 1;
        mention[3..len].parse::<u64>().ok()
    } else if mention.starts_with("<@") {
        let len = mention.len() - 1;
        mention[2..len].parse::<u64>().ok()
    } else {
        None
    }
}

/// Retreives an Id from a role mention.
///
/// If the mention is invalid, then `None` is returned.
///
/// # Examples
///
/// Retrieving an Id from a valid [`Role`] mention:
///
/// ```rust
/// use serenity::utils::parse_role;
///
/// assert_eq!(parse_role("<@&136107769680887808>"), Some(136107769680887808));
/// ```
///
/// Asserting that an invalid role mention returns `None`:
///
/// ```rust
/// use serenity::utils::parse_role;
///
/// assert!(parse_role("<@&136107769680887808").is_none());
/// ```
///
/// [`Role`]: ../model/struct.Role.html
pub fn parse_role(mention: &str) -> Option<u64> {
    if mention.len() < 4 {
        return None;
    }

    if mention.starts_with("<@&") && mention.ends_with('>') {
        let len = mention.len() - 1;
        mention[3..len].parse::<u64>().ok()
    } else {
        None
    }
}

/// Retreives an Id from a channel mention.
///
/// If the channel mention is invalid, then `None` is returned.
///
/// # Examples
///
/// Retrieving an Id from a valid [`Channel`] mention:
///
/// ```rust
/// use serenity::utils::parse_channel;
///
/// assert_eq!(parse_channel("<#81384788765712384>"), Some(81384788765712384));
/// ```
///
/// Asserting that an invalid channel mention returns `None`:
///
/// ```rust
/// use serenity::utils::parse_channel;
///
/// assert!(parse_channel("<#!81384788765712384>").is_none());
/// assert!(parse_channel("<#81384788765712384").is_none());
/// ```
///
/// [`Channel`]: ../model/enum.Channel.html
pub fn parse_channel(mention: &str) -> Option<u64> {
    if mention.len() < 4 {
        return None;
    }

    if mention.starts_with("<#") && mention.ends_with('>') {
        let len = mention.len() - 1;
        mention[2..len].parse::<u64>().ok()
    } else {
        None
    }
}

/// Retreives the name and Id from an emoji mention, in the form of an
/// `EmojiIdentifier`.
///
/// If the emoji usage is invalid, then `None` is returned.
///
/// # Examples
///
/// Ensure that a valid [`Emoji`] usage is correctly parsed:
///
/// ```rust
/// use serenity::model::{EmojiId, EmojiIdentifier};
/// use serenity::utils::parse_emoji;
///
/// let expected = EmojiIdentifier {
///     id: EmojiId(302516740095606785),
///     name: "smugAnimeFace".to_owned(),
/// };
///
/// assert_eq!(parse_emoji("<:smugAnimeFace:302516740095606785>").unwrap(), expected);
/// ```
///
/// Asserting that an invalid emoji usage returns `None`:
///
/// ```rust
/// use serenity::utils::parse_emoji;
///
/// assert!(parse_emoji("<:smugAnimeFace:302516740095606785").is_none());
/// ```
///
/// [`Emoji`]: ../model/struct.Emoji.html
pub fn parse_emoji(mention: &str) -> Option<EmojiIdentifier> {
    let len = mention.len();

    if len < 6 || len > 56 {
        return None;
    }

    if mention.starts_with("<:") && mention.ends_with('>') {
        let mut name = String::default();
        let mut id = String::default();

        for (i, x) in mention[2..].chars().enumerate() {
            if x == ':' {
                let from = i + 3;

                for y in mention[from..].chars() {
                    if y == '>' {
                        break;
                    } else {
                        id.push(y);
                    }
                }

                break;
            } else {
                name.push(x);
            }
        }

        match id.parse::<u64>() {
            Ok(x) => Some(EmojiIdentifier {
                name: name,
                id: EmojiId(x),
            }),
            _ => None,
        }
    } else {
        None
    }
}

/// Reads an image from a path and encodes it into base64.
///
/// This can be used for methods like [`EditProfile::avatar`].
///
/// # Examples
///
/// Reads an image located at `./cat.png` into a base64-encoded string:
///
/// ```rust,no_run
/// use serenity::utils;
///
/// let image = utils::read_image("./cat.png").expect("Failed to read image");
/// ```
///
/// [`EditProfile::avatar`]: ../builder/struct.EditProfile.html#method.avatar
pub fn read_image<P: AsRef<Path>>(path: P) -> Result<String> {
    let path = path.as_ref();

    let mut v = Vec::default();
    let mut f = File::open(path)?;
    let _ = f.read_to_end(&mut v);

    let b64 = base64::encode(&v);
    let ext = if path.extension() == Some(OsStr::new("png")) {
        "png"
    } else {
        "jpg"
    };

    Ok(format!("data:image/{};base64,{}", ext, b64))
}

/// Turns a string into a vector of string arguments, splitting by spaces, but
/// parsing content within quotes as one individual argument.
///
/// # Examples
///
/// Parsing two quoted commands:
///
/// ```rust
/// use serenity::utils::parse_quotes;
///
/// let command = r#""this is the first" "this is the second""#;
/// let expected = vec![
///     "this is the first".to_owned(),
///     "this is the second".to_owned()
/// ];
///
/// assert_eq!(parse_quotes(command), expected);
/// ```
///
/// ```rust
/// use serenity::utils::parse_quotes;
///
/// let command = r#""this is a quoted command that doesn't have an ending quotation"#;
/// let expected = vec![
///     "this is a quoted command that doesn't have an ending quotation".to_owned(),
/// ];
///
/// assert_eq!(parse_quotes(command), expected);
/// ```
pub fn parse_quotes(s: &str) -> Vec<String> {
    let mut args = vec![];
    let mut in_string = false;
    let mut escaping = false;
    let mut current_str = String::default();

    for x in s.chars() {
        if in_string {
            if x == '\\' && !escaping {
                escaping = true;
            } else if x == '"' && !escaping {
                if !current_str.is_empty() {
                    args.push(current_str);
                }

                current_str = String::default();
                in_string = false;
            } else {
                current_str.push(x);
                escaping = false;
            }
        } else if x == ' ' {
            if !current_str.is_empty() {
                args.push(current_str.clone());
            }

            current_str = String::default();
        } else if x == '"' {
            if !current_str.is_empty() {
                args.push(current_str.clone());
            }

            in_string = true;
            current_str = String::default();
        } else {
            current_str.push(x);
        }
    }

    if !current_str.is_empty() {
        args.push(current_str);
    }

    args
}

/// Calculates the Id of the shard responsible for a guild, given its Id and
/// total number of shards used.
///
/// # Examples
///
/// Retrieve the Id of the shard for a guild with Id `81384788765712384`, using
/// 17 shards:
///
/// ```rust
/// use serenity::utils;
///
/// assert_eq!(utils::shard_id(81384788765712384, 17), 7);
/// ```
#[inline]
pub fn shard_id(guild_id: u64, shard_count: u64) -> u64 { (guild_id >> 22) % shard_count }

/// A function for doing automatic `read`ing (and the releasing of the guard as well)
/// This is particularly useful if you just want to use the cache for this one time,
/// or don't want to be messing with the `RwLock` directly.
///
/// # Examples
///
/// Return the bot's id
///
/// ```rust,ignore
/// use serenity::utils;
///
/// // assuming that the id is `1234`:
/// assert_eq!(1234, utils::with_cache(|cache| cache.user.id));
/// ```
pub fn with_cache<T, F>(f: F) -> T
    where F: Fn(&Cache) -> T {
    let cache = CACHE.read().unwrap();
    f(&cache)
}

/// Like [`with_cache`] but as the name says, allows for modifications to be done.
///
/// # Examples
///
/// Return the bot's id, and changes the shard count
///
/// ```rust,ignore
/// use serenity::utils;
///
/// // assuming that the id is `1234`:
/// assert_eq!(1234, utils::with_cache_mut(|cache| { cache.shard_count = 8; cache.user.id }));
/// ```
///
/// [`with_cache`]: #fn.with_cache
pub fn with_cache_mut<T, F>(mut f: F) -> T
    where F: FnMut(&mut Cache) -> T {
    let mut cache = CACHE.write().unwrap();
    f(&mut cache)
}
<|endoftext|>


<commit_before>use std::ops::Add;

pub enum LpType {
    Binary,
    Integer,
    Continuous
}

#[derive(Debug, Clone, Copy)]
pub enum LpVariable {
    BinaryVariable {
        name: &'static str,
    },
    IntegerVariable {
        name: &'static str,
        lower_bound: Option<i32>,
        upper_bound: Option<i32>,
    },
    ContinuousVariable {
        name: &'static str,
        lower_bound: Option<i32>,
        upper_bound: Option<i32>,
    }
}

impl LpVariable {
    pub fn new(name: &'static str, var_type: LpType) -> LpVariable {
        match var_type {
            LpType::Binary => LpVariable::BinaryVariable { name: name },
            LpType::Integer => LpVariable::IntegerVariable { name: name, lower_bound: None, upper_bound: None },
            LpType::Continuous => LpVariable::ContinuousVariable { name: name, lower_bound: None, upper_bound: None }

        }
    }
    fn lower_bound(&self, lw: i32) -> LpVariable {
        match self {
            &LpVariable::BinaryVariable { name: ref n } =>
                LpVariable::BinaryVariable {
                    name: n.clone()
                },
            &LpVariable::IntegerVariable { name: ref n, lower_bound: _, upper_bound: u } =>
                LpVariable::IntegerVariable {
                    name: n.clone(),
                    lower_bound: Some(lw),
                    upper_bound: u
                },
            &LpVariable::ContinuousVariable { name: ref n, lower_bound: _, upper_bound: u } =>
                LpVariable::ContinuousVariable {
                    name: n.clone(),
                    lower_bound: Some(lw),
                    upper_bound: u
                }
        }
    }
    fn upper_bound(&self, up: i32) -> LpVariable {
        match self {
            &LpVariable::BinaryVariable { name: ref n } =>
                LpVariable::BinaryVariable {
                    name: n.clone()
                },
            &LpVariable::IntegerVariable { name: ref n, lower_bound: l, upper_bound: _ } =>
                LpVariable::IntegerVariable {
                    name: n.clone(),
                    lower_bound: l,
                    upper_bound: Some(up)
                },
            &LpVariable::ContinuousVariable { name: ref n, lower_bound: l, upper_bound: _ } =>
                LpVariable::ContinuousVariable {
                    name: n.clone(),
                    lower_bound: l,
                    upper_bound: Some(up)
                }
        }
    }
}

enum LpExpression {
    LpElement,
    Expr(Box<LpExpression>)
}

impl Add for LpVariable {
    type Output = LpVariable;
    fn add(self, _rhs: LpVariable) -> LpVariable {
        println!("Adding!");
        LpVariable::BinaryVariable { name: "coucou" }
    }
}
<commit_msg>Remove useless clone()<commit_after>use std::ops::Add;

pub enum LpType {
    Binary,
    Integer,
    Continuous
}

#[derive(Debug, Clone, Copy)]
pub enum LpVariable {
    BinaryVariable {
        name: &'static str,
    },
    IntegerVariable {
        name: &'static str,
        lower_bound: Option<i32>,
        upper_bound: Option<i32>,
    },
    ContinuousVariable {
        name: &'static str,
        lower_bound: Option<i32>,
        upper_bound: Option<i32>,
    }
}

impl LpVariable {
    pub fn new(name: &'static str, var_type: LpType) -> LpVariable {
        match var_type {
            LpType::Binary => LpVariable::BinaryVariable { name: name },
            LpType::Integer => LpVariable::IntegerVariable { name: name, lower_bound: None, upper_bound: None },
            LpType::Continuous => LpVariable::ContinuousVariable { name: name, lower_bound: None, upper_bound: None }

        }
    }
    fn lower_bound(&self, lw: i32) -> LpVariable {
        match self {
            &LpVariable::BinaryVariable { name: ref n } =>
                LpVariable::BinaryVariable {
                    name: n
                },
            &LpVariable::IntegerVariable { name: ref n, lower_bound: _, upper_bound: u } =>
                LpVariable::IntegerVariable {
                    name: n,
                    lower_bound: Some(lw),
                    upper_bound: u
                },
            &LpVariable::ContinuousVariable { name: ref n, lower_bound: _, upper_bound: u } =>
                LpVariable::ContinuousVariable {
                    name: n,
                    lower_bound: Some(lw),
                    upper_bound: u
                }
        }
    }
    fn upper_bound(&self, up: i32) -> LpVariable {
        match self {
            &LpVariable::BinaryVariable { name: ref n } =>
                LpVariable::BinaryVariable {
                    name: n.clone()
                },
            &LpVariable::IntegerVariable { name: ref n, lower_bound: l, upper_bound: _ } =>
                LpVariable::IntegerVariable {
                    name: n.clone(),
                    lower_bound: l,
                    upper_bound: Some(up)
                },
            &LpVariable::ContinuousVariable { name: ref n, lower_bound: l, upper_bound: _ } =>
                LpVariable::ContinuousVariable {
                    name: n.clone(),
                    lower_bound: l,
                    upper_bound: Some(up)
                }
        }
    }
}

enum LpExpression {
    LpElement,
    Expr(Box<LpExpression>)
}

impl Add for LpVariable {
    type Output = LpVariable;
    fn add(self, _rhs: LpVariable) -> LpVariable {
        println!("Adding!");
        LpVariable::BinaryVariable { name: "coucou" }
    }
}
<|endoftext|>


<commit_before>use graphics::math::Matrix2d;
use std::f64;
use vec2::Vec2;

#[derive(Copy, Clone)]
pub struct Transform {
    position: Vec2,
    rotation: f64,
}

impl Transform {
    pub fn new() -> Transform {
        // zero format for Matrix2d. Reverse engineered from Piston.
        // x = 0, y = 0, rotation = 0
        Transform {
            position: Vec2 { x: 0.0, y: 0.0 },
            rotation: 0.0,
        }
    }

    pub fn from_x_y_rotation(x: f64, y: f64, rotation: f64) -> Transform {
        let mut value = Transform::new();
        *value.mut_x() = x;
        *value.mut_y() = y;
        *value.mut_rotation() = rotation;
        value
    }

    pub fn position(&self) -> &Vec2 {
        &self.position
    }

    pub fn mut_position(&mut self) -> &mut Vec2 {
        &mut self.position
    }

    pub fn x(&self) -> &f64 {
        &self.position.x
    }

    pub fn y(&self) -> &f64 {
        &self.position.y
    }

    pub fn rotation(&self) -> &f64 {
        &self.rotation
    }

    pub fn mut_x(&mut self) -> &mut f64 {
        &mut self.position.x
    }

    pub fn mut_y(&mut self) -> &mut f64 {
        &mut self.position.y
    }

    pub fn mut_rotation(&mut self) -> &mut f64 {
        self.rotation %= 2.0 * f64::consts::PI;
        &mut self.rotation
    }

    pub fn forward_vec2(&self) -> Vec2 {
        Vec2 {
            x: -self.rotation().sin(),
            y: self.rotation().cos(),
        }
    }

    pub fn right_vec2(&self) -> Vec2 {
        Vec2 {
            x: self.rotation().cos(),
            y: -self.rotation().sin(),
        }
    }
}

// Raw format reverse engineered from Piston internals.
pub fn get_raw(nitro_transform: &Transform) -> Matrix2d {
    let c = nitro_transform.rotation.cos();
    let s = nitro_transform.rotation.sin();
    [[c, -s, nitro_transform.position.x], [s, c, nitro_transform.position.y]]
}
<commit_msg>Woops, fix the right vec optimization.<commit_after>use graphics::math::Matrix2d;
use std::f64;
use vec2::Vec2;

#[derive(Copy, Clone)]
pub struct Transform {
    position: Vec2,
    rotation: f64,
}

impl Transform {
    pub fn new() -> Transform {
        // zero format for Matrix2d. Reverse engineered from Piston.
        // x = 0, y = 0, rotation = 0
        Transform {
            position: Vec2 { x: 0.0, y: 0.0 },
            rotation: 0.0,
        }
    }

    pub fn from_x_y_rotation(x: f64, y: f64, rotation: f64) -> Transform {
        let mut value = Transform::new();
        *value.mut_x() = x;
        *value.mut_y() = y;
        *value.mut_rotation() = rotation;
        value
    }

    pub fn position(&self) -> &Vec2 {
        &self.position
    }

    pub fn mut_position(&mut self) -> &mut Vec2 {
        &mut self.position
    }

    pub fn x(&self) -> &f64 {
        &self.position.x
    }

    pub fn y(&self) -> &f64 {
        &self.position.y
    }

    pub fn rotation(&self) -> &f64 {
        &self.rotation
    }

    pub fn mut_x(&mut self) -> &mut f64 {
        &mut self.position.x
    }

    pub fn mut_y(&mut self) -> &mut f64 {
        &mut self.position.y
    }

    pub fn mut_rotation(&mut self) -> &mut f64 {
        self.rotation %= 2.0 * f64::consts::PI;
        &mut self.rotation
    }

    pub fn forward_vec2(&self) -> Vec2 {
        Vec2 {
            x: -self.rotation().sin(),
            y: self.rotation().cos(),
        }
    }

    pub fn right_vec2(&self) -> Vec2 {
        Vec2 {
            x: self.rotation().cos(),
            y: self.rotation().sin(),
        }
    }
}

// Raw format reverse engineered from Piston internals.
pub fn get_raw(nitro_transform: &Transform) -> Matrix2d {
    let c = nitro_transform.rotation.cos();
    let s = nitro_transform.rotation.sin();
    [[c, -s, nitro_transform.position.x], [s, c, nitro_transform.position.y]]
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::fs::{self, OpenOptions};
use std::io::{BufWriter, Read, Write};
use std::path::Path;
use std::process::Command;

use rayon::prelude::*;
use toml;

mod codegen;

use crate::cargo;
use crate::{Service, ServiceConfig, ServiceDefinition};

fn generate_examples(crate_dir_path: &Path) -> Option<String> {
    let examples_dir_path = crate_dir_path.join("examples");

    if !examples_dir_path.exists() {
        return None;
    }

    let mut output = "//!\n//! # Examples\n".to_string();

    for dir_entry_result in fs::read_dir(&examples_dir_path).expect("failed to read examples dir") {
        let dir_entry = dir_entry_result.expect("failed to read examples dir");
        let mut contents = Vec::new();
        let mut file = fs::File::open(dir_entry.path()).expect("failed to open example");
        file.read_to_end(&mut contents)
            .expect("failed to read from example file");
        let string_contents =
            String::from_utf8(contents).expect("example file has invalid encoding");

        output.push_str("//!\n");

        let mut inside_header_section = true;
        for line in string_contents.lines() {
            if line.starts_with("//!") {
                output.push_str(line);
                output.push('\n');
            } else {
                if inside_header_section {
                    // switching from header to code section
                    output.push_str("//!\n//! ```rust,no_run\n");
                    inside_header_section = false;
                }
                output.push_str("//! ");
                output.push_str(line);
                output.push('\n');
            }
        }
        output.push_str("//! ```\n");
    }

    Some(output)
}

pub fn generate_services(
    services: &BTreeMap<String, ServiceConfig>,
    out_dir: &Path,
    service_to_generate: Option<&Vec<&str>>,
) {
    if !out_dir.exists() {
        fs::create_dir(out_dir).expect("Unable to create output directory");
    }

    services.par_iter().for_each(|(name, service_config)| {
        if !service_to_generate.map(|s| s.contains(&name.as_str())).unwrap_or(true) {
            return;
        }

        let service = match ServiceDefinition::load(name, &service_config.protocol_version) {
            Ok(sd) => Service::new(service_config, sd),
            Err(_) => panic!("Failed to load service {}. Make sure the botocore submodule has been initialized!", name),
        };

        let crate_dir = out_dir.join(&name);
        let crate_name = format!("rusoto_{}", &name.replace('-', "_"));

        println!("Generating crate for {} @ {}...", service.full_name(), service.api_version());

        if !crate_dir.exists() {
            fs::create_dir(&crate_dir).unwrap_or_else(|_| panic!("Unable to create directory at {}", crate_dir.display()));
        }

        let mut features = BTreeMap::new();
        features.insert("default".into(), vec!["native-tls".into()]);
        features.insert("native-tls".into(), vec!["rusoto_core/native-tls".into()]);
        features.insert("rustls".into(), vec!["rusoto_core/rustls".into()]);
        features.insert("serialize_structs".into(), vec![]);

        let service_dependencies = service.get_dependencies();
        let service_dev_dependencies = service.get_dev_dependencies();

        let mut extern_crates = service_dependencies.iter().map(|(k, _)| {
            if k == "xml-rs" {
                return "extern crate xml;".into();
            }
            let safe_name = k.replace("-", "_");
            let use_macro = k == "serde_derive" || k == "lazy_static";
            if use_macro {
                return format!("#[macro_use]\nextern crate {};", safe_name);
            }
            format!("extern crate {};", safe_name)
        }).collect::<Vec<String>>().join("\n");
        // S3 needs the external test crate for benchmark tests
        if service.full_name() == "Amazon Simple Storage Service" {
            extern_crates.push_str("\n#[cfg(nightly)]\nextern crate test;");
        }

        let mut cargo_manifest = BufWriter::new(
            OpenOptions::new()
            .write(true)
            .truncate(true)
            .create(true)
            .open(crate_dir.join("Cargo.toml"))
            .expect("Unable to write Cargo.toml")
        );

        let mut name_for_keyword = name.clone().to_string();
        if name_for_keyword.len() >= 20 {
            name_for_keyword = name_for_keyword[..20].to_string();
        }

        let manifest = cargo::Manifest {
            package: cargo::Metadata {
                authors: Some(vec![
                    "Anthony DiMarco <ocramida@gmail.com>".into(),
                    "Jimmy Cuadra <jimmy@jimmycuadra.com>".into(),
                    "Matthew Mayer <matthewkmayer@gmail.com>".into(),
                    "Nikita Pekin <contact@nikitapek.in>".into()
                ]),
                description: Some(format!("AWS SDK for Rust - {} @ {}", service.full_name(), service.api_version())),
                documentation: Some(format!("https://docs.rs/{}", crate_name)),
                keywords: Some(vec!["AWS".into(), "Amazon".into(), name_for_keyword]),
                license: Some("MIT".into()),
                name: crate_name.clone(),
                readme: Some("README.md".into()),
                repository: Some("https://github.com/rusoto/rusoto".into()),
                version: service_config.version.clone(),
                homepage: Some("https://www.rusoto.org/".into()),
                edition: "2018".into(),
                exclude: Some(vec!["test_resources/*".into()])
            },
            features: Some(features),
            dependencies: service_dependencies,
            dev_dependencies: service_dev_dependencies,
            ..cargo::Manifest::default()
        };

        cargo_manifest.write_all(toml::to_string(&manifest).unwrap().as_bytes()).unwrap();

        let mut readme_file = BufWriter::new(
            OpenOptions::new()
            .write(true)
            .truncate(true)
            .create(true)
            .open(crate_dir.join("README.md"))
            .expect("Unable to write README.md")
        );

        writeln!(readme_file, r#"
# Rusoto {short_name}
Rust SDK for {aws_name}

You may be looking for:

* [An overview of Rusoto][rusoto-overview]
* [AWS services supported by Rusoto][supported-aws-services]
* [API documentation][api-documentation]
* [Getting help with Rusoto][rusoto-help]

## Requirements

Rust stable or beta are required to use Rusoto. Nightly is tested, but not guaranteed to be supported. Older
versions _may_ be supported. The currently supported Rust versions can be found in the Rusoto project
[`travis.yml`](https://github.com/rusoto/rusoto/blob/master/.travis.yml).

On Linux, OpenSSL is required.

## Installation

To use `{crate_name}` in your application, add it as a dependency in your `Cargo.toml`:

```toml
[dependencies]
{crate_name} = "{version}"
```

## Crate Features
- `native-tls` - use platform-specific TLS implementation.
- `rustls` - use rustls TLS implementation.
- `serialize_structs` - output structs of most operations get `derive(Serialize)`.

Note: the crate will use the `native-tls` TLS implementation by default.

## Contributing

See [CONTRIBUTING][contributing].

## License

Rusoto is distributed under the terms of the MIT license.

See [LICENSE][license] for details.

[api-documentation]: https://docs.rs/{crate_name} "API documentation"
[license]: https://github.com/rusoto/rusoto/blob/master/LICENSE "MIT License"
[contributing]: https://github.com/rusoto/rusoto/blob/master/CONTRIBUTING.md "Contributing Guide"
[rusoto-help]: https://www.rusoto.org/help.html "Getting help with Rusoto"
[rusoto-overview]: https://www.rusoto.org/ "Rusoto overview"
[supported-aws-services]: https://www.rusoto.org/supported-aws-services.html "List of AWS services supported by Rusoto"
        "#,
        short_name = service.service_type_name(),
        aws_name = service.full_name(),
        crate_name = crate_name,
        version = service_config.version
        ).expect("Couldn't write README for crate");

        {
            let src_dir = crate_dir.join("src");

            if !src_dir.exists() {
                fs::create_dir(&src_dir).unwrap_or_else(|_| panic!("Unable to create directory at {}", src_dir.display()));
            }

            let lib_file_path = src_dir.join("lib.rs");

            let mut lib_file = BufWriter::new(
                OpenOptions::new()
                .write(true)
                .truncate(true)
                .create(true)
                .open(&lib_file_path)
                .expect("Unable to write lib.rs")
            );

            writeln!(lib_file, r#"
// =================================================================
//
//                           * WARNING *
//
//                    This file is generated!
//
//  Changes made to this file will be overwritten. If changes are
//  required to the generated code, the service_crategen project
//  must be updated to generate the changes.
//
// =================================================================

#![doc(html_logo_url = "https://raw.githubusercontent.com/rusoto/rusoto/master/assets/logo-square.png")]
{service_docs}
//!
//! If you're using the service, you're probably looking for [{client_name}](struct.{client_name}.html) and [{trait_name}](trait.{trait_name}.html).
{examples}
{extern_crates}

mod generated;
mod custom;

pub use crate::generated::*;
pub use crate::custom::*;
            "#,
            service_docs = crate::doco::Module(service.documentation().unwrap_or(&service.full_name().to_owned())),
            client_name = service.client_type_name(),
            trait_name = service.service_type_name(),
            examples = generate_examples(&crate_dir).unwrap_or_else(|| "".to_string()),
            extern_crates = extern_crates
            ).expect("Couldn't write library file");

            let gen_file_path = src_dir.join("generated.rs");

            let mut gen_writer = BufWriter::new(
                OpenOptions::new()
                .create(true)
                .write(true)
                .truncate(true)
                .open(&gen_file_path)
                .expect("Unable to write generated.rs")
            );

            codegen::generate_source(&service, &mut gen_writer).unwrap();

            let custom_dir_path = src_dir.join("custom");

            if !custom_dir_path.exists() {
                fs::create_dir(&custom_dir_path).unwrap_or_else(|_| panic!("Unable to create directory at {}", custom_dir_path.display()));
            }

            let custom_mod_file_path = custom_dir_path.join("mod.rs");

            if !custom_mod_file_path.exists() {
                OpenOptions::new()
                    .write(true)
                    .create_new(true)
                    .open(&custom_mod_file_path)
                    .expect("Unable to write mod.rs");
            }
        }

        {
            let src_dir = crate_dir.join("src");
            let gen_file_path = src_dir.join("generated.rs");

            let status = Command::new("rustfmt")
                .args(&["--emit", "files"])
                .args(&["--config-path", "rustfmt.toml"])
                .arg(gen_file_path)
                .status()
                .expect("rustfmt command failed to start");
            if !status.success() {
                panic!("rustfmt failed");
            }
        }

        {
            let test_resources_dir = crate_dir.join("test_resources");

            if !test_resources_dir.exists() {
                fs::create_dir(&test_resources_dir).unwrap_or_else(|_| panic!("Unable to create directory at {}", test_resources_dir.display()));
            }

            let generated_test_resources_dir = test_resources_dir.join("generated");

            if !generated_test_resources_dir.exists() {
                fs::create_dir(&generated_test_resources_dir).unwrap_or_else(|_| panic!("Unable to create directory at {}", generated_test_resources_dir.display()));
            }

            let test_valid_resources = codegen::tests::find_valid_responses_for_service(&service);
            if !test_valid_resources.is_empty() {
                let test_valid_resources_dir = generated_test_resources_dir.join("valid");

                if !test_valid_resources_dir.exists() {
                    fs::create_dir(&test_valid_resources_dir).unwrap_or_else(|_| panic!("Unable to create directory at {}", generated_test_resources_dir.display()));
                }

                for resource in test_valid_resources {
                    fs::copy(resource.full_path, test_valid_resources_dir.join(&resource.file_name)).expect("Failed to copy test resource file");
                }
            }

            let test_error_resources = codegen::tests::find_error_responses_for_service(&service);
            if !test_error_resources.is_empty() {
                let test_error_resources_dir = generated_test_resources_dir.join("error");

                if !test_error_resources_dir.exists() {
                    fs::create_dir(&test_error_resources_dir).unwrap_or_else(|_| panic!("Unable to create directory at {}", generated_test_resources_dir.display()));
                }

                for resource in test_error_resources {
                    fs::copy(resource.full_path, test_error_resources_dir.join(&resource.file_name)).expect("Failed to copy test resource file");
                }
            }
        }
    });
}
<commit_msg>This clippy lint should be ignored in crategen.<commit_after>use std::collections::BTreeMap;
use std::fs::{self, OpenOptions};
use std::io::{BufWriter, Read, Write};
use std::path::Path;
use std::process::Command;

use rayon::prelude::*;
use toml;

mod codegen;

use crate::cargo;
use crate::{Service, ServiceConfig, ServiceDefinition};

fn generate_examples(crate_dir_path: &Path) -> Option<String> {
    let examples_dir_path = crate_dir_path.join("examples");

    if !examples_dir_path.exists() {
        return None;
    }

    let mut output = "//!\n//! # Examples\n".to_string();

    for dir_entry_result in fs::read_dir(&examples_dir_path).expect("failed to read examples dir") {
        let dir_entry = dir_entry_result.expect("failed to read examples dir");
        let mut contents = Vec::new();
        let mut file = fs::File::open(dir_entry.path()).expect("failed to open example");
        file.read_to_end(&mut contents)
            .expect("failed to read from example file");
        let string_contents =
            String::from_utf8(contents).expect("example file has invalid encoding");

        output.push_str("//!\n");

        let mut inside_header_section = true;
        for line in string_contents.lines() {
            if line.starts_with("//!") {
                output.push_str(line);
                output.push('\n');
            } else {
                if inside_header_section {
                    // switching from header to code section
                    output.push_str("//!\n//! ```rust,no_run\n");
                    inside_header_section = false;
                }
                output.push_str("//! ");
                output.push_str(line);
                output.push('\n');
            }
        }
        output.push_str("//! ```\n");
    }

    Some(output)
}

pub fn generate_services(
    services: &BTreeMap<String, ServiceConfig>,
    out_dir: &Path,
    service_to_generate: Option<&Vec<&str>>,
) {
    if !out_dir.exists() {
        fs::create_dir(out_dir).expect("Unable to create output directory");
    }

    services.par_iter().for_each(|(name, service_config)| {
        if !service_to_generate.map(|s| s.contains(&name.as_str())).unwrap_or(true) {
            return;
        }

        // Panicking on error is okay because we can't do anything if the definition isn't present
        #[allow(clippy::match_wild_err_arm)]
        let service = match ServiceDefinition::load(name, &service_config.protocol_version) {
            Ok(sd) => Service::new(service_config, sd),
            Err(_) => panic!("Failed to load service {}. Make sure the botocore submodule has been initialized!", name),
        };

        let crate_dir = out_dir.join(&name);
        let crate_name = format!("rusoto_{}", &name.replace('-', "_"));

        println!("Generating crate for {} @ {}...", service.full_name(), service.api_version());

        if !crate_dir.exists() {
            fs::create_dir(&crate_dir).unwrap_or_else(|_| panic!("Unable to create directory at {}", crate_dir.display()));
        }

        let mut features = BTreeMap::new();
        features.insert("default".into(), vec!["native-tls".into()]);
        features.insert("native-tls".into(), vec!["rusoto_core/native-tls".into()]);
        features.insert("rustls".into(), vec!["rusoto_core/rustls".into()]);
        features.insert("serialize_structs".into(), vec![]);

        let service_dependencies = service.get_dependencies();
        let service_dev_dependencies = service.get_dev_dependencies();

        let mut extern_crates = service_dependencies.iter().map(|(k, _)| {
            if k == "xml-rs" {
                return "extern crate xml;".into();
            }
            let safe_name = k.replace("-", "_");
            let use_macro = k == "serde_derive" || k == "lazy_static";
            if use_macro {
                return format!("#[macro_use]\nextern crate {};", safe_name);
            }
            format!("extern crate {};", safe_name)
        }).collect::<Vec<String>>().join("\n");
        // S3 needs the external test crate for benchmark tests
        if service.full_name() == "Amazon Simple Storage Service" {
            extern_crates.push_str("\n#[cfg(nightly)]\nextern crate test;");
        }

        let mut cargo_manifest = BufWriter::new(
            OpenOptions::new()
            .write(true)
            .truncate(true)
            .create(true)
            .open(crate_dir.join("Cargo.toml"))
            .expect("Unable to write Cargo.toml")
        );

        let mut name_for_keyword = name.clone().to_string();
        if name_for_keyword.len() >= 20 {
            name_for_keyword = name_for_keyword[..20].to_string();
        }

        let manifest = cargo::Manifest {
            package: cargo::Metadata {
                authors: Some(vec![
                    "Anthony DiMarco <ocramida@gmail.com>".into(),
                    "Jimmy Cuadra <jimmy@jimmycuadra.com>".into(),
                    "Matthew Mayer <matthewkmayer@gmail.com>".into(),
                    "Nikita Pekin <contact@nikitapek.in>".into()
                ]),
                description: Some(format!("AWS SDK for Rust - {} @ {}", service.full_name(), service.api_version())),
                documentation: Some(format!("https://docs.rs/{}", crate_name)),
                keywords: Some(vec!["AWS".into(), "Amazon".into(), name_for_keyword]),
                license: Some("MIT".into()),
                name: crate_name.clone(),
                readme: Some("README.md".into()),
                repository: Some("https://github.com/rusoto/rusoto".into()),
                version: service_config.version.clone(),
                homepage: Some("https://www.rusoto.org/".into()),
                edition: "2018".into(),
                exclude: Some(vec!["test_resources/*".into()])
            },
            features: Some(features),
            dependencies: service_dependencies,
            dev_dependencies: service_dev_dependencies,
            ..cargo::Manifest::default()
        };

        cargo_manifest.write_all(toml::to_string(&manifest).unwrap().as_bytes()).unwrap();

        let mut readme_file = BufWriter::new(
            OpenOptions::new()
            .write(true)
            .truncate(true)
            .create(true)
            .open(crate_dir.join("README.md"))
            .expect("Unable to write README.md")
        );

        writeln!(readme_file, r#"
# Rusoto {short_name}
Rust SDK for {aws_name}

You may be looking for:

* [An overview of Rusoto][rusoto-overview]
* [AWS services supported by Rusoto][supported-aws-services]
* [API documentation][api-documentation]
* [Getting help with Rusoto][rusoto-help]

## Requirements

Rust stable or beta are required to use Rusoto. Nightly is tested, but not guaranteed to be supported. Older
versions _may_ be supported. The currently supported Rust versions can be found in the Rusoto project
[`travis.yml`](https://github.com/rusoto/rusoto/blob/master/.travis.yml).

On Linux, OpenSSL is required.

## Installation

To use `{crate_name}` in your application, add it as a dependency in your `Cargo.toml`:

```toml
[dependencies]
{crate_name} = "{version}"
```

## Crate Features
- `native-tls` - use platform-specific TLS implementation.
- `rustls` - use rustls TLS implementation.
- `serialize_structs` - output structs of most operations get `derive(Serialize)`.

Note: the crate will use the `native-tls` TLS implementation by default.

## Contributing

See [CONTRIBUTING][contributing].

## License

Rusoto is distributed under the terms of the MIT license.

See [LICENSE][license] for details.

[api-documentation]: https://docs.rs/{crate_name} "API documentation"
[license]: https://github.com/rusoto/rusoto/blob/master/LICENSE "MIT License"
[contributing]: https://github.com/rusoto/rusoto/blob/master/CONTRIBUTING.md "Contributing Guide"
[rusoto-help]: https://www.rusoto.org/help.html "Getting help with Rusoto"
[rusoto-overview]: https://www.rusoto.org/ "Rusoto overview"
[supported-aws-services]: https://www.rusoto.org/supported-aws-services.html "List of AWS services supported by Rusoto"
        "#,
        short_name = service.service_type_name(),
        aws_name = service.full_name(),
        crate_name = crate_name,
        version = service_config.version
        ).expect("Couldn't write README for crate");

        {
            let src_dir = crate_dir.join("src");

            if !src_dir.exists() {
                fs::create_dir(&src_dir).unwrap_or_else(|_| panic!("Unable to create directory at {}", src_dir.display()));
            }

            let lib_file_path = src_dir.join("lib.rs");

            let mut lib_file = BufWriter::new(
                OpenOptions::new()
                .write(true)
                .truncate(true)
                .create(true)
                .open(&lib_file_path)
                .expect("Unable to write lib.rs")
            );

            writeln!(lib_file, r#"
// =================================================================
//
//                           * WARNING *
//
//                    This file is generated!
//
//  Changes made to this file will be overwritten. If changes are
//  required to the generated code, the service_crategen project
//  must be updated to generate the changes.
//
// =================================================================

#![doc(html_logo_url = "https://raw.githubusercontent.com/rusoto/rusoto/master/assets/logo-square.png")]
{service_docs}
//!
//! If you're using the service, you're probably looking for [{client_name}](struct.{client_name}.html) and [{trait_name}](trait.{trait_name}.html).
{examples}
{extern_crates}

mod generated;
mod custom;

pub use crate::generated::*;
pub use crate::custom::*;
            "#,
            service_docs = crate::doco::Module(service.documentation().unwrap_or(&service.full_name().to_owned())),
            client_name = service.client_type_name(),
            trait_name = service.service_type_name(),
            examples = generate_examples(&crate_dir).unwrap_or_else(|| "".to_string()),
            extern_crates = extern_crates
            ).expect("Couldn't write library file");

            let gen_file_path = src_dir.join("generated.rs");

            let mut gen_writer = BufWriter::new(
                OpenOptions::new()
                .create(true)
                .write(true)
                .truncate(true)
                .open(&gen_file_path)
                .expect("Unable to write generated.rs")
            );

            codegen::generate_source(&service, &mut gen_writer).unwrap();

            let custom_dir_path = src_dir.join("custom");

            if !custom_dir_path.exists() {
                fs::create_dir(&custom_dir_path).unwrap_or_else(|_| panic!("Unable to create directory at {}", custom_dir_path.display()));
            }

            let custom_mod_file_path = custom_dir_path.join("mod.rs");

            if !custom_mod_file_path.exists() {
                OpenOptions::new()
                    .write(true)
                    .create_new(true)
                    .open(&custom_mod_file_path)
                    .expect("Unable to write mod.rs");
            }
        }

        {
            let src_dir = crate_dir.join("src");
            let gen_file_path = src_dir.join("generated.rs");

            let status = Command::new("rustfmt")
                .args(&["--emit", "files"])
                .args(&["--config-path", "rustfmt.toml"])
                .arg(gen_file_path)
                .status()
                .expect("rustfmt command failed to start");
            if !status.success() {
                panic!("rustfmt failed");
            }
        }

        {
            let test_resources_dir = crate_dir.join("test_resources");

            if !test_resources_dir.exists() {
                fs::create_dir(&test_resources_dir).unwrap_or_else(|_| panic!("Unable to create directory at {}", test_resources_dir.display()));
            }

            let generated_test_resources_dir = test_resources_dir.join("generated");

            if !generated_test_resources_dir.exists() {
                fs::create_dir(&generated_test_resources_dir).unwrap_or_else(|_| panic!("Unable to create directory at {}", generated_test_resources_dir.display()));
            }

            let test_valid_resources = codegen::tests::find_valid_responses_for_service(&service);
            if !test_valid_resources.is_empty() {
                let test_valid_resources_dir = generated_test_resources_dir.join("valid");

                if !test_valid_resources_dir.exists() {
                    fs::create_dir(&test_valid_resources_dir).unwrap_or_else(|_| panic!("Unable to create directory at {}", generated_test_resources_dir.display()));
                }

                for resource in test_valid_resources {
                    fs::copy(resource.full_path, test_valid_resources_dir.join(&resource.file_name)).expect("Failed to copy test resource file");
                }
            }

            let test_error_resources = codegen::tests::find_error_responses_for_service(&service);
            if !test_error_resources.is_empty() {
                let test_error_resources_dir = generated_test_resources_dir.join("error");

                if !test_error_resources_dir.exists() {
                    fs::create_dir(&test_error_resources_dir).unwrap_or_else(|_| panic!("Unable to create directory at {}", generated_test_resources_dir.display()));
                }

                for resource in test_error_resources {
                    fs::copy(resource.full_path, test_error_resources_dir.join(&resource.file_name)).expect("Failed to copy test resource file");
                }
            }
        }
    });
}
<|endoftext|>