<commit_before>#![cfg(feature = "s3")]
extern crate rusoto;
extern crate time;
extern crate hyper;
extern crate env_logger;
extern crate log;

use hyper::Client;
use std::fs::File;
use std::io::Read;
use time::get_time;

use rusoto::{DefaultCredentialsProvider, Region};
use rusoto::s3::{S3, S3Client, HeadObjectRequest, CopyObjectRequest, GetObjectRequest,
                 PutObjectRequest, DeleteObjectRequest, PutBucketCorsRequest, CORSConfiguration,
                 CORSRule, CreateBucketRequest, DeleteBucketRequest, CreateMultipartUploadRequest,
                 UploadPartRequest, CompleteMultipartUploadRequest, CompletedMultipartUpload,
                 CompletedPart, CompletedPartList, ListObjectsV2Request};
use rusoto::default_tls_client;

type TestClient = S3Client<DefaultCredentialsProvider, Client>;

// Rust is in bad need of an integration test harness
// This creates the S3 resources needed for a suite of tests,
// executes those tests, and then destroys the resources
#[test]
fn test_all_the_things() {
    let _ = env_logger::init();

    let client = S3Client::new(default_tls_client().unwrap(),
                               DefaultCredentialsProvider::new().unwrap(),
                               Region::UsEast1);

    let test_bucket = format!("rusoto_test_bucket_{}", get_time().sec);
    let filename = format!("test_file_{}", get_time().sec);
    let binary_filename = format!("test_file_b{}", get_time().sec);
    let multipart_filename = format!("test_multipart_file_{}", get_time().sec);

    // get a list of list_buckets
    test_list_buckets(&client);

    // create a bucket for these tests
    test_create_bucket(&client, &test_bucket);

    // list items v2
    list_items_in_bucket(&client, &test_bucket);

    // do a multipart upload
    test_multipart_upload(&client, &test_bucket, &multipart_filename);

    // modify the bucket's CORS properties
    test_put_bucket_cors(&client, &test_bucket);

    // PUT an object (no_credentials is an arbitrary choice)
    test_put_object_with_filename(&client,
                                  &test_bucket,
                                  &filename,
                                  &"tests/sample-data/no_credentials");

    // HEAD the object that was PUT
    test_head_object(&client, &test_bucket, &filename);

    // GET the object
    test_get_object(&client, &test_bucket, &filename);
    test_get_object_range(&client, &test_bucket, &filename);
    // copy the object to change its settings
    test_copy_object(&client, &test_bucket, &filename);

    // DELETE the object
    test_delete_object(&client, &test_bucket, &filename);

    // Binary objects:
    test_put_object_with_filename(&client,
                                  &test_bucket,
                                  &binary_filename,
                                  &"tests/sample-data/binary-file");
    test_get_object(&client, &test_bucket, &binary_filename);
    test_delete_object(&client, &test_bucket, &binary_filename);

    // delete the test bucket
    test_delete_bucket(&client, &test_bucket);
}

fn test_multipart_upload(client: &TestClient, bucket: &str, filename: &str) {
    let create_multipart_req = CreateMultipartUploadRequest {
        bucket: bucket.to_owned(),
        key: filename.to_owned(),
        ..Default::default()
    };

    // start the multipart upload and note the upload_id generated
    let response = client.create_multipart_upload(&create_multipart_req).unwrap();
    println!("{:#?}", response);
    let upload_id = response.upload_id.unwrap();

    // create 2 upload parts
    let create_upload_part = |body: Vec<u8>, part_number: i64| -> UploadPartRequest {
        UploadPartRequest {
            body: Some(body),
            bucket: bucket.to_owned(),
            key: filename.to_owned(),
            upload_id: upload_id.to_owned(),
            part_number: part_number,
            ..Default::default()
        }
    };

    // minimum size for a non-final multipart upload part is 5MB
    let part_req1 = create_upload_part(vec!['a' as u8; 1024 * 1024 * 5], 1);
    let part_req2 = create_upload_part("foo".as_bytes().to_vec(), 2);

    // upload 2 parts and note the etags generated for them
    let mut completed_parts = CompletedPartList::new();
    for req in [part_req1, part_req2].into_iter() {
        let response = client.upload_part(&req).unwrap();
        println!("{:#?}", response);
        completed_parts.push(CompletedPart {
            e_tag: response.e_tag.clone(),
            part_number: Some(req.part_number),
        });
    }

    // complete the multipart upload with the etags of the parts
    let completed_upload = CompletedMultipartUpload { parts: Some(completed_parts) };

    let complete_req = CompleteMultipartUploadRequest {
        bucket: bucket.to_owned(),
        key: filename.to_owned(),
        upload_id: upload_id.to_owned(),
        multipart_upload: Some(completed_upload),
        ..Default::default()
    };

    let response = client.complete_multipart_upload(&complete_req).unwrap();
    println!("{:#?}", response);

    // delete the completed file
    test_delete_object(client, bucket, filename);
}

fn test_create_bucket(client: &TestClient, bucket: &str) {
    let create_bucket_req = CreateBucketRequest { bucket: bucket.to_owned(), ..Default::default() };

    let result = client.create_bucket(&create_bucket_req).unwrap();
    println!("{:#?}", result);
}

fn test_delete_bucket(client: &TestClient, bucket: &str) {
    let delete_bucket_req = DeleteBucketRequest { bucket: bucket.to_owned(), ..Default::default() };

    let result = client.delete_bucket(&delete_bucket_req).unwrap();
    println!("{:#?}", result);
}

fn test_put_object_with_filename(client: &TestClient,
                                 bucket: &str,
                                 dest_filename: &str,
                                 local_filename: &str) {
    let mut f = File::open(local_filename).unwrap();
    let mut contents: Vec<u8> = Vec::new();
    match f.read_to_end(&mut contents) {
        Err(why) => panic!("Error opening file to send to S3: {}", why),
        Ok(_) => {
            let req = PutObjectRequest {
                bucket: bucket.to_owned(),
                key: dest_filename.to_owned(),
                body: Some(contents),
                ..Default::default()
            };
            let result = client.put_object(&req);
            println!("{:#?}", result);
        }
    }
}

fn test_head_object(client: &TestClient, bucket: &str, filename: &str) {
    let head_req = HeadObjectRequest {
        bucket: bucket.to_owned(),
        key: filename.to_owned(),
        ..Default::default()
    };

    let result = client.head_object(&head_req).unwrap();
    println!("{:#?}", result);
}

fn test_get_object(client: &TestClient, bucket: &str, filename: &str) {
    let get_req = GetObjectRequest {
        bucket: bucket.to_owned(),
        key: filename.to_owned(),
        ..Default::default()
    };

    let result = client.get_object(&get_req).unwrap();
    println!("get object result: {:#?}", result);
    assert!(result.body.unwrap().len() > 0);
}

fn test_get_object_range(client: &TestClient, bucket: &str, filename: &str) {
    let get_req = GetObjectRequest {
        bucket: bucket.to_owned(),
        key: filename.to_owned(),
        range: Some("bytes=0-1".to_owned()),
        ..Default::default()
    };

    let result = client.get_object(&get_req).unwrap();
    println!("\nget object range result: {:#?}", result);
    assert_eq!(result.content_length.unwrap(), 2);
}

fn test_copy_object(client: &TestClient, bucket: &str, filename: &str) {
    let req = CopyObjectRequest {
        bucket: bucket.to_owned(),
        key: filename.to_owned(),
        copy_source: format!("{}/{}", bucket, filename),
        cache_control: Some("max-age=123".to_owned()),
        content_type: Some("application/json".to_owned()),
        metadata_directive: Some("REPLACE".to_owned()),
        ..Default::default()
    };

    let result = client.copy_object(&req).unwrap();
    println!("{:#?}", result);
}

fn test_delete_object(client: &TestClient, bucket: &str, filename: &str) {
    let del_req = DeleteObjectRequest {
        bucket: bucket.to_owned(),
        key: filename.to_owned(),
        ..Default::default()
    };

    let result = client.delete_object(&del_req).unwrap();
    println!("{:#?}", result);
}

fn test_list_buckets(client: &TestClient) {
    let result = client.list_buckets().unwrap();
    println!("\nbuckets available: {:#?}", result);
}

fn list_items_in_bucket(client: &TestClient, bucket: &str) {
    let list_obj_req = ListObjectsV2Request {
        bucket: bucket.to_owned(),
        start_after: Some("foo".to_owned()),
        ..Default::default()
    };
    let result = client.list_objects_v2(&list_obj_req).unwrap();
    println!("Items in bucket: {:#?}", result);
}

fn test_put_bucket_cors(client: &TestClient, bucket: &str) {
    let cors_rules =
        vec![CORSRule {
                 allowed_methods: vec!["PUT".to_owned(), "POST".to_owned(), "DELETE".to_owned()],
                 allowed_origins: vec!["http://www.example.com".to_owned()],
                 allowed_headers: Some(vec!["*".to_owned()]),
                 max_age_seconds: Some(3000),
                 expose_headers: Some(vec!["x-amz-server-side-encryption".to_owned()]),
                 ..Default::default()
             }];

    let cors_configuration = CORSConfiguration { cors_rules: cors_rules };

    let req = PutBucketCorsRequest {
        bucket: bucket.to_owned(),
        cors_configuration: cors_configuration,
        ..Default::default()
    };

    let result = client.put_bucket_cors(&req).unwrap();
    println!("{:#?}", result);
}
<commit_msg>Gets S3 paging test working.<commit_after>#![cfg(feature = "s3")]
extern crate rusoto;
extern crate time;
extern crate hyper;
extern crate env_logger;
extern crate log;

use hyper::Client;
use std::fs::File;
use std::io::Read;
use time::get_time;

use rusoto::{DefaultCredentialsProvider, Region};
use rusoto::s3::{S3, S3Client, HeadObjectRequest, CopyObjectRequest, GetObjectRequest,
                 PutObjectRequest, DeleteObjectRequest, PutBucketCorsRequest, CORSConfiguration,
                 CORSRule, CreateBucketRequest, DeleteBucketRequest, CreateMultipartUploadRequest,
                 UploadPartRequest, CompleteMultipartUploadRequest, CompletedMultipartUpload,
                 CompletedPart, CompletedPartList, ListObjectsV2Request};
use rusoto::default_tls_client;

type TestClient = S3Client<DefaultCredentialsProvider, Client>;

