<commit_before>use std::io::Write;

use inflector::Inflector;

use super::{
    error_type_name, generate_field_name, rest_request_generator, rest_response_parser, FileWriter,
    GenerateProtocol, IoResult,
};
use crate::botocore::{Operation, Shape, ShapeType};
use crate::Service;

pub struct RestJsonGenerator;

impl GenerateProtocol for RestJsonGenerator {
    fn generate_method_signatures(&self, writer: &mut FileWriter, service: &Service<'_>) -> IoResult {
        for (operation_name, operation) in service.operations().iter() {
            let input_type = match &operation.input {
                Some(_) => operation.input_shape(),
                None => "", // ?
            };
            let output_type = operation.output_shape_or("()");

            // Retrieve the `Shape` for the input for this operation.
            let input_shape = &service.get_shape(input_type);

            writeln!(
                writer,
                "
                {documentation}
                {method_signature} -> \
                      RusotoFuture<{output_type}, {error_type}>;
                ",
                documentation = generate_documentation(operation).unwrap_or_else(|| "".to_owned()),
                method_signature = generate_method_signature(operation, input_shape),
                error_type = error_type_name(service, operation_name),
                output_type = output_type
            )?
        }
        Ok(())
    }

    fn generate_method_impls(&self, writer: &mut FileWriter, service: &Service<'_>) -> IoResult {
        for (operation_name, operation) in service.operations().iter() {
            let input_type = operation.input_shape_or("()");
            let output_type = operation.output_shape_or("()");

            // Retrieve the `Shape` for the input for this operation.
            let input_shape = &service.get_shape(input_type);

            let (request_uri, _) =
                rest_request_generator::parse_query_string(&operation.http.request_uri);

            writeln!(writer,"
                {documentation}
                {method_signature} -> RusotoFuture<{output_type}, {error_type}> {{
                    {request_uri_formatter}

                    let mut request = SignedRequest::new(\"{http_method}\", \"{endpoint_prefix}\", &self.region, &request_uri);
                    {default_headers}
                    {set_headers}
                    {modify_endpoint_prefix}
                    {load_payload}
                    {load_headers}
                    {load_params}

                    self.client.sign_and_dispatch(request, |response| {{
                        if {status_check} {{
                            Box::new(response.buffer().from_err().and_then(|response| {{
                                {parse_body}
                                {parse_headers}
                                {parse_status_code}
                                Ok(result)
                            }}))
                        }} else {{
                            Box::new(response.buffer().from_err().and_then(|response| {{
                                Err({error_type}::from_response(response))
                            }}))
                        }}
                    }})
                }}
                ",
                documentation = generate_documentation(operation).unwrap_or_else(|| "".to_owned()),
                method_signature = generate_method_signature(operation, input_shape),
                endpoint_prefix = service.signing_name(),
                modify_endpoint_prefix = generate_endpoint_modification(service).unwrap_or_else(|| "".to_owned()),
                http_method = operation.http.method,
                error_type = error_type_name(service, operation_name),
                status_check = http_code_expected(operation.http.response_code),
                parse_body = generate_body_parser(operation, service),
                parse_status_code = generate_status_code_parser(operation, service),
                output_type = output_type,
                load_headers = rest_request_generator::generate_headers(service, operation).unwrap_or_else(|| "".to_string()),
                parse_headers = rest_response_parser::generate_response_headers_parser(service, operation)
                    .unwrap_or_else(|| "".to_owned()),
                request_uri_formatter = rest_request_generator::generate_uri_formatter(
                    &request_uri,
                    service,
                    operation
                ).unwrap_or_else(|| "".to_string()),
                load_payload = generate_payload(service, input_shape).unwrap_or_else(|| "".to_string()),
                load_params = rest_request_generator::generate_params_loading_string(service, operation).unwrap_or_else(|| "".to_string()),
                default_headers = generate_default_headers(service),
                set_headers = generate_headers(service).unwrap_or_else(|| "".to_string()),
            )?
        }
        Ok(())
    }

    fn generate_prelude(&self, writer: &mut FileWriter, service: &Service<'_>) -> IoResult {
        // avoid unused imports when building services that don't use params
        if service_has_query_parameters(service) {
            writeln!(writer, "use rusoto_core::param::{{Params, ServiceParams}};")?;
        }

        let res = writeln!(
            writer,
            "use rusoto_core::signature::SignedRequest;
                  use rusoto_core::proto;"
        );
        if service.needs_serde_json_crate() {
            return writeln!(writer, "use serde_json;");
        }
        res
    }

    fn serialize_trait(&self) -> Option<&'static str> {
        Some("Serialize")
    }

    fn deserialize_trait(&self) -> Option<&'static str> {
        Some("Deserialize")
    }

    fn timestamp_type(&self) -> &'static str {
        "f64"
    }
}

fn http_code_expected(code: Option<i32>) -> String {
    match code {
        Some(actual_code) => format!("response.status.as_u16() == {}", actual_code),
        // Some service definitions such as elastictranscoder don't specify
        // the response code, we'll assume 2xx is okay:
        None => "response.status.is_success()".to_string(),
    }
}

// Glacier needs a special header added, not included in botocore definition.  See
// http://docs.aws.amazon.com/amazonglacier/latest/dev/api-common-request-headers.html
fn generate_headers(service: &Service<'_>) -> Option<String> {
    if service.full_name() == "Amazon Glacier" {
        return Some("request.add_header(\"x-amz-glacier-version\", \"2012-06-01\");".to_string());
    }
    None
}

// SageMaker Runtime allows to overwrite content-type
fn generate_default_headers(service: &Service<'_>) -> String {
    if service.full_name() == "Amazon SageMaker Runtime" {
        return "if input.content_type.is_none() {
                    request.set_content_type(\"application/x-amz-json-1.1\".to_owned());
                }"
        .to_string();
    }
    "request.set_content_type(\"application/x-amz-json-1.1\".to_owned());".to_string()
}

// IoT has an endpoint_prefix and a signing_name that differ
fn generate_endpoint_modification(service: &Service<'_>) -> Option<String> {
    if service.signing_name() == service.endpoint_prefix() {
        None
    } else {
        Some(format!(
            "request.set_endpoint_prefix(\"{}\".to_string());",
            service.endpoint_prefix()
        ))
    }
}

// IoT defines a lot of empty (and therefore unnecessary) request shapes
// don't clutter method signatures with them
fn generate_method_signature(operation: &Operation, shape: &Option<&Shape>) -> String {
    match shape {
        Some(s) => {
            if s.members.is_some() && !s.members.as_ref().unwrap().is_empty() {
                format!(
                    "fn {method_name}(&self, input: {input_type})",
                    method_name = operation.name.to_snake_case(),
                    input_type = operation.input_shape()
                )
            } else {
                format!(
                    "fn {method_name}(&self)",
                    method_name = operation.name.to_snake_case()
                )
            }
        }
        None => format!(
            "fn {method_name}(&self)",
            method_name = operation.name.to_snake_case()
        ),
    }
}

// Figure out what, if anything, should be sent as the body of the http request
fn generate_payload(service: &Service<'_>, input_shape: &Option<&Shape>) -> Option<String> {
    let i = input_shape.as_ref()?;
    let declare_payload = match i.payload {
        // if the input shape explicitly specifies a payload field, use that
        Some(ref payload_member_name) => {
            Some(declared_payload(i, payload_member_name, service))
        }

        // otherwise see if the input_shape itself should be serialized as the payload
        None => {
            // only use the input_shape if it has non-query, non-header members
            // (i.e., location unspecified)
            if i
                .members
                .as_ref()
                .unwrap()
                .iter()
                .any(|(_, member)| member.location.is_none())
            {
                Some("let encoded = Some(serde_json::to_vec(&input).unwrap());".to_owned())
            } else {
                None
            }
        }
    };

    if declare_payload.is_some() {
        Some(declare_payload.unwrap() + "request.set_payload(encoded);")
    } else {
        None
    }
}

fn declared_payload(input_shape: &Shape, payload_member_name: &str, service: &Service<'_>) -> String {
    let payload_member_shape = &input_shape.members.as_ref().unwrap()[payload_member_name].shape;
    let payload_shape = &service
        .get_shape(payload_member_shape)
        .expect("Shape missing from service definition");

    let field_name = generate_field_name(payload_member_name);

    match payload_shape.shape_type {
        // if it's a String or a Blob, send it as the raw payload
        payload_type if payload_type == ShapeType::Blob || payload_type == ShapeType::String => {
            if input_shape.required(payload_member_name) {
                format!("let encoded = Some(input.{}.to_owned());", field_name)
            } else {
                format!(
                    "let encoded = if let Some(ref payload) = input.{} {{
                            Some(payload.to_owned())
                        }} else {{
                            None
                        }};",
                    field_name
                )
            }
        }

        // otherwise serialize the payload member as json and use that
        _ => format!(
            "let encoded = Some(serde_json::to_vec(&input.{}).unwrap());",
            field_name
        ),
    }
}

// Do any input operations in the entire service use query parameters?
fn service_has_query_parameters(service: &Service<'_>) -> bool {
    service
        .operations()
        .iter()
        .filter(|operation| operation.1.input.is_some())
        .map(|(_, operation)| operation.input_shape())
        .map(|input_type| service.get_shape(input_type).unwrap())
        .any(|input_shape| input_shape.has_query_parameters())
}

fn generate_documentation(operation: &Operation) -> Option<String> {
    operation
        .documentation
        .as_ref()
        .map(|docs| crate::doco::Item(docs).to_string())
}

/// Generate code to plumb the response status code into any fields
/// in the output shape that specify it
fn generate_status_code_parser(operation: &Operation, service: &Service<'_>) -> String {
    if operation.output.is_none() {
        return "".to_owned();
    }

    let shape_name = &operation.output.as_ref().unwrap().shape;
    let output_shape = &service
        .get_shape(shape_name)
        .expect("Shape missing from service definition");

    let mut status_code_parser = "".to_string();

    for (member_name, member) in output_shape.members.as_ref().unwrap() {
        if let Some(ref location) = member.location {
            if location == "statusCode" {
                if output_shape.required(member_name) {
                    status_code_parser += &format!(
                        "result.{} = Some(response.status.as_u16());",
                        member_name.to_snake_case()
                    );
                } else {
                    status_code_parser += &format!(
                        "result.{} = Some(response.status.as_u16() as i64);",
                        member_name.to_snake_case()
                    );
                }
            }
        }
    }

    status_code_parser
}

/// Generate code to parse the http response body, either as a JSON object
/// deserialized with serde, or as a raw payload that's assigned to one of
/// the fields in the result object.
///
/// Needs to determine whether or not other fields in the result object
/// will be set later (e.g. from headers), so the compiler won't spit out
/// warnings about unnecessary mutability
fn generate_body_parser(operation: &Operation, service: &Service<'_>) -> String {
    if operation.output.is_none() {
        return "let result = ::std::mem::drop(response);".to_string();
    }

    let shape_name = &operation.output.as_ref().unwrap().shape;
    let output_shape = &service
        .get_shape(shape_name)
        .expect("Shape missing from service definition");

    let mutable_result = output_shape
        .members
        .as_ref()
        .unwrap()
        .iter()
        .any(|(_, member)| member.location.is_some())
        || output_shape.payload.is_some();

    match output_shape.payload {
        None => json_body_parser(shape_name, mutable_result),
        Some(ref payload_member_name) => {
            let payload_member_shape =
                &output_shape.members.as_ref().unwrap()[payload_member_name].shape;
            let payload_shape = &service
                .get_shape(payload_member_shape)
                .expect("Shape missing from service definition");
            // is the shape required?
            let payload_shape_required = match output_shape.required {
                Some(ref s) => {
                    // if there's any required shape present the body payload parser will handle it
                    // This can't be converted to `s.is_empty()`. TODO: find out why.
                    s.len() > 0
                }
                None => false,
            };
            match payload_shape.shape_type {
                payload_type
                    if payload_type == ShapeType::Blob || payload_type == ShapeType::String =>
                {
                    payload_body_parser(
                        payload_type,
                        shape_name,
                        payload_member_name,
                        mutable_result,
                        payload_shape_required,
                    )
                }
                _ => json_body_parser(shape_name, false),
            }
        }
    }
}

/// Take the raw http response body and assign it to the payload field
/// on the result object
fn payload_body_parser(
    payload_type: ShapeType,
    output_shape: &str,
    payload_member: &str,
    mutable_result: bool,
    payload_required: bool,
) -> String {
    let response_body = match payload_required {
        true => match payload_type {
            ShapeType::Blob => "response.body",
            _ => "String::from_utf8_lossy(response.body.as_ref())",
        },
        false => match payload_type {
            ShapeType::Blob => "Some(response.body)",
            _ => "Some(String::from_utf8_lossy(response.body.as_ref()).into_owned())",
        },
    };

    format!(
        "
        let {mutable} result = {output_shape}::default();
        result.{payload_member} = {response_body};
        ",
        output_shape = output_shape,
        payload_member = payload_member.to_snake_case(),
        response_body = response_body,
        mutable = if mutable_result { "mut" } else { "" }
    )
}

/// Parse the http response body as a JSON object with serde, and use that
/// as the result object
fn json_body_parser(output_shape: &str, mutable_result: bool) -> String {
    format!(
        "let {mutable} result = proto::json::ResponsePayload::new(&response).deserialize::<{output_shape}, _>()?;",
        output_shape = output_shape,
        mutable = if mutable_result { "mut" } else { "" }
    )
}
<commit_msg>Take review suggestions and rustfmt again.<commit_after>use std::io::Write;

use inflector::Inflector;

use super::{
    error_type_name, generate_field_name, rest_request_generator, rest_response_parser, FileWriter,
    GenerateProtocol, IoResult,
};
use crate::botocore::{Operation, Shape, ShapeType};
use crate::Service;

pub struct RestJsonGenerator;

impl GenerateProtocol for RestJsonGenerator {
    fn generate_method_signatures(&self, writer: &mut FileWriter, service: &Service<'_>) -> IoResult {
        for (operation_name, operation) in service.operations().iter() {
            let input_type = match &operation.input {
                Some(_) => operation.input_shape(),
                None => "", // ?
            };
            let output_type = operation.output_shape_or("()");

            // Retrieve the `Shape` for the input for this operation.
            let input_shape = &service.get_shape(input_type);

            writeln!(
                writer,
                "
                {documentation}
                {method_signature} -> \
                      RusotoFuture<{output_type}, {error_type}>;
                ",
                documentation = generate_documentation(operation).unwrap_or_else(|| "".to_owned()),
                method_signature = generate_method_signature(operation, input_shape),
                error_type = error_type_name(service, operation_name),
                output_type = output_type
            )?
        }
        Ok(())
    }

    fn generate_method_impls(&self, writer: &mut FileWriter, service: &Service<'_>) -> IoResult {
        for (operation_name, operation) in service.operations().iter() {
            let input_type = operation.input_shape_or("()");
            let output_type = operation.output_shape_or("()");

            // Retrieve the `Shape` for the input for this operation.
            let input_shape = &service.get_shape(input_type);

            let (request_uri, _) =
                rest_request_generator::parse_query_string(&operation.http.request_uri);

            writeln!(writer,"
                {documentation}
                {method_signature} -> RusotoFuture<{output_type}, {error_type}> {{
                    {request_uri_formatter}

                    let mut request = SignedRequest::new(\"{http_method}\", \"{endpoint_prefix}\", &self.region, &request_uri);
                    {default_headers}
                    {set_headers}
                    {modify_endpoint_prefix}
                    {load_payload}
                    {load_headers}
                    {load_params}

                    self.client.sign_and_dispatch(request, |response| {{
                        if {status_check} {{
                            Box::new(response.buffer().from_err().and_then(|response| {{
                                {parse_body}
                                {parse_headers}
                                {parse_status_code}
                                Ok(result)
                            }}))
                        }} else {{
                            Box::new(response.buffer().from_err().and_then(|response| {{
                                Err({error_type}::from_response(response))
                            }}))
                        }}
                    }})
                }}
                ",
                documentation = generate_documentation(operation).unwrap_or_else(|| "".to_owned()),
                method_signature = generate_method_signature(operation, input_shape),
                endpoint_prefix = service.signing_name(),
                modify_endpoint_prefix = generate_endpoint_modification(service).unwrap_or_else(|| "".to_owned()),
                http_method = operation.http.method,
                error_type = error_type_name(service, operation_name),
                status_check = http_code_expected(operation.http.response_code),
                parse_body = generate_body_parser(operation, service),
                parse_status_code = generate_status_code_parser(operation, service),
                output_type = output_type,
                load_headers = rest_request_generator::generate_headers(service, operation).unwrap_or_else(|| "".to_string()),
                parse_headers = rest_response_parser::generate_response_headers_parser(service, operation)
                    .unwrap_or_else(|| "".to_owned()),
                request_uri_formatter = rest_request_generator::generate_uri_formatter(
                    &request_uri,
                    service,
                    operation
                ).unwrap_or_else(|| "".to_string()),
                load_payload = generate_payload(service, input_shape).unwrap_or_else(|| "".to_string()),
                load_params = rest_request_generator::generate_params_loading_string(service, operation).unwrap_or_else(|| "".to_string()),
                default_headers = generate_default_headers(service),
                set_headers = generate_headers(service).unwrap_or_else(|| "".to_string()),
            )?
        }
        Ok(())
    }

    fn generate_prelude(&self, writer: &mut FileWriter, service: &Service<'_>) -> IoResult {
        // avoid unused imports when building services that don't use params
        if service_has_query_parameters(service) {
            writeln!(writer, "use rusoto_core::param::{{Params, ServiceParams}};")?;
        }

        let res = writeln!(
            writer,
            "use rusoto_core::signature::SignedRequest;
                  use rusoto_core::proto;"
        );
        if service.needs_serde_json_crate() {
            return writeln!(writer, "use serde_json;");
        }
        res
    }

    fn serialize_trait(&self) -> Option<&'static str> {
        Some("Serialize")
    }

    fn deserialize_trait(&self) -> Option<&'static str> {
        Some("Deserialize")
    }

    fn timestamp_type(&self) -> &'static str {
        "f64"
    }
}

fn http_code_expected(code: Option<i32>) -> String {
    match code {
        Some(actual_code) => format!("response.status.as_u16() == {}", actual_code),
        // Some service definitions such as elastictranscoder don't specify
        // the response code, we'll assume 2xx is okay:
        None => "response.status.is_success()".to_string(),
    }
}

// Glacier needs a special header added, not included in botocore definition.  See
// http://docs.aws.amazon.com/amazonglacier/latest/dev/api-common-request-headers.html
fn generate_headers(service: &Service<'_>) -> Option<String> {
    if service.full_name() == "Amazon Glacier" {
        return Some("request.add_header(\"x-amz-glacier-version\", \"2012-06-01\");".to_string());
    }
    None
}

// SageMaker Runtime allows to overwrite content-type
fn generate_default_headers(service: &Service<'_>) -> String {
    if service.full_name() == "Amazon SageMaker Runtime" {
        return "if input.content_type.is_none() {
                    request.set_content_type(\"application/x-amz-json-1.1\".to_owned());
                }"
        .to_string();
    }
    "request.set_content_type(\"application/x-amz-json-1.1\".to_owned());".to_string()
}

// IoT has an endpoint_prefix and a signing_name that differ
fn generate_endpoint_modification(service: &Service<'_>) -> Option<String> {
    if service.signing_name() == service.endpoint_prefix() {
        None
    } else {
        Some(format!(
            "request.set_endpoint_prefix(\"{}\".to_string());",
            service.endpoint_prefix()
        ))
    }
}

// IoT defines a lot of empty (and therefore unnecessary) request shapes
// don't clutter method signatures with them
fn generate_method_signature(operation: &Operation, shape: &Option<&Shape>) -> String {
    match shape {
        Some(s) => match s.members {
            Some(ref members) if !members.is_empty() => format!(
                "fn {method_name}(&self, input: {input_type})",
                method_name = operation.name.to_snake_case(),
                input_type = operation.input_shape()
            ),
            _ => format!(
                "fn {method_name}(&self)",
                method_name = operation.name.to_snake_case()
            ),
        },
        None => format!(
            "fn {method_name}(&self)",
            method_name = operation.name.to_snake_case()
        ),
    }
}

// Figure out what, if anything, should be sent as the body of the http request
fn generate_payload(service: &Service<'_>, input_shape: &Option<&Shape>) -> Option<String> {
    let i = input_shape.as_ref()?;
    let declare_payload = match i.payload {
        // if the input shape explicitly specifies a payload field, use that
        Some(ref payload_member_name) => Some(declared_payload(i, payload_member_name, service)),

        // otherwise see if the input_shape itself should be serialized as the payload
        None => {
            // only use the input_shape if it has non-query, non-header members
            // (i.e., location unspecified)
            if i.members
                .as_ref()
                .unwrap()
                .iter()
                .any(|(_, member)| member.location.is_none())
            {
                Some("let encoded = Some(serde_json::to_vec(&input).unwrap());".to_owned())
            } else {
                None
            }
        }
    };

    if declare_payload.is_some() {
        Some(declare_payload.unwrap() + "request.set_payload(encoded);")
    } else {
        None
    }
}

fn declared_payload(input_shape: &Shape, payload_member_name: &str, service: &Service<'_>) -> String {
    let payload_member_shape = &input_shape.members.as_ref().unwrap()[payload_member_name].shape;
    let payload_shape = &service
        .get_shape(payload_member_shape)
        .expect("Shape missing from service definition");

    let field_name = generate_field_name(payload_member_name);

    match payload_shape.shape_type {
        // if it's a String or a Blob, send it as the raw payload
        payload_type if payload_type == ShapeType::Blob || payload_type == ShapeType::String => {
            if input_shape.required(payload_member_name) {
                format!("let encoded = Some(input.{}.to_owned());", field_name)
            } else {
                format!(
                    "let encoded = if let Some(ref payload) = input.{} {{
                            Some(payload.to_owned())
                        }} else {{
                            None
                        }};",
                    field_name
                )
            }
        }

        // otherwise serialize the payload member as json and use that
        _ => format!(
            "let encoded = Some(serde_json::to_vec(&input.{}).unwrap());",
            field_name
        ),
    }
}

// Do any input operations in the entire service use query parameters?
fn service_has_query_parameters(service: &Service<'_>) -> bool {
    service
        .operations()
        .iter()
        .filter(|operation| operation.1.input.is_some())
        .map(|(_, operation)| operation.input_shape())
        .map(|input_type| service.get_shape(input_type).unwrap())
        .any(|input_shape| input_shape.has_query_parameters())
}

fn generate_documentation(operation: &Operation) -> Option<String> {
    operation
        .documentation
        .as_ref()
        .map(|docs| crate::doco::Item(docs).to_string())
}

/// Generate code to plumb the response status code into any fields
/// in the output shape that specify it
fn generate_status_code_parser(operation: &Operation, service: &Service<'_>) -> String {
    if operation.output.is_none() {
        return "".to_owned();
    }

    let shape_name = &operation.output.as_ref().unwrap().shape;
    let output_shape = &service
        .get_shape(shape_name)
        .expect("Shape missing from service definition");

    let mut status_code_parser = "".to_string();

    for (member_name, member) in output_shape.members.as_ref().unwrap() {
        if let Some(ref location) = member.location {
            if location == "statusCode" {
                if output_shape.required(member_name) {
                    status_code_parser += &format!(
                        "result.{} = Some(response.status.as_u16());",
                        member_name.to_snake_case()
                    );
                } else {
                    status_code_parser += &format!(
                        "result.{} = Some(response.status.as_u16() as i64);",
                        member_name.to_snake_case()
                    );
                }
            }
        }
    }

    status_code_parser
}

/// Generate code to parse the http response body, either as a JSON object
/// deserialized with serde, or as a raw payload that's assigned to one of
/// the fields in the result object.
///
/// Needs to determine whether or not other fields in the result object
/// will be set later (e.g. from headers), so the compiler won't spit out
/// warnings about unnecessary mutability
fn generate_body_parser(operation: &Operation, service: &Service<'_>) -> String {
    if operation.output.is_none() {
        return "let result = ::std::mem::drop(response);".to_string();
    }

    let shape_name = &operation.output.as_ref().unwrap().shape;
    let output_shape = &service
        .get_shape(shape_name)
        .expect("Shape missing from service definition");

    let mutable_result = output_shape
        .members
        .as_ref()
        .unwrap()
        .iter()
        .any(|(_, member)| member.location.is_some())
        || output_shape.payload.is_some();

    match output_shape.payload {
        None => json_body_parser(shape_name, mutable_result),
        Some(ref payload_member_name) => {
            let payload_member_shape =
                &output_shape.members.as_ref().unwrap()[payload_member_name].shape;
            let payload_shape = &service
                .get_shape(payload_member_shape)
                .expect("Shape missing from service definition");
            // is the shape required?
            let payload_shape_required = match output_shape.required {
                Some(ref s) => {
                    // if there's any required shape present the body payload parser will handle it
                    // This can't be converted to `s.is_empty()`. TODO: find out why.
                    s.len() > 0
                }
                None => false,
            };
            match payload_shape.shape_type {
                payload_type
                    if payload_type == ShapeType::Blob || payload_type == ShapeType::String =>
                {
                    payload_body_parser(
                        payload_type,
                        shape_name,
                        payload_member_name,
                        mutable_result,
                        payload_shape_required,
                    )
                }
                _ => json_body_parser(shape_name, false),
            }
        }
    }
}

/// Take the raw http response body and assign it to the payload field
/// on the result object
fn payload_body_parser(
    payload_type: ShapeType,
    output_shape: &str,
    payload_member: &str,
    mutable_result: bool,
    payload_required: bool,
) -> String {
    let response_body = match payload_required {
        true => match payload_type {
            ShapeType::Blob => "response.body",
            _ => "String::from_utf8_lossy(response.body.as_ref())",
        },
        false => match payload_type {
            ShapeType::Blob => "Some(response.body)",
            _ => "Some(String::from_utf8_lossy(response.body.as_ref()).into_owned())",
        },
    };

    format!(
        "
        let {mutable} result = {output_shape}::default();
        result.{payload_member} = {response_body};
        ",
        output_shape = output_shape,
        payload_member = payload_member.to_snake_case(),
        response_body = response_body,
        mutable = if mutable_result { "mut" } else { "" }
    )
}

/// Parse the http response body as a JSON object with serde, and use that
/// as the result object
fn json_body_parser(output_shape: &str, mutable_result: bool) -> String {
    format!(
        "let {mutable} result = proto::json::ResponsePayload::new(&response).deserialize::<{output_shape}, _>()?;",
        output_shape = output_shape,
        mutable = if mutable_result { "mut" } else { "" }
    )
}
<|endoftext|>


<commit_before>use futures::{Async, Future, Poll};
use std::cell::UnsafeCell;
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
use std::rc::Rc;

use error::Error;
use handler::{AsyncResult, AsyncResultItem, FromRequest, Handler, Responder};
use httprequest::HttpRequest;
use httpresponse::HttpResponse;

/// Extractor configuration
///
/// `Route::with()` and `Route::with_async()` returns instance
/// of the `ExtractorConfig` type. It could be used for extractor configuration.
///
/// In this example `Form<FormData>` configured.
///
/// ```rust
/// # extern crate actix_web;
/// #[macro_use] extern crate serde_derive;
/// use actix_web::{http, App, Form, Result};
///
/// #[derive(Deserialize)]
/// struct FormData {
///     username: String,
/// }
///
/// fn index(form: Form<FormData>) -> Result<String> {
///     Ok(format!("Welcome {}!", form.username))
/// }
///
/// fn main() {
///     let app = App::new().resource(
///         "/index.html",
///         |r| {
///             r.method(http::Method::GET).with(index).limit(4096);
///         }, // <- change form extractor configuration
///     );
/// }
/// ```
///
/// Same could be donce with multiple extractors
///
/// ```rust
/// # extern crate actix_web;
/// #[macro_use] extern crate serde_derive;
/// use actix_web::{http, App, Form, Path, Result};
///
/// #[derive(Deserialize)]
/// struct FormData {
///     username: String,
/// }
///
/// fn index(data: (Path<(String,)>, Form<FormData>)) -> Result<String> {
///     Ok(format!("Welcome {}!", data.1.username))
/// }
///
/// fn main() {
///     let app = App::new().resource(
///         "/index.html",
///         |r| {
///             r.method(http::Method::GET).with(index).1.limit(4096);
///         }, // <- change form extractor configuration
///     );
/// }
/// ```
pub struct ExtractorConfig<S: 'static, T: FromRequest<S>> {
    cfg: Rc<UnsafeCell<T::Config>>,
}

impl<S: 'static, T: FromRequest<S>> Default for ExtractorConfig<S, T> {
    fn default() -> Self {
        ExtractorConfig {
            cfg: Rc::new(UnsafeCell::new(T::Config::default())),
        }
    }
}

impl<S: 'static, T: FromRequest<S>> ExtractorConfig<S, T> {
    pub(crate) fn clone(&self) -> Self {
        ExtractorConfig {
            cfg: Rc::clone(&self.cfg),
        }
    }
}

impl<S: 'static, T: FromRequest<S>> AsRef<T::Config> for ExtractorConfig<S, T> {
    fn as_ref(&self) -> &T::Config {
        unsafe { &*self.cfg.get() }
    }
}

impl<S: 'static, T: FromRequest<S>> Deref for ExtractorConfig<S, T> {
    type Target = T::Config;

    fn deref(&self) -> &T::Config {
        unsafe { &*self.cfg.get() }
    }
}

impl<S: 'static, T: FromRequest<S>> DerefMut for ExtractorConfig<S, T> {
    fn deref_mut(&mut self) -> &mut T::Config {
        unsafe { &mut *self.cfg.get() }
    }
}

pub struct With<T, S, F, R>
where
    F: Fn(T) -> R,
    T: FromRequest<S>,
    S: 'static,
{
    hnd: Rc<WithHnd<T, S, F, R>>,
    cfg: ExtractorConfig<S, T>,
}

pub struct WithHnd<T, S, F, R>
where
    F: Fn(T) -> R,
    T: FromRequest<S>,
    S: 'static,
{
    hnd: Rc<UnsafeCell<F>>,
    _t: PhantomData<T>,
    _s: PhantomData<S>,
}

impl<T, S, F, R> With<T, S, F, R>
where
    F: Fn(T) -> R,
    T: FromRequest<S>,
    S: 'static,
{
    pub fn new(f: F, cfg: ExtractorConfig<S, T>) -> Self {
        With {
            cfg,
            hnd: Rc::new(WithHnd {
                hnd: Rc::new(UnsafeCell::new(f)),
                _t: PhantomData,
                _s: PhantomData,
            }),
        }
    }
}

impl<T, S, F, R> Handler<S> for With<T, S, F, R>
where
    F: Fn(T) -> R + 'static,
    R: Responder + 'static,
    T: FromRequest<S> + 'static,
    S: 'static,
{
    type Result = AsyncResult<HttpResponse>;

    fn handle(&mut self, req: HttpRequest<S>) -> Self::Result {
        let mut fut = WithHandlerFut {
            req,
            started: false,
            hnd: Rc::clone(&self.hnd),
            cfg: self.cfg.clone(),
            fut1: None,
            fut2: None,
        };

        match fut.poll() {
            Ok(Async::Ready(resp)) => AsyncResult::ok(resp),
            Ok(Async::NotReady) => AsyncResult::async(Box::new(fut)),
            Err(e) => AsyncResult::err(e),
        }
    }
}

struct WithHandlerFut<T, S, F, R>
where
    F: Fn(T) -> R,
    R: Responder,
    T: FromRequest<S> + 'static,
    S: 'static,
{
    started: bool,
    hnd: Rc<WithHnd<T, S, F, R>>,
    cfg: ExtractorConfig<S, T>,
    req: HttpRequest<S>,
    fut1: Option<Box<Future<Item = T, Error = Error>>>,
    fut2: Option<Box<Future<Item = HttpResponse, Error = Error>>>,
}

impl<T, S, F, R> Future for WithHandlerFut<T, S, F, R>
where
    F: Fn(T) -> R,
    R: Responder + 'static,
    T: FromRequest<S> + 'static,
    S: 'static,
{
    type Item = HttpResponse;
    type Error = Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        if let Some(ref mut fut) = self.fut2 {
            return fut.poll();
        }

        let item = if !self.started {
            self.started = true;
            let reply = T::from_request(&self.req, self.cfg.as_ref()).into();
            match reply.into() {
                AsyncResultItem::Err(err) => return Err(err),
                AsyncResultItem::Ok(msg) => msg,
                AsyncResultItem::Future(fut) => {
                    self.fut1 = Some(fut);
                    return self.poll();
                }
            }
        } else {
            match self.fut1.as_mut().unwrap().poll()? {
                Async::Ready(item) => item,
                Async::NotReady => return Ok(Async::NotReady),
            }
        };

        let fut = {
            // clone handler, inicrease ref counter
            let h = self.hnd.as_ref().hnd.clone();
            // Enforce invariants before entering unsafe code.
            // Only two references could exists With struct owns one, and line above
            if Rc::weak_count(&h) != 0 && Rc::strong_count(&h) != 2 {
                panic!("Multiple copies of handler are in use")
            }
            let hnd: &mut F = unsafe { &mut *h.as_ref().get() };
            let item = match (*hnd)(item).respond_to(&self.req) {
                Ok(item) => item.into(),
                Err(e) => return Err(e.into()),
            };

            match item.into() {
                AsyncResultItem::Err(err) => return Err(err),
                AsyncResultItem::Ok(resp) => return Ok(Async::Ready(resp)),
                AsyncResultItem::Future(fut) => fut,
            }
        };
        self.fut2 = Some(fut);
        self.poll()
    }
}

pub struct WithAsync<T, S, F, R, I, E>
where
    F: Fn(T) -> R,
    R: Future<Item = I, Error = E>,
    I: Responder,
    E: Into<E>,
    T: FromRequest<S>,
    S: 'static,
{
    hnd: Rc<WithHnd<T, S, F, R>>,
    cfg: ExtractorConfig<S, T>,
}

impl<T, S, F, R, I, E> WithAsync<T, S, F, R, I, E>
where
    F: Fn(T) -> R,
    R: Future<Item = I, Error = E>,
    I: Responder,
    E: Into<Error>,
    T: FromRequest<S>,
    S: 'static,
{
    pub fn new(f: F, cfg: ExtractorConfig<S, T>) -> Self {
        WithAsync {
            cfg,
            hnd: Rc::new(WithHnd {
                hnd: Rc::new(UnsafeCell::new(f)),
                _s: PhantomData,
                _t: PhantomData,
            }),
        }
    }
}

impl<T, S, F, R, I, E> Handler<S> for WithAsync<T, S, F, R, I, E>
where
    F: Fn(T) -> R + 'static,
    R: Future<Item = I, Error = E> + 'static,
    I: Responder + 'static,
    E: Into<Error> + 'static,
    T: FromRequest<S> + 'static,
    S: 'static,
{
    type Result = AsyncResult<HttpResponse>;

    fn handle(&mut self, req: HttpRequest<S>) -> Self::Result {
        let mut fut = WithAsyncHandlerFut {
            req,
            started: false,
            hnd: Rc::clone(&self.hnd),
            cfg: self.cfg.clone(),
            fut1: None,
            fut2: None,
            fut3: None,
        };

        match fut.poll() {
            Ok(Async::Ready(resp)) => AsyncResult::ok(resp),
            Ok(Async::NotReady) => AsyncResult::async(Box::new(fut)),
            Err(e) => AsyncResult::err(e),
        }
    }
}

struct WithAsyncHandlerFut<T, S, F, R, I, E>
where
    F: Fn(T) -> R,
    R: Future<Item = I, Error = E> + 'static,
    I: Responder + 'static,
    E: Into<Error> + 'static,
    T: FromRequest<S> + 'static,
    S: 'static,
{
    started: bool,
    hnd: Rc<WithHnd<T, S, F, R>>,
    cfg: ExtractorConfig<S, T>,
    req: HttpRequest<S>,
    fut1: Option<Box<Future<Item = T, Error = Error>>>,
    fut2: Option<R>,
    fut3: Option<Box<Future<Item = HttpResponse, Error = Error>>>,
}

impl<T, S, F, R, I, E> Future for WithAsyncHandlerFut<T, S, F, R, I, E>
where
    F: Fn(T) -> R,
    R: Future<Item = I, Error = E> + 'static,
    I: Responder + 'static,
    E: Into<Error> + 'static,
    T: FromRequest<S> + 'static,
    S: 'static,
{
    type Item = HttpResponse;
    type Error = Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        if let Some(ref mut fut) = self.fut3 {
            return fut.poll();
        }

        if self.fut2.is_some() {
            return match self.fut2.as_mut().unwrap().poll() {
                Ok(Async::NotReady) => Ok(Async::NotReady),
                Ok(Async::Ready(r)) => match r.respond_to(&self.req) {
                    Ok(r) => match r.into().into() {
                        AsyncResultItem::Err(err) => Err(err),
                        AsyncResultItem::Ok(resp) => Ok(Async::Ready(resp)),
                        AsyncResultItem::Future(fut) => {
                            self.fut3 = Some(fut);
                            self.poll()
                        }
                    },
                    Err(e) => Err(e.into()),
                },
                Err(e) => Err(e.into()),
            };
        }

        let item = if !self.started {
            self.started = true;
            let reply = T::from_request(&self.req, self.cfg.as_ref()).into();
            match reply.into() {
                AsyncResultItem::Err(err) => return Err(err),
                AsyncResultItem::Ok(msg) => msg,
                AsyncResultItem::Future(fut) => {
                    self.fut1 = Some(fut);
                    return self.poll();
                }
            }
        } else {
            match self.fut1.as_mut().unwrap().poll()? {
                Async::Ready(item) => item,
                Async::NotReady => return Ok(Async::NotReady),
            }
        };

        self.fut2 = {
            // clone handler, inicrease ref counter
            let h = self.hnd.as_ref().hnd.clone();
            // Enforce invariants before entering unsafe code.
            // Only two references could exists With struct owns one, and line above
            if Rc::weak_count(&h) != 0 && Rc::strong_count(&h) != 2 {
                panic!("Multiple copies of handler are in use")
            }
            let hnd: &mut F = unsafe { &mut *h.as_ref().get() };
            Some((*hnd)(item))
        };
        self.poll()
    }
}
<commit_msg>fix condition<commit_after>use futures::{Async, Future, Poll};
use std::cell::UnsafeCell;
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
use std::rc::Rc;

use error::Error;
use handler::{AsyncResult, AsyncResultItem, FromRequest, Handler, Responder};
use httprequest::HttpRequest;
use httpresponse::HttpResponse;

/// Extractor configuration
///
/// `Route::with()` and `Route::with_async()` returns instance
/// of the `ExtractorConfig` type. It could be used for extractor configuration.
///
/// In this example `Form<FormData>` configured.
///
/// ```rust
/// # extern crate actix_web;
/// #[macro_use] extern crate serde_derive;
/// use actix_web::{http, App, Form, Result};
///
/// #[derive(Deserialize)]
/// struct FormData {
///     username: String,
/// }
///
/// fn index(form: Form<FormData>) -> Result<String> {
///     Ok(format!("Welcome {}!", form.username))
/// }
///
/// fn main() {
///     let app = App::new().resource(
///         "/index.html",
///         |r| {
///             r.method(http::Method::GET).with(index).limit(4096);
///         }, // <- change form extractor configuration
///     );
/// }
/// ```
///
/// Same could be donce with multiple extractors
///
/// ```rust
/// # extern crate actix_web;
/// #[macro_use] extern crate serde_derive;
/// use actix_web::{http, App, Form, Path, Result};
///
/// #[derive(Deserialize)]
/// struct FormData {
///     username: String,
/// }
///
/// fn index(data: (Path<(String,)>, Form<FormData>)) -> Result<String> {
///     Ok(format!("Welcome {}!", data.1.username))
/// }
///
/// fn main() {
///     let app = App::new().resource(
///         "/index.html",
///         |r| {
///             r.method(http::Method::GET).with(index).1.limit(4096);
///         }, // <- change form extractor configuration
///     );
/// }
/// ```
pub struct ExtractorConfig<S: 'static, T: FromRequest<S>> {
    cfg: Rc<UnsafeCell<T::Config>>,
}

impl<S: 'static, T: FromRequest<S>> Default for ExtractorConfig<S, T> {
    fn default() -> Self {
        ExtractorConfig {
            cfg: Rc::new(UnsafeCell::new(T::Config::default())),
        }
    }
}

impl<S: 'static, T: FromRequest<S>> ExtractorConfig<S, T> {
    pub(crate) fn clone(&self) -> Self {
        ExtractorConfig {
            cfg: Rc::clone(&self.cfg),
        }
    }
}

impl<S: 'static, T: FromRequest<S>> AsRef<T::Config> for ExtractorConfig<S, T> {
    fn as_ref(&self) -> &T::Config {
        unsafe { &*self.cfg.get() }
    }
}

impl<S: 'static, T: FromRequest<S>> Deref for ExtractorConfig<S, T> {
    type Target = T::Config;

    fn deref(&self) -> &T::Config {
        unsafe { &*self.cfg.get() }
    }
}

impl<S: 'static, T: FromRequest<S>> DerefMut for ExtractorConfig<S, T> {
    fn deref_mut(&mut self) -> &mut T::Config {
        unsafe { &mut *self.cfg.get() }
    }
}

pub struct With<T, S, F, R>
where
    F: Fn(T) -> R,
    T: FromRequest<S>,
    S: 'static,
{
    hnd: Rc<WithHnd<T, S, F, R>>,
    cfg: ExtractorConfig<S, T>,
}

pub struct WithHnd<T, S, F, R>
where
    F: Fn(T) -> R,
    T: FromRequest<S>,
    S: 'static,
{
    hnd: Rc<UnsafeCell<F>>,
    _t: PhantomData<T>,
    _s: PhantomData<S>,
}

impl<T, S, F, R> With<T, S, F, R>
where
    F: Fn(T) -> R,
    T: FromRequest<S>,
    S: 'static,
{
    pub fn new(f: F, cfg: ExtractorConfig<S, T>) -> Self {
        With {
            cfg,
            hnd: Rc::new(WithHnd {
                hnd: Rc::new(UnsafeCell::new(f)),
                _t: PhantomData,
                _s: PhantomData,
            }),
        }
    }
}

impl<T, S, F, R> Handler<S> for With<T, S, F, R>
where
    F: Fn(T) -> R + 'static,
    R: Responder + 'static,
    T: FromRequest<S> + 'static,
    S: 'static,
{
    type Result = AsyncResult<HttpResponse>;

    fn handle(&mut self, req: HttpRequest<S>) -> Self::Result {
        let mut fut = WithHandlerFut {
            req,
            started: false,
            hnd: Rc::clone(&self.hnd),
            cfg: self.cfg.clone(),
            fut1: None,
            fut2: None,
        };

        match fut.poll() {
            Ok(Async::Ready(resp)) => AsyncResult::ok(resp),
            Ok(Async::NotReady) => AsyncResult::async(Box::new(fut)),
            Err(e) => AsyncResult::err(e),
        }
    }
}

struct WithHandlerFut<T, S, F, R>
where
    F: Fn(T) -> R,
    R: Responder,
    T: FromRequest<S> + 'static,
    S: 'static,
{
    started: bool,
    hnd: Rc<WithHnd<T, S, F, R>>,
    cfg: ExtractorConfig<S, T>,
    req: HttpRequest<S>,
    fut1: Option<Box<Future<Item = T, Error = Error>>>,
    fut2: Option<Box<Future<Item = HttpResponse, Error = Error>>>,
}

impl<T, S, F, R> Future for WithHandlerFut<T, S, F, R>
where
    F: Fn(T) -> R,
    R: Responder + 'static,
    T: FromRequest<S> + 'static,
    S: 'static,
{
    type Item = HttpResponse;
    type Error = Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        if let Some(ref mut fut) = self.fut2 {
            return fut.poll();
        }

        let item = if !self.started {
            self.started = true;
            let reply = T::from_request(&self.req, self.cfg.as_ref()).into();
            match reply.into() {
                AsyncResultItem::Err(err) => return Err(err),
                AsyncResultItem::Ok(msg) => msg,
                AsyncResultItem::Future(fut) => {
                    self.fut1 = Some(fut);
                    return self.poll();
                }
            }
        } else {
            match self.fut1.as_mut().unwrap().poll()? {
                Async::Ready(item) => item,
                Async::NotReady => return Ok(Async::NotReady),
            }
        };

        let fut = {
            // clone handler, inicrease ref counter
            let h = self.hnd.as_ref().hnd.clone();
            // Enforce invariants before entering unsafe code.
            // Only two references could exists With struct owns one, and line above
            if Rc::weak_count(&h) != 0 || Rc::strong_count(&h) != 2 {
                panic!("Multiple copies of handler are in use")
            }
            let hnd: &mut F = unsafe { &mut *h.as_ref().get() };
            let item = match (*hnd)(item).respond_to(&self.req) {
                Ok(item) => item.into(),
                Err(e) => return Err(e.into()),
            };

            match item.into() {
                AsyncResultItem::Err(err) => return Err(err),
                AsyncResultItem::Ok(resp) => return Ok(Async::Ready(resp)),
                AsyncResultItem::Future(fut) => fut,
            }
        };
        self.fut2 = Some(fut);
        self.poll()
    }
}

pub struct WithAsync<T, S, F, R, I, E>
where
    F: Fn(T) -> R,
    R: Future<Item = I, Error = E>,
    I: Responder,
    E: Into<E>,
    T: FromRequest<S>,
    S: 'static,
{
    hnd: Rc<WithHnd<T, S, F, R>>,
    cfg: ExtractorConfig<S, T>,
}

impl<T, S, F, R, I, E> WithAsync<T, S, F, R, I, E>
where
    F: Fn(T) -> R,
    R: Future<Item = I, Error = E>,
    I: Responder,
    E: Into<Error>,
    T: FromRequest<S>,
    S: 'static,
{
    pub fn new(f: F, cfg: ExtractorConfig<S, T>) -> Self {
        WithAsync {
            cfg,
            hnd: Rc::new(WithHnd {
                hnd: Rc::new(UnsafeCell::new(f)),
                _s: PhantomData,
                _t: PhantomData,
            }),
        }
    }
}

impl<T, S, F, R, I, E> Handler<S> for WithAsync<T, S, F, R, I, E>
where
    F: Fn(T) -> R + 'static,
    R: Future<Item = I, Error = E> + 'static,
    I: Responder + 'static,
    E: Into<Error> + 'static,
    T: FromRequest<S> + 'static,
    S: 'static,
{
    type Result = AsyncResult<HttpResponse>;

    fn handle(&mut self, req: HttpRequest<S>) -> Self::Result {
        let mut fut = WithAsyncHandlerFut {
            req,
            started: false,
            hnd: Rc::clone(&self.hnd),
            cfg: self.cfg.clone(),
            fut1: None,
            fut2: None,
            fut3: None,
        };

        match fut.poll() {
            Ok(Async::Ready(resp)) => AsyncResult::ok(resp),
            Ok(Async::NotReady) => AsyncResult::async(Box::new(fut)),
            Err(e) => AsyncResult::err(e),
        }
    }
}

struct WithAsyncHandlerFut<T, S, F, R, I, E>
where
    F: Fn(T) -> R,
    R: Future<Item = I, Error = E> + 'static,
    I: Responder + 'static,
    E: Into<Error> + 'static,
    T: FromRequest<S> + 'static,
    S: 'static,
{
    started: bool,
    hnd: Rc<WithHnd<T, S, F, R>>,
    cfg: ExtractorConfig<S, T>,
    req: HttpRequest<S>,
    fut1: Option<Box<Future<Item = T, Error = Error>>>,
    fut2: Option<R>,
    fut3: Option<Box<Future<Item = HttpResponse, Error = Error>>>,
}

impl<T, S, F, R, I, E> Future for WithAsyncHandlerFut<T, S, F, R, I, E>
where
    F: Fn(T) -> R,
    R: Future<Item = I, Error = E> + 'static,
    I: Responder + 'static,
    E: Into<Error> + 'static,
    T: FromRequest<S> + 'static,
    S: 'static,
{
    type Item = HttpResponse;
    type Error = Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        if let Some(ref mut fut) = self.fut3 {
            return fut.poll();
        }

        if self.fut2.is_some() {
            return match self.fut2.as_mut().unwrap().poll() {
                Ok(Async::NotReady) => Ok(Async::NotReady),
                Ok(Async::Ready(r)) => match r.respond_to(&self.req) {
                    Ok(r) => match r.into().into() {
                        AsyncResultItem::Err(err) => Err(err),
                        AsyncResultItem::Ok(resp) => Ok(Async::Ready(resp)),
                        AsyncResultItem::Future(fut) => {
                            self.fut3 = Some(fut);
                            self.poll()
                        }
                    },
                    Err(e) => Err(e.into()),
                },
                Err(e) => Err(e.into()),
            };
        }

        let item = if !self.started {
            self.started = true;
            let reply = T::from_request(&self.req, self.cfg.as_ref()).into();
            match reply.into() {
                AsyncResultItem::Err(err) => return Err(err),
                AsyncResultItem::Ok(msg) => msg,
                AsyncResultItem::Future(fut) => {
                    self.fut1 = Some(fut);
                    return self.poll();
                }
            }
        } else {
            match self.fut1.as_mut().unwrap().poll()? {
                Async::Ready(item) => item,
                Async::NotReady => return Ok(Async::NotReady),
            }
        };

        self.fut2 = {
            // clone handler, inicrease ref counter
            let h = self.hnd.as_ref().hnd.clone();
            // Enforce invariants before entering unsafe code.
            // Only two references could exists With struct owns one, and line above
            if Rc::weak_count(&h) != 0 || Rc::strong_count(&h) != 2 {
                panic!("Multiple copies of handler are in use")
            }
            let hnd: &mut F = unsafe { &mut *h.as_ref().get() };
            Some((*hnd)(item))
        };
        self.poll()
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate clap;

use clap::{Arg, App, SubCommand, ArgMatches};
use std::path::Path;
use rusqlite as rs;

use std::error::Error;
use std::vec::Vec;

fn main() {
    let matches = App::new("Karmator db maintance batch")
        .version(crate_version!())
        .author(crate_authors!("\n"))
        .about("Handles the maintance work on the karmator db")
        .arg(Arg::with_name("FILE")
                .help("Database file to operate on")
                .required(true)
                .index(1))
        .subcommand(SubCommand::with_name("runs")
                .about("Detect runs of votes")
                .arg(Arg::with_name("min")
                    .short("m")
                    .help("Min count of runs before outputting")
                    .takes_value(true))
                .arg(Arg::with_name("delete")
                    .long("delete")
                    .help("Delete the runs detected")))
        .get_matches();

    let filename = matches.value_of("FILE").unwrap_or("db.sqlite");
    match matches.subcommand() {
        ("runs", Some(m)) => run(m, filename),
        _ => {
            println!("{}", matches.usage());
            Ok(())
        },
    };
}

#[derive(Debug, Clone)]
struct Vote {
    id: i32,
    by_whom_name: String,
    for_what_name: String,
    amount: i8,
}
impl PartialEq for Vote {
    fn eq(&self, other: &Self) -> bool {
        (self.by_whom_name == other.by_whom_name) &&
        (self.for_what_name == other.for_what_name) &&
        (self.amount == other.amount)
    }
}

#[derive(Debug)]
struct RunVal {
    oldest_id: i32,
    newest_id: i32,
    by_whom_name: String,
    for_what_name: String,
    amount: i8,
    count: u32,
}

fn get_run_val(srv: &Vote, pv: &Vote, count: u32) -> RunVal {
    RunVal {
        oldest_id: srv.id,
        newest_id: pv.id,
        by_whom_name: srv.by_whom_name.clone(),
        for_what_name: srv.for_what_name.clone(),
        amount: srv.amount,
        count: count,
    }
}

fn str_amount(amount: i8) -> &'static str {
    match amount {
        -1 => "Down",
        0  => "Side",
        1  => "Up",
        _  => panic!("invalid amount"),
    }
}

fn run(matches: &ArgMatches, filename: &str) -> Result<(), Box<dyn Error>> {
    let min = value_t!(matches, "min", u32).unwrap_or(10);
    let delete = matches.is_present("delete");

    let conn = rs::Connection::open_with_flags(
        Path::new(filename),
        rs::OpenFlags::SQLITE_OPEN_READ_WRITE,
    ).expect(&format!("Connection error: {}", filename));

    let mut stmt = conn.prepare("SELECT id, by_whom_name, for_what_name, amount FROM votes")?;
    let vote_iter = stmt.query_map(rs::params![], |row| {
        Ok(Vote {
            id: row.get(0)?,
            by_whom_name: row.get(1)?,
            for_what_name: row.get(2)?,
            amount: row.get(3)?,
        })
    })?;

    // Time to compute the run
    let mut runs = Vec::new();

    let mut start_run_vote = None;
    let mut prev_vote = None;
    let mut count = 0;

    for rvote in vote_iter {
        let vote = rvote?;

        match (&start_run_vote, &prev_vote) {
            (None, None) => {
                start_run_vote = Some(vote.clone());
                prev_vote = Some(vote);
                count = 1; // Run of 1
            },
            (Some(srv), Some(pv)) => {
                if pv == &vote {
                    // Current vote + prev vote are the same, inc prev vote
                    prev_vote = Some(vote);
                    count += 1;
                } else {
                    // Current vote != prev vote, record the run, and reset
                    runs.push(get_run_val(srv, pv, count));

                    start_run_vote = Some(vote.clone());
                    prev_vote = Some(vote);
                    count = 1; // Run of 1
                }
            },
            (_, _) => panic!("Shouldn't happen"),
        };
    }

    // Record the last run
    runs.push(get_run_val(&start_run_vote.unwrap(), &prev_vote.unwrap(), count));

    if delete {
        // Scan and delete the offenders
        let mut stmt = conn.prepare("DELETE FROM votes WHERE id >= ? and id <= ?")?;
        for r in &runs {
            if r.count > min {
                let deleted = stmt.execute(rs::params![r.oldest_id, r.newest_id])?;

                if (r.count as usize) != deleted {
                    panic!("Expected: {} to be deleted, got {}", r.count, deleted);
                }
            }
        }
    } else {
        // Now we can scan for anything that > min and print them
        println!(
            "{: >8}, {: >8}, {: >14.14}, {: >14.14}, {: >6}, {: >5}",
             "start_id", "end_id", "by_whom_name", "for_what_name", "amount", "count"
        );
        for r in &runs {
            if r.count > min {
                println!(
                    "{: >8}, {: >8}, {: >14.14}, {: >14.14}, {: >6}, {: >5}",
                    r.oldest_id, r.newest_id, r.by_whom_name, r.for_what_name, str_amount(r.amount), r.count
                );

            }
        }
    }

    Ok(())
}
<commit_msg>rustfmt<commit_after>#[macro_use]
extern crate clap;

use clap::{App, Arg, ArgMatches, SubCommand};
use rusqlite as rs;
use std::path::Path;

use std::error::Error;
use std::vec::Vec;

fn main() {
    let matches = App::new("Karmator db maintance batch")
        .version(crate_version!())
        .author(crate_authors!("\n"))
        .about("Handles the maintance work on the karmator db")
        .arg(
            Arg::with_name("FILE")
                .help("Database file to operate on")
                .required(true)
                .index(1),
        )
        .subcommand(
            SubCommand::with_name("runs")
                .about("Detect runs of votes")
                .arg(
                    Arg::with_name("min")
                        .short("m")
                        .help("Min count of runs before outputting")
                        .takes_value(true),
                )
                .arg(
                    Arg::with_name("delete")
                        .long("delete")
                        .help("Delete the runs detected"),
                ),
        )
        .get_matches();

    let filename = matches.value_of("FILE").unwrap_or("db.sqlite");
    match matches.subcommand() {
        ("runs", Some(m)) => run(m, filename),
        _ => {
            println!("{}", matches.usage());
            Ok(())
        }
    };
}

#[derive(Debug, Clone)]
struct Vote {
    id: i32,
    by_whom_name: String,
    for_what_name: String,
    amount: i8,
}
impl PartialEq for Vote {
    fn eq(&self, other: &Self) -> bool {
        (self.by_whom_name == other.by_whom_name)
            && (self.for_what_name == other.for_what_name)
            && (self.amount == other.amount)
    }
}

#[derive(Debug)]
struct RunVal {
    oldest_id: i32,
    newest_id: i32,
    by_whom_name: String,
    for_what_name: String,
    amount: i8,
    count: u32,
}

fn get_run_val(srv: &Vote, pv: &Vote, count: u32) -> RunVal {
    RunVal {
        oldest_id: srv.id,
        newest_id: pv.id,
        by_whom_name: srv.by_whom_name.clone(),
        for_what_name: srv.for_what_name.clone(),
        amount: srv.amount,
        count: count,
    }
}

fn str_amount(amount: i8) -> &'static str {
    match amount {
        -1 => "Down",
        0 => "Side",
        1 => "Up",
        _ => panic!("invalid amount"),
    }
}

fn run(matches: &ArgMatches, filename: &str) -> Result<(), Box<dyn Error>> {
    let min = value_t!(matches, "min", u32).unwrap_or(10);
    let delete = matches.is_present("delete");

    let conn =
        rs::Connection::open_with_flags(Path::new(filename), rs::OpenFlags::SQLITE_OPEN_READ_WRITE)
            .expect(&format!("Connection error: {}", filename));

    let mut stmt = conn.prepare("SELECT id, by_whom_name, for_what_name, amount FROM votes")?;
    let vote_iter = stmt.query_map(rs::params![], |row| {
        Ok(Vote {
            id: row.get(0)?,
            by_whom_name: row.get(1)?,
            for_what_name: row.get(2)?,
            amount: row.get(3)?,
        })
    })?;

    // Time to compute the run
    let mut runs = Vec::new();

    let mut start_run_vote = None;
    let mut prev_vote = None;
    let mut count = 0;

    for rvote in vote_iter {
        let vote = rvote?;

        match (&start_run_vote, &prev_vote) {
            (None, None) => {
                start_run_vote = Some(vote.clone());
                prev_vote = Some(vote);
                count = 1; // Run of 1
            }
            (Some(srv), Some(pv)) => {
                if pv == &vote {
                    // Current vote + prev vote are the same, inc prev vote
                    prev_vote = Some(vote);
                    count += 1;
                } else {
                    // Current vote != prev vote, record the run, and reset
                    runs.push(get_run_val(srv, pv, count));

                    start_run_vote = Some(vote.clone());
                    prev_vote = Some(vote);
                    count = 1; // Run of 1
                }
            }
            (_, _) => panic!("Shouldn't happen"),
        };
    }

    // Record the last run
    runs.push(get_run_val(
        &start_run_vote.unwrap(),
        &prev_vote.unwrap(),
        count,
    ));

    if delete {
        // Scan and delete the offenders
        let mut stmt = conn.prepare("DELETE FROM votes WHERE id >= ? and id <= ?")?;
        for r in &runs {
            if r.count > min {
                let deleted = stmt.execute(rs::params![r.oldest_id, r.newest_id])?;

                if (r.count as usize) != deleted {
                    panic!("Expected: {} to be deleted, got {}", r.count, deleted);
                }
            }
        }
    } else {
        // Now we can scan for anything that > min and print them
        println!(
            "{: >8}, {: >8}, {: >14.14}, {: >14.14}, {: >6}, {: >5}",
            "start_id", "end_id", "by_whom_name", "for_what_name", "amount", "count"
        );
        for r in &runs {
            if r.count > min {
                println!(
                    "{: >8}, {: >8}, {: >14.14}, {: >14.14}, {: >6}, {: >5}",
                    r.oldest_id,
                    r.newest_id,
                    r.by_whom_name,
                    r.for_what_name,
                    str_amount(r.amount),
                    r.count
                );
            }
        }
    }

    Ok(())
}
<|endoftext|>


<commit_before>use std::default::Default;
use std::iter::repeat;

use parser::ast::*;
use parser::ast::visit::Visitor;
use parser::interner::Interner;

use self::Entry::*;

pub fn build<'a>(ast: &'a Ast, interner: &Interner) -> Map<'a> {
    let mut map = Map {
        ast: ast,
        entries: Vec::new()
    };

    {
        let mut visitor = MapVisitor {
            interner: interner,
            parent_id: NodeId(0),
            map: &mut map
        };

        visitor.visit_ast(ast);
    }

    map
}

#[derive(Clone)]
enum Entry<'a> {
    EmptyEntry,

    EntryFct(NodeId, &'a Function),
    EntryParam(NodeId, &'a Param),
    EntryType(NodeId, &'a Type),
    EntryStmt(NodeId, &'a Stmt),
    EntryExpr(NodeId, &'a Expr),
}

impl<'a> Entry<'a> {
    fn is_empty(&self) -> bool {
        match *self {
            EmptyEntry => true,
            _ => false
        }
    }

    fn to_fct(&self) -> Option<&Function> {
        match *self {
            EntryFct(_, fct) => Some(fct),
            _ => None
        }
    }

    fn to_type(&self) -> Option<&Type> {
        match *self {
            EntryType(_, ty) => Some(ty),
            _ => None
        }
    }

    fn to_stmt(&self) -> Option<&Stmt> {
        match *self {
            EntryStmt(_, stmt) => Some(stmt),
            _ => None
        }
    }

    fn to_expr(&self) -> Option<&Expr> {
        match *self {
            EntryExpr(_, expr) => Some(expr),
            _ => None
        }
    }

    fn to_param(&self) -> Option<&Param> {
        match *self {
            EntryParam(_, param) => Some(param),
            _ => None
        }
    }
}

impl<'a> Default for Entry<'a> {
    fn default() -> Entry<'a> {
        EmptyEntry
    }
}

pub struct Map<'ast> {
    ast: &'ast Ast,
    entries: Vec<Entry<'ast>>,
}

impl<'ast> Map<'ast> {
    fn entry(&self, id: NodeId) -> &Entry<'ast> {
        &self.entries[id.0]
    }

    fn insert(&mut self, id: NodeId, entry: Entry<'ast>) {
        let len = self.entries.len();
        let idx = id.0;

        if idx >= len {
            let allocate = idx - len + 1;
            self.entries.extend(repeat(EmptyEntry).take(allocate));
        }

        self.entries[id.0] = entry;
    }
}

pub struct MapVisitor<'a, 'ast> where 'ast: 'a {
    interner: &'a Interner,
    parent_id: NodeId,
    map: &'a mut Map<'ast>
}

impl<'a, 'b> MapVisitor<'a, 'b>{
    fn use_parent<F>(&mut self, new_id: NodeId, fct: F) where F: FnOnce(&mut MapVisitor<'a, 'b>) -> () {
        let old = self.parent_id;
        self.parent_id = new_id;

        fct(self);

        self.parent_id = old;
    }
}

impl<'a, 'ast> visit::Visitor<'ast> for MapVisitor<'a, 'ast> where 'ast :'a {
    fn visit_fct(&mut self, f: &'ast Function) {
        self.map.insert(f.id, EntryFct(self.parent_id, f));
        self.use_parent(f.id, |this| visit::walk_fct(this, f));
    }

    fn visit_param(&mut self, p: &'ast Param) {
        self.map.insert(p.id, EntryParam(self.parent_id, p));
        self.use_parent(p.id, |this| visit::walk_param(this, p));
    }

    fn visit_type(&mut self, t: &'ast Type) {
        let id = t.id();

        self.map.insert(id, EntryType(self.parent_id, t));
        self.use_parent(id, |this| visit::walk_type(this, t));
    }

    fn visit_stmt(&mut self, s: &'ast Stmt) {
        let id = s.id();

        self.map.insert(id, EntryStmt(self.parent_id, s));
        self.use_parent(id, |this| visit::walk_stmt(this, s));
    }

    fn visit_expr(&mut self, e: &'ast Expr) {
        let id = e.id();

        self.map.insert(id, EntryExpr(self.parent_id, e));
        self.use_parent(id, |this| visit::walk_expr(this, e));
    }
}
<commit_msg>ast: added parent_id function<commit_after>use std::default::Default;
use std::iter::repeat;

use parser::ast::*;
use parser::ast::visit::Visitor;
use parser::interner::Interner;

use self::Entry::*;

pub fn build<'a>(ast: &'a Ast, interner: &Interner) -> Map<'a> {
    let mut map = Map {
        ast: ast,
        entries: Vec::new()
    };

    {
        let mut visitor = MapVisitor {
            interner: interner,
            parent_id: NodeId(0),
            map: &mut map
        };

        visitor.visit_ast(ast);
    }

    map
}

#[derive(Clone)]
enum Entry<'a> {
    EmptyEntry,

    EntryFct(NodeId, &'a Function),
    EntryParam(NodeId, &'a Param),
    EntryType(NodeId, &'a Type),
    EntryStmt(NodeId, &'a Stmt),
    EntryExpr(NodeId, &'a Expr),
}

impl<'a> Entry<'a> {
    fn parent_id(&self) -> NodeId {
        match *self {
            EntryFct(id, _) => id,
            EntryParam(id, _) => id,
            EntryType(id, _) => id,
            EntryStmt(id, _) => id,
            EntryExpr(id, _) => id,
            _ => unreachable!()
        }
    }

    fn is_empty(&self) -> bool {
        match *self {
            EmptyEntry => true,
            _ => false
        }
    }

    fn to_fct(&self) -> Option<&Function> {
        match *self {
            EntryFct(_, fct) => Some(fct),
            _ => None
        }
    }

    fn to_type(&self) -> Option<&Type> {
        match *self {
            EntryType(_, ty) => Some(ty),
            _ => None
        }
    }

    fn to_stmt(&self) -> Option<&Stmt> {
        match *self {
            EntryStmt(_, stmt) => Some(stmt),
            _ => None
        }
    }

    fn to_expr(&self) -> Option<&Expr> {
        match *self {
            EntryExpr(_, expr) => Some(expr),
            _ => None
        }
    }

    fn to_param(&self) -> Option<&Param> {
        match *self {
            EntryParam(_, param) => Some(param),
            _ => None
        }
    }
}

impl<'a> Default for Entry<'a> {
    fn default() -> Entry<'a> {
        EmptyEntry
    }
}

pub struct Map<'ast> {
    ast: &'ast Ast,
    entries: Vec<Entry<'ast>>,
}

impl<'ast> Map<'ast> {
    fn entry(&self, id: NodeId) -> &Entry<'ast> {
        &self.entries[id.0]
    }

    fn insert(&mut self, id: NodeId, entry: Entry<'ast>) {
        let len = self.entries.len();
        let idx = id.0;

        if idx >= len {
            let allocate = idx - len + 1;
            self.entries.extend(repeat(EmptyEntry).take(allocate));
        }

        self.entries[id.0] = entry;
    }
}

pub struct MapVisitor<'a, 'ast> where 'ast: 'a {
    interner: &'a Interner,
    parent_id: NodeId,
    map: &'a mut Map<'ast>
}

impl<'a, 'b> MapVisitor<'a, 'b>{
    fn use_parent<F>(&mut self, new_id: NodeId, fct: F) where F: FnOnce(&mut MapVisitor<'a, 'b>) -> () {
        let old = self.parent_id;
        self.parent_id = new_id;

        fct(self);

        self.parent_id = old;
    }
}

impl<'a, 'ast> visit::Visitor<'ast> for MapVisitor<'a, 'ast> where 'ast :'a {
    fn visit_fct(&mut self, f: &'ast Function) {
        self.map.insert(f.id, EntryFct(self.parent_id, f));
        self.use_parent(f.id, |this| visit::walk_fct(this, f));
    }

    fn visit_param(&mut self, p: &'ast Param) {
        self.map.insert(p.id, EntryParam(self.parent_id, p));
        self.use_parent(p.id, |this| visit::walk_param(this, p));
    }

    fn visit_type(&mut self, t: &'ast Type) {
        let id = t.id();

        self.map.insert(id, EntryType(self.parent_id, t));
        self.use_parent(id, |this| visit::walk_type(this, t));
    }

    fn visit_stmt(&mut self, s: &'ast Stmt) {
        let id = s.id();

        self.map.insert(id, EntryStmt(self.parent_id, s));
        self.use_parent(id, |this| visit::walk_stmt(this, s));
    }

    fn visit_expr(&mut self, e: &'ast Expr) {
        let id = e.id();

        self.map.insert(id, EntryExpr(self.parent_id, e));
        self.use_parent(id, |this| visit::walk_expr(this, e));
    }
}
<|endoftext|>


<commit_before>
//! A color type, with utility methods for modifying colors and parsing colors from hex integers and strings.

use gl;
use gl::types::*;
use std;
use shader::UniformValue;
use buffer::VertexData;

/// A color with red, green, blue and alpha components. All components are expected to be
/// between 0 and 1, both inclusinve.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Color {
    pub r: f32,
    pub g: f32,
    pub b: f32,
    pub a: f32,
}

impl Color {
    /// Creates a new, completly opaque (alpha = 1), color.
    ///
    /// All parameters are clamped so that they are between 0 and 1, both inclusive.
    pub fn rgb(r: f32, g: f32, b: f32) -> Color {
        Color {
            r: clamp(r, 0.0, 1.0),
            g: clamp(g, 0.0, 1.0),
            b: clamp(b, 0.0, 1.0),
            a: 1.0
        }
    }

    /// Creates a new color.
    ///
    /// All parameters are clamped so that they are between 0 and 1, both inclusive.
    pub fn rgba(r: f32, g: f32, b: f32, a: f32) -> Color {
        Color {
            r: clamp(r, 0.0, 1.0),
            g: clamp(g, 0.0, 1.0),
            b: clamp(b, 0.0, 1.0),
            a: clamp(a, 0.0, 1.0)
        }
    }

    /// Creates a color from a hex string. The string should be of the format "#rrggbb" or
    /// "rrggbb", where each of r, g and b is a hexadecimal digit. Note that this currently does
    /// not support loading colors with a alpha channel. All colors created will be completly
    /// opaque.
    pub fn hex(string: &str) -> Option<Color> {
        let value = {
            if string.len() == 6 {
                u32::from_str_radix(string, 16)
            } else if string.len() == 7 {
                u32::from_str_radix(&string[1..], 16)
            } else {
                return None
            }
        };

        match value {
            Ok(value) => Some(Color::hex_int(value)),
            Err(_) =>    None,
        }
    }

    /// Creates a color from a hex int. Bit `0..8` (The eight least significant bits) are the
    /// red channel. Bit `8..16` are the green channel. Bit `16..24` are the blue channel. Note
    /// that this function currently ignores the alpha channel.
    ///
    /// # Example
    /// ```rust
    /// # use gondola::Color;
    /// let color = Color::hex_int(0xff00ff);
    ///
    /// assert_eq!(color, Color::rgb(1.0, 0.0, 1.0));
    /// ```
    pub fn hex_int(value: u32) -> Color {
        let r = value >> 16 & 0xff;
        let g = value >> 8 & 0xff;
        let b = value & 0xff;

        let r = r as f32 / 255.0;
        let g = g as f32 / 255.0;
        let b = b as f32 / 255.0;

        Color { r: r, g: g, b: b, a: 1.0 }
    }

    /// Converts this color to a hex string like "#ffa13b". Note that this function currently
    /// ignores the alpha channel.
    pub fn to_hex(&self) -> String {
        let r = (self.r * 255.0) as u32;
        let g = (self.g * 255.0) as u32;
        let b = (self.b * 255.0) as u32;
        let value = r << 16 | g << 8 | b;
        format!("#{:06x}", value)
    }

    /// Creates a new color based on this color, with the red, green and blue components multiplied
    /// by the given factor.
    pub fn with_lightness(&self, factor: f32) -> Color {
        Color {
            r: clamp(self.r*factor, 0.0, 1.0),
            g: clamp(self.g*factor, 0.0, 1.0),
            b: clamp(self.b*factor, 0.0, 1.0),
            a: self.a
        }
    }
}

// Does not properly handle NaN, which should not really matter
fn clamp(value: f32, min: f32, max: f32) -> f32 {
    if value < min {
        return min;
    }
    if value > max {
        return max;
    }
    value
}

impl VertexData for Color {
    type Primitive = f32;
    fn bytes() -> usize { std::mem::size_of::<f32>() * 4 }
    fn primitives() -> usize { 4 }
}
impl UniformValue for Color {
    unsafe fn set_uniform(color: &Color, location: GLint) {
        gl::Uniform4f(location, color.r, color.g, color.b, color.a);
    }

    unsafe fn set_uniform_slice(colors: &[Color], location: GLint) {
        gl::Uniform4fv(location, colors.len() as GLsizei, colors.as_ptr() as *const GLfloat);
    }
}

// Custom serialization
#[cfg(feature = "serialize")]
mod serialize {
    use super::*;

    use std::fmt;
    use serde::{Serialize, Deserialize, Serializer, Deserializer};
    use serde::de::{Visitor, Error};

    impl Serialize for Color {
        fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
            s.serialize_str(&self.to_hex())
        }
    }

    impl<'de> Deserialize<'de> for Color {
        fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
            d.deserialize_str(ColorVisitor)
        }
    }

    struct ColorVisitor;
    impl<'de> Visitor<'de> for ColorVisitor {
        type Value = Color;

        fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
            f.write_str("A string representing a valid hex color")
        }

        fn visit_str<E: Error>(self, v: &str) -> Result<Self::Value, E> {
            match Color::hex(v) {
                Some(color) => Ok(color),
                None =>        Err(E::custom(format!("\"{}\" is not a valid color string", v))),
            }
        }
    }
}

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

    #[test]
    fn test_to_hex() {
        assert_eq!("#ffa3b1", Color::hex("#ffa3b1").unwrap().to_hex());
        assert_eq!("#a300f1", Color::hex("#a300f1").unwrap().to_hex());
        assert_eq!("#000000", Color::hex("#000000").unwrap().to_hex());
        assert_eq!("#000001", Color::hex("#000001").unwrap().to_hex());
        assert_eq!("#100000", Color::hex("#100000").unwrap().to_hex());
    }
}

<commit_msg>Added `hex_int_alhpa` constructor to color<commit_after>
//! A color type, with utility methods for modifying colors and parsing colors from hex integers and strings.

use gl;
use gl::types::*;
use std;
use shader::UniformValue;
use buffer::VertexData;

/// A color with red, green, blue and alpha components. All components are expected to be
/// between 0 and 1, both inclusinve.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Color {
    pub r: f32,
    pub g: f32,
    pub b: f32,
    pub a: f32,
}

impl Color {
    /// Creates a new, completly opaque (alpha = 1), color.
    ///
    /// All parameters are clamped so that they are between 0 and 1, both inclusive.
    pub fn rgb(r: f32, g: f32, b: f32) -> Color {
        Color {
            r: clamp(r, 0.0, 1.0),
            g: clamp(g, 0.0, 1.0),
            b: clamp(b, 0.0, 1.0),
            a: 1.0
        }
    }

    /// Creates a new color.
    ///
    /// All parameters are clamped so that they are between 0 and 1, both inclusive.
    pub fn rgba(r: f32, g: f32, b: f32, a: f32) -> Color {
        Color {
            r: clamp(r, 0.0, 1.0),
            g: clamp(g, 0.0, 1.0),
            b: clamp(b, 0.0, 1.0),
            a: clamp(a, 0.0, 1.0)
        }
    }

    /// Creates a color from a hex string. The string should be of the format "#rrggbb" or
    /// "rrggbb", where each of r, g and b is a hexadecimal digit. Note that this currently does
    /// not support loading colors with a alpha channel. All colors created will be completly
    /// opaque.
    pub fn hex(string: &str) -> Option<Color> {
        let value = {
            if string.len() == 6 {
                u32::from_str_radix(string, 16)
            } else if string.len() == 7 {
                u32::from_str_radix(&string[1..], 16)
            } else {
                return None
            }
        };

        match value {
            Ok(value) => Some(Color::hex_int(value)),
            Err(_) =>    None,
        }
    }

    /// Creates a color from a hex int. Bit `0..8` (The eight least significant bits) are the
    /// red channel. Bit `8..16` are the green channel. Bit `16..24` are the blue channel. Note
    /// that this function currently ignores the alpha channel.
    ///
    /// # Example
    /// ```rust
    /// # use gondola::Color;
    /// let color = Color::hex_int(0xff00ff);
    ///
    /// assert_eq!(color, Color::rgb(1.0, 0.0, 1.0));
    /// ```
    pub fn hex_int(value: u32) -> Color {
        let r = value >> 16 & 0xff;
        let g = value >> 8 & 0xff;
        let b = value & 0xff;

        let r = r as f32 / 255.0;
        let g = g as f32 / 255.0;
        let b = b as f32 / 255.0;

        Color { r: r, g: g, b: b, a: 1.0 }
    }

    /// Same as [`hex_int`], but allows specifying the alpha channel. `alpha` should be between 0
    /// and 1, both inclusive.
    ///
    /// [`hex_int`]: struct.Color.html#method.hex_int
    pub fn hex_int_alpha(value: u32, alpha: f32) -> Color {
        let r = value >> 16 & 0xff;
        let g = value >> 8 & 0xff;
        let b = value & 0xff;

        let r = r as f32 / 255.0;
        let g = g as f32 / 255.0;
        let b = b as f32 / 255.0;

        Color { r: r, g: g, b: b, a: alpha }
    }

    /// Converts this color to a hex string like "#ffa13b". Note that this function currently
    /// ignores the alpha channel.
    pub fn to_hex(&self) -> String {
        let r = (self.r * 255.0) as u32;
        let g = (self.g * 255.0) as u32;
        let b = (self.b * 255.0) as u32;
        let value = r << 16 | g << 8 | b;
        format!("#{:06x}", value)
    }

    /// Creates a new color based on this color, with the red, green and blue components multiplied
    /// by the given factor.
    pub fn with_lightness(&self, factor: f32) -> Color {
        Color {
            r: clamp(self.r*factor, 0.0, 1.0),
            g: clamp(self.g*factor, 0.0, 1.0),
            b: clamp(self.b*factor, 0.0, 1.0),
            a: self.a
        }
    }
}

// Does not properly handle NaN, which should not really matter
fn clamp(value: f32, min: f32, max: f32) -> f32 {
    if value < min {
        return min;
    }
    if value > max {
        return max;
    }
    value
}

impl VertexData for Color {
    type Primitive = f32;
    fn bytes() -> usize { std::mem::size_of::<f32>() * 4 }
    fn primitives() -> usize { 4 }
}
impl UniformValue for Color {
    unsafe fn set_uniform(color: &Color, location: GLint) {
        gl::Uniform4f(location, color.r, color.g, color.b, color.a);
    }

    unsafe fn set_uniform_slice(colors: &[Color], location: GLint) {
        gl::Uniform4fv(location, colors.len() as GLsizei, colors.as_ptr() as *const GLfloat);
    }
}

// Custom serialization
#[cfg(feature = "serialize")]
mod serialize {
    use super::*;

    use std::fmt;
    use serde::{Serialize, Deserialize, Serializer, Deserializer};
    use serde::de::{Visitor, Error};

    impl Serialize for Color {
        fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
            s.serialize_str(&self.to_hex())
        }
    }

    impl<'de> Deserialize<'de> for Color {
        fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
            d.deserialize_str(ColorVisitor)
        }
    }

    struct ColorVisitor;
    impl<'de> Visitor<'de> for ColorVisitor {
        type Value = Color;

        fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
            f.write_str("A string representing a valid hex color")
        }

        fn visit_str<E: Error>(self, v: &str) -> Result<Self::Value, E> {
            match Color::hex(v) {
                Some(color) => Ok(color),
                None =>        Err(E::custom(format!("\"{}\" is not a valid color string", v))),
            }
        }
    }
}

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

    #[test]
    fn test_to_hex() {
        assert_eq!("#ffa3b1", Color::hex("#ffa3b1").unwrap().to_hex());
        assert_eq!("#a300f1", Color::hex("#a300f1").unwrap().to_hex());
        assert_eq!("#000000", Color::hex("#000000").unwrap().to_hex());
        assert_eq!("#000001", Color::hex("#000001").unwrap().to_hex());
        assert_eq!("#100000", Color::hex("#100000").unwrap().to_hex());
    }
}

<|endoftext|>


<commit_before><commit_msg>Fix db tests, drop tables in reverse<commit_after><|endoftext|>


<commit_before>extern crate crypto;

use crypto::digest::Digest;
use crypto::sha2::Sha256;

fn main() {
    println!("24 days of Rust - rust-crypto (day 21)");
    let input = "Hello world!";
    let mut sha = Sha256::new();
    sha.input_str(input);
    println!("{}", sha.result_str());
}
<commit_msg>Base64 encoding.<commit_after>extern crate crypto;
extern crate "rustc-serialize" as serialize;

use crypto::digest::Digest;
use crypto::sha2::Sha256;

use serialize::base64::{STANDARD, ToBase64};

fn main() {
    println!("24 days of Rust - rust-crypto (day 21)");
    let input = "Hello world!";
    let mut sha = Sha256::new();
    sha.input_str(input);
    println!("{}", sha.result_str());
    let mut bytes = Vec::from_elem(sha.output_bytes(), 0u8);
    sha.result(bytes.as_mut_slice());
    println!("{}", bytes.to_base64(STANDARD));
}
<|endoftext|>