<commit_before>use std::time::Duration;
use std::cell::RefCell;
use std::sync::Mutex;

use core::generate_sas;
use core::error::AzureRequestError;
use super::brokeredmessage::*;

use url;
use time2;
use hyper::client::Client;
use hyper::header::*;
use hyper::status::StatusCode;
use hyper::mime::Mime;

const CONTENT_TYPE: &'static str = "application/atom+xml;type=entry;charset=utf-8";
const SAS_BUFFER_TIME: usize = 15;

// Ideally this should be a field on the client, but we don't want to expose it through
// the trait, and if we don't then we can't share code.
lazy_static!{
    static ref CLIENT: Client = Client::new();
}

pub trait Queue {
    fn queue(&self) -> &str;
    fn refresh_sas(&self) -> String;
    fn endpoint(&self) -> &url::Url;

    fn send(&self, message: BrokeredMessage) -> Result<(), AzureRequestError> {
        let timeout = Duration::from_secs(30);
        self.send_with_timeout(message, timeout)
    }

    fn receive(&self) -> Result<BrokeredMessage, AzureRequestError> {
        let timeout = Duration::from_secs(30);
        self.receive_with_timeout(timeout)
    }

    fn receive_and_delete(&self) -> Result<BrokeredMessage, AzureRequestError> {
        let timeout = Duration::from_secs(30);
        self.receive_and_delete_with_timeout(timeout)
    }

    fn send_with_timeout(&self,
                         message: BrokeredMessage,
                         timeout: Duration)
                         -> Result<(), AzureRequestError> {

        let sas = self.refresh_sas();
        let path = format!("{}/messages?timeout={}", self.queue(), timeout.as_secs());
        match self.endpoint().join(&*path) {
            Ok(uri) => {
                // let sas = self.sas_key.borrow().clone();
                let mut header = Headers::new();
                header.set(Authorization(sas));

                // This will always succeed.
                let content_type: Mime = CONTENT_TYPE.parse().unwrap();
                header.set(ContentType(content_type));
                header.set(BrokerPropertiesHeader(message.props_as_json()));

                let result = CLIENT.post(uri).headers(header).body(message.get_body_raw()).send();

                match result {
                    Ok(response) => interpret_results(response.status),
                    Err(_) => Err(AzureRequestError::HyperError),
                }
            }
            Err(_) => Err(AzureRequestError::InvalidEndpoint),
        }
    }

    fn receive_and_delete_with_timeout(&self,
                                       timeout: Duration)
                                       -> Result<BrokeredMessage, AzureRequestError> {

        let sas = self.refresh_sas();
        let path = format!("{}/messages/head?timeout={}",
                           self.queue(),
                           timeout.as_secs());

        match self.endpoint().join(&*path) {
            Ok(uri) => {
                let mut header = Headers::new();
                header.set(Authorization(sas));
                let result = CLIENT.delete(uri).headers(header).send();
                if let Ok(response) = result {
                    match interpret_results(response.status) {
                        Ok(()) => Ok(BrokeredMessage::with_response(response)),
                        Err(e) => Err(e),
                    }
                } else {
                    Err(AzureRequestError::HyperError)
                }
            }
            Err(_) => Err(AzureRequestError::InvalidEndpoint),
        }
    }
    fn receive_with_timeout(&self,
                            timeout: Duration)
                            -> Result<BrokeredMessage, AzureRequestError> {
        let sas = self.refresh_sas();
        let path = format!("{}/messages/head?timeout={}",
                           self.queue(),
                           timeout.as_secs());

        match self.endpoint().join(&*path) {
            Ok(uri) => {
                let mut header = Headers::new();
                header.set(Authorization(sas));
                let result = CLIENT.post(uri).headers(header).send();
                if let Ok(response) = result {
                    match interpret_results(response.status) {
                        Ok(()) => Ok(BrokeredMessage::with_response(response)),
                        Err(e) => Err(e),
                    }
                } else {
                    Err(AzureRequestError::HyperError)
                }
            }
            Err(_) => Err(AzureRequestError::InvalidEndpoint),
        }
    }

    fn complete_message(&self, message: BrokeredMessage) -> Result<(), AzureRequestError> {
        let sas = self.refresh_sas();

        // Take either the Sequence number or the Message ID
        // Then add the lock token and finally join it into the targer
        let target = message.props
            .SequenceNumber
            .map(|seq| seq.to_string())
            .or(message.props.MessageId.clone())
            .and_then(|id| message.props.LockToken.as_ref().map(|lock| (id, lock)))
            .map(|(id, lock)| format!("/{}/messages/{}/{}", self.queue(), id, lock))
            .and_then(|path| self.endpoint().join(&*path).ok());

        if let Some(target) = target {
            let mut header = Headers::new();
            header.set(Authorization(sas));
            let result = CLIENT.delete(target).headers(header).send();
            if let Ok(response) = result {
                interpret_results(response.status)
            } else {
                Err(AzureRequestError::HyperError)
            }
        } else {
            Err(AzureRequestError::LocalMessage)
        }
    }

    fn on_message<H>(&self, handler: H) -> AzureRequestError
        where H: Fn(BrokeredMessage)
    {
        loop {
            let res = self.receive_and_delete();
            match res {
                Ok(message) => handler(message),
                Err(AzureRequestError::EmptyBus) => {}
                Err(e) => return e,
            }
        }
    }
}

// This version is Send but not Sync
// It's probably slightly more performant than the concurrent version.
pub struct QueueClient {
    connection_string: String,
    queue_name: String,
    endpoint: url::Url,
    sas_info: RefCell<(String, usize)>,
}

impl QueueClient {
    pub fn with_conn_and_queue(connection_string: &str,
                               queue: &str)
                               -> Result<QueueClient, url::ParseError> {
        let duration = Duration::from_secs(60 * 6);
        let mut endpoint = String::new();
        for param in connection_string.split(";") {
            let idx = param.find("=").unwrap_or(0);
            let (mut k, mut value) = param.split_at(idx);
            k = k.trim();
            value = value.trim();
            // cut out the equal sign if there was one.
            if value.len() > 0 {
                value = &value[1..]
            }
            match k {
                "Endpoint" => endpoint = value.to_string(),
                _ => {}
            };
        }
        endpoint = String::new() + "https" + endpoint.split_at(endpoint.find(":").unwrap_or(0)).1;
        match url::Url::parse(&*endpoint) {
            Ok(url) => {
                let (sas_key, expiry) = generate_sas(connection_string, duration);
                let conn_string = connection_string.to_string();

                Ok(QueueClient {
                    connection_string: conn_string,
                    queue_name: queue.to_string(),
                    endpoint: url,
                    sas_info: RefCell::new((sas_key, expiry - SAS_BUFFER_TIME)),
                })
            }
            Err(e) => Err(e),
        }
    }
}

impl Queue for QueueClient {
    fn queue(&self) -> &str {
        &self.queue_name
    }

    fn endpoint(&self) -> &url::Url {
        &self.endpoint
    }

    fn refresh_sas(&self) -> String {
        let curr_time = time2::now_utc().to_timespec().sec as usize;
        let mut sas_tuple = self.sas_info.borrow_mut();
        if curr_time > sas_tuple.1 {
            let duration = Duration::from_secs(60 * 6);
            let (key, expiry) = generate_sas(&*self.connection_string, duration);
            sas_tuple.1 = expiry;
            sas_tuple.0 = key;
        }
        sas_tuple.0.clone()
    }
}

// The ConcurrentQueueClient is Send and Sync
// Wrap it in an Arc and it can be shared between threads freely.
pub struct ConcurrentQueueClient {
    connection_string: String,
    queue_name: String,
    endpoint: url::Url,
    sas_info: Mutex<(String, usize)>,
}

impl ConcurrentQueueClient {
    pub fn with_conn_and_queue(connection_string: &str,
                               queue: &str)
                               -> Result<ConcurrentQueueClient, url::ParseError> {
        let duration = Duration::from_secs(60 * 6);
        let mut endpoint = String::new();
        for param in connection_string.split(";") {
            let idx = param.find("=").unwrap_or(0);
            let (mut k, mut value) = param.split_at(idx);
            k = k.trim();
            value = value.trim();
            // cut out the equal sign if there was one.
            if value.len() > 0 {
                value = &value[1..]
            }
            match k {
                "Endpoint" => endpoint = value.to_string(),
                _ => {}
            };
        }
        endpoint = String::new() + "https" + endpoint.split_at(endpoint.find(":").unwrap_or(0)).1;
        match url::Url::parse(&*endpoint) {
            Ok(url) => {
                let (sas_key, expiry) = generate_sas(connection_string, duration);
                let conn_string = connection_string.to_string();

                Ok(ConcurrentQueueClient {
                    connection_string: conn_string,
                    queue_name: queue.to_string(),
                    endpoint: url,
                    sas_info: Mutex::new((sas_key, expiry - SAS_BUFFER_TIME)),
                })
            }
            Err(e) => Err(e),
        }
    }
}

impl Queue for ConcurrentQueueClient {
    fn queue(&self) -> &str {
        &self.queue_name
    }

    fn endpoint(&self) -> &url::Url {
        &self.endpoint
    }

    fn refresh_sas(&self) -> String {
        let curr_time = time2::now_utc().to_timespec().sec as usize;
        let mut sas_tuple = match self.sas_info.lock() {
            Ok(guard) => guard,
            Err(poison) => poison.into_inner(),
        };
        if curr_time > sas_tuple.1 {
            let duration = Duration::from_secs(60 * 6);
            let (key, expiry) = generate_sas(&*self.connection_string, duration);
            sas_tuple.1 = expiry;
            sas_tuple.0 = key;
        }
        sas_tuple.0.clone()
    }
}

// Here's one function that interprets what all of the error codes mean for consistency.
// This might even get elevated out of this module, but preferabbly not.
fn interpret_results(status: StatusCode) -> Result<(), AzureRequestError> {
    use core::error::AzureRequestError::*;
    match status {
        StatusCode::Unauthorized => Err(AuthorizationFailure),
        StatusCode::InternalServerError => Err(InternalError),
        StatusCode::BadRequest => Err(BadRequest),
        StatusCode::Forbidden => Err(ResourceFailure),
        StatusCode::Gone => Err(ResourceNotFound),
        // These are the successful cases.
        StatusCode::Created => Ok(()),
        StatusCode::Ok => Ok(()),
        _ => Err(UnknownError),
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use servicebus::brokeredmessage::BrokeredMessage;

    lazy_static!{
        static ref CONNECTION_STRING: String = {
            use std::io::BufReader;
            use std::fs::File;
            use std::io::prelude::*;
            let mut s = String::new();
            let mut reader = BufReader::new(File::open("connection_string.txt").unwrap());
            reader.read_line(&mut s).unwrap();
            s
        };
    }

    #[test]
    fn queue_send_message() {
        let queue = QueueClient::with_conn_and_queue(&*CONNECTION_STRING, "test1").unwrap();
        let message = BrokeredMessage::with_body("Cats and Dogs");
        match queue.send(message) {
            Err(e) => {
                println!("{:?}", e);
                panic!("Failed to send message.")
            }
            _ => assert!(true),
        }
    }

    #[test]
    fn queue_receive_message() {
        let queue = QueueClient::with_conn_and_queue(&*CONNECTION_STRING, "test1").unwrap();
        match queue.receive_and_delete() {
            Err(e) => {
                println!("{:?}", e);
                panic!("Failed to receive message.")
            }
            Ok(_) => {}
        }
    }

    #[test]
    fn queue_complete_message() {
        let queue = QueueClient::with_conn_and_queue(&*CONNECTION_STRING, "test1").unwrap();
        queue.send(BrokeredMessage::with_body("Complete this message")).unwrap();
        match queue.receive() {
            Err(e) => {
                println!("{:?}", e);
                panic!("Failed to receive message.")
            }
            Ok(message) => {
                match queue.complete_message(message.clone()) {
                    Err(e) => {
                        println!("{:?}", e);
                        println!("{:?}", message);
                        panic!("Failed to complete the message");
                    }
                    _ => {}
                }
            }
        }
    }

    #[test]
    fn conncurrent_queue_send_message() {
        let queue = ConcurrentQueueClient::with_conn_and_queue(&*CONNECTION_STRING, "test1")
            .unwrap();
        let message = BrokeredMessage::with_body("Cats and Dogs");
        match queue.send(message) {
            Err(e) => {
                println!("{:?}", e);
                panic!("Failed to send message.");
            }
            _ => {}
        }
    }

    #[test]
    fn concurrent_queue_receive_message() {
        let queue = ConcurrentQueueClient::with_conn_and_queue(&*CONNECTION_STRING, "test1")
            .unwrap();
        match queue.receive_and_delete() {
            Err(e) => {
                println!("{:?}", e);
                panic!("Failed to receive a message");
            }
            Ok(_) => {}
        }
    }
}<commit_msg>Initial commit. Did a significant amount of work on this project<commit_after>use std::time::Duration;
use std::cell::RefCell;
use std::sync::Mutex;

use core::generate_sas;
use core::error::AzureRequestError;
use super::brokeredmessage::*;

use url;
use time2;
use hyper::client::Client;
use hyper::header::*;
use hyper::status::StatusCode;
use hyper::mime::Mime;

const CONTENT_TYPE: &'static str = "application/atom+xml;type=entry;charset=utf-8";
const SAS_BUFFER_TIME: usize = 15;

// Ideally this should be a field on the client, but we don't want to expose it through
// the trait, and if we don't then we can't share code.
lazy_static!{
    static ref CLIENT: Client = Client::new();
}

pub trait Queue {
    fn queue(&self) -> &str;
    fn refresh_sas(&self) -> String;
    fn endpoint(&self) -> &url::Url;

    fn send(&self, message: BrokeredMessage) -> Result<(), AzureRequestError> {
        let timeout = Duration::from_secs(30);
        self.send_with_timeout(message, timeout)
    }

    fn receive(&self) -> Result<BrokeredMessage, AzureRequestError> {
        let timeout = Duration::from_secs(30);
        self.receive_with_timeout(timeout)
    }

    fn receive_and_delete(&self) -> Result<BrokeredMessage, AzureRequestError> {
        let timeout = Duration::from_secs(30);
        self.receive_and_delete_with_timeout(timeout)
    }

    fn send_with_timeout(&self,
                         message: BrokeredMessage,
                         timeout: Duration)
                         -> Result<(), AzureRequestError> {

        let sas = self.refresh_sas();
        let path = format!("{}/messages?timeout={}", self.queue(), timeout.as_secs());
        match self.endpoint().join(&*path) {
            Ok(uri) => {
                // let sas = self.sas_key.borrow().clone();
                let mut header = Headers::new();
                header.set(Authorization(sas));

                // This will always succeed.
                let content_type: Mime = CONTENT_TYPE.parse().unwrap();
                header.set(ContentType(content_type));
                header.set(BrokerPropertiesHeader(message.props_as_json()));

                let result = CLIENT.post(uri).headers(header).body(message.get_body_raw()).send();

                match result {
                    Ok(response) => interpret_results(response.status),
                    Err(_) => Err(AzureRequestError::HyperError),
                }
            }
            Err(_) => Err(AzureRequestError::InvalidEndpoint),
        }
    }

    fn receive_and_delete_with_timeout(&self,
                                       timeout: Duration)
                                       -> Result<BrokeredMessage, AzureRequestError> {

        let sas = self.refresh_sas();
        let path = format!("{}/messages/head?timeout={}",
                           self.queue(),
                           timeout.as_secs());

        match self.endpoint().join(&*path) {
            Ok(uri) => {
                let mut header = Headers::new();
                header.set(Authorization(sas));
                let result = CLIENT.delete(uri).headers(header).send();
                if let Ok(response) = result {
                    match interpret_results(response.status) {
                        Ok(()) => Ok(BrokeredMessage::with_response(response)),
                        Err(e) => Err(e),
                    }
                } else {
                    Err(AzureRequestError::HyperError)
                }
            }
            Err(_) => Err(AzureRequestError::InvalidEndpoint),
        }
    }
    fn receive_with_timeout(&self,
                            timeout: Duration)
                            -> Result<BrokeredMessage, AzureRequestError> {
        let sas = self.refresh_sas();
        let path = format!("{}/messages/head?timeout={}",
                           self.queue(),
                           timeout.as_secs());

        match self.endpoint().join(&*path) {
            Ok(uri) => {
                let mut header = Headers::new();
                header.set(Authorization(sas));
                let result = CLIENT.post(uri).headers(header).send();
                if let Ok(response) = result {
                    match interpret_results(response.status) {
                        Ok(()) => Ok(BrokeredMessage::with_response(response)),
                        Err(e) => Err(e),
                    }
                } else {
                    Err(AzureRequestError::HyperError)
                }
            }
            Err(_) => Err(AzureRequestError::InvalidEndpoint),
        }
    }

    fn complete_message(&self, message: BrokeredMessage) -> Result<(), AzureRequestError> {
        let sas = self.refresh_sas();

        // Take either the Sequence number or the Message ID
        // Then add the lock token and finally join it into the targer
        let target = message.props
            .SequenceNumber
            .map(|seq| seq.to_string())
            .or(message.props.MessageId.clone())
            .and_then(|id| message.props.LockToken.as_ref().map(|lock| (id, lock)))
            .map(|(id, lock)| format!("/{}/messages/{}/{}", self.queue(), id, lock))
            .and_then(|path| self.endpoint().join(&*path).ok());

        if let Some(target) = target {
            let mut header = Headers::new();
            header.set(Authorization(sas));
            let result = CLIENT.delete(target).headers(header).send();
            if let Ok(response) = result {
                interpret_results(response.status)
            } else {
                Err(AzureRequestError::HyperError)
            }
        } else {
            Err(AzureRequestError::LocalMessage)
        }
    }

    fn on_message<H>(&self, handler: H) -> AzureRequestError
        where H: Fn(BrokeredMessage)
    {
        loop {
            let res = self.receive_and_delete();
            match res {
                Ok(message) => handler(message),
                Err(AzureRequestError::EmptyBus) => {}
                Err(e) => return e,
            }
        }
    }
}

// This version is Send but not Sync
// It's probably slightly more performant than the concurrent version.
pub struct QueueClient {
    connection_string: String,
    queue_name: String,
    endpoint: url::Url,
    sas_info: RefCell<(String, usize)>,
}

impl QueueClient {
    pub fn with_conn_and_queue(connection_string: &str,
                               queue: &str)
                               -> Result<QueueClient, url::ParseError> {
        let duration = Duration::from_secs(60 * 6);
        let mut endpoint = String::new();
        for param in connection_string.split(";") {
            let idx = param.find("=").unwrap_or(0);
            let (mut k, mut value) = param.split_at(idx);
            k = k.trim();
            value = value.trim();
            // cut out the equal sign if there was one.
            if value.len() > 0 {
                value = &value[1..]
            }
            match k {
                "Endpoint" => endpoint = value.to_string(),
                _ => {}
            };
        }
        endpoint = String::new() + "https" + endpoint.split_at(endpoint.find(":").unwrap_or(0)).1;
        match url::Url::parse(&*endpoint) {
            Ok(url) => {
                let (sas_key, expiry) = generate_sas(connection_string, duration);
                let conn_string = connection_string.to_string();

                Ok(QueueClient {
                    connection_string: conn_string,
                    queue_name: queue.to_string(),
                    endpoint: url,
                    sas_info: RefCell::new((sas_key, expiry - SAS_BUFFER_TIME)),
                })
            }
            Err(e) => Err(e),
        }
    }
}

impl Queue for QueueClient {
    fn queue(&self) -> &str {
        &self.queue_name
    }

    fn endpoint(&self) -> &url::Url {
        &self.endpoint
    }

    fn refresh_sas(&self) -> String {
        let curr_time = time2::now_utc().to_timespec().sec as usize;
        let mut sas_tuple = self.sas_info.borrow_mut();
        if curr_time > sas_tuple.1 {
            let duration = Duration::from_secs(60 * 6);
            let (key, expiry) = generate_sas(&*self.connection_string, duration);
            sas_tuple.1 = expiry;
            sas_tuple.0 = key;
        }
        sas_tuple.0.clone()
    }
}

// The ConcurrentQueueClient is Send and Sync
// Wrap it in an Arc and it can be shared between threads freely.
pub struct ConcurrentQueueClient {
    connection_string: String,
    queue_name: String,
    endpoint: url::Url,
    sas_info: Mutex<(String, usize)>,
}

impl ConcurrentQueueClient {
    pub fn with_conn_and_queue(connection_string: &str,
                               queue: &str)
                               -> Result<ConcurrentQueueClient, url::ParseError> {
        let duration = Duration::from_secs(60 * 6);
        let mut endpoint = String::new();
        for param in connection_string.split(";") {
            let idx = param.find("=").unwrap_or(0);
            let (mut k, mut value) = param.split_at(idx);
            k = k.trim();
            value = value.trim();
            // cut out the equal sign if there was one.
            if value.len() > 0 {
                value = &value[1..]
            }
            match k {
                "Endpoint" => endpoint = value.to_string(),
                _ => {}
            };
        }
        endpoint = String::new() + "https" + endpoint.split_at(endpoint.find(":").unwrap_or(0)).1;
        match url::Url::parse(&*endpoint) {
            Ok(url) => {
                let (sas_key, expiry) = generate_sas(connection_string, duration);
                let conn_string = connection_string.to_string();

                Ok(ConcurrentQueueClient {
                    connection_string: conn_string,
                    queue_name: queue.to_string(),
                    endpoint: url,
                    sas_info: Mutex::new((sas_key, expiry - SAS_BUFFER_TIME)),
                })
            }
            Err(e) => Err(e),
        }
    }
}

impl Queue for ConcurrentQueueClient {
    fn queue(&self) -> &str {
        &self.queue_name
    }

    fn endpoint(&self) -> &url::Url {
        &self.endpoint
    }

    fn refresh_sas(&self) -> String {
        let curr_time = time2::now_utc().to_timespec().sec as usize;
        let mut sas_tuple = match self.sas_info.lock() {
            Ok(guard) => guard,
            Err(poison) => poison.into_inner(),
        };
        if curr_time > sas_tuple.1 {
            let duration = Duration::from_secs(60 * 6);
            let (key, expiry) = generate_sas(&*self.connection_string, duration);
            sas_tuple.1 = expiry;
            sas_tuple.0 = key;
        }
        sas_tuple.0.clone()
    }
}

// Here's one function that interprets what all of the error codes mean for consistency.
// This might even get elevated out of this module, but preferabbly not.
fn interpret_results(status: StatusCode) -> Result<(), AzureRequestError> {
    use core::error::AzureRequestError::*;
    match status {
        StatusCode::Unauthorized => Err(AuthorizationFailure),
        StatusCode::InternalServerError => Err(InternalError),
        StatusCode::BadRequest => Err(BadRequest),
        StatusCode::Forbidden => Err(ResourceFailure),
        StatusCode::Gone => Err(ResourceNotFound),
        // These are the successful cases.
        StatusCode::Created => Ok(()),
        StatusCode::Ok => Ok(()),
        _ => Err(UnknownError),
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use servicebus::brokeredmessage::BrokeredMessage;

    lazy_static!{
        static ref CONNECTION_STRING: String = {
            use std::io::BufReader;
            use std::fs::File;
            use std::io::prelude::*;
            let mut s = String::new();
            let mut reader = BufReader::new(File::open("connection_string.txt").unwrap());
            reader.read_line(&mut s).unwrap();
            s
        };
    }

    #[test]
    fn queue_send_message() {
        let queue = QueueClient::with_conn_and_queue(&CONNECTION_STRING, "test1").unwrap();
        let message = BrokeredMessage::with_body("Cats and Dogs");
        match queue.send(message) {
            Err(e) => {
                println!("{:?}", e);
                panic!("Failed to send message.")
            }
            _ => assert!(true),
        }
    }

    #[test]
    fn queue_receive_message() {
        let queue = QueueClient::with_conn_and_queue(&*CONNECTION_STRING, "test1").unwrap();
        match queue.receive_and_delete() {
            Err(e) => {
                println!("{:?}", e);
                panic!("Failed to receive message.")
            }
            Ok(_) => {}
        }
    }

    #[test]
    fn queue_complete_message() {
        let queue = QueueClient::with_conn_and_queue(&*CONNECTION_STRING, "test1").unwrap();
        queue.send(BrokeredMessage::with_body("Complete this message")).unwrap();
        match queue.receive() {
            Err(e) => {
                println!("{:?}", e);
                panic!("Failed to receive message.")
            }
            Ok(message) => {
                match queue.complete_message(message.clone()) {
                    Err(e) => {
                        println!("{:?}", e);
                        println!("{:?}", message);
                        panic!("Failed to complete the message");
                    }
                    _ => {}
                }
            }
        }
    }

    #[test]
    fn conncurrent_queue_send_message() {
        let queue = ConcurrentQueueClient::with_conn_and_queue(&*CONNECTION_STRING, "test1")
            .unwrap();
        let message = BrokeredMessage::with_body("Cats and Dogs");
        match queue.send(message) {
            Err(e) => {
                println!("{:?}", e);
                panic!("Failed to send message.");
            }
            _ => {}
        }
    }

    #[test]
    fn concurrent_queue_receive_message() {
        let queue = ConcurrentQueueClient::with_conn_and_queue(&*CONNECTION_STRING, "test1")
            .unwrap();
        match queue.receive_and_delete() {
            Err(e) => {
                println!("{:?}", e);
                panic!("Failed to receive a message");
            }
            Ok(_) => {}
        }
    }
}<|endoftext|>


<commit_before>#![feature(macro_rules)]
#![crate_id = "codegen#0.1"]

use std::os;
use std::io::BufferedWriter;
use std::io::File;
use std::io;
use std::io::UserDir;
use std::io::stdio::println;
use std::io::fs::mkdir_recursive;
use std::path::GenericPath;
pub mod branchify;
pub mod keycode;
pub mod scancode;

fn main() {
    let args = os::args();
    match args.len() {
        0 => {
            println("usage: codegen [keycode|scancode].rs destdir");
            os::set_exit_status(1);
        },
        3 => {
            let output_dir = GenericPath::new(args.get(2).clone());
            match mkdir_recursive(&output_dir, UserDir) {
                Err(e) => fail!("Could not create directory for generated sources: {:s}", e.desc),
                Ok(_) => {},
            };

            if "keycode.rs" == *args.get(1) {
                match keycode::generate(&output_dir) {
                    Ok(_) => {},
                    Err(e) => fail!("Could not automatically generate sources for keycodes: {:s}", e.desc),
                };
            } else if "scancode.rs" == *args.get(1) {
                match scancode::generate(&output_dir) {
                    Ok(_)    => {},
                    Err(e) => fail!("Could not automatically generate sources for scancodes: {:s}", e.desc),
                };
            } else {
                println!("unknown thing-to-generate '{}'", args.get(1));
                os::set_exit_status(1);
            }
        },
        _ => {
            println!("usage: {} [keycode|scancode].rs destdir", args.get(0));
            os::set_exit_status(1);
        }
    }
}

pub fn get_writer(output_dir: &Path, filename: &str) -> BufferedWriter<File> {
    match File::open_mode(&output_dir.join(filename), io::Truncate, io::Write) {
        Ok(writer) => BufferedWriter::new(writer),
        Err(e) => fail!("Unable to write file: {:s}", e.desc),
    }
}
<commit_msg>Fixed codegen to use as_slice() instead of clone() for arguments<commit_after>#![feature(macro_rules)]
#![crate_id = "codegen#0.1"]

use std::os;
use std::io::BufferedWriter;
use std::io::File;
use std::io;
use std::io::UserDir;
use std::io::stdio::println;
use std::io::fs::mkdir_recursive;
use std::path::GenericPath;
pub mod branchify;
pub mod keycode;
pub mod scancode;

fn main() {
    let args = os::args();
    match args.len() {
        0 => {
            println("usage: codegen [keycode|scancode].rs destdir");
            os::set_exit_status(1);
        },
        3 => {
            let output_dir = GenericPath::new(args.get(2).as_slice());
            match mkdir_recursive(&output_dir, UserDir) {
                Err(e) => fail!("Could not create directory for generated sources: {:s}", e.desc),
                Ok(_) => {},
            };

            if "keycode.rs" == *args.get(1) {
                match keycode::generate(&output_dir) {
                    Ok(_) => {},
                    Err(e) => fail!("Could not automatically generate sources for keycodes: {:s}", e.desc),
                };
            } else if "scancode.rs" == *args.get(1) {
                match scancode::generate(&output_dir) {
                    Ok(_)    => {},
                    Err(e) => fail!("Could not automatically generate sources for scancodes: {:s}", e.desc),
                };
            } else {
                println!("unknown thing-to-generate '{}'", args.get(1));
                os::set_exit_status(1);
            }
        },
        _ => {
            println!("usage: {} [keycode|scancode].rs destdir", args.get(0));
            os::set_exit_status(1);
        }
    }
}

pub fn get_writer(output_dir: &Path, filename: &str) -> BufferedWriter<File> {
    match File::open_mode(&output_dir.join(filename), io::Truncate, io::Write) {
        Ok(writer) => BufferedWriter::new(writer),
        Err(e) => fail!("Unable to write file: {:s}", e.desc),
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::io;
use std::fs::File;
use std::io::prelude::*;

fn main() {
    if let Some(path) = env::args().nth(1) {
        let mut contents = String::new();
        match File::open(path) {
            Ok(mut file) => {
                match file.read_to_string(&mut contents) {
                    Ok(_) => {
                        match brainfuck::read(&contents) {
                            Ok(program) => {
                                let stdio = io::stdin();
                                let input = stdio.lock();
                                let output = io::stdout();
                                brainfuck::eval(program, input, output);
                            }
                            Err(msg) => println!("Read the file, but could not parse it: {}", msg),
                        }
                    }
                    Err(_) => println!("Found the file but failed to read it."),
                }
            }
            Err(_) => println!("Failed to open the file for reading."),
        };
    } else {
        println!("Please provide a path to some brainfuck source as the first argument.")
    }
}

mod brainfuck {
    use std::io::{Read, Write}
;

    #[derive(PartialEq)]
    #[derive(Debug)]
    pub enum Command {
        IncrementPointer,
        DecrementPointer,
        IncrementValue,
        DecrementValue,
        OutputValue,
        InputValue,
        ForwardsTo(usize),
        BackwardsTo(usize),
    }

    pub fn read(source: &str) -> Result<Vec<Command>, &'static str> {
        let mut forward_pointers: Vec<usize> = vec![];
        let mut backward_pointers: Vec<usize> = vec![];
        let mut position: usize = 0;
        let mut program: Vec<Command> = source
            .chars()
            .filter_map(|token| {
                let command = match token {
                    '>' => Some(Command::IncrementPointer),
                    '<' => Some(Command::DecrementPointer),
                    '+' => Some(Command::IncrementValue),
                    '-' => Some(Command::DecrementValue),
                    '.' => Some(Command::OutputValue),
                    ',' => Some(Command::InputValue),
                    '[' => {
                        forward_pointers.push(position);
                        Some(Command::BackwardsTo(position))
                    }
                    ']' => {
                        backward_pointers.push(position);
                        Some(Command::ForwardsTo(position))
                    }
                    _ => None,
                };

                if command.is_some() {
                    position += 1
                }

                command
            })
            .collect();

        if forward_pointers.len() == backward_pointers.len() {
            for (a, b) in forward_pointers.iter().zip(backward_pointers) {
                program.swap(*a, b)
            }

            Ok(program)
        } else {
            Err("Found an unmatched square brace.")
        }
    }

    fn write_byte<W>(mut writer: W, byte: u8)
        where W: Write
    {
        write!(&mut writer, "{}", byte as char).expect("Unable to write");
    }

    fn read_byte<R>(reader: R) -> u8
        where R: Read
    {
        reader
            .bytes()
            .next()
            .and_then(|result| result.ok())
            .map(|byte| byte as u8)
            .unwrap_or(0)
    }

    pub fn eval<R, W>(program: Vec<Command>, mut reader: R, mut writer: W)
        where R: Read,
              W: Write
    {
        let mut memory: Vec<u8> = vec![0; 30000];
        let mut mem_pointer: usize = 0;
        let mut prog_pointer: usize = 0;
        let prog_len = program.len();

        while prog_pointer < prog_len {
            match program[prog_pointer] {
                Command::IncrementPointer => {
                    mem_pointer += 1;
                }
                Command::DecrementPointer => {
                    mem_pointer -= 1;
                }
                Command::IncrementValue => {
                    memory[mem_pointer] += 1;
                }
                Command::DecrementValue => {
                    memory[mem_pointer] -= 1;
                }
                Command::OutputValue => {
                    write_byte(&mut writer, memory[mem_pointer]);
                }
                Command::InputValue => {
                    memory[mem_pointer] = read_byte(&mut reader);
                }
                Command::ForwardsTo(next) => {
                    if memory[mem_pointer] == 0 {
                        prog_pointer = next;
                    }
                }
                Command::BackwardsTo(next) => {
                    println!("<- {}", next);
                    if memory[mem_pointer] != 0 {
                        prog_pointer = next;
                    }
                }
            };

            prog_pointer += 1;
        }
    }
}

#[cfg(test)]
mod tests {
    use brainfuck::*;
    use brainfuck::Command::*;
    use std::io::Cursor;

    #[test]
    fn read_empty() {
        let source = "";
        let expected: Vec<Command> = vec![];

        match read(source) {
            Ok(actual) => assert_eq!(expected, actual),
            Err(_) => assert!(false),
        };
    }

    #[test]
    fn read_simple() {
        let source = "+>-<.,<.-+>,";
        let expected = vec![IncrementValue,
                            IncrementPointer,
                            DecrementValue,
                            DecrementPointer,
                            OutputValue,
                            InputValue,
                            DecrementPointer,
                            OutputValue,
                            DecrementValue,
                            IncrementValue,
                            IncrementPointer,
                            InputValue];

        match read(source) {
            Ok(actual) => assert_eq!(expected, actual),
            Err(_) => assert!(false),
        };
    }

    #[test]
    fn read_garbage() {
        let source = ",.+lol,hey.>there<";
        let expected = vec![InputValue,
                            OutputValue,
                            IncrementValue,
                            InputValue,
                            OutputValue,
                            IncrementPointer,
                            DecrementPointer];

        match read(source) {
            Ok(actual) => assert_eq!(expected, actual),
            Err(_) => assert!(false),
        };
    }

    #[test]
    fn read_loop() {
        let source = "[->+<]";
        let expected = vec![ForwardsTo(5),
                            DecrementValue,
                            IncrementPointer,
                            IncrementValue,
                            DecrementPointer,
                            BackwardsTo(0)];

        match read(source) {
            Ok(actual) => assert_eq!(expected, actual),
            Err(_) => assert!(false),
        };
    }

    #[test]
    fn read_bad_loop() {
        let source = "[,.[,.>+-][./.[]]";
        let expected = "Found an unmatched square brace.";

        match read(source) {
            Ok(_) => assert!(false),
            Err(actual) => assert_eq!(expected, actual),
        };
    }

    #[test]
    fn eval_empty() {
        let input = Cursor::new(&b""[..]);
        let mut output = Cursor::new(vec![]);

        match read("") {
            Ok(program) => eval(program, input, &mut output),
            Err(_) => assert!(false),
        }

        let expected = "";
        let actual = String::from_utf8(output.into_inner()).expect("Not UTF-8");

        assert_eq!(expected, actual);
    }

    #[test]
    fn eval_new_line() {
        let input = Cursor::new(&b""[..]);
        let mut output = Cursor::new(vec![]);

        match read("++++++++++.") {
            Ok(program) => eval(program, input, &mut output),
            Err(_) => assert!(false),
        }

        let expected = "\n";
        let actual = String::from_utf8(output.into_inner()).expect("Not UTF-8");

        assert_eq!(expected, actual);
    }

    #[test]
    fn eval_cat() {
        let input = Cursor::new(&b"Hello, World!"[..]);
        let mut output = Cursor::new(vec![]);

        match read(",[.,]") {
            Ok(program) => eval(program, input, &mut output),
            Err(_) => assert!(false),
        }

        let expected = "Hello, World!";
        let actual = String::from_utf8(output.into_inner()).expect("Not UTF-8");

        assert_eq!(expected, actual);
    }
}
<commit_msg>Added a failing test for eval, I think it's loops<commit_after>use std::env;
use std::io;
use std::fs::File;
use std::io::prelude::*;

fn main() {
    if let Some(path) = env::args().nth(1) {
        let mut contents = String::new();
        match File::open(path) {
            Ok(mut file) => {
                match file.read_to_string(&mut contents) {
                    Ok(_) => {
                        match brainfuck::read(&contents) {
                            Ok(program) => {
                                let stdio = io::stdin();
                                let input = stdio.lock();
                                let output = io::stdout();
                                brainfuck::eval(program, input, output);
                            }
                            Err(msg) => println!("Read the file, but could not parse it: {}", msg),
                        }
                    }
                    Err(_) => println!("Found the file but failed to read it."),
                }
            }
            Err(_) => println!("Failed to open the file for reading."),
        };
    } else {
        println!("Please provide a path to some brainfuck source as the first argument.")
    }
}

mod brainfuck {
    use std::io::{Read, Write}
;

    #[derive(PartialEq)]
    #[derive(Debug)]
    pub enum Command {
        IncrementPointer,
        DecrementPointer,
        IncrementValue,
        DecrementValue,
        OutputValue,
        InputValue,
        ForwardsTo(usize),
        BackwardsTo(usize),
    }

    pub fn read(source: &str) -> Result<Vec<Command>, &'static str> {
        let mut forward_pointers: Vec<usize> = vec![];
        let mut backward_pointers: Vec<usize> = vec![];
        let mut position: usize = 0;
        let mut program: Vec<Command> = source
            .chars()
            .filter_map(|token| {
                let command = match token {
                    '>' => Some(Command::IncrementPointer),
                    '<' => Some(Command::DecrementPointer),
                    '+' => Some(Command::IncrementValue),
                    '-' => Some(Command::DecrementValue),
                    '.' => Some(Command::OutputValue),
                    ',' => Some(Command::InputValue),
                    '[' => {
                        forward_pointers.push(position);
                        Some(Command::BackwardsTo(position))
                    }
                    ']' => {
                        backward_pointers.push(position);
                        Some(Command::ForwardsTo(position))
                    }
                    _ => None,
                };

                if command.is_some() {
                    position += 1
                }

                command
            })
            .collect();

        if forward_pointers.len() == backward_pointers.len() {
            for (a, b) in forward_pointers.iter().zip(backward_pointers) {
                program.swap(*a, b)
            }

            Ok(program)
        } else {
            Err("Found an unmatched square brace.")
        }
    }

    fn write_byte<W>(mut writer: W, byte: u8)
        where W: Write
    {
        write!(&mut writer, "{}", byte as char).expect("Unable to write");
    }

    fn read_byte<R>(reader: R) -> u8
        where R: Read
    {
        reader
            .bytes()
            .next()
            .and_then(|result| result.ok())
            .map(|byte| byte as u8)
            .unwrap_or(0)
    }

    pub fn eval<R, W>(program: Vec<Command>, mut reader: R, mut writer: W)
        where R: Read,
              W: Write
    {
        let mut memory: Vec<u8> = vec![0; 30000];
        let mut mem_pointer: usize = 0;
        let mut prog_pointer: usize = 0;
        let prog_len = program.len();

        while prog_pointer < prog_len {
            match program[prog_pointer] {
                Command::IncrementPointer => {
                    mem_pointer += 1;
                }
                Command::DecrementPointer => {
                    mem_pointer -= 1;
                }
                Command::IncrementValue => {
                    memory[mem_pointer] += 1;
                }
                Command::DecrementValue => {
                    memory[mem_pointer] -= 1;
                }
                Command::OutputValue => {
                    write_byte(&mut writer, memory[mem_pointer]);
                }
                Command::InputValue => {
                    memory[mem_pointer] = read_byte(&mut reader);
                }
                Command::ForwardsTo(next) => {
                    if memory[mem_pointer] == 0 {
                        prog_pointer = next;
                    }
                }
                Command::BackwardsTo(next) => {
                    if memory[mem_pointer] != 0 {
                        prog_pointer = next;
                    }
                }
            };

            prog_pointer += 1;
        }
    }
}

#[cfg(test)]
mod tests {
    use brainfuck::*;
    use brainfuck::Command::*;
    use std::io::Cursor;

    #[test]
    fn read_empty() {
        let source = "";
        let expected: Vec<Command> = vec![];

        match read(source) {
            Ok(actual) => assert_eq!(expected, actual),
            Err(_) => assert!(false),
        };
    }

    #[test]
    fn read_simple() {
        let source = "+>-<.,<.-+>,";
        let expected = vec![IncrementValue,
                            IncrementPointer,
                            DecrementValue,
                            DecrementPointer,
                            OutputValue,
                            InputValue,
                            DecrementPointer,
                            OutputValue,
                            DecrementValue,
                            IncrementValue,
                            IncrementPointer,
                            InputValue];

        match read(source) {
            Ok(actual) => assert_eq!(expected, actual),
            Err(_) => assert!(false),
        };
    }

    #[test]
    fn read_garbage() {
        let source = ",.+lol,hey.>there<";
        let expected = vec![InputValue,
                            OutputValue,
                            IncrementValue,
                            InputValue,
                            OutputValue,
                            IncrementPointer,
                            DecrementPointer];

        match read(source) {
            Ok(actual) => assert_eq!(expected, actual),
            Err(_) => assert!(false),
        };
    }

    #[test]
    fn read_loop() {
        let source = "[->+<]";
        let expected = vec![ForwardsTo(5),
                            DecrementValue,
                            IncrementPointer,
                            IncrementValue,
                            DecrementPointer,
                            BackwardsTo(0)];

        match read(source) {
            Ok(actual) => assert_eq!(expected, actual),
            Err(_) => assert!(false),
        };
    }

    #[test]
    fn read_bad_loop() {
        let source = "[,.[,.>+-][./.[]]";
        let expected = "Found an unmatched square brace.";

        match read(source) {
            Ok(_) => assert!(false),
            Err(actual) => assert_eq!(expected, actual),
        };
    }

    #[test]
    fn eval_empty() {
        let input = Cursor::new(&b""[..]);
        let mut output = Cursor::new(vec![]);

        match read("") {
            Ok(program) => eval(program, input, &mut output),
            Err(_) => assert!(false),
        }

        let expected = "";
        let actual = String::from_utf8(output.into_inner()).expect("Not UTF-8");

        assert_eq!(expected, actual);
    }

    #[test]
    fn eval_new_line() {
        let input = Cursor::new(&b""[..]);
        let mut output = Cursor::new(vec![]);

        match read("++++++++++.") {
            Ok(program) => eval(program, input, &mut output),
            Err(_) => assert!(false),
        }

        let expected = "\n";
        let actual = String::from_utf8(output.into_inner()).expect("Not UTF-8");

        assert_eq!(expected, actual);
    }

    #[test]
    fn eval_cat() {
        let input = Cursor::new(&b"Hello, World!"[..]);
        let mut output = Cursor::new(vec![]);

        match read(",[.,]") {
            Ok(program) => eval(program, input, &mut output),
            Err(_) => assert!(false),
        }

        let expected = "Hello, World!";
        let actual = String::from_utf8(output.into_inner()).expect("Not UTF-8");

        assert_eq!(expected, actual);
    }

    #[test]
    fn eval_hello_world() {
        let input = Cursor::new(&b""[..]);
        let mut output = Cursor::new(vec![]);

        match read("--------[>+>+++++>-->-->--->++++>------<<<<<<<-------]>.>---.>----..>-.>++++.>.>+++++++.<<<.+++.<.<-.>>>>+.") {
            Ok(program) => eval(program, input, &mut output),
            Err(_) => assert!(false),
        }

        let expected = "Hello, World!";
        let actual = String::from_utf8(output.into_inner()).expect("Not UTF-8");

        assert_eq!(expected, actual);
    }
}
<|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

use std::iter::{repeat};
use std::num::{Float, SignedInt};
use cgmath::{Vector};
use common::types::{Size2, ZInt, MapPos};
use dir::{Dir, DirIter, dirs};

#[derive(Clone)]
pub enum Terrain {
    Plain,
    Trees,
    // Swamp,
    Building,
}

// TODO: Replace with generic map: Map<PathfinderTile>
pub struct Map<T> {
    tiles: Vec<T>,
    size: Size2<ZInt>,
}

impl<T: Clone> Map<T> {
    // TODO: remove 'empty'
    pub fn new(size: &Size2<ZInt>, empty: T) -> Map<T> {
        let tiles_count = size.w * size.h;
        let tiles = repeat(empty).take(tiles_count as usize).collect();
        Map {
            tiles: tiles,
            size: size.clone(),
        }
    }

    pub fn size(&self) -> &Size2<ZInt> {
        &self.size
    }

    pub fn tile_mut(&mut self, pos: &MapPos) -> &mut T {
        assert!(self.is_inboard(pos));
        let index = self.size.w * pos.v.y + pos.v.x;
        &mut self.tiles[index as usize]
    }

    pub fn tile(&self, pos: &MapPos) -> &T {
        assert!(self.is_inboard(pos));
        let index = self.size.w * pos.v.y + pos.v.x;
        &self.tiles[index as usize]
    }

    pub fn is_inboard(&self, pos: &MapPos) -> bool {
        let x = pos.v.x;
        let y = pos.v.y;
        x >= 0 && y >= 0 && x < self.size.w && y < self.size.h
    }

    pub fn get_iter(&self) -> MapPosIter {
        MapPosIter::new(self.size())
    }
}

pub struct MapPosIter {
    cursor: MapPos,
    map_size: Size2<ZInt>,
}

impl MapPosIter {
    fn new(map_size: &Size2<ZInt>) -> MapPosIter {
        MapPosIter {
            cursor: MapPos{v: Vector::from_value(0)},
            map_size: map_size.clone(),
        }
    }
}

impl Iterator for MapPosIter {
    type Item = MapPos;

    fn next(&mut self) -> Option<MapPos> {
        let current_pos = if self.cursor.v.y >= self.map_size.h {
            None
        } else {
            Some(self.cursor.clone())
        };
        self.cursor.v.x += 1;
        if self.cursor.v.x >= self.map_size.w {
            self.cursor.v.x = 0;
            self.cursor.v.y += 1;
        }
        current_pos
    }
}

pub struct RingIter {
    cursor: MapPos,
    segment_index: ZInt,
    dir_iter: DirIter,
    radius: ZInt,
    dir: Dir,
}

pub fn ring_iter(pos: &MapPos, radius: ZInt) -> RingIter {
    let mut pos = pos.clone();
    pos.v.x -= radius;
    let mut dir_iter = dirs();
    let dir = dir_iter.next().unwrap();
    assert_eq!(dir, Dir::SouthEast);
    RingIter {
        cursor: pos.clone(),
        radius: radius,
        segment_index: 0,
        dir_iter: dir_iter,
        dir: dir,
    }
}

impl RingIter {
    fn simple_step(&mut self) -> Option<MapPos> {
        self.cursor = Dir::get_neighbour_pos(
            &self.cursor, &self.dir);
        self.segment_index += 1;
        Some(self.cursor.clone())
    }

    fn rotate(&mut self, dir: Dir) -> Option<MapPos> {
        self.segment_index = 0;
        self.cursor = Dir::get_neighbour_pos(&self.cursor, &self.dir);
        self.dir = dir;
        Some(self.cursor.clone())
    }
}

impl Iterator for RingIter {
    type Item = MapPos;

    fn next(&mut self) -> Option<MapPos> {
        if self.segment_index >= self.radius - 1 {
            if let Some(dir) = self.dir_iter.next() {
                self.rotate(dir)
            } else {
                if self.segment_index == self.radius {
                    None
                } else {
                    // last pos
                    self.simple_step()
                }
            }
        } else {
            self.simple_step()
        }
    }
}

pub struct SpiralIter {
    ring_iter: RingIter,
    radius: ZInt,
    last_radius: ZInt,
    origin: MapPos,
}

pub fn spiral_iter(pos: &MapPos, radius: ZInt) -> SpiralIter {
    assert!(radius >= 1);
    SpiralIter {
        ring_iter: ring_iter(pos, 1),
        radius: 1,
        last_radius: radius,
        origin: pos.clone(),
    }
}

impl Iterator for SpiralIter {
    type Item = MapPos;

    fn next(&mut self) -> Option<MapPos> {
        let pos = self.ring_iter.next();
        if pos.is_some() {
            pos
        } else {
            self.radius += 1;
            if self.radius > self.last_radius {
                None
            } else {
                self.ring_iter = ring_iter(
                    &self.origin, self.radius);
                self.ring_iter.next()
            }
        }
    }
}

pub fn distance(from: &MapPos, to: &MapPos) -> ZInt {
    let to = to.v;
    let from = from.v;
    let dx = (to.x + to.y / 2) - (from.x + from.y / 2);
    let dy = to.y - from.y;
    (dx.abs() + dy.abs() + (dx - dy).abs()) / 2
}

#[cfg(test)]
mod tests {
    use cgmath::{Vector2};
    use common::types::{MapPos};
    use super::{ring_iter, spiral_iter};

    #[test]
    fn test_ring_1() {
        let radius = 1;
        let start_pos = MapPos{v: Vector2{x: 0, y: 0}};
        let expected = [
            (0, -1), (1, -1), (1, 0), (1, 1), (0, 1), (-1, 0) ];
        let mut expected = expected.iter();
        for p in ring_iter(&start_pos, radius) {
            let expected = expected.next().expect(
                "Can not get next element from expected vector");
            assert_eq!(*expected, (p.v.x, p.v.y));
        }
        assert!(expected.next().is_none());
    }

    #[test]
    fn test_ring_2() {
        let radius = 2;
        let start_pos = MapPos{v: Vector2{x: 0, y: 0}};
        let expected = [
            (-1, -1),
            (-1, -2),
            (0, -2),
            (1, -2),
            (2, -1),
            (2, 0),
            (2, 1),
            (1, 2),
            (0, 2),
            (-1, 2),
            (-1, 1),
            (-2, 0),
        ];
        let mut expected = expected.iter();
        for p in ring_iter(&start_pos, radius) {
            let expected = expected.next().expect(
                "Can not get next element from expected vector");
            assert_eq!(*expected, (p.v.x, p.v.y));
        }
        assert!(expected.next().is_none());
    }

    #[test]
    fn test_spiral_1() {
        let radius = 2;
        let start_pos = MapPos{v: Vector2{x: 0, y: 0}};
        let expected = [
            // ring 1
            (0, -1),
            (1, -1),
            (1, 0),
            (1, 1),
            (0, 1),
            (-1, 0),
            // ring 2
            (-1, -1),
            (-1, -2),
            (0, -2),
            (1, -2),
            (2, -1),
            (2, 0),
            (2, 1),
            (1, 2),
            (0, 2),
            (-1, 2),
            (-1, 1),
            (-2, 0),
        ];
        let mut expected = expected.iter();
        for p in spiral_iter(&start_pos, radius) {
            let expected = expected.next().expect(
                "Can not get next element from expected vector");
            assert_eq!(*expected, (p.v.x, p.v.y));
        }
        assert!(expected.next().is_none());
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<commit_msg>map.rs: Removed outdated todo-comment about generic map<commit_after>// See LICENSE file for copyright and license details.

use std::iter::{repeat};
use std::num::{Float, SignedInt};
use cgmath::{Vector};
use common::types::{Size2, ZInt, MapPos};
use dir::{Dir, DirIter, dirs};

#[derive(Clone)]
pub enum Terrain {
    Plain,
    Trees,
    // Swamp,
    Building,
}

pub struct Map<T> {
    tiles: Vec<T>,
    size: Size2<ZInt>,
}

impl<T: Clone> Map<T> {
    // TODO: remove 'empty'
    pub fn new(size: &Size2<ZInt>, empty: T) -> Map<T> {
        let tiles_count = size.w * size.h;
        let tiles = repeat(empty).take(tiles_count as usize).collect();
        Map {
            tiles: tiles,
            size: size.clone(),
        }
    }

    pub fn size(&self) -> &Size2<ZInt> {
        &self.size
    }

    pub fn tile_mut(&mut self, pos: &MapPos) -> &mut T {
        assert!(self.is_inboard(pos));
        let index = self.size.w * pos.v.y + pos.v.x;
        &mut self.tiles[index as usize]
    }

    pub fn tile(&self, pos: &MapPos) -> &T {
        assert!(self.is_inboard(pos));
        let index = self.size.w * pos.v.y + pos.v.x;
        &self.tiles[index as usize]
    }

    pub fn is_inboard(&self, pos: &MapPos) -> bool {
        let x = pos.v.x;
        let y = pos.v.y;
        x >= 0 && y >= 0 && x < self.size.w && y < self.size.h
    }

    pub fn get_iter(&self) -> MapPosIter {
        MapPosIter::new(self.size())
    }
}

pub struct MapPosIter {
    cursor: MapPos,
    map_size: Size2<ZInt>,
}

impl MapPosIter {
    fn new(map_size: &Size2<ZInt>) -> MapPosIter {
        MapPosIter {
            cursor: MapPos{v: Vector::from_value(0)},
            map_size: map_size.clone(),
        }
    }
}

impl Iterator for MapPosIter {
    type Item = MapPos;

    fn next(&mut self) -> Option<MapPos> {
        let current_pos = if self.cursor.v.y >= self.map_size.h {
            None
        } else {
            Some(self.cursor.clone())
        };
        self.cursor.v.x += 1;
        if self.cursor.v.x >= self.map_size.w {
            self.cursor.v.x = 0;
            self.cursor.v.y += 1;
        }
        current_pos
    }
}

pub struct RingIter {
    cursor: MapPos,
    segment_index: ZInt,
    dir_iter: DirIter,
    radius: ZInt,
    dir: Dir,
}

pub fn ring_iter(pos: &MapPos, radius: ZInt) -> RingIter {
    let mut pos = pos.clone();
    pos.v.x -= radius;
    let mut dir_iter = dirs();
    let dir = dir_iter.next().unwrap();
    assert_eq!(dir, Dir::SouthEast);
    RingIter {
        cursor: pos.clone(),
        radius: radius,
        segment_index: 0,
        dir_iter: dir_iter,
        dir: dir,
    }
}

impl RingIter {
    fn simple_step(&mut self) -> Option<MapPos> {
        self.cursor = Dir::get_neighbour_pos(
            &self.cursor, &self.dir);
        self.segment_index += 1;
        Some(self.cursor.clone())
    }

    fn rotate(&mut self, dir: Dir) -> Option<MapPos> {
        self.segment_index = 0;
        self.cursor = Dir::get_neighbour_pos(&self.cursor, &self.dir);
        self.dir = dir;
        Some(self.cursor.clone())
    }
}

impl Iterator for RingIter {
    type Item = MapPos;

    fn next(&mut self) -> Option<MapPos> {
        if self.segment_index >= self.radius - 1 {
            if let Some(dir) = self.dir_iter.next() {
                self.rotate(dir)
            } else {
                if self.segment_index == self.radius {
                    None
                } else {
                    // last pos
                    self.simple_step()
                }
            }
        } else {
            self.simple_step()
        }
    }
}

pub struct SpiralIter {
    ring_iter: RingIter,
    radius: ZInt,
    last_radius: ZInt,
    origin: MapPos,
}

pub fn spiral_iter(pos: &MapPos, radius: ZInt) -> SpiralIter {
    assert!(radius >= 1);
    SpiralIter {
        ring_iter: ring_iter(pos, 1),
        radius: 1,
        last_radius: radius,
        origin: pos.clone(),
    }
}

impl Iterator for SpiralIter {
    type Item = MapPos;

    fn next(&mut self) -> Option<MapPos> {
        let pos = self.ring_iter.next();
        if pos.is_some() {
            pos
        } else {
            self.radius += 1;
            if self.radius > self.last_radius {
                None
            } else {
                self.ring_iter = ring_iter(
                    &self.origin, self.radius);
                self.ring_iter.next()
            }
        }
    }
}

pub fn distance(from: &MapPos, to: &MapPos) -> ZInt {
    let to = to.v;
    let from = from.v;
    let dx = (to.x + to.y / 2) - (from.x + from.y / 2);
    let dy = to.y - from.y;
    (dx.abs() + dy.abs() + (dx - dy).abs()) / 2
}

#[cfg(test)]
mod tests {
    use cgmath::{Vector2};
    use common::types::{MapPos};
    use super::{ring_iter, spiral_iter};

    #[test]
    fn test_ring_1() {
        let radius = 1;
        let start_pos = MapPos{v: Vector2{x: 0, y: 0}};
        let expected = [
            (0, -1), (1, -1), (1, 0), (1, 1), (0, 1), (-1, 0) ];
        let mut expected = expected.iter();
        for p in ring_iter(&start_pos, radius) {
            let expected = expected.next().expect(
                "Can not get next element from expected vector");
            assert_eq!(*expected, (p.v.x, p.v.y));
        }
        assert!(expected.next().is_none());
    }

    #[test]
    fn test_ring_2() {
        let radius = 2;
        let start_pos = MapPos{v: Vector2{x: 0, y: 0}};
        let expected = [
            (-1, -1),
            (-1, -2),
            (0, -2),
            (1, -2),
            (2, -1),
            (2, 0),
            (2, 1),
            (1, 2),
            (0, 2),
            (-1, 2),
            (-1, 1),
            (-2, 0),
        ];
        let mut expected = expected.iter();
        for p in ring_iter(&start_pos, radius) {
            let expected = expected.next().expect(
                "Can not get next element from expected vector");
            assert_eq!(*expected, (p.v.x, p.v.y));
        }
        assert!(expected.next().is_none());
    }

    #[test]
    fn test_spiral_1() {
        let radius = 2;
        let start_pos = MapPos{v: Vector2{x: 0, y: 0}};
        let expected = [
            // ring 1
            (0, -1),
            (1, -1),
            (1, 0),
            (1, 1),
            (0, 1),
            (-1, 0),
            // ring 2
            (-1, -1),
            (-1, -2),
            (0, -2),
            (1, -2),
            (2, -1),
            (2, 0),
            (2, 1),
            (1, 2),
            (0, 2),
            (-1, 2),
            (-1, 1),
            (-2, 0),
        ];
        let mut expected = expected.iter();
        for p in spiral_iter(&start_pos, radius) {
            let expected = expected.next().expect(
                "Can not get next element from expected vector");
            assert_eq!(*expected, (p.v.x, p.v.y));
        }
        assert!(expected.next().is_none());
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<|endoftext|>


<commit_before><commit_msg>Fix compilation on nightly<commit_after><|endoftext|>


<commit_before><commit_msg>Add input types.<commit_after><|endoftext|>


<commit_before>//! Bare MIPS32r2, little endian, softfloat, O32 calling convention
//!
//! Can be used for MIPS M4K core (e.g. on PIC32MX devices)

use crate::spec::abi::Abi;
use crate::spec::{LinkerFlavor, LldFlavor, RelocModel};
use crate::spec::{PanicStrategy, Target, TargetOptions};

pub fn target() -> Target {
    Target {
        llvm_target: "mipsel-unknown-none".to_string(),
        target_endian: "little".to_string(),
        pointer_width: 32,
        target_c_int_width: "32".to_string(),
        data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(),
        arch: "mips".to_string(),
        target_os: "none".to_string(),
        target_env: String::new(),
        target_vendor: String::new(),
        linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),

        options: TargetOptions {
            cpu: "mips32r2".to_string(),
            features: "+mips32r2,+soft-float,+noabicalls".to_string(),
            max_atomic_width: Some(32),
            executables: true,
            linker: Some("rust-lld".to_owned()),
            panic_strategy: PanicStrategy::Abort,
            relocation_model: RelocModel::Static,
            unsupported_abis: vec![
                Abi::Stdcall,
                Abi::Fastcall,
                Abi::Vectorcall,
                Abi::Thiscall,
                Abi::Win64,
                Abi::SysV64,
            ],
            emit_debug_gdb_scripts: false,
            ..Default::default()
        },
    }
}
<commit_msg>Update recently added targets<commit_after>//! Bare MIPS32r2, little endian, softfloat, O32 calling convention
//!
//! Can be used for MIPS M4K core (e.g. on PIC32MX devices)

use crate::spec::abi::Abi;
use crate::spec::{LinkerFlavor, LldFlavor, RelocModel};
use crate::spec::{PanicStrategy, Target, TargetOptions};

pub fn target() -> Target {
    Target {
        llvm_target: "mipsel-unknown-none".to_string(),
        pointer_width: 32,
        data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(),
        arch: "mips".to_string(),

        options: TargetOptions {
            target_vendor: String::new(),
            linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
            cpu: "mips32r2".to_string(),
            features: "+mips32r2,+soft-float,+noabicalls".to_string(),
            max_atomic_width: Some(32),
            executables: true,
            linker: Some("rust-lld".to_owned()),
            panic_strategy: PanicStrategy::Abort,
            relocation_model: RelocModel::Static,
            unsupported_abis: vec![
                Abi::Stdcall,
                Abi::Fastcall,
                Abi::Vectorcall,
                Abi::Thiscall,
                Abi::Win64,
                Abi::SysV64,
            ],
            emit_debug_gdb_scripts: false,
            ..Default::default()
        },
    }
}
<|endoftext|>


<commit_before>use turtle::Turtle;
use chrono::{Local, Timelike};
use std::{thread, time};

fn main() {
    let hours = 12;
    let minutes = 60.0;
    let seconds = 60.0;
    let full_circle = 360.0;
    let second = time::Duration::from_millis(1000);

    let mut turtle = Turtle::new();
    turtle.set_speed("instant");
    turtle.hide();

    //A clock runs forever
    loop{
        //clean everything
        turtle.clear();
        turtle.pen_up();
        turtle.home();

        //Get local time
        let now = Local::now();

        //Draw the clock
        for i in 1..=hours{
            turtle.forward(205.0);
            turtle.set_pen_size(if (i - 1) % 3 == 0 {5.0} else {1.0});
            turtle.pen_down();
            turtle.forward(5.0);
            turtle.pen_up();
            turtle.home();
            turtle.right(full_circle / hours as f64 * i as f64);
        }

        //Draw the hour hand
        turtle.home();
        turtle.right(full_circle / hours as f64 * now.hour() as f64);
        turtle.set_pen_size(5.0);
        turtle.pen_down();
        turtle.forward(120.0);
        turtle.pen_up();

        //Draw the minute hand
        turtle.home();
        turtle.right(full_circle / minutes * now.minute() as f64);
        turtle.set_pen_size(3.0);
        turtle.pen_down();
        turtle.forward(150.0);
        turtle.pen_up();

        //Draw the second hand
        turtle.home();
        turtle.right(full_circle / seconds * now.second() as f64);
        turtle.set_pen_size(1.0);
        turtle.pen_down();
        turtle.forward(180.0);

        //And update every second
        thread::sleep(second);
    }
}<commit_msg>reducing calls to the pen_up() and pen_down() functions<commit_after>use turtle::Turtle;
use chrono::{Local, Timelike};
use std::{thread, time};

fn main() {
    let hours = 12;
    let minutes = 60.0;
    let seconds = 60.0;
    let full_circle = 360.0;
    let second = time::Duration::from_millis(1000);

    let mut turtle = Turtle::new();
    turtle.set_speed("instant");
    turtle.hide();

    //A clock runs forever
    loop{
        //clean everything
        turtle.clear();
        turtle.pen_up();
        turtle.home();

        //Get local time
        let now = Local::now();

        //Draw the clock
        for i in 1..=hours{
            turtle.forward(205.0);
            turtle.set_pen_size(if (i - 1) % 3 == 0 {5.0} else {1.0});
            turtle.pen_down();
            turtle.forward(5.0);
            turtle.pen_up();
            turtle.home();
            turtle.right(full_circle / hours as f64 * i as f64);
        }
        turtle.pen_down();

        //Draw the hour hand
        turtle.home();
        turtle.right(full_circle / hours as f64 * now.hour() as f64);
        turtle.set_pen_size(5.0);
        turtle.forward(120.0);

        //Draw the minute hand
        turtle.home();
        turtle.right(full_circle / minutes * now.minute() as f64);
        turtle.set_pen_size(3.0);
        turtle.forward(150.0);

        //Draw the second hand
        turtle.home();
        turtle.right(full_circle / seconds * now.second() as f64);
        turtle.set_pen_size(1.0);
        turtle.forward(180.0);

        //And update every second
        thread::sleep(second);
    }
}<|endoftext|>


<commit_before>#![cfg(feature = "unstable-dynamic")]

#[test]
fn suggest_subcommand_subset() {
    let name = "test";
    let mut cmd = clap::Command::new(name)
        .subcommand(clap::Command::new("hello-world"))
        .subcommand(clap::Command::new("hello-moon"))
        .subcommand(clap::Command::new("goodbye-world"));

    let args = [name, "he"];
    let arg_index = 1;
    let args = IntoIterator::into_iter(args)
        .map(|s| std::ffi::OsString::from(s))
        .collect::<Vec<_>>();
    let comp_type = clap_complete::dynamic::bash::CompType::default();
    let trailing_space = true;
    let current_dir = None;

    let completions = clap_complete::dynamic::bash::complete(
        &mut cmd,
        args,
        arg_index,
        comp_type,
        trailing_space,
        current_dir,
    )
    .unwrap();
    let completions = completions
        .into_iter()
        .map(|s| s.to_string_lossy().into_owned())
        .collect::<Vec<_>>();

    assert_eq!(completions, ["hello-moon", "hello-world", "help"]);
}

#[test]
fn suggest_additional_short_flags() {
    let name = "test";
    let mut cmd = clap::Command::new(name)
        .arg(clap::Arg::new("a").short('a').multiple_occurrences(true))
        .arg(clap::Arg::new("b").short('b').multiple_occurrences(true))
        .arg(clap::Arg::new("c").short('c').multiple_occurrences(true));

    let args = [name, "-a"];
    let arg_index = 1;
    let args = IntoIterator::into_iter(args)
        .map(|s| std::ffi::OsString::from(s))
        .collect::<Vec<_>>();
    let comp_type = clap_complete::dynamic::bash::CompType::default();
    let trailing_space = true;
    let current_dir = None;

    let completions = clap_complete::dynamic::bash::complete(
        &mut cmd,
        args,
        arg_index,
        comp_type,
        trailing_space,
        current_dir,
    )
    .unwrap();
    let completions = completions
        .into_iter()
        .map(|s| s.to_string_lossy().into_owned())
        .collect::<Vec<_>>();

    assert_eq!(completions, ["-ah", "-aa", "-ab", "-ac"]);
}
<commit_msg>test(complete): Cover long flags<commit_after>#![cfg(feature = "unstable-dynamic")]

#[test]
fn suggest_subcommand_subset() {
    let name = "test";
    let mut cmd = clap::Command::new(name)
        .subcommand(clap::Command::new("hello-world"))
        .subcommand(clap::Command::new("hello-moon"))
        .subcommand(clap::Command::new("goodbye-world"));

    let args = [name, "he"];
    let arg_index = 1;
    let args = IntoIterator::into_iter(args)
        .map(|s| std::ffi::OsString::from(s))
        .collect::<Vec<_>>();
    let comp_type = clap_complete::dynamic::bash::CompType::default();
    let trailing_space = true;
    let current_dir = None;

    let completions = clap_complete::dynamic::bash::complete(
        &mut cmd,
        args,
        arg_index,
        comp_type,
        trailing_space,
        current_dir,
    )
    .unwrap();
    let completions = completions
        .into_iter()
        .map(|s| s.to_string_lossy().into_owned())
        .collect::<Vec<_>>();

    assert_eq!(completions, ["hello-moon", "hello-world", "help"]);
}

#[test]
fn suggest_long_flag_subset() {
    let name = "test";
    let mut cmd = clap::Command::new(name)
        .arg(
            clap::Arg::new("hello-world")
                .long("--hello-world")
                .multiple_occurrences(true),
        )
        .arg(
            clap::Arg::new("hello-moon")
                .long("--hello-moon")
                .multiple_occurrences(true),
        )
        .arg(
            clap::Arg::new("goodbye-world")
                .long("--goodbye-world")
                .multiple_occurrences(true),
        );

    let args = [name, "--he"];
    let arg_index = 1;
    let args = IntoIterator::into_iter(args)
        .map(|s| std::ffi::OsString::from(s))
        .collect::<Vec<_>>();
    let comp_type = clap_complete::dynamic::bash::CompType::default();
    let trailing_space = true;
    let current_dir = None;

    let completions = clap_complete::dynamic::bash::complete(
        &mut cmd,
        args,
        arg_index,
        comp_type,
        trailing_space,
        current_dir,
    )
    .unwrap();
    let completions = completions
        .into_iter()
        .map(|s| s.to_string_lossy().into_owned())
        .collect::<Vec<_>>();

    assert_eq!(completions, ["--help", "--hello-world", "--hello-moon"]);
}

#[test]
fn suggest_additional_short_flags() {
    let name = "test";
    let mut cmd = clap::Command::new(name)
        .arg(clap::Arg::new("a").short('a').multiple_occurrences(true))
        .arg(clap::Arg::new("b").short('b').multiple_occurrences(true))
        .arg(clap::Arg::new("c").short('c').multiple_occurrences(true));

    let args = [name, "-a"];
    let arg_index = 1;
    let args = IntoIterator::into_iter(args)
        .map(|s| std::ffi::OsString::from(s))
        .collect::<Vec<_>>();
    let comp_type = clap_complete::dynamic::bash::CompType::default();
    let trailing_space = true;
    let current_dir = None;

    let completions = clap_complete::dynamic::bash::complete(
        &mut cmd,
        args,
        arg_index,
        comp_type,
        trailing_space,
        current_dir,
    )
    .unwrap();
    let completions = completions
        .into_iter()
        .map(|s| s.to_string_lossy().into_owned())
        .collect::<Vec<_>>();

    assert_eq!(completions, ["-ah", "-aa", "-ab", "-ac"]);
}
<|endoftext|>


<commit_before>extern crate getopts;
#[macro_use]
extern crate modparse_derive;
#[macro_use]
extern crate derive_builder;
#[macro_use]
extern crate torchrs;

use torchrs::autograd::{Variable, VariableArgs, VarAccess};
use torchrs::tensor::Tensor;
use torchrs::optim;
use torchrs::nn;
use torchrs::nn::{ModuleStruct, ModIntf, ModDelegate, Module};
use torchrs::nn::functional as F;
use torchrs::utils::data as D;
use torchrs::utils::torchvision::{datasets, transforms};

use getopts::Options;
use std::env;

#[derive(Clone, Builder)]
struct NetArgs {
    #[builder(default="64")]
    batch_size: usize,
    #[builder(default="1000")]
    test_batch_size: usize,
    #[builder(default="10")]
    epochs: u32,
    #[builder(default="0.01")]
    lr: f32,
    #[builder(default="0.5")]
    momentum: f32,
    #[builder(default="true")]
    cuda: bool,
    #[builder(default="1")]
    seed: usize,
    #[builder(default="10")]
    log_interval: usize,
}

impl Default for NetArgs {
    fn default() -> Self {
        NetArgsBuilder::default().build().unwrap()
    }
}

fn parse_args() -> NetArgs {
    unimplemented!();
    let cmd_args: Vec<String> = env::args().collect();
    let mut args = NetArgs::default();
    let mut opts = Options::new();

    /*
    	* XXX do parsey stuff
    	*/
    args
}

#[derive(ModParse)]
struct Net<T: Default + Copy> {
    delegate: nn::Module<T>,
    conv1: nn::Conv2d<T>,
    conv2: nn::Conv2d<T>,
    fc1: nn::Linear<T>,
    fc2: nn::Linear<T>,
}

impl<T: Default + Copy> Net<T> {
    pub fn new() -> Net<T> {
        Net {
                delegate: nn::Module::new(),
                conv1: nn::Conv2d::build(1, 10, (5, 5)).done(),
                conv2: nn::Conv2d::build(10, 20, (5, 5)).done(),
                fc1: nn::Linear::build(320, 50).done(),
                fc2: nn::Linear::build(50, 10).done(),
            }
            .init_module()
    }
}
impl_mod_delegate!(Net);

// The forward operations could take on one of two implementations.
// The first supporting a near verbatim version of the python
// implementation, and the second supporting a slightly more
// idiomatic to Rust method chaining.

// a) as a near verbatim implementation of the python version
impl ModIntf<f32> for Net<f32> {
    fn forward(&mut self, args: &mut Variable<f32>) -> Variable<f32> {
        let pool_val = F::MaxPool2dArgs::default();
        let mut dropout_val = F::DropoutArgs::default();
        dropout_val.training = self.delegate.training;
        let mut x = F::relu(&F::max_pool2d(&self.conv1.f(args), (2, 2), &pool_val));
        x = F::relu(&F::max_pool2d(&F::dropout2d(&self.conv2.f(&mut x), &dropout_val),
                                   (2, 2),
                                   &pool_val));
        x = x.view(&[-1, 320]);
        x = F::relu(&self.fc1.f(&mut x));
        x = F::dropout(&x, &dropout_val);
        x = self.fc2.f(&mut x);
        F::log_softmax(&x)
    }
}

fn train(model: &mut Net<f32>,
         args: &NetArgs,
         train_loader: &D::BatchLoader<f32, i64>,
         epoch: u32,
         optimizer: &mut optim::OptIntf) {
    model.train();
    for (batch_idx, (ref data, ref target)) in train_loader.iter().enumerate() {
        let (mut data, target) = if args.cuda {
            (Variable::new(data.cuda(None).clone()), Variable::new(target.cuda(None).clone()))
        } else {
            (Variable::new(data.clone()), Variable::new(target.clone()))
        };
        optimizer.zero_grad();
        let output = model.f(&mut data);
        let mut loss = F::nll_loss(&output, &target, &F::NLLLossArgs::default());
        loss.backward();
        optimizer.step();
        if batch_idx % args.log_interval == 0 {
            println!("Train Epoch: {} [{}/{} ({:.0}%)]\tLoss: {:.6}",
                     epoch,
                     batch_idx * data.data().len(),
                     train_loader.dataset.len(),
                     100. * (batch_idx as f32) / train_loader.len() as f32,
                     loss.data()[0]);
        }
    }
}

fn test(model: &mut Net<f32>, args: &NetArgs, test_loader: &D::BatchLoader<f32, i64>) {
    model.eval();
    let mut test_loss = 0.;
    let mut correct = 0;
    for (ref data, ref target) in test_loader.iter() {
        let varargs = VariableArgs {
            volatile: true,
            ..Default::default()
        };
        let (mut data, mut target) = if args.cuda {
            (Variable::new_args(data.cuda(None).clone(), &varargs),
             Variable::new(target.cuda(None).clone()))
        } else {
            (Variable::new_args(data.clone(), &varargs), Variable::new(target.clone()))
        };
        let mut output = model.f(&mut data);
        test_loss += F::nll_loss(&output, &target, &F::NLLLossArgs::default());
        let pred = output.data().max_reduce(1).1;
        correct += pred.eq_tensor(&*target.data()).cpu().sum() as u32;
    }
    test_loss /= test_loader.len() as f32;
    println!("\nTest set: Average loss: {:.4}, Accuracy: {}/{} ({:.0}%)\n",
             test_loss,
             correct,
             test_loader.dataset.len(),
             100. * (correct as f32) / (test_loader.dataset.len() as f32))

}

fn main() {
    // no data loaders yet so demonstrate with Vec placeholder

    let train_loader: D::BatchLoader<f32, i64> =
        D::DataLoader::new(datasets::MNIST::build("../data").done(),
                           D::DataLoaderArgs::default());
    let test_loader: D::BatchLoader<f32, i64> =
        D::DataLoader::new(datasets::MNIST::build("../data").done(),
                           D::DataLoaderArgs::default());
    let args = parse_args();
    let mut optimizer = optim::SGD::new();

    let mut model = Net::new();
    for epoch in 1..args.epochs + 1 {
        train(&mut model, &args, &train_loader, epoch, &mut optimizer);
        test(&mut model, &args, &test_loader);
    }
}
<commit_msg>parse CLI options for MNIST<commit_after>#[macro_use]
extern crate modparse_derive;
#[macro_use]
extern crate derive_builder;
#[macro_use]
extern crate torchrs;
#[macro_use]
extern crate clap;

use torchrs::autograd::{Variable, VariableArgs, VarAccess};
use torchrs::tensor::Tensor;
use torchrs::optim;
use torchrs::nn;
use torchrs::nn::{ModuleStruct, ModIntf, ModDelegate, Module};
use torchrs::nn::functional as F;
use torchrs::utils::data as D;
use torchrs::utils::torchvision::{datasets, transforms};

use clap::{Arg, App, SubCommand};

use std::env;

#[derive(Clone, Builder)]
struct NetArgs {
    #[builder(default="64")]
    batch_size: usize,
    #[builder(default="1000")]
    test_batch_size: usize,
    #[builder(default="10")]
    epochs: u32,
    #[builder(default="0.01")]
    lr: f32,
    #[builder(default="0.5")]
    momentum: f32,
    #[builder(default="true")]
    cuda: bool,
    #[builder(default="1")]
    seed: usize,
    #[builder(default="10")]
    log_interval: usize,
}

impl Default for NetArgs {
    fn default() -> Self {
        NetArgsBuilder::default().build().unwrap()
    }
}

fn parse_args() -> NetArgs {
    unimplemented!();
    let cmd_args: Vec<String> = env::args().collect();
    let mut args = NetArgs::default();
    let matches = App::new("Torch.rs MNIST Example")
        .version("0.1")
        .author("Some Guy")
        .about("recognize handwritten digits")
        .arg(Arg::with_name("batch-size").takes_value(true))
        .arg(Arg::with_name("test-batch-size").takes_value(true))
        .arg(Arg::with_name("epochs").takes_value(true))
        .arg(Arg::with_name("lr").takes_value(true))
        .arg(Arg::with_name("momentum").takes_value(true))
        .arg(Arg::with_name("no-cuda").takes_value(false))
        .arg(Arg::with_name("seed").takes_value(true))
        .arg(Arg::with_name("log-interval").takes_value(true))
        .get_matches();
    let (b_size, tb_size, epochs, lr, seed, momentum, log_int) =
        (value_t!(matches.value_of("batch-size"), usize),
         value_t!(matches.value_of("test-batch-size"), usize),
         value_t!(matches.value_of("epochs"), u32),
         value_t!(matches.value_of("lr"), f32),
         value_t!(matches.value_of("momentum"), f32),
         value_t!(matches.value_of("seed"), u32),
         value_t!(matches.value_of("log-interval"), u32));
    if let Some(b_size) = b_size {args.batch_size = b_size}
    if let Some(tb_size) = tb_size {args.test_batch_size = tb_size}
    if let Some(epochs) = epochs {args.epochs = epochs}
    if let Some(lr) = lr {args.lr = lr}
    if let Some(momentum) = momentum {args.momentum = momentum}
    if let Some(seed) = seed {args.seed = seed}
    if let Some(log_int) = log_int {args.log_interval = log_int}
    //XXX CUDA?
    args
}

#[derive(ModParse)]
struct Net<T: Default + Copy> {
    delegate: nn::Module<T>,
    conv1: nn::Conv2d<T>,
    conv2: nn::Conv2d<T>,
    fc1: nn::Linear<T>,
    fc2: nn::Linear<T>,
}

impl<T: Default + Copy> Net<T> {
    pub fn new() -> Net<T> {
        Net {
                delegate: nn::Module::new(),
                conv1: nn::Conv2d::build(1, 10, (5, 5)).done(),
                conv2: nn::Conv2d::build(10, 20, (5, 5)).done(),
                fc1: nn::Linear::build(320, 50).done(),
                fc2: nn::Linear::build(50, 10).done(),
            }
            .init_module()
    }
}
impl_mod_delegate!(Net);

// The forward operations could take on one of two implementations.
// The first supporting a near verbatim version of the python
// implementation, and the second supporting a slightly more
// idiomatic to Rust method chaining.

// a) as a near verbatim implementation of the python version
impl ModIntf<f32> for Net<f32> {
    fn forward(&mut self, args: &mut Variable<f32>) -> Variable<f32> {
        let pool_val = F::MaxPool2dArgs::default();
        let mut dropout_val = F::DropoutArgs::default();
        dropout_val.training = self.delegate.training;
        let mut x = F::relu(&F::max_pool2d(&self.conv1.f(args), (2, 2), &pool_val));
        x = F::relu(&F::max_pool2d(&F::dropout2d(&self.conv2.f(&mut x), &dropout_val),
                                   (2, 2),
                                   &pool_val));
        x = x.view(&[-1, 320]);
        x = F::relu(&self.fc1.f(&mut x));
        x = F::dropout(&x, &dropout_val);
        x = self.fc2.f(&mut x);
        F::log_softmax(&x)
    }
}

fn train(model: &mut Net<f32>,
         args: &NetArgs,
         train_loader: &D::BatchLoader<f32, i64>,
         epoch: u32,
         optimizer: &mut optim::OptIntf) {
    model.train();
    for (batch_idx, (ref data, ref target)) in train_loader.iter().enumerate() {
        let (mut data, target) = if args.cuda {
            (Variable::new(data.cuda(None).clone()), Variable::new(target.cuda(None).clone()))
        } else {
            (Variable::new(data.clone()), Variable::new(target.clone()))
        };
        optimizer.zero_grad();
        let output = model.f(&mut data);
        let mut loss = F::nll_loss(&output, &target, &F::NLLLossArgs::default());
        loss.backward();
        optimizer.step();
        if batch_idx % args.log_interval == 0 {
            println!("Train Epoch: {} [{}/{} ({:.0}%)]\tLoss: {:.6}",
                     epoch,
                     batch_idx * data.data().len(),
                     train_loader.dataset.len(),
                     100. * (batch_idx as f32) / train_loader.len() as f32,
                     loss.data()[0]);
        }
    }
}

fn test(model: &mut Net<f32>, args: &NetArgs, test_loader: &D::BatchLoader<f32, i64>) {
    model.eval();
    let mut test_loss = 0.;
    let mut correct = 0;
    for (ref data, ref target) in test_loader.iter() {
        let varargs = VariableArgs {
            volatile: true,
            ..Default::default()
        };
        let (mut data, mut target) = if args.cuda {
            (Variable::new_args(data.cuda(None).clone(), &varargs),
             Variable::new(target.cuda(None).clone()))
        } else {
            (Variable::new_args(data.clone(), &varargs), Variable::new(target.clone()))
        };
        let mut output = model.f(&mut data);
        test_loss += F::nll_loss(&output, &target, &F::NLLLossArgs::default());
        let pred = output.data().max_reduce(1).1;
        correct += pred.eq_tensor(&*target.data()).cpu().sum() as u32;
    }
    test_loss /= test_loader.len() as f32;
    println!("\nTest set: Average loss: {:.4}, Accuracy: {}/{} ({:.0}%)\n",
             test_loss,
             correct,
             test_loader.dataset.len(),
             100. * (correct as f32) / (test_loader.dataset.len() as f32))

}

fn main() {
    // no data loaders yet so demonstrate with Vec placeholder

    let train_loader: D::BatchLoader<f32, i64> =
        D::DataLoader::new(datasets::MNIST::build("../data").done(),
                           D::DataLoaderArgs::default());
    let test_loader: D::BatchLoader<f32, i64> =
        D::DataLoader::new(datasets::MNIST::build("../data").done(),
                           D::DataLoaderArgs::default());
    let args = parse_args();
    let mut optimizer = optim::SGD::new();

    let mut model = Net::new();
    for epoch in 1..args.epochs + 1 {
        train(&mut model, &args, &train_loader, epoch, &mut optimizer);
        test(&mut model, &args, &test_loader);
    }
}
<|endoftext|>


<commit_before>extern crate rand;
extern crate pbr;
use rand::Rng;
use pbr::MultiBar;
use std::thread;
use std::time::Duration;

fn main() {
    let mut mb = MultiBar::new();
    mb.println("Your Application Header:");
    mb.println("");

    for i in 1..6 {
        let count = 100 * i;
        let mut pb = mb.create_bar(count);
        pb.tick_format("▏▎▍▌▋▊▉██▉▊▋▌▍▎▏");
        pb.show_message = true;
        thread::spawn(move || {
            for _ in 0..count / 20 {
                for _ in 0..20 {
                    pb.message("Waiting  : ");
                    thread::sleep(Duration::from_millis(50));
                    pb.tick();
                }
                for _ in 0..20 {
                    let n = rand::thread_rng().gen_range(0, 100 * i);
                    pb.message("Connected: ");
                    thread::sleep(Duration::from_millis(n));
                    pb.inc();
                }
            }
            for _ in 0..20 {
                pb.message("Cleaning :");
                thread::sleep(Duration::from_millis(100));
                pb.tick();
            }
            pb.finish_print(&format!("Bar {} completed !", i));
        });
    }

    mb.println("");
    mb.println("Text lines separate between two sections: ");
    mb.println("");

    for i in 1..4 {
        let count = 100 * i;
        let mut pb = mb.create_bar(count);
        thread::spawn(move || {
            for _ in 0..count {
                pb.inc();
                let n = rand::thread_rng().gen_range(0, 100 * i);
                thread::sleep(Duration::from_millis(n));
            }
            pb.finish();
        });
    }

    mb.listen();

    println!("\nall bars done!\n");
}
<commit_msg>example: generate random string at the end<commit_after>extern crate rand;
extern crate pbr;
use rand::Rng;
use pbr::MultiBar;
use std::thread;
use std::time::Duration;

fn main() {
    let mut mb = MultiBar::new();
    mb.println("Your Application Header:");
    mb.println("");

    for i in 1..6 {
        let count = 100 * i;
        let mut pb = mb.create_bar(count);
        pb.tick_format("▏▎▍▌▋▊▉██▉▊▋▌▍▎▏");
        pb.show_message = true;
        thread::spawn(move || {
            for _ in 0..count / 20 {
                for _ in 0..20 {
                    pb.message("Waiting  : ");
                    thread::sleep(Duration::from_millis(50));
                    pb.tick();
                }
                for _ in 0..20 {
                    let n = rand::thread_rng().gen_range(0, 100 * i);
                    pb.message("Connected: ");
                    thread::sleep(Duration::from_millis(n));
                    pb.inc();
                }
            }
            for _ in 0..20 {
                pb.message("Cleaning :");
                thread::sleep(Duration::from_millis(100));
                pb.tick();
            }
            pb.finish_print(&format!("{}: Pull complete", rand_string()));
        });
    }

    mb.println("");
    mb.println("Text lines separate between two sections: ");
    mb.println("");

    for i in 1..4 {
        let count = 100 * i;
        let mut pb = mb.create_bar(count);
        thread::spawn(move || {
            for _ in 0..count {
                pb.inc();
                let n = rand::thread_rng().gen_range(0, 100 * i);
                thread::sleep(Duration::from_millis(n));
            }
            pb.finish();
        });
    }

    mb.listen();

    println!("\nall bars done!\n");
}

fn rand_string() -> String {
    let mut v = Vec::new();
    while v.len() < 12 {
        let b = rand::random::<u8>();
        // [0-9a-f]
        if b > 47 && b < 58 || b > 96 && b < 103 {
            v.push(b);
        }
    }
    std::str::from_utf8(&v).unwrap().to_string()
}
<|endoftext|>