// Rust is in bad need of an integration test harness
// This creates the S3 resources needed for a suite of tests,
// executes those tests, and then destroys the resources
#[test]
fn test_all_the_things() {
    let _ = env_logger::init();

    let client = S3Client::new(default_tls_client().unwrap(),
                               DefaultCredentialsProvider::new().unwrap(),
                               Region::UsEast1);

    let test_bucket = format!("rusoto_test_bucket_{}", get_time().sec);
    let filename = format!("test_file_{}", get_time().sec);
    let binary_filename = format!("test_file_b{}", get_time().sec);
    let multipart_filename = format!("test_multipart_file_{}", get_time().sec);

    // get a list of list_buckets
    test_list_buckets(&client);

    // create a bucket for these tests
    test_create_bucket(&client, &test_bucket);

    // list items v2
    list_items_in_bucket(&client, &test_bucket);

    // do a multipart upload
    test_multipart_upload(&client, &test_bucket, &multipart_filename);

    // modify the bucket's CORS properties
    test_put_bucket_cors(&client, &test_bucket);

    // PUT an object (no_credentials is an arbitrary choice)
    test_put_object_with_filename(&client,
                                  &test_bucket,
                                  &filename,
                                  &"tests/sample-data/no_credentials");

    // HEAD the object that was PUT
    test_head_object(&client, &test_bucket, &filename);

    // GET the object
    test_get_object(&client, &test_bucket, &filename);
    test_get_object_range(&client, &test_bucket, &filename);
    // copy the object to change its settings
    test_copy_object(&client, &test_bucket, &filename);

    // Binary objects:
    test_put_object_with_filename(&client,
                                  &test_bucket,
                                  &binary_filename,
                                  &"tests/sample-data/binary-file");
    test_get_object(&client, &test_bucket, &binary_filename);

    // paging test requires three items in the bucket, put another item there:
    // PUT an object (no_credentials is an arbitrary choice)
    let another_filename = format!("foo{}", filename);
    test_put_object_with_filename(&client,
                                  &test_bucket,
                                  &another_filename,
                                  &"tests/sample-data/no_credentials");

    // list items with paging
    list_items_in_bucket_paged(&client, &test_bucket);

    test_delete_object(&client, &test_bucket, &binary_filename);
    test_delete_object(&client, &test_bucket, &another_filename);

    // DELETE the object
    test_delete_object(&client, &test_bucket, &filename);

    // delete the test bucket
    test_delete_bucket(&client, &test_bucket);
}

fn test_multipart_upload(client: &TestClient, bucket: &str, filename: &str) {
    let create_multipart_req = CreateMultipartUploadRequest {
        bucket: bucket.to_owned(),
        key: filename.to_owned(),
        ..Default::default()
    };

    // start the multipart upload and note the upload_id generated
    let response = client.create_multipart_upload(&create_multipart_req).unwrap();
    println!("{:#?}", response);
    let upload_id = response.upload_id.unwrap();

    // create 2 upload parts
    let create_upload_part = |body: Vec<u8>, part_number: i64| -> UploadPartRequest {
        UploadPartRequest {
            body: Some(body),
            bucket: bucket.to_owned(),
            key: filename.to_owned(),
            upload_id: upload_id.to_owned(),
            part_number: part_number,
            ..Default::default()
        }
    };

    // minimum size for a non-final multipart upload part is 5MB
    let part_req1 = create_upload_part(vec!['a' as u8; 1024 * 1024 * 5], 1);
    let part_req2 = create_upload_part("foo".as_bytes().to_vec(), 2);

    // upload 2 parts and note the etags generated for them
    let mut completed_parts = CompletedPartList::new();
    for req in [part_req1, part_req2].into_iter() {
        let response = client.upload_part(&req).unwrap();
        println!("{:#?}", response);
        completed_parts.push(CompletedPart {
            e_tag: response.e_tag.clone(),
            part_number: Some(req.part_number),
        });
    }

    // complete the multipart upload with the etags of the parts
    let completed_upload = CompletedMultipartUpload { parts: Some(completed_parts) };

    let complete_req = CompleteMultipartUploadRequest {
        bucket: bucket.to_owned(),
        key: filename.to_owned(),
        upload_id: upload_id.to_owned(),
        multipart_upload: Some(completed_upload),
        ..Default::default()
    };

    let response = client.complete_multipart_upload(&complete_req).unwrap();
    println!("{:#?}", response);

    // delete the completed file
    test_delete_object(client, bucket, filename);
}

fn test_create_bucket(client: &TestClient, bucket: &str) {
    let create_bucket_req = CreateBucketRequest { bucket: bucket.to_owned(), ..Default::default() };

    let result = client.create_bucket(&create_bucket_req).unwrap();
    println!("{:#?}", result);
}

fn test_delete_bucket(client: &TestClient, bucket: &str) {
    let delete_bucket_req = DeleteBucketRequest { bucket: bucket.to_owned(), ..Default::default() };

    let result = client.delete_bucket(&delete_bucket_req).unwrap();
    println!("{:#?}", result);
}

fn test_put_object_with_filename(client: &TestClient,
                                 bucket: &str,
                                 dest_filename: &str,
                                 local_filename: &str) {
    let mut f = File::open(local_filename).unwrap();
    let mut contents: Vec<u8> = Vec::new();
    match f.read_to_end(&mut contents) {
        Err(why) => panic!("Error opening file to send to S3: {}", why),
        Ok(_) => {
            let req = PutObjectRequest {
                bucket: bucket.to_owned(),
                key: dest_filename.to_owned(),
                body: Some(contents),
                ..Default::default()
            };
            let result = client.put_object(&req);
            println!("{:#?}", result);
        }
    }
}

fn test_head_object(client: &TestClient, bucket: &str, filename: &str) {
    let head_req = HeadObjectRequest {
        bucket: bucket.to_owned(),
        key: filename.to_owned(),
        ..Default::default()
    };

    let result = client.head_object(&head_req).unwrap();
    println!("{:#?}", result);
}

fn test_get_object(client: &TestClient, bucket: &str, filename: &str) {
    let get_req = GetObjectRequest {
        bucket: bucket.to_owned(),
        key: filename.to_owned(),
        ..Default::default()
    };

    let result = client.get_object(&get_req).unwrap();
    println!("get object result: {:#?}", result);
    assert!(result.body.unwrap().len() > 0);
}

fn test_get_object_range(client: &TestClient, bucket: &str, filename: &str) {
    let get_req = GetObjectRequest {
        bucket: bucket.to_owned(),
        key: filename.to_owned(),
        range: Some("bytes=0-1".to_owned()),
        ..Default::default()
    };

    let result = client.get_object(&get_req).unwrap();
    println!("\nget object range result: {:#?}", result);
    assert_eq!(result.content_length.unwrap(), 2);
}

fn test_copy_object(client: &TestClient, bucket: &str, filename: &str) {
    let req = CopyObjectRequest {
        bucket: bucket.to_owned(),
        key: filename.to_owned(),
        copy_source: format!("{}/{}", bucket, filename),
        cache_control: Some("max-age=123".to_owned()),
        content_type: Some("application/json".to_owned()),
        metadata_directive: Some("REPLACE".to_owned()),
        ..Default::default()
    };

    let result = client.copy_object(&req).unwrap();
    println!("{:#?}", result);
}

fn test_delete_object(client: &TestClient, bucket: &str, filename: &str) {
    let del_req = DeleteObjectRequest {
        bucket: bucket.to_owned(),
        key: filename.to_owned(),
        ..Default::default()
    };

    let result = client.delete_object(&del_req).unwrap();
    println!("{:#?}", result);
}

fn test_list_buckets(client: &TestClient) {
    let result = client.list_buckets().unwrap();
    println!("\nbuckets available: {:#?}", result);
}

fn list_items_in_bucket(client: &TestClient, bucket: &str) {
    let list_obj_req = ListObjectsV2Request {
        bucket: bucket.to_owned(),
        start_after: Some("foo".to_owned()),
        ..Default::default()
    };
    let result = client.list_objects_v2(&list_obj_req).unwrap();
    println!("Items in bucket: {:#?}", result);
}

// Assuming there's already more than three item in our test bucket:
fn list_items_in_bucket_paged(client: &TestClient, bucket: &str) {
    let mut list_obj_req = ListObjectsV2Request {
        bucket: bucket.to_owned(),
        max_keys: Some(1),
        ..Default::default()
    };
    let result = client.list_objects_v2(&list_obj_req).unwrap();
    println!("Items in bucket, page 1: {:#?}", result);
    assert!(result.next_continuation_token.is_some());

    list_obj_req.continuation_token = result.next_continuation_token;
    let result = client.list_objects_v2(&list_obj_req).unwrap();
    println!("Items in bucket, page 2: {:#?}", result);
    // For the second call it the token is in `continuation_token` not `next_continuation_token`
    assert!(result.continuation_token.is_some());
}

fn test_put_bucket_cors(client: &TestClient, bucket: &str) {
    let cors_rules =
        vec![CORSRule {
                 allowed_methods: vec!["PUT".to_owned(), "POST".to_owned(), "DELETE".to_owned()],
                 allowed_origins: vec!["http://www.example.com".to_owned()],
                 allowed_headers: Some(vec!["*".to_owned()]),
                 max_age_seconds: Some(3000),
                 expose_headers: Some(vec!["x-amz-server-side-encryption".to_owned()]),
                 ..Default::default()
             }];

    let cors_configuration = CORSConfiguration { cors_rules: cors_rules };

    let req = PutBucketCorsRequest {
        bucket: bucket.to_owned(),
        cors_configuration: cors_configuration,
        ..Default::default()
    };

    let result = client.put_bucket_cors(&req).unwrap();
    println!("{:#?}", result);
}
<|endoftext|>


<commit_before>//! The module implements the client side of the HTTP/2 protocol and exposes
//! an API for using it.
use std::io;
use std::convert::From;
use std::error::Error;

use hpack::decoder::DecoderError;

pub mod frame;
pub mod transport;
pub mod connection;
pub mod session;

/// An alias for the type that represents the ID of an HTTP/2 stream
pub type StreamId = u32;
/// An alias for the type that represents HTTP/2 haders. For now we only alias
/// the tuple of byte vectors instead of going with a full struct representation.
pub type Header = (Vec<u8>, Vec<u8>);

/// A set of protocol names that the library should use to indicate that HTTP/2
/// is supported during protocol negotiation (NPN or ALPN).
/// We include some of the drafts' protocol names, since there is basically no
/// difference for all intents and purposes (and some servers out there still
/// only officially advertise draft support).
/// TODO: Eventually only use "h2".
pub const ALPN_PROTOCOLS: &'static [&'static [u8]] = &[
    b"h2",
    b"h2-16",
    b"h2-15",
    b"h2-14",
];

/// An enum representing errors that can arise when performing operations
/// involving an HTTP/2 connection.
#[derive(Debug)]
pub enum HttpError {
    IoError(io::Error),
    InvalidFrame,
    CompressionError(DecoderError),
    UnknownStreamId,
    UnableToConnect,
    MalformedResponse,
}

/// Implement the trait that allows us to automatically convert `io::Error`s
/// into an `HttpError` by wrapping the given `io::Error` into an `HttpError::IoError` variant.
impl From<io::Error> for HttpError {
    fn from(err: io::Error) -> HttpError {
        HttpError::IoError(err)
    }
}

/// Implementation of the `PartialEq` trait as a convenience for tests.
#[cfg(test)]
impl PartialEq for HttpError {
    fn eq(&self, other: &HttpError) -> bool {
        match (self, other) {
            (&HttpError::IoError(ref e1), &HttpError::IoError(ref e2)) => {
                e1.kind() == e2.kind() && e1.description() == e2.description()
            },
            (&HttpError::InvalidFrame, &HttpError::InvalidFrame) => true,
            (&HttpError::CompressionError(ref e1), &HttpError::CompressionError(ref e2)) => {
                e1 == e2
            },
            (&HttpError::UnknownStreamId, &HttpError::UnknownStreamId) => true,
            (&HttpError::UnableToConnect, &HttpError::UnableToConnect) => true,
            (&HttpError::MalformedResponse, &HttpError::MalformedResponse) => true,
            _ => false,
        }
    }
}

/// A convenience `Result` type that has the `HttpError` type as the error
/// type and a generic Ok result type.
pub type HttpResult<T> = Result<T, HttpError>;

/// An enum representing the two possible HTTP schemes.
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum HttpScheme {
    /// The variant corresponding to `http://`
    Http,
    /// The variant corresponding to `https://`
    Https,
}

impl HttpScheme {
    /// Returns a byte string representing the scheme.
    #[inline]
    pub fn as_bytes(&self) -> &'static [u8] {
        match *self {
            HttpScheme::Http => b"http",
            HttpScheme::Https => b"https",
        }
    }
}

/// A struct representing the full raw response received on an HTTP/2 connection.
///
/// The full body of the response is included, regardless how large it may be.
/// The headers contain both the meta-headers, as well as the actual headers.
#[derive(Clone)]
pub struct Response {
    /// The ID of the stream to which the response is associated. HTTP/1.1 does
    /// not really have an equivalent to this.
    pub stream_id: StreamId,
    /// Exposes *all* the raw response headers, including the meta-headers.
    /// (For now the only meta header allowed in HTTP/2 responses is the
    /// `:status`.)
    pub headers: Vec<Header>,
    /// The full body of the response as an uninterpreted sequence of bytes.
    pub body: Vec<u8>,
}

impl Response {
    /// Creates a new `Response` with all the components already provided.
    pub fn new(stream_id: StreamId, headers: Vec<Header>, body: Vec<u8>)
            -> Response {
        Response {
            stream_id: stream_id,
            headers: headers,
            body: body,
        }
    }

    /// Gets the response status code from the pseudo-header. If the response
    /// does not contain the response as the first pseuo-header, an error is
    /// returned as such a response is malformed.
    pub fn status_code(&self) -> HttpResult<u16> {
        // Since pseudo-headers MUST be found before any regular header fields
        // and the *only* pseudo-header defined for responses is the `:status`
        // field, the `:status` MUST be the first header; otherwise, the
        // response is malformed.
        if self.headers.len() < 1 {
            return Err(HttpError::MalformedResponse)
        }
        if &self.headers[0].0 != &b":status" {
            Err(HttpError::MalformedResponse)
        } else {
            Ok(try!(Response::parse_status_code(&self.headers[0].1)))
        }
    }

    /// A helper function that parses a given buffer as a status code and
    /// returns it as a `u16`, if it is valid.
    fn parse_status_code(buf: &[u8]) -> HttpResult<u16> {
        // "The status-code element is a three-digit integer code [...]"
        if buf.len() != 3 {
            return Err(HttpError::MalformedResponse);
        }

        // "There are five values for the first digit"
        if buf[0] < b'1' || buf[0] > b'5' {
            return Err(HttpError::MalformedResponse);
        }

        // The rest of them just have to be digits
        if buf[1] < b'0' || buf[1] > b'9' || buf[2] < b'0' || buf[2] > b'9' {
            return Err(HttpError::MalformedResponse);
        }

        // Finally, we can merge them into an integer
        Ok(100 * ((buf[0] - b'0') as u16) +
           10 * ((buf[1] - b'0') as u16) +
           1 * ((buf[2] - b'0') as u16))
    }
}

/// A struct representing a full HTTP/2 request, along with the full body, as a
/// sequence of bytes.
#[derive(Clone)]
pub struct Request {
    pub stream_id: u32,
    pub headers: Vec<Header>,
    pub body: Vec<u8>,
}

#[cfg(test)]
mod tests {
    use super::{Response, HttpError, HttpScheme};

    /// Tests that the `Response` struct correctly parses a status code from
    /// its headers list.
    #[test]
    fn test_parse_status_code_response() {
        {
            // Only status => Ok
            let resp = Response::new(
                1,
                vec![(b":status".to_vec(), b"200".to_vec())],
                vec![]);
            assert_eq!(resp.status_code().ok().unwrap(), 200);
        }
        {
            // Extra headers => still works
            let resp = Response::new(
                1,
                vec![(b":status".to_vec(), b"200".to_vec()),
                     (b"key".to_vec(), b"val".to_vec())],
                vec![]);
            assert_eq!(resp.status_code().ok().unwrap(), 200);
        }
        {
            // Status is not the first header => malformed
            let resp = Response::new(
                1,
                vec![(b"key".to_vec(), b"val".to_vec()),
                     (b":status".to_vec(), b"200".to_vec())],
                vec![]);
            assert_eq!(resp.status_code().err().unwrap(),
                       HttpError::MalformedResponse);
        }
        {
            // No headers at all => Malformed
            let resp = Response::new(1, vec![], vec![]);
            assert_eq!(resp.status_code().err().unwrap(),
                       HttpError::MalformedResponse);
        }
    }

    /// Tests that the `HttpScheme` enum returns the correct scheme strings for
    /// the two variants.
    #[test]
    fn test_scheme_string() {
        assert_eq!(HttpScheme::Http.as_bytes(), b"http");
        assert_eq!(HttpScheme::Https.as_bytes(), b"https");
    }
}
<commit_msg>http/mod.rs: Update the top-level module docs<commit_after>//! The module implements the framing layer of HTTP/2 and exposes an API for using it.
use std::io;
use std::convert::From;
use std::error::Error;

use hpack::decoder::DecoderError;

pub mod frame;
pub mod transport;
pub mod connection;
pub mod session;

/// An alias for the type that represents the ID of an HTTP/2 stream
pub type StreamId = u32;
/// An alias for the type that represents HTTP/2 haders. For now we only alias
/// the tuple of byte vectors instead of going with a full struct representation.
pub type Header = (Vec<u8>, Vec<u8>);

/// A set of protocol names that the library should use to indicate that HTTP/2
/// is supported during protocol negotiation (NPN or ALPN).
/// We include some of the drafts' protocol names, since there is basically no
/// difference for all intents and purposes (and some servers out there still
/// only officially advertise draft support).
/// TODO: Eventually only use "h2".
pub const ALPN_PROTOCOLS: &'static [&'static [u8]] = &[
    b"h2",
    b"h2-16",
    b"h2-15",
    b"h2-14",
];

/// An enum representing errors that can arise when performing operations
/// involving an HTTP/2 connection.
#[derive(Debug)]
pub enum HttpError {
    IoError(io::Error),
    InvalidFrame,
    CompressionError(DecoderError),
    UnknownStreamId,
    UnableToConnect,
    MalformedResponse,
}

/// Implement the trait that allows us to automatically convert `io::Error`s
/// into an `HttpError` by wrapping the given `io::Error` into an `HttpError::IoError` variant.
impl From<io::Error> for HttpError {
    fn from(err: io::Error) -> HttpError {
        HttpError::IoError(err)
    }
}

/// Implementation of the `PartialEq` trait as a convenience for tests.
#[cfg(test)]
impl PartialEq for HttpError {
    fn eq(&self, other: &HttpError) -> bool {
        match (self, other) {
            (&HttpError::IoError(ref e1), &HttpError::IoError(ref e2)) => {
                e1.kind() == e2.kind() && e1.description() == e2.description()
            },
            (&HttpError::InvalidFrame, &HttpError::InvalidFrame) => true,
            (&HttpError::CompressionError(ref e1), &HttpError::CompressionError(ref e2)) => {
                e1 == e2
            },
            (&HttpError::UnknownStreamId, &HttpError::UnknownStreamId) => true,
            (&HttpError::UnableToConnect, &HttpError::UnableToConnect) => true,
            (&HttpError::MalformedResponse, &HttpError::MalformedResponse) => true,
            _ => false,
        }
    }
}

/// A convenience `Result` type that has the `HttpError` type as the error
/// type and a generic Ok result type.
pub type HttpResult<T> = Result<T, HttpError>;

/// An enum representing the two possible HTTP schemes.
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum HttpScheme {
    /// The variant corresponding to `http://`
    Http,
    /// The variant corresponding to `https://`
    Https,
}

impl HttpScheme {
    /// Returns a byte string representing the scheme.
    #[inline]
    pub fn as_bytes(&self) -> &'static [u8] {
        match *self {
            HttpScheme::Http => b"http",
            HttpScheme::Https => b"https",
        }
    }
}

/// A struct representing the full raw response received on an HTTP/2 connection.
///
/// The full body of the response is included, regardless how large it may be.
/// The headers contain both the meta-headers, as well as the actual headers.
#[derive(Clone)]
pub struct Response {
    /// The ID of the stream to which the response is associated. HTTP/1.1 does
    /// not really have an equivalent to this.
    pub stream_id: StreamId,
    /// Exposes *all* the raw response headers, including the meta-headers.
    /// (For now the only meta header allowed in HTTP/2 responses is the
    /// `:status`.)
    pub headers: Vec<Header>,
    /// The full body of the response as an uninterpreted sequence of bytes.
    pub body: Vec<u8>,
}

impl Response {
    /// Creates a new `Response` with all the components already provided.
    pub fn new(stream_id: StreamId, headers: Vec<Header>, body: Vec<u8>)
            -> Response {
        Response {
            stream_id: stream_id,
            headers: headers,
            body: body,
        }
    }

    /// Gets the response status code from the pseudo-header. If the response
    /// does not contain the response as the first pseuo-header, an error is
    /// returned as such a response is malformed.
    pub fn status_code(&self) -> HttpResult<u16> {
        // Since pseudo-headers MUST be found before any regular header fields
        // and the *only* pseudo-header defined for responses is the `:status`
        // field, the `:status` MUST be the first header; otherwise, the
        // response is malformed.
        if self.headers.len() < 1 {
            return Err(HttpError::MalformedResponse)
        }
        if &self.headers[0].0 != &b":status" {
            Err(HttpError::MalformedResponse)
        } else {
            Ok(try!(Response::parse_status_code(&self.headers[0].1)))
        }
    }

    /// A helper function that parses a given buffer as a status code and
    /// returns it as a `u16`, if it is valid.
    fn parse_status_code(buf: &[u8]) -> HttpResult<u16> {
        // "The status-code element is a three-digit integer code [...]"
        if buf.len() != 3 {
            return Err(HttpError::MalformedResponse);
        }

        // "There are five values for the first digit"
        if buf[0] < b'1' || buf[0] > b'5' {
            return Err(HttpError::MalformedResponse);
        }

        // The rest of them just have to be digits
        if buf[1] < b'0' || buf[1] > b'9' || buf[2] < b'0' || buf[2] > b'9' {
            return Err(HttpError::MalformedResponse);
        }

        // Finally, we can merge them into an integer
        Ok(100 * ((buf[0] - b'0') as u16) +
           10 * ((buf[1] - b'0') as u16) +
           1 * ((buf[2] - b'0') as u16))
    }
}

/// A struct representing a full HTTP/2 request, along with the full body, as a
/// sequence of bytes.
#[derive(Clone)]
pub struct Request {
    pub stream_id: u32,
    pub headers: Vec<Header>,
    pub body: Vec<u8>,
}

#[cfg(test)]
mod tests {
    use super::{Response, HttpError, HttpScheme};

    /// Tests that the `Response` struct correctly parses a status code from
    /// its headers list.
    #[test]
    fn test_parse_status_code_response() {
        {
            // Only status => Ok
            let resp = Response::new(
                1,
                vec![(b":status".to_vec(), b"200".to_vec())],
                vec![]);
            assert_eq!(resp.status_code().ok().unwrap(), 200);
        }
        {
            // Extra headers => still works
            let resp = Response::new(
                1,
                vec![(b":status".to_vec(), b"200".to_vec()),
                     (b"key".to_vec(), b"val".to_vec())],
                vec![]);
            assert_eq!(resp.status_code().ok().unwrap(), 200);
        }
        {
            // Status is not the first header => malformed
            let resp = Response::new(
                1,
                vec![(b"key".to_vec(), b"val".to_vec()),
                     (b":status".to_vec(), b"200".to_vec())],
                vec![]);
            assert_eq!(resp.status_code().err().unwrap(),
                       HttpError::MalformedResponse);
        }
        {
            // No headers at all => Malformed
            let resp = Response::new(1, vec![], vec![]);
            assert_eq!(resp.status_code().err().unwrap(),
                       HttpError::MalformedResponse);
        }
    }

    /// Tests that the `HttpScheme` enum returns the correct scheme strings for
    /// the two variants.
    #[test]
    fn test_scheme_string() {
        assert_eq!(HttpScheme::Http.as_bytes(), b"http");
        assert_eq!(HttpScheme::Https.as_bytes(), b"https");
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! Manages system resources that can be allocated to VMs and their devices.

#[cfg(feature = "wl-dmabuf")]
extern crate gpu_buffer;
extern crate libc;
extern crate sys_util;
extern crate msg_socket;

mod address_allocator;
mod gpu_allocator;
mod system_allocator;

pub use address_allocator::AddressAllocator;
pub use gpu_allocator::{GpuMemoryAllocator, GpuMemoryDesc, GpuMemoryPlaneDesc};
pub use system_allocator::{AddressRanges, SystemAllocator};
<commit_msg>resources: re-alphabetize imports<commit_after>// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! Manages system resources that can be allocated to VMs and their devices.

#[cfg(feature = "wl-dmabuf")]
extern crate gpu_buffer;
extern crate libc;
extern crate msg_socket;
extern crate sys_util;

mod address_allocator;
mod gpu_allocator;
mod system_allocator;

pub use address_allocator::AddressAllocator;
pub use gpu_allocator::{GpuMemoryAllocator, GpuMemoryDesc, GpuMemoryPlaneDesc};
pub use system_allocator::{AddressRanges, SystemAllocator};
<|endoftext|>


<commit_before>#![allow(unstable)]

use std::io::{TcpListener, TcpStream};
use std::str;

use std::collections::HashMap;

use utils;

pub fn print_stuff() {
    println!("module fuck yeah")
}

pub fn get_http_stream() -> TcpListener {
    TcpListener::bind("127.0.0.1:4000").unwrap()
}

pub fn new_conn(mut stream: TcpStream) {
    let msg: String = read_to_crlf(&mut stream);
    println!("{}", msg)
}

fn read_to_crlf(stream: &mut TcpStream) -> String {
    const BUFFER_SIZE: usize = 4096;
    let mut buffer: &mut [u8; BUFFER_SIZE] = &mut [0; BUFFER_SIZE];
    let n = stream.read(buffer).unwrap();

    if n >= 4096 {
        panic!("Buffer full!")
    } else {
        println!("read {} bytes", n)
    }

    let s = String::from_str(str::from_utf8(buffer).unwrap());
    println!("------MESSAGE------");
    println!("{}", s);
    println!("--------END--------\n\n");
    s
}

fn parse_headers(headers: &str) -> HashMap<&str, &str> {
   let mut keystore = HashMap::new();
   for l in headers.lines() {
        let i: Option<usize> = utils::contains(l, ':');
        match i {
            Some(n) => {
                let k = &l[..n];
                let v = &l[n+1..];
                keystore.insert(k, v);
            },
            None(..) => {}
        }
   }
   keystore
}
<commit_msg>Header parser works pretty good.<commit_after>#![allow(unstable)]

use std::io::{TcpListener, TcpStream};
use std::str;

use std::collections::HashMap;

use utils;

pub fn print_stuff() {
    println!("module fuck yeah")
}

pub fn get_http_stream() -> TcpListener {
    TcpListener::bind("127.0.0.1:4000").unwrap()
}

pub fn new_conn(mut stream: TcpStream) {
    let msg: String = read_to_crlf(&mut stream);
    println!("{}", msg)
}

fn read_to_crlf(stream: &mut TcpStream) -> String {
    const BUFFER_SIZE: usize = 4096;
    let mut buffer: &mut [u8; BUFFER_SIZE] = &mut [0; BUFFER_SIZE];
    let n = stream.read(buffer).unwrap();

    if n >= 4096 {
        panic!("Buffer full!")
    } else {
        println!("read {} bytes", n)
    }

    let s: &str = str::from_utf8(buffer).unwrap();
    let string = String::from_str(s);
    println!("------MESSAGE------");
    println!("{}", s);
    println!("--------END--------\n\n");

    let headers = parse_headers(s);
    for (k, v) in headers.iter() {
        println!("Key: [{}]\tValue: [{}]", k, v)
    }

    string
}

fn parse_headers(headers: &str) -> HashMap<&str, &str> {
   let mut keystore = HashMap::new();
   for l in headers.lines() {
        let i: Option<usize> = utils::contains(l, ':');
        match i {
            Some(n) => {
                let k = l[..n].trim();
                let v = l[n+1..].trim();
                keystore.insert(k, v);
            },
            None(..) => {}
        }
   }
   keystore
}
<|endoftext|>


<commit_before>use crate::common::util::*;

#[test]
fn test_count_up() {
    new_ucmd!()
        .args(&["10"])
        .run()
        .stdout_is("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n");
}

#[test]
fn test_count_down() {
    new_ucmd!()
        .args(&["--", "5", "-1", "1"])
        .run()
        .stdout_is("5\n4\n3\n2\n1\n");
        new_ucmd!()
        .args(&["5", "-1", "1"])
        .run()
        .stdout_is("5\n4\n3\n2\n1\n");
}

#[test]
fn test_separator_and_terminator() {
    new_ucmd!()
        .args(&["-s", ",", "-t", "!", "2", "6"])
        .run()
        .stdout_is("2,3,4,5,6!");
}

#[test]
fn test_equalize_widths() {
    new_ucmd!()
        .args(&["-w", "5", "10"])
        .run()
        .stdout_is("05\n06\n07\n08\n09\n10\n");
}

#[test]
fn test_seq_wrong_arg() {
    new_ucmd!().args(&["-w", "5", "10", "33", "32"]).fails();
}
<commit_msg>fix formatting fr test_seq<commit_after>use crate::common::util::*;

#[test]
fn test_count_up() {
    new_ucmd!()
        .args(&["10"])
        .run()
        .stdout_is("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n");
}

#[test]
fn test_count_down() {
    new_ucmd!()
        .args(&["--", "5", "-1", "1"])
        .run()
        .stdout_is("5\n4\n3\n2\n1\n");
    new_ucmd!()
        .args(&["5", "-1", "1"])
        .run()
        .stdout_is("5\n4\n3\n2\n1\n");
}

#[test]
fn test_separator_and_terminator() {
    new_ucmd!()
        .args(&["-s", ",", "-t", "!", "2", "6"])
        .run()
        .stdout_is("2,3,4,5,6!");
}

#[test]
fn test_equalize_widths() {
    new_ucmd!()
        .args(&["-w", "5", "10"])
        .run()
        .stdout_is("05\n06\n07\n08\n09\n10\n");
}

#[test]
fn test_seq_wrong_arg() {
    new_ucmd!().args(&["-w", "5", "10", "33", "32"]).fails();
}
<|endoftext|>


<commit_before>use super::{CHUNK_SIZE, HexPillar, PillarIndexComponent};
use std::ops;
use std::iter;
use math::*;

/// Represents one part of the game world.
///
/// A chunk saves `CHUNK_SIZE`² many hex pillars which are arranged rougly in
/// the form of a parallelogram. See [this blog post][1] for more information
/// (the shape is called "rhombus" there).
///
/// This type implements the `Index` trait and can be indexed with an
/// `AxialPoint`.
///
/// [1]: http://www.redblobgames.com/grids/hexagons/#map-storage
pub struct Chunk {
    /// All pillars are layed out in this one dimensional vector which saves
    /// all rows (same r-value) consecutive.
    pillars: Vec<HexPillar>,
}

impl Chunk {
    /// Creates a dummy chunk for early testing. FIXME: remove
    pub fn dummy() -> Self {
        let pillars = iter::repeat(HexPillar::dummy())
            .take(CHUNK_SIZE.pow(2) as usize)
            .collect();
        Chunk { pillars: pillars }
    }

    pub fn pillars(&self) -> &[HexPillar] {
        &self.pillars
    }
}

impl ops::Index<AxialPoint> for Chunk {
    type Output = HexPillar;

    fn index(&self, pos: AxialPoint) -> Option<&Self::Output> {
        let chunk_size: PillarIndexComponent = CHUNK_SIZE.into();

        if pos.q >= 0 && pos.q < chunk_size && pos.r >= 0 && pos.r < chunk_size {
            return None;
        } else {
            return Some(&self.pillars[(pos.r as usize) * (CHUNK_SIZE as usize) + (pos.q as usize)]);
        }
    }
}
<commit_msg>Add get method for chunk<commit_after>use super::{CHUNK_SIZE, HexPillar, PillarIndexComponent};
use std::ops;
use std::iter;
use math::*;

/// Represents one part of the game world.
///
/// A chunk saves `CHUNK_SIZE`² many hex pillars which are arranged rougly in
/// the form of a parallelogram. See [this blog post][1] for more information
/// (the shape is called "rhombus" there).
///
/// This type implements the `Index` trait and can be indexed with an
/// `AxialPoint`.
///
/// [1]: http://www.redblobgames.com/grids/hexagons/#map-storage
pub struct Chunk {
    /// All pillars are layed out in this one dimensional vector which saves
    /// all rows (same r-value) consecutive.
    pillars: Vec<HexPillar>,
}

impl Chunk {
    /// Creates a dummy chunk for early testing. FIXME: remove
    pub fn dummy() -> Self {
        let pillars = iter::repeat(HexPillar::dummy())
            .take(CHUNK_SIZE.pow(2) as usize)
            .collect();
        Chunk { pillars: pillars }
    }

    pub fn pillars(&self) -> &[HexPillar] {
        &self.pillars
    }
    /// Safer method to get through a chunk with an ìndex
    pub fn get(&self, pos: AxialPoint) -> Option<&HexPillar> {
        let chunk_size: PillarIndexComponent = CHUNK_SIZE.into();

        if pos.q >= 0 && pos.q < chunk_size && pos.r >= 0 && pos.r < chunk_size {
            None
        } else {
            Some(&self.pillars[(pos.r as usize) * (CHUNK_SIZE as usize) + (pos.q as usize)])
        }
    }
}

impl ops::Index<AxialPoint> for Chunk {
    type Output = HexPillar;

    fn index(&self, pos: AxialPoint) -> &Self::Output {
        let chunk_size: PillarIndexComponent = CHUNK_SIZE.into();

        assert!(pos.q >= 0 && pos.q < chunk_size && pos.r >= 0 && pos.r < chunk_size);
        (&self.pillars[(pos.r as usize) * (CHUNK_SIZE as usize) + (pos.q as usize)])
    }
}
<|endoftext|>


<commit_before>use std::fs;
use std::io::Read;
use std::io::Write;
use std::io;
use std::path;

use atomicwrites;
use config;
use models;

use url;

use rustc_serialize::json;
use rustc_serialize::Decodable;
use rustc_serialize::Encodable;

use termion::raw::IntoRawMode;
use termion::input::TermRead;

quick_error! {
    // FIXME: https://github.com/tailhook/quick-error/issues/3
    #[derive(Debug)]
    pub enum ServerError {
        Io(error: io::Error) {
            display("{}", error)
            description(error.description())
            cause(error)
            from()
        }
        JsonDecode(error: json::DecoderError) {
            display("{}", error)
            description(error.description())
            cause(error)
            from()
        }
        JsonEncode(error: json::EncoderError) {
            display("{}", error)
            description(error.description())
            cause(error)
            from()
        }
        Config(error: config::Error) {
            display("{}", error)
            description(error.description())
            cause(error)
            from()
        }
        Model(error: models::Error) {
            display("{}", error)
            description(error.description())
            cause(error)
            from()
        }
    }
}

pub fn safe_join<P: AsRef<path::Path>, Q: AsRef<path::Path>>(base: P, user_input: Q) -> Option<path::PathBuf> {
    let a = base.as_ref();
    let b = user_input.as_ref();

    let rv = a.join(b);
    if rv.starts_with(a) && rv.is_absolute() {
        Some(rv)
    } else {
        None
    }
}

pub fn prompt<T: AsRef<str>>(text: T) -> String {
    let mut stdout = io::stdout();
    stdout.write_all(text.as_ref().as_bytes()).unwrap();
    stdout.flush().unwrap();

    let stdin = io::stdin();
    let mut response = String::new();
    stdin.read_line(&mut response).unwrap();
    if response.ends_with('\n') { response.pop(); }
    response
}

pub fn double_password_prompt<T: AsRef<str>>(text: T) -> Option<String> {
    let stdin = io::stdin();
    let mut stdin = stdin.lock();
    let stdout = io::stdout();
    let mut stdout = stdout.lock();

    let again_text = {
        let mut x = "(repeat to confirm) ".to_owned();
        x.push_str(text.as_ref());
        x
    };

    fn read_passwd<R: Read, W: Write>(reader: &mut R, writer: &mut W) -> io::Result<Option<String>> {
        let _raw = writer.into_raw_mode();
        reader.read_line()
    };

    macro_rules! p {
        ($text:expr) => {{
            stdout.write_all($text).unwrap();
            stdout.flush().unwrap();
            let result = read_passwd(&mut stdin, &mut stdout);
            stdout.write_all(b"\n").unwrap();

            match result {
                Ok(Some(x)) => if x.len() == 0 {
                    println!("Empty input.");
                    return None;
                } else {
                    x
                },
                _ => return None
            }
        }}
    }

    let first = p!(text.as_ref().as_bytes());
    let second = p!(again_text.as_bytes());

    if first != second {
        println!("Inputs don't match.");
        return None;
    };

    Some(first)
}

pub fn prompt_confirm<T: AsRef<str>>(question: T, default: bool) -> bool {
    let mut question = question.as_ref().to_owned();
    question.push_str(" ");
    question.push_str(if default { "[Y/n]" } else { "[y/N]" });
    question.push_str(" ");
    loop {
        let response = prompt(&question[..]);
        return match response.trim() {
            "y" | "Y" => true,
            "n" | "N" => false,
            "" => default,
            _ => {
                println!("Invalid answer.");
                continue;
            }
        };
    };
}

pub fn read_json_file<T: Decodable, P: AsRef<path::Path>>(p: P) -> Result<T, ServerError> {
    let mut f = try!(fs::File::open(p.as_ref()));
    let mut s = String::new();
    try!(f.read_to_string(&mut s));
    let rv = try!(json::decode(&s));
    Ok(rv)
}

pub fn write_json_file<T: Encodable, P: AsRef<path::Path>>(t: T, p: P) -> Result<(), ServerError> {
    let data = try!(json::encode(&t)).into_bytes();
    let f = atomicwrites::AtomicFile::new(p, atomicwrites::AllowOverwrite);
    try!(f.write(|f| f.write_all(&data)));
    Ok(())
}

/// Apply a function to each parent directory of given file `f_path`, stops at folder path `until`.
///
/// The function's Ok-value indicates whether mapping should continue.
pub fn map_parent_dirs<F, A, B>(f_path: A, until: B, f: F)
    -> io::Result<()>
    where F: Fn(&path::Path) -> io::Result<bool>,
          A: AsRef<path::Path>,
          B: AsRef<path::Path> {

    let mut cur_dir = f_path.as_ref();
    let stop = until.as_ref();

    loop {
        cur_dir = match cur_dir.parent() {
            Some(x) => x,
            None => break
        };

        if !cur_dir.starts_with(stop) && cur_dir != stop {
            break;
        }

        if !try!(f(cur_dir)) {
            break;
        }
    };

    Ok(())
}

pub fn format_origin(u: &url::Url) -> String {
    // FIXME: Ugly
    match u.origin() {
        url::Origin::Tuple(..) => (),
        _ => panic!("Invalid URL: {:?}", u)
    };
    u.origin().ascii_serialization()
}
<commit_msg>Remove FIXME<commit_after>use std::fs;
use std::io::Read;
use std::io::Write;
use std::io;
use std::path;

use atomicwrites;
use config;
use models;

use url;

use rustc_serialize::json;
use rustc_serialize::Decodable;
use rustc_serialize::Encodable;

use termion::raw::IntoRawMode;
use termion::input::TermRead;

quick_error! {
    // FIXME: https://github.com/tailhook/quick-error/issues/3
    #[derive(Debug)]
    pub enum ServerError {
        Io(error: io::Error) {
            display("{}", error)
            description(error.description())
            cause(error)
            from()
        }
        JsonDecode(error: json::DecoderError) {
            display("{}", error)
            description(error.description())
            cause(error)
            from()
        }
        JsonEncode(error: json::EncoderError) {
            display("{}", error)
            description(error.description())
            cause(error)
            from()
        }
        Config(error: config::Error) {
            display("{}", error)
            description(error.description())
            cause(error)
            from()
        }
        Model(error: models::Error) {
            display("{}", error)
            description(error.description())
            cause(error)
            from()
        }
    }
}

pub fn safe_join<P: AsRef<path::Path>, Q: AsRef<path::Path>>(base: P, user_input: Q) -> Option<path::PathBuf> {
    let a = base.as_ref();
    let b = user_input.as_ref();

    let rv = a.join(b);
    if rv.starts_with(a) && rv.is_absolute() {
        Some(rv)
    } else {
        None
    }
}

pub fn prompt<T: AsRef<str>>(text: T) -> String {
    let mut stdout = io::stdout();
    stdout.write_all(text.as_ref().as_bytes()).unwrap();
    stdout.flush().unwrap();

    let stdin = io::stdin();
    let mut response = String::new();
    stdin.read_line(&mut response).unwrap();
    if response.ends_with('\n') { response.pop(); }
    response
}

pub fn double_password_prompt<T: AsRef<str>>(text: T) -> Option<String> {
    let stdin = io::stdin();
    let mut stdin = stdin.lock();
    let stdout = io::stdout();
    let mut stdout = stdout.lock();

    let again_text = {
        let mut x = "(repeat to confirm) ".to_owned();
        x.push_str(text.as_ref());
        x
    };

    fn read_passwd<R: Read, W: Write>(reader: &mut R, writer: &mut W) -> io::Result<Option<String>> {
        let _raw = writer.into_raw_mode();
        reader.read_line()
    };

    macro_rules! p {
        ($text:expr) => {{
            stdout.write_all($text).unwrap();
            stdout.flush().unwrap();
            let result = read_passwd(&mut stdin, &mut stdout);
            stdout.write_all(b"\n").unwrap();

            match result {
                Ok(Some(x)) => if x.len() == 0 {
                    println!("Empty input.");
                    return None;
                } else {
                    x
                },
                _ => return None
            }
        }}
    }

    let first = p!(text.as_ref().as_bytes());
    let second = p!(again_text.as_bytes());

    if first != second {
        println!("Inputs don't match.");
        return None;
    };

    Some(first)
}

pub fn prompt_confirm<T: AsRef<str>>(question: T, default: bool) -> bool {
    let mut question = question.as_ref().to_owned();
    question.push_str(" ");
    question.push_str(if default { "[Y/n]" } else { "[y/N]" });
    question.push_str(" ");
    loop {
        let response = prompt(&question[..]);
        return match response.trim() {
            "y" | "Y" => true,
            "n" | "N" => false,
            "" => default,
            _ => {
                println!("Invalid answer.");
                continue;
            }
        };
    };
}

pub fn read_json_file<T: Decodable, P: AsRef<path::Path>>(p: P) -> Result<T, ServerError> {
    let mut f = try!(fs::File::open(p.as_ref()));
    let mut s = String::new();
    try!(f.read_to_string(&mut s));
    let rv = try!(json::decode(&s));
    Ok(rv)
}

pub fn write_json_file<T: Encodable, P: AsRef<path::Path>>(t: T, p: P) -> Result<(), ServerError> {
    let data = try!(json::encode(&t)).into_bytes();
    let f = atomicwrites::AtomicFile::new(p, atomicwrites::AllowOverwrite);
    try!(f.write(|f| f.write_all(&data)));
    Ok(())
}

/// Apply a function to each parent directory of given file `f_path`, stops at folder path `until`.
///
/// The function's Ok-value indicates whether mapping should continue.
pub fn map_parent_dirs<F, A, B>(f_path: A, until: B, f: F)
    -> io::Result<()>
    where F: Fn(&path::Path) -> io::Result<bool>,
          A: AsRef<path::Path>,
          B: AsRef<path::Path> {

    let mut cur_dir = f_path.as_ref();
    let stop = until.as_ref();

    loop {
        cur_dir = match cur_dir.parent() {
            Some(x) => x,
            None => break
        };

        if !cur_dir.starts_with(stop) && cur_dir != stop {
            break;
        }

        if !try!(f(cur_dir)) {
            break;
        }
    };

    Ok(())
}

pub fn format_origin(u: &url::Url) -> String {
    // FIXME: Ugly
    let origin = u.origin();
    if !origin.is_tuple() {
        panic!("Invalid URL: {:?}", u);
    }
    origin.ascii_serialization()
}
<|endoftext|>


<commit_before>use {Module,Global,Expression,Function,Value,value,Condition,Block};
use util;
use util::Identifiable;
use std::fmt;
use std::collections::HashMap;

/// A hack to be able to implement `Display` on a module.
///
/// This is to work around Rust's orphan rules.
pub struct Printable<'a>(&'a Module);

impl<'a> fmt::Display for Printable<'a>
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        self::module(self.0, fmt)
    }
}

/// Creates a printable module.
pub fn printable(module: &Module) -> Printable {
    Printable(module)
}

/// Holds IR printing state.
pub struct Printer<'a>
{
    /// The module that is being printed.
    module: &'a Module,

    /// Keeps track of the current register number for
    /// each function.
    register_accumulator: u32,

    /// Holds unnamed register ids and the register numbers we map
    /// them to. Can be cleared upon each function.
    register_map: HashMap<util::Id,u32>,
}

impl<'a> Printer<'a>
{
    /// Assigns a number to a register internally.
    /// Returns the registers newly assigned number.
    fn assign_register(&mut self, reg: &value::Register) -> u32 {

        let id = reg.get_id();
        let num = self.register_accumulator;

        self.register_accumulator += 1;
        self.register_map.insert(id, num);

        num
    }

    /// Gets the assigned number of a register.
    fn register_number(&self, id: util::Id) -> u32 {
        self.register_map.get(&id).unwrap().clone()
    }

    /// Clears the stored register state for the current function.
    fn clear_registers(&mut self) {
        self.register_accumulator = 0;
        self.register_map.clear();
    }
}

/// Prints an IR module.
pub fn module(module: &Module, fmt: &mut fmt::Formatter) -> fmt::Result {

    let mut printer = Printer {
        register_map: HashMap::new(),
        module: module,
        register_accumulator: 0,
    };

    for global in module.globals() {
        try!(self::global(global, &mut printer, fmt));
    }

    try!(write!(fmt, "\n"));

    for func in module.functions() {
         try!(self::function(func, &mut printer, fmt));
         try!(write!(fmt, "\n"));
    }

    Ok(())
}

pub fn global(global: &Global,
              printer: &mut Printer,
              fmt: &mut fmt::Formatter) -> fmt::Result {
    try!(write!(fmt, "%{} = ", global.name()));
    try!(plain_value(global.value(), printer, fmt));
    write!(fmt, "\n")
}

pub fn function(func: &Function,
                printer: &mut Printer,
                fmt: &mut fmt::Formatter) -> fmt::Result {
    // Initialise register accounting
    printer.clear_registers();

    try!(write!(fmt, "fn @{}", func.name()));
    try!(function_parameters(&func, fmt));
    try!(function_tail(func, fmt));

    try!(write!(fmt, " {{\n"));

    for block in func.blocks() {
        try!(self::block(block, printer, fmt));
    }

    write!(fmt, "}}\n")
}

pub fn function_parameters(func: &Function,
                           fmt: &mut fmt::Formatter) -> fmt::Result {
    let params = func.signature().parameters().map(|p|
        format!("%{}", p)
    );

    write!(fmt, "({})", util::comma_separated_values(params))
}

pub fn function_tail(func: &Function,
                     fmt: &mut fmt::Formatter) -> fmt::Result {
    let returns = func.signature().returns();

    if func.signature().has_returns() {
        try!(write!(fmt, " -> {}",
               util::comma_separated_values(returns)));
    }
    Ok(())
}

pub fn block(block: &Block,
             printer: &mut Printer,
             fmt: &mut fmt::Formatter) -> fmt::Result {

    try!(write!(fmt, "{}:\n", block.name()));

    for value in block.values() {
        try!(self::root_value(value, printer, fmt));
    }

    Ok(())
}

pub fn condition(cond: &Condition,
                 printer: &mut Printer,
                 fmt: &mut fmt::Formatter) -> fmt::Result {
    match *cond {
        // trivial conditions
        Condition::True => write!(fmt, "true"),
        Condition::False => write!(fmt, "false"),

        // binary conditions
        Condition::Equal(ref lhs, ref rhs) |
        Condition::NotEqual(ref lhs, ref rhs) |
        Condition::GreaterThan(ref lhs, ref rhs) |
        Condition::GreaterThanOrEq(ref lhs, ref rhs) |
        Condition::LessThan(ref lhs, ref rhs) |
        Condition::LessThanOrEq(ref lhs, ref rhs) => {
            try!(value(lhs, printer, fmt));
            try!(write!(fmt, " {} ", cond.abbreviation()));
            try!(value(rhs, printer, fmt));

            Ok(())
        },
    }
}

pub fn root_value(value: &Value,
                  printer: &mut Printer,
                  fmt: &mut fmt::Formatter) -> fmt::Result {
    root_expression(value.expression(), printer, fmt)
}

pub fn root_expression(expression: &Expression,
                       printer: &mut Printer,
                       fmt: &mut fmt::Formatter) -> fmt::Result {
    try!(write!(fmt, "\t"));
    try!(self::expression::plain(expression, printer, fmt));
    write!(fmt, "\n")
}

pub fn value(value: &Value,
             printer: &mut Printer,
             fmt: &mut fmt::Formatter) -> fmt::Result {
    expression::expression(value.expression(), printer, fmt)
}

pub fn plain_value(value: &Value,
                   printer: &mut Printer,
                   fmt: &mut fmt::Formatter) -> fmt::Result {
    expression::plain(value.expression(), printer, fmt)
}

pub mod expression
{
    use {Expression,value};
    use std::fmt;
    use lang;
    use super::Printer;

    pub fn expression(expr: &Expression,
                      printer: &mut Printer,
                      fmt: &mut fmt::Formatter) -> fmt::Result {
        use lang::Value;

        // simple values are not parenthesised.
        if !expr.is_simple() {
            try!(write!(fmt, "("));
        }

        try!(self::plain(expr, printer, fmt));

        if !expr.is_simple() {
            try!(write!(fmt, ")"));
        }

        Ok(())
    }

    pub fn plain(expr: &Expression,
                 printer: &mut Printer,
                 fmt: &mut fmt::Formatter) -> fmt::Result {

        match *expr {
            Expression::Literal(ref val) => self::literal(val, fmt),
            Expression::Register(ref val) => self::register(val, printer, fmt),
            Expression::Instruction(ref val) => self::instruction::instruction(val, printer, fmt),
            Expression::GlobalRef(ref val) => self::global_ref(val, printer, fmt),
            Expression::BlockRef(ref val) => self::block_ref(val, printer, fmt),
            Expression::FunctionRef(ref val) => self::function_ref(val, printer, fmt),
            Expression::RegisterRef(ref val) => self::register_ref(val, printer, fmt),
            Expression::ArgumentRef(ref val) => self::argument_ref(val, printer, fmt),
            Expression::String(ref val) => self::string(val, fmt),
        }
    }

    pub fn literal(literal: &value::Literal,
                   fmt: &mut fmt::Formatter) -> fmt::Result {
        match *literal {
            value::Literal::Integer(ref val) => self::literal_integer(val, fmt),
            _ => unimplemented!(),
        }
    }

    pub fn literal_integer(literal: &value::literal::Integer,
                           fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{} {}", literal.ty(), literal.value())
    }

    pub fn literal_struct(_literal: &value::literal::Struct,
                          _printer: &mut Printer,
                          _fmt: &mut fmt::Formatter) -> fmt::Result {
        unimplemented!();
        //write!(fmt, "{{ {} }}", util::comma_separated_values(value.fields()))
    }

    pub fn register(reg: &value::Register,
                    printer: &mut Printer,
                    fmt: &mut fmt::Formatter) -> fmt::Result {

        try!(write!(fmt, "%"));

        match *reg.name() {
            lang::Name::Unnamed => {
                let number = printer.assign_register(reg);
                try!(write!(fmt, "{}", number));
            },
            // the register has an explicit name
            lang::Name::Named(ref name) => {
                try!(write!(fmt, "{}", name));
            }
        }

        try!(write!(fmt, " = "));
        super::value(reg.subvalue(), printer, fmt)
    }

    pub fn global_ref(global_ref: &value::GlobalRef,
                      printer: &mut Printer,
                      fmt: &mut fmt::Formatter) -> fmt::Result {

        let global = printer.module.get_global(global_ref.global_id());
        write!(fmt, "%{}", global.name())
    }

    pub fn block_ref(block_ref: &value::BlockRef,
                     printer: &mut Printer,
                     fmt: &mut fmt::Formatter) -> fmt::Result {
        let block = printer.module.get_block(block_ref.block_id());
        write!(fmt, "{}", block.name())
    }

    pub fn function_ref(_func_ref: &value::FunctionRef,
                        _printer: &mut Printer,
                        _fmt: &mut fmt::Formatter) -> fmt::Result {
        unimplemented!();
    }

    pub fn register_ref(reg_ref: &value::RegisterRef,
                        printer: &mut Printer,
                        fmt: &mut fmt::Formatter) -> fmt::Result {
        let number = printer.register_number(reg_ref.register_id());
        write!(fmt, "%{}", number)
    }

    pub fn argument_ref(_arg_ref: &value::ArgumentRef,
                        _printer: &mut Printer,
                        _fmt: &mut fmt::Formatter) -> fmt::Result {
        unimplemented!();
    }

    pub fn string(s: &value::String,
                  fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "\"{}\"", s.text())
    }

    pub mod instruction
    {
        use {Expression,Instruction};
        use instruction::{self,Binary};
        use std::fmt;
        use util;
        use super::super::value;
        use super::super::Printer;

        pub fn instruction(inst: &Instruction,
                           printer: &mut Printer,
                           fmt: &mut fmt::Formatter) -> fmt::Result {
            match *inst {
                Instruction::Add(ref i) => arithmetic_binop("add", i, printer, fmt),
                Instruction::Sub(ref i) => arithmetic_binop("sub", i, printer, fmt),
                Instruction::Mul(ref i) => arithmetic_binop("mul", i, printer, fmt),
                Instruction::Div(ref i) => arithmetic_binop("div", i, printer, fmt),
                Instruction::Shl(ref i) => arithmetic_binop("shl", i, printer, fmt),
                Instruction::Shr(ref i) => arithmetic_binop("shr", i, printer, fmt),

                Instruction::Call(ref i) => call(i, fmt),
                Instruction::Break(ref i) => br(i, printer, fmt),
                Instruction::Return(ref i) => ret(i, printer, fmt),
            }
        }

        pub fn arithmetic_binop<I>(mnemonic: &'static str,
                                   inst: &I,
                                   printer: &mut Printer,
                                   fmt: &mut fmt::Formatter) -> fmt::Result
            where I: Binary {

            let (lhs,rhs) = inst.operands();

            try!(write!(fmt, "{} ", mnemonic));
            try!(value(lhs, printer, fmt));
            try!(write!(fmt, ", "));
            try!(value(rhs, printer, fmt));
            Ok(())
        }

        pub fn call(inst: &instruction::Call,
                    fmt: &mut fmt::Formatter) -> fmt::Result {
            let func = if let Expression::FunctionRef(ref f) = *inst.target().expression()  {
                f
            } else {
                unreachable!(); // target must be function
            };
            write!(fmt, "call {} {}",
                   util::comma_separated_values(func.signature().returns()),
                   func.name())

        }

        pub fn br(inst: &instruction::Break,
                  printer: &mut Printer,
                  fmt: &mut fmt::Formatter) -> fmt::Result {
            try!(write!(fmt, "break "));
            try!(super::super::condition(inst.condition(), printer, fmt));
            try!(write!(fmt, " "));
            value(inst.target(), printer, fmt)
        }

        pub fn ret(inst: &instruction::Return,
                   printer: &mut Printer,
                   fmt: &mut fmt::Formatter) -> fmt::Result {
            try!(write!(fmt, "ret "));

            match inst.subvalue() {
                Some(i) => value(i, printer, fmt),
                None => write!(fmt, "void"),
            }
        }
    }
}
<commit_msg>Don't use tabs for IR printing, use spaces<commit_after>use {Module,Global,Expression,Function,Value,value,Condition,Block};
use util;
use util::Identifiable;
use std::fmt;
use std::collections::HashMap;

pub const TAB_STRING: &'static str = "  ";

/// A hack to be able to implement `Display` on a module.
///
/// This is to work around Rust's orphan rules.
pub struct Printable<'a>(&'a Module);

impl<'a> fmt::Display for Printable<'a>
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        self::module(self.0, fmt)
    }
}

/// Creates a printable module.
pub fn printable(module: &Module) -> Printable {
    Printable(module)
}

/// Holds IR printing state.
pub struct Printer<'a>
{
    /// The module that is being printed.
    module: &'a Module,

    /// Keeps track of the current register number for
    /// each function.
    register_accumulator: u32,

    /// Holds unnamed register ids and the register numbers we map
    /// them to. Can be cleared upon each function.
    register_map: HashMap<util::Id,u32>,
}

impl<'a> Printer<'a>
{
    /// Assigns a number to a register internally.
    /// Returns the registers newly assigned number.
    fn assign_register(&mut self, reg: &value::Register) -> u32 {

        let id = reg.get_id();
        let num = self.register_accumulator;

        self.register_accumulator += 1;
        self.register_map.insert(id, num);

        num
    }

    /// Gets the assigned number of a register.
    fn register_number(&self, id: util::Id) -> u32 {
        self.register_map.get(&id).unwrap().clone()
    }

    /// Clears the stored register state for the current function.
    fn clear_registers(&mut self) {
        self.register_accumulator = 0;
        self.register_map.clear();
    }
}

/// Prints an IR module.
pub fn module(module: &Module, fmt: &mut fmt::Formatter) -> fmt::Result {

    let mut printer = Printer {
        register_map: HashMap::new(),
        module: module,
        register_accumulator: 0,
    };

    for global in module.globals() {
        try!(self::global(global, &mut printer, fmt));
    }

    try!(write!(fmt, "\n"));

    for func in module.functions() {
         try!(self::function(func, &mut printer, fmt));
         try!(write!(fmt, "\n"));
    }

    Ok(())
}

pub fn global(global: &Global,
              printer: &mut Printer,
              fmt: &mut fmt::Formatter) -> fmt::Result {
    try!(write!(fmt, "%{} = ", global.name()));
    try!(plain_value(global.value(), printer, fmt));
    write!(fmt, "\n")
}

pub fn function(func: &Function,
                printer: &mut Printer,
                fmt: &mut fmt::Formatter) -> fmt::Result {
    // Initialise register accounting
    printer.clear_registers();

    try!(write!(fmt, "fn @{}", func.name()));
    try!(function_parameters(&func, fmt));
    try!(function_tail(func, fmt));

    try!(write!(fmt, " {{\n"));

    for block in func.blocks() {
        try!(self::block(block, printer, fmt));
    }

    write!(fmt, "}}\n")
}

pub fn function_parameters(func: &Function,
                           fmt: &mut fmt::Formatter) -> fmt::Result {
    let params = func.signature().parameters().map(|p|
        format!("%{}", p)
    );

    write!(fmt, "({})", util::comma_separated_values(params))
}

pub fn function_tail(func: &Function,
                     fmt: &mut fmt::Formatter) -> fmt::Result {
    let returns = func.signature().returns();

    if func.signature().has_returns() {
        try!(write!(fmt, " -> {}",
               util::comma_separated_values(returns)));
    }
    Ok(())
}

pub fn block(block: &Block,
             printer: &mut Printer,
             fmt: &mut fmt::Formatter) -> fmt::Result {

    try!(write!(fmt, "{}:\n", block.name()));

    for value in block.values() {
        try!(self::root_value(value, printer, fmt));
    }

    Ok(())
}

pub fn condition(cond: &Condition,
                 printer: &mut Printer,
                 fmt: &mut fmt::Formatter) -> fmt::Result {
    match *cond {
        // trivial conditions
        Condition::True => write!(fmt, "true"),
        Condition::False => write!(fmt, "false"),

        // binary conditions
        Condition::Equal(ref lhs, ref rhs) |
        Condition::NotEqual(ref lhs, ref rhs) |
        Condition::GreaterThan(ref lhs, ref rhs) |
        Condition::GreaterThanOrEq(ref lhs, ref rhs) |
        Condition::LessThan(ref lhs, ref rhs) |
        Condition::LessThanOrEq(ref lhs, ref rhs) => {
            try!(value(lhs, printer, fmt));
            try!(write!(fmt, " {} ", cond.abbreviation()));
            try!(value(rhs, printer, fmt));

            Ok(())
        },
    }
}

pub fn root_value(value: &Value,
                  printer: &mut Printer,
                  fmt: &mut fmt::Formatter) -> fmt::Result {
    root_expression(value.expression(), printer, fmt)
}

pub fn root_expression(expression: &Expression,
                       printer: &mut Printer,
                       fmt: &mut fmt::Formatter) -> fmt::Result {
    try!(write!(fmt, "{}", TAB_STRING));
    try!(self::expression::plain(expression, printer, fmt));
    write!(fmt, "\n")
}

pub fn value(value: &Value,
             printer: &mut Printer,
             fmt: &mut fmt::Formatter) -> fmt::Result {
    expression::expression(value.expression(), printer, fmt)
}

pub fn plain_value(value: &Value,
                   printer: &mut Printer,
                   fmt: &mut fmt::Formatter) -> fmt::Result {
    expression::plain(value.expression(), printer, fmt)
}

pub mod expression
{
    use {Expression,value};
    use std::fmt;
    use lang;
    use super::Printer;

    pub fn expression(expr: &Expression,
                      printer: &mut Printer,
                      fmt: &mut fmt::Formatter) -> fmt::Result {
        use lang::Value;

        // simple values are not parenthesised.
        if !expr.is_simple() {
            try!(write!(fmt, "("));
        }

        try!(self::plain(expr, printer, fmt));

        if !expr.is_simple() {
            try!(write!(fmt, ")"));
        }

        Ok(())
    }

    pub fn plain(expr: &Expression,
                 printer: &mut Printer,
                 fmt: &mut fmt::Formatter) -> fmt::Result {

        match *expr {
            Expression::Literal(ref val) => self::literal(val, fmt),
            Expression::Register(ref val) => self::register(val, printer, fmt),
            Expression::Instruction(ref val) => self::instruction::instruction(val, printer, fmt),
            Expression::GlobalRef(ref val) => self::global_ref(val, printer, fmt),
            Expression::BlockRef(ref val) => self::block_ref(val, printer, fmt),
            Expression::FunctionRef(ref val) => self::function_ref(val, printer, fmt),
            Expression::RegisterRef(ref val) => self::register_ref(val, printer, fmt),
            Expression::ArgumentRef(ref val) => self::argument_ref(val, printer, fmt),
            Expression::String(ref val) => self::string(val, fmt),
        }
    }

    pub fn literal(literal: &value::Literal,
                   fmt: &mut fmt::Formatter) -> fmt::Result {
        match *literal {
            value::Literal::Integer(ref val) => self::literal_integer(val, fmt),
            _ => unimplemented!(),
        }
    }

    pub fn literal_integer(literal: &value::literal::Integer,
                           fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{} {}", literal.ty(), literal.value())
    }

    pub fn literal_struct(_literal: &value::literal::Struct,
                          _printer: &mut Printer,
                          _fmt: &mut fmt::Formatter) -> fmt::Result {
        unimplemented!();
        //write!(fmt, "{{ {} }}", util::comma_separated_values(value.fields()))
    }

    pub fn register(reg: &value::Register,
                    printer: &mut Printer,
                    fmt: &mut fmt::Formatter) -> fmt::Result {

        try!(write!(fmt, "%"));

        match *reg.name() {
            lang::Name::Unnamed => {
                let number = printer.assign_register(reg);
                try!(write!(fmt, "{}", number));
            },
            // the register has an explicit name
            lang::Name::Named(ref name) => {
                try!(write!(fmt, "{}", name));
            }
        }

        try!(write!(fmt, " = "));
        super::value(reg.subvalue(), printer, fmt)
    }

    pub fn global_ref(global_ref: &value::GlobalRef,
                      printer: &mut Printer,
                      fmt: &mut fmt::Formatter) -> fmt::Result {

        let global = printer.module.get_global(global_ref.global_id());
        write!(fmt, "%{}", global.name())
    }

    pub fn block_ref(block_ref: &value::BlockRef,
                     printer: &mut Printer,
                     fmt: &mut fmt::Formatter) -> fmt::Result {
        let block = printer.module.get_block(block_ref.block_id());
        write!(fmt, "{}", block.name())
    }

    pub fn function_ref(_func_ref: &value::FunctionRef,
                        _printer: &mut Printer,
                        _fmt: &mut fmt::Formatter) -> fmt::Result {
        unimplemented!();
    }

    pub fn register_ref(reg_ref: &value::RegisterRef,
                        printer: &mut Printer,
                        fmt: &mut fmt::Formatter) -> fmt::Result {
        let number = printer.register_number(reg_ref.register_id());
        write!(fmt, "%{}", number)
    }

    pub fn argument_ref(_arg_ref: &value::ArgumentRef,
                        _printer: &mut Printer,
                        _fmt: &mut fmt::Formatter) -> fmt::Result {
        unimplemented!();
    }

    pub fn string(s: &value::String,
                  fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "\"{}\"", s.text())
    }

    pub mod instruction
    {
        use {Expression,Instruction};
        use instruction::{self,Binary};
        use std::fmt;
        use util;
        use super::super::value;
        use super::super::Printer;

        pub fn instruction(inst: &Instruction,
                           printer: &mut Printer,
                           fmt: &mut fmt::Formatter) -> fmt::Result {
            match *inst {
                Instruction::Add(ref i) => arithmetic_binop("add", i, printer, fmt),
                Instruction::Sub(ref i) => arithmetic_binop("sub", i, printer, fmt),
                Instruction::Mul(ref i) => arithmetic_binop("mul", i, printer, fmt),
                Instruction::Div(ref i) => arithmetic_binop("div", i, printer, fmt),
                Instruction::Shl(ref i) => arithmetic_binop("shl", i, printer, fmt),
                Instruction::Shr(ref i) => arithmetic_binop("shr", i, printer, fmt),

                Instruction::Call(ref i) => call(i, fmt),
                Instruction::Break(ref i) => br(i, printer, fmt),
                Instruction::Return(ref i) => ret(i, printer, fmt),
            }
        }

        pub fn arithmetic_binop<I>(mnemonic: &'static str,
                                   inst: &I,
                                   printer: &mut Printer,
                                   fmt: &mut fmt::Formatter) -> fmt::Result
            where I: Binary {

            let (lhs,rhs) = inst.operands();

            try!(write!(fmt, "{} ", mnemonic));
            try!(value(lhs, printer, fmt));
            try!(write!(fmt, ", "));
            try!(value(rhs, printer, fmt));
            Ok(())
        }

        pub fn call(inst: &instruction::Call,
                    fmt: &mut fmt::Formatter) -> fmt::Result {
            let func = if let Expression::FunctionRef(ref f) = *inst.target().expression()  {
                f
            } else {
                unreachable!(); // target must be function
            };
            write!(fmt, "call {} {}",
                   util::comma_separated_values(func.signature().returns()),
                   func.name())

        }

        pub fn br(inst: &instruction::Break,
                  printer: &mut Printer,
                  fmt: &mut fmt::Formatter) -> fmt::Result {
            try!(write!(fmt, "break "));
            try!(super::super::condition(inst.condition(), printer, fmt));
            try!(write!(fmt, " "));
            value(inst.target(), printer, fmt)
        }

        pub fn ret(inst: &instruction::Return,
                   printer: &mut Printer,
                   fmt: &mut fmt::Formatter) -> fmt::Result {
            try!(write!(fmt, "ret "));

            match inst.subvalue() {
                Some(i) => value(i, printer, fmt),
                None => write!(fmt, "void"),
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::io::net::ip::{Ipv4Addr, SocketAddr};

mod libtorresmo {
    extern crate time;

    use std::io::net::udp::UdpSocket;
    use std::io::net::ip::SocketAddr;
    use std::io::IoResult;
    use std::mem::{to_be32, to_be16, transmute};
    use std::rand::random;

    #[allow(dead_code,non_camel_case_types)]
    enum UtpPacketType {
        ST_DATA  = 0,
        ST_FIN   = 1,
        ST_STATE = 2,
        ST_RESET = 3,
        ST_SYN   = 4,
    }

    #[allow(dead_code)]
    struct UtpPacketHeader {
        type_ver: u8, // type: u4, ver: u4
        extension: u8,
        connection_id: u16,
        timestamp_microseconds: u32,
        timestamp_difference_microseconds: u32,
        wnd_size: u32,
        seq_nr: u16,
        ack_nr: u16,
    }

    impl UtpPacketHeader {
        fn bytes(&self) -> &[u8] {
            unsafe {
                let buf: &[u8, ..20] = transmute(self);
                return buf.as_slice();
            }
        }

        fn len(&self) -> uint {
            static HEADER_SIZE: uint = 20;
            return HEADER_SIZE;
        }
    }

    #[allow(dead_code)]
    struct UtpPacket {
        header: UtpPacketHeader,
        payload: Vec<u8>,
    }

    impl UtpPacket {
        /// Constructs a new, empty UtpPacket.
        fn new() -> UtpPacket {
            UtpPacket {
                header: UtpPacketHeader {
                    type_ver: ST_DATA as u8 << 4 | 1,
                    extension: 0,
                    connection_id: 0,
                    timestamp_microseconds: 0,
                    timestamp_difference_microseconds: 0,
                    wnd_size: 0,
                    seq_nr: 0,
                    ack_nr: 0,
                },
                payload: Vec::new(),
            }
        }

        fn bytes(&self) -> Vec<u8> {
            let mut buf: Vec<u8> = Vec::with_capacity(self.len());
            buf.push_all(self.header.bytes());
            buf.push_all(self.payload.as_slice());
            return buf;
        }

        fn len(&self) -> uint {
            self.header.len() + self.payload.len()
        }
    }

    pub struct UtpSocket {
        socket: UdpSocket,
        seq_nr: u16,
    }

    impl UtpSocket {
        pub fn bind(addr: SocketAddr) -> IoResult<UtpSocket> {
            let skt = UdpSocket::bind(addr);
            match skt {
                Ok(x)  => Ok(UtpSocket { socket: x, seq_nr: 1 }),
                Err(e) => Err(e)
            }
        }

        pub fn sendto(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> {
            let mut packet = UtpPacket::new();
            packet.payload = Vec::from_slice(buf);
            packet.header.seq_nr = to_be16(self.seq_nr);
            packet.header.connection_id = to_be16(random());
            let t = time::get_time();
            packet.header.timestamp_microseconds = to_be32((t.sec * 1_000_000) as u32 + (t.nsec/1000) as u32);

            // Send packet
            let result = self.socket.sendto(packet.bytes().as_slice(), dst);

            self.seq_nr += 1;
            result
        }

        pub fn recvfrom(&mut self, buf: &mut[u8]) -> IoResult<(uint,SocketAddr)> {
            self.socket.recvfrom(buf)
        }
    }

    impl Clone for UtpSocket {
        fn clone(&self) -> UtpSocket {
            UtpSocket {
                socket: self.socket.clone(),
                seq_nr: self.seq_nr,
            }
        }
    }
}

fn main() {
    use libtorresmo::{UtpSocket};

    let mut buf = [0, ..512];
    let sock = UtpSocket::bind(SocketAddr { ip: Ipv4Addr(127,0,0,1), port: 8080 }).unwrap();

    loop {
        let mut sock = sock.clone();
        match sock.recvfrom(buf) {
            Ok((_, src)) => {
                spawn(proc() {
                    let mut sock = sock;
                    let payload = String::from_str("Hello\n").into_bytes();

                    // Send uTP packet
                    let _ = sock.sendto(payload.as_slice(), src);
                })
            }
            Err(_) => {}
        }
    }
    drop(sock);
}
<commit_msg>Allow flexibility on address it's serving on.<commit_after>use std::io::net::ip::{Ipv4Addr, SocketAddr};

mod libtorresmo {
    extern crate time;

    use std::io::net::udp::UdpSocket;
    use std::io::net::ip::SocketAddr;
    use std::io::IoResult;
    use std::mem::{to_be32, to_be16, transmute};
    use std::rand::random;

    #[allow(dead_code,non_camel_case_types)]
    enum UtpPacketType {
        ST_DATA  = 0,
        ST_FIN   = 1,
        ST_STATE = 2,
        ST_RESET = 3,
        ST_SYN   = 4,
    }

    #[allow(dead_code)]
    struct UtpPacketHeader {
        type_ver: u8, // type: u4, ver: u4
        extension: u8,
        connection_id: u16,
        timestamp_microseconds: u32,
        timestamp_difference_microseconds: u32,
        wnd_size: u32,
        seq_nr: u16,
        ack_nr: u16,
    }

    impl UtpPacketHeader {
        fn bytes(&self) -> &[u8] {
            unsafe {
                let buf: &[u8, ..20] = transmute(self);
                return buf.as_slice();
            }
        }

        fn len(&self) -> uint {
            static HEADER_SIZE: uint = 20;
            return HEADER_SIZE;
        }
    }

    #[allow(dead_code)]
    struct UtpPacket {
        header: UtpPacketHeader,
        payload: Vec<u8>,
    }

    impl UtpPacket {
        /// Constructs a new, empty UtpPacket.
        fn new() -> UtpPacket {
            UtpPacket {
                header: UtpPacketHeader {
                    type_ver: ST_DATA as u8 << 4 | 1,
                    extension: 0,
                    connection_id: 0,
                    timestamp_microseconds: 0,
                    timestamp_difference_microseconds: 0,
                    wnd_size: 0,
                    seq_nr: 0,
                    ack_nr: 0,
                },
                payload: Vec::new(),
            }
        }

        fn bytes(&self) -> Vec<u8> {
            let mut buf: Vec<u8> = Vec::with_capacity(self.len());
            buf.push_all(self.header.bytes());
            buf.push_all(self.payload.as_slice());
            return buf;
        }

        fn len(&self) -> uint {
            self.header.len() + self.payload.len()
        }
    }

    pub struct UtpSocket {
        socket: UdpSocket,
        seq_nr: u16,
    }

    impl UtpSocket {
        pub fn bind(addr: SocketAddr) -> IoResult<UtpSocket> {
            let skt = UdpSocket::bind(addr);
            match skt {
                Ok(x)  => Ok(UtpSocket { socket: x, seq_nr: 1 }),
                Err(e) => Err(e)
            }
        }

        pub fn sendto(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> {
            let mut packet = UtpPacket::new();
            packet.payload = Vec::from_slice(buf);
            packet.header.seq_nr = to_be16(self.seq_nr);
            packet.header.connection_id = to_be16(random());
            let t = time::get_time();
            packet.header.timestamp_microseconds = to_be32((t.sec * 1_000_000) as u32 + (t.nsec/1000) as u32);

            // Send packet
            let result = self.socket.sendto(packet.bytes().as_slice(), dst);

            self.seq_nr += 1;
            result
        }

        pub fn recvfrom(&mut self, buf: &mut[u8]) -> IoResult<(uint,SocketAddr)> {
            self.socket.recvfrom(buf)
        }
    }

    impl Clone for UtpSocket {
        fn clone(&self) -> UtpSocket {
            UtpSocket {
                socket: self.socket.clone(),
                seq_nr: self.seq_nr,
            }
        }
    }
}

fn main() {
    use libtorresmo::{UtpSocket};
    use std::from_str::FromStr;

    // Defaults
    let mut addr = SocketAddr { ip: Ipv4Addr(127,0,0,1), port: 8080 };

    let args = std::os::args();

    if args.len() > 1 {
        let ip = FromStr::from_str(args.get(1).as_slice()).unwrap();
        let port = FromStr::from_str(args.get(2).as_slice()).unwrap();
        addr = SocketAddr { ip: ip, port: port };
    }

    let mut buf = [0, ..512];
    let sock = UtpSocket::bind(addr).unwrap();
    println!("Serving on {}", addr);

    loop {
        let mut sock = sock.clone();
        match sock.recvfrom(buf) {
            Ok((_, src)) => {
                spawn(proc() {
                    let mut sock = sock;
                    let payload = String::from_str("Hello\n").into_bytes();

                    // Send uTP packet
                    let _ = sock.sendto(payload.as_slice(), src);
                })
            }
            Err(_) => {}
        }
    }
    drop(sock);
}
<|endoftext|>