<commit_before>use std::ascii::AsciiExt;
use serialize::json::{ToJson};
use jsonway::{self, MutableJson};
use framework::{self, Nesting};
use server::header::common::access_control::allow_origin;

#[allow(unused_variables)]
pub fn fill_paths(current_path: &str, paths: &mut jsonway::ObjectBuilder, handlers: &framework::ApiHandlers) {
    let mut current_path = current_path.to_string();

    for handler in handlers.iter() {
        if handler.is::<framework::Api>() {
            let api = handler.downcast_ref::<framework::Api>().unwrap();
            if api.prefix.len() > 0 {
                current_path.push_str((api.prefix.to_string() + "/").as_slice());
            }
            if api.versioning.is_some() {
                match api.versioning.as_ref().unwrap() {
                    &framework::Versioning::Path if api.version.is_some() => {
                        current_path.push_str((api.version.as_ref().unwrap().to_string() + "/").as_slice())
                    },
                    _ => ()
                }
            }
            fill_paths(current_path.as_slice(), paths, &api.handlers);
        } else if handler.is::<framework::Namespace>() {
            let namespace = handler.downcast_ref::<framework::Namespace>().unwrap();
            current_path.push_str((namespace.path.path.to_string() + "/").as_slice());
            fill_paths(current_path.as_slice(), paths, &namespace.handlers);
        } else if handler.is::<framework::Endpoint>() {
            let endpoint = handler.downcast_ref::<framework::Endpoint>().unwrap();
            current_path.push_str((endpoint.path.path.to_string() + "/").as_slice());

            let definition = jsonway::JsonWay::object(|def| {
                // A list of tags for API documentation control. Tags can be used for logical grouping
                // of operations by resources or any other qualifier.
                def.array("tags", |tags| {});

                // A short summary of what the operation does. For maximum readability in the swagger-ui,
                // this field SHOULD be less than 120 characters.
                def.set("summary", "Summary".to_string());

                // A verbose explanation of the operation behavior.
                // GFM syntax can be used for rich text representation.
                def.set("description",  "Description".to_string());

                // External Documentation Object
                // Additional external documentation for this operation.
                def.object("externalDocs", |external_docs| {
                    // A short description of the target documentation.
                    // GFM syntax can be used for rich text representation.
                    external_docs.set("description", "Description".to_string());
                    //  Required. The URL for the target documentation. Value MUST be in the format of a URL.
                    external_docs.set("url", "http://google.com".to_string());
                });

                // A friendly name for the operation. The id MUST be unique among all operations described
                // in the API. Tools and libraries MAY use the operation id to uniquely identify an operation.
                def.set("operationId", "OP".to_string());

                // A list of MIME types the operation can consume.
                // This overrides the [consumes](#swaggerConsumes) definition at the Swagger Object.
                // An empty value MAY be used to clear the global definition.
                // Value MUST be as described under Mime Types.
                def.array("consumes", |consumes| {});

                // A list of MIME types the operation can produce.
                // This overrides the [produces](#swaggerProduces) definition at the Swagger Object.
                // An empty value MAY be used to clear the global definition.
                // Value MUST be as described under Mime Types.
                def.array("produces", |produces| {});

                // A list of parameters that are applicable for this operation.
                // If a parameter is already defined at the Path Item, the new definition will override it,
                // but can never remove it. The list MUST NOT include duplicated parameters.
                // A unique parameter is defined by a combination of a name and location.
                // The list can use the Reference Object to link to parameters that are
                // defined at the Swagger Object's parameters. There can be one "body" parameter at most.
                def.array("parameters", |parameters| {});

                // Required. The list of possible responses as they are returned from executing this operation.
                def.object("responses",  |responses| {
                    responses.object("default", |default| {
                        // Required. A short description of the response.
                        // GFM syntax can be used for rich text representation.
                        default.set("description", "Description".to_string());

                        // A definition of the response structure. It can be a primitive, an array or an object.
                        // If this field does not exist, it means no content is returned as part of the response.
                        // As an extension to the Schema Object, its root type value may also be "file".
                        // This SHOULD be accompanied by a relevant produces mime-type.
                        default.object("schema", |schema| {});

                        // A list of headers that are sent with the response.
                        default.object("headers", |headers| {});

                        // An example of the response message.
                        default.object("examples", |examples| {});
                    })
                });

                // The transfer protocol for the operation. Values MUST be from the list: "http", "https",
                // "ws", "wss". The value overrides the Swagger Object schemes definition.
                def.array("schemes", |schemes| {});

                // Declares this operation to be deprecated. Usage of the declared operation should be refrained.
                // Default value is false.
                def.set("deprecated", false);

                // A declaration of which security schemes are applied for this operation.
                // The list of values describes alternative security schemes that can be used
                // (that is, there is a logical OR between the security requirements).
                // This definition overrides any declared top-level security.
                // To remove a top-level security declaration, an empty array can be used.
                def.array("security", |security| {});
            });

            let method = format!("{:?}", endpoint.method).to_ascii_lowercase();
            let present = {
                let maybe_path_obj = paths.object.get_mut(current_path.as_slice());
                if maybe_path_obj.is_some() {
                    let path_obj = maybe_path_obj.unwrap().as_object_mut().unwrap();
                    path_obj.insert(method.to_string(), definition.to_json());
                    true
                } else {
                    false
                }
            };

            if !present {
                paths.object(current_path.as_slice(), move |: path_item| {
                    path_item.set(method, definition);
                })
            }
        }
    }
}

#[allow(dead_code)]
#[allow(unused_variables)]
pub fn create_swagger_api(path: &str) -> framework::Api {
    framework::Api::build(|api| {
        api.namespace(path, |docs| {
            docs.options("", |endpoint| {
                endpoint.handle(|&: mut client, _params| {
                    client.set_header(allow_origin::AccessControlAllowOrigin::AllowStar);
                    client.empty()
                })
            });
            docs.get("", |endpoint| {
                endpoint.handle(|&: mut client, _params| {
                    client.set_header(allow_origin::AccessControlAllowOrigin::AllowStar);
                    let swagger_data = &jsonway::JsonWay::object(|json| {
                        // Required. Specifies the Swagger Specification version being used.
                        // It can be used by the Swagger UI and other clients to interpret the API listing.
                        // The value MUST be "2.0".
                        json.set("swagger", "2.0".to_string());

                        // Required. Provides metadata about the API. The metadata can be used by the clients if needed.
                        json.object("info", |info| {
                            // Required. The title of the application.
                            info.set("title", "Rustless API".to_string());

                            // A short description of the application. GFM syntax can be used for rich text representation.
                            info.set("description", "Rustless API description".to_string());

                            // The Terms of Service for the API.
                            info.set("termsOfService", "Terms of service".to_string());

                            // The contact information for the exposed API.
                            info.object("contact", |contact| {
                                // The identifying name of the contact person/organization.
                                contact.set("name", "API owner".to_string());
                                // The URL pointing to the contact information. MUST be in the format of a URL.
                                contact.set("url", "http://localhost".to_string());
                                // The email address of the contact person/organization. MUST be in the format of an email address.
                                contact.set("email", "admin@example.com".to_string());
                            });

                            info.object("license", |license| {
                                // The license name used for the API.
                                license.set("name", "MIT".to_string());

                                // An URL to the license used for the API. MUST be in the format of a URL.
                                license.set("url", "http://opensource.org/licenses/MIT".to_string());
                            });

                            // Required Provides the version of the application API (not to be confused by the specification version).
                            info.set("version", "1.0".to_string());
                        });

                        // The host (name or ip) serving the API. This MUST be the host only and does not
                        // include the scheme nor sub-paths. It MAY include a port. If the host is not included,
                        // the host serving the documentation is to be used (including the port).
                        // The host does not support path templating.
                        json.set("host", "localhost:4000".to_string());

                        // The base path on which the API is served, which is relative to the host.
                        // If it is not included, the API is served directly under the host.
                        // The value MUST start with a leading slash (/). The basePath does not support path
                        // templating.
                        json.set("basePath", "/".to_string());

                        // The transfer protocol of the API. Values MUST be from the list:
                        // "http", "https", "ws", "wss". If the schemes is not included, the default
                        // scheme to be used is the one used to access the specification.
                        json.array("schemes", |schemes| {
                            schemes.push("http".to_string())
                        });

                        // A list of MIME types the APIs can consume. This is global to all APIs but can be
                        // overridden on specific API calls. Value MUST be as described under Mime Types.
                        json.array("consumes", |consumes| {
                            consumes.push("application/json".to_string())
                        });

                        // A list of MIME types the APIs can produce. This is global to all APIs but can
                        // be overridden on specific API calls. Value MUST be as described under Mime Types.
                        json.array("produces", |produces| {
                            produces.push("application/json".to_string())
                        });

                        // Required. The available paths and operations for the API.
                        json.object("paths", |paths| {
                            fill_paths("/", paths, &client.app.root_api.handlers);
                        });

                         // An object to hold data types produced and consumed by operations.
                        json.object("definitions", |definitions| {

                        });

                        // An object to hold parameters that can be used across operations.
                        // This property does not define global parameters for all operations.
                        json.object("parameters", |parameters| {

                        });

                        // An object to hold responses that can be used across operations.
                        // This property does not define global responses for all operations.
                        json.object("responses", |responses| {

                        });

                        // Security scheme definitions that can be used across the specification.
                        json.object("securityDefinitions", |security_definitions| {

                        });

                        // A declaration of which security schemes are applied for the API as a whole.
                        // The list of values describes alternative security schemes that can be used
                        // (that is, there is a logical OR between the security requirements).
                        // Individual operations can override this definition.
                        json.array("security", |security| {

                        });

                        // A list of tags used by the specification with additional metadata.
                        // The order of the tags can be used to reflect on their order by the parsing tools.
                        // Not all tags that are used by the Operation Object must be declared.
                        // The tags that are not declared may be organized randomly or based on the tools' logic.
                        // Each tag name in the list MUST be unique.
                        json.array("security", |responses| {

                        });

                        // Additional external documentation.
                        json.object("externalDocs", |external_docs| {

                        })
                    }).unwrap();
                    client.json(swagger_data)
                })
            })
        })
    })
}<commit_msg>feat(swagger): use the another way to generate endpoint urls;<commit_after>use std::ascii::AsciiExt;
use serialize::json::{ToJson};
use jsonway::{self, MutableJson};
use framework::{self, Nesting};
use server::header::common::access_control::allow_origin;

#[allow(unused_variables)]
pub fn fill_paths(current_path: &str, paths: &mut jsonway::ObjectBuilder, handlers: &framework::ApiHandlers) {
    for handler in handlers.iter() {
        if handler.is::<framework::Api>() {
            let mut path = current_path.to_string();

            let api = handler.downcast_ref::<framework::Api>().unwrap();
            if api.prefix.len() > 0 {
                path.push_str((api.prefix).as_slice());
            }
            if api.versioning.is_some() {
                match api.versioning.as_ref().unwrap() {
                    &framework::Versioning::Path if api.version.is_some() => {
                        path.push_str((api.version.as_ref().unwrap().to_string() + "/").as_slice())
                    },
                    _ => ()
                }
            }
            fill_paths(path.as_slice(), paths, &api.handlers);

        } else if handler.is::<framework::Namespace>() {
            let mut path = current_path.to_string();
            let namespace = handler.downcast_ref::<framework::Namespace>().unwrap();
            path.push_str(("/".to_string() + namespace.path.path.as_slice()).as_slice());
            fill_paths(path.as_slice(), paths, &namespace.handlers);

        } else if handler.is::<framework::Endpoint>() {
            let mut path = current_path.to_string();
            let endpoint = handler.downcast_ref::<framework::Endpoint>().unwrap();

            if endpoint.path.path.len() > 0 {
                path.push_str(("/".to_string() + endpoint.path.path.as_slice()).as_slice());
            }

            let definition = jsonway::JsonWay::object(|def| {
                // A list of tags for API documentation control. Tags can be used for logical grouping
                // of operations by resources or any other qualifier.
                // def.array("tags", |tags| { });

                // A short summary of what the operation does. For maximum readability in the swagger-ui,
                // this field SHOULD be less than 120 characters.
                def.set("summary", "Summary".to_string());

                // A verbose explanation of the operation behavior.
                // GFM syntax can be used for rich text representation.
                def.set("description",  "Description".to_string());

                // External Documentation Object
                // Additional external documentation for this operation.
                def.object("externalDocs", |external_docs| {
                    // A short description of the target documentation.
                    // GFM syntax can be used for rich text representation.
                    external_docs.set("description", "Description".to_string());
                    //  Required. The URL for the target documentation. Value MUST be in the format of a URL.
                    external_docs.set("url", "http://google.com".to_string());
                });

                // A friendly name for the operation. The id MUST be unique among all operations described
                // in the API. Tools and libraries MAY use the operation id to uniquely identify an operation.
                def.set("operationId", "OP".to_string());

                // A list of MIME types the operation can consume.
                // This overrides the [consumes](#swaggerConsumes) definition at the Swagger Object.
                // An empty value MAY be used to clear the global definition.
                // Value MUST be as described under Mime Types.
                def.array("consumes", |consumes| {});

                // A list of MIME types the operation can produce.
                // This overrides the [produces](#swaggerProduces) definition at the Swagger Object.
                // An empty value MAY be used to clear the global definition.
                // Value MUST be as described under Mime Types.
                def.array("produces", |produces| {});

                // A list of parameters that are applicable for this operation.
                // If a parameter is already defined at the Path Item, the new definition will override it,
                // but can never remove it. The list MUST NOT include duplicated parameters.
                // A unique parameter is defined by a combination of a name and location.
                // The list can use the Reference Object to link to parameters that are
                // defined at the Swagger Object's parameters. There can be one "body" parameter at most.
                def.array("parameters", |parameters| {});

                // Required. The list of possible responses as they are returned from executing this operation.
                def.object("responses",  |responses| {
                    responses.object("200", |default| {
                        // Required. A short description of the response.
                        // GFM syntax can be used for rich text representation.
                        default.set("description", "Description".to_string());

                        // A definition of the response structure. It can be a primitive, an array or an object.
                        // If this field does not exist, it means no content is returned as part of the response.
                        // As an extension to the Schema Object, its root type value may also be "file".
                        // This SHOULD be accompanied by a relevant produces mime-type.
                        default.object("schema", |schema| {});

                        // A list of headers that are sent with the response.
                        default.object("headers", |headers| {});

                        // An example of the response message.
                        default.object("examples", |examples| {});
                    })
                });

                // The transfer protocol for the operation. Values MUST be from the list: "http", "https",
                // "ws", "wss". The value overrides the Swagger Object schemes definition.
                def.array("schemes", |schemes| {});

                // Declares this operation to be deprecated. Usage of the declared operation should be refrained.
                // Default value is false.
                def.set("deprecated", false);

                // A declaration of which security schemes are applied for this operation.
                // The list of values describes alternative security schemes that can be used
                // (that is, there is a logical OR between the security requirements).
                // This definition overrides any declared top-level security.
                // To remove a top-level security declaration, an empty array can be used.
                def.array("security", |security| {});
            });

            let method = format!("{:?}", endpoint.method).to_ascii_lowercase();
            let present = {
                let maybe_path_obj = paths.object.get_mut(path.as_slice());
                if maybe_path_obj.is_some() {
                    let path_obj = maybe_path_obj.unwrap().as_object_mut().unwrap();
                    path_obj.insert(method.to_string(), definition.to_json());
                    true
                } else {
                    false
                }
            };

            if !present {
                paths.object(path.as_slice(), move |: path_item| {
                    path_item.set(method, definition);
                })
            }

        }
    }
}

#[allow(dead_code)]
#[allow(unused_variables)]
pub fn create_swagger_api(path: &str) -> framework::Api {
    framework::Api::build(|api| {
        api.namespace(path, |docs| {
            docs.options("", |endpoint| {
                endpoint.handle(|&: mut client, _params| {
                    client.set_header(allow_origin::AccessControlAllowOrigin::AllowStar);
                    client.empty()
                })
            });
            docs.get("", |endpoint| {
                endpoint.handle(|&: mut client, _params| {
                    client.set_header(allow_origin::AccessControlAllowOrigin::AllowStar);
                    let swagger_data = &jsonway::JsonWay::object(|json| {
                        // Required. Specifies the Swagger Specification version being used.
                        // It can be used by the Swagger UI and other clients to interpret the API listing.
                        // The value MUST be "2.0".
                        json.set("swagger", "2.0".to_string());

                        // Required. Provides metadata about the API. The metadata can be used by the clients if needed.
                        json.object("info", |info| {
                            // Required. The title of the application.
                            info.set("title", "Rustless API".to_string());

                            // A short description of the application. GFM syntax can be used for rich text representation.
                            info.set("description", "Rustless API description".to_string());

                            // The Terms of Service for the API.
                            info.set("termsOfService", "Terms of service".to_string());

                            // The contact information for the exposed API.
                            info.object("contact", |contact| {
                                // The identifying name of the contact person/organization.
                                contact.set("name", "API owner".to_string());
                                // The URL pointing to the contact information. MUST be in the format of a URL.
                                contact.set("url", "http://localhost".to_string());
                                // The email address of the contact person/organization. MUST be in the format of an email address.
                                contact.set("email", "admin@example.com".to_string());
                            });

                            info.object("license", |license| {
                                // The license name used for the API.
                                license.set("name", "MIT".to_string());

                                // An URL to the license used for the API. MUST be in the format of a URL.
                                license.set("url", "http://opensource.org/licenses/MIT".to_string());
                            });

                            // Required Provides the version of the application API (not to be confused by the specification version).
                            info.set("version", "1.0".to_string());
                        });

                        // The host (name or ip) serving the API. This MUST be the host only and does not
                        // include the scheme nor sub-paths. It MAY include a port. If the host is not included,
                        // the host serving the documentation is to be used (including the port).
                        // The host does not support path templating.
                        json.set("host", "localhost:4000".to_string());

                        // The base path on which the API is served, which is relative to the host.
                        // If it is not included, the API is served directly under the host.
                        // The value MUST start with a leading slash (/). The basePath does not support path
                        // templating.
                        json.set("basePath", "/".to_string());

                        // The transfer protocol of the API. Values MUST be from the list:
                        // "http", "https", "ws", "wss". If the schemes is not included, the default
                        // scheme to be used is the one used to access the specification.
                        json.array("schemes", |schemes| {
                            schemes.push("http".to_string())
                        });

                        // A list of MIME types the APIs can consume. This is global to all APIs but can be
                        // overridden on specific API calls. Value MUST be as described under Mime Types.
                        json.array("consumes", |consumes| {
                            consumes.push("application/json".to_string())
                        });

                        // A list of MIME types the APIs can produce. This is global to all APIs but can
                        // be overridden on specific API calls. Value MUST be as described under Mime Types.
                        json.array("produces", |produces| {
                            produces.push("application/json".to_string())
                        });

                        // Required. The available paths and operations for the API.
                        json.object("paths", |paths| {
                            fill_paths("", paths, &client.app.root_api.handlers);
                        });

                         // An object to hold data types produced and consumed by operations.
                        json.object("definitions", |definitions| {

                        });

                        // An object to hold parameters that can be used across operations.
                        // This property does not define global parameters for all operations.
                        json.object("parameters", |parameters| {

                        });

                        // An object to hold responses that can be used across operations.
                        // This property does not define global responses for all operations.
                        json.object("responses", |responses| {

                        });

                        // Security scheme definitions that can be used across the specification.
                        json.object("securityDefinitions", |security_definitions| {

                        });

                        // A declaration of which security schemes are applied for the API as a whole.
                        // The list of values describes alternative security schemes that can be used
                        // (that is, there is a logical OR between the security requirements).
                        // Individual operations can override this definition.
                        json.array("security", |security| {

                        });

                        // A list of tags used by the specification with additional metadata.
                        // The order of the tags can be used to reflect on their order by the parsing tools.
                        // Not all tags that are used by the Operation Object must be declared.
                        // The tags that are not declared may be organized randomly or based on the tools' logic.
                        // Each tag name in the list MUST be unique.
                        json.array("tags", |tags| {

                        });

                        // Additional external documentation.
                        json.object("externalDocs", |external_docs| {

                        })
                    }).unwrap();
                    client.json(swagger_data)
                })
            })
        })
    })
}<|endoftext|>


<commit_before>// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use syntax_pos::symbol::Symbol;
use back::write::create_target_machine;
use llvm;
use rustc::session::Session;
use rustc::session::config::PrintRequest;
use libc::c_int;
use std::ffi::CString;

use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Once;

static POISONED: AtomicBool = AtomicBool::new(false);
static INIT: Once = Once::new();

pub(crate) fn init(sess: &Session) {
    unsafe {
        // Before we touch LLVM, make sure that multithreading is enabled.
        INIT.call_once(|| {
            if llvm::LLVMStartMultithreaded() != 1 {
                // use an extra bool to make sure that all future usage of LLVM
                // cannot proceed despite the Once not running more than once.
                POISONED.store(true, Ordering::SeqCst);
            }

            configure_llvm(sess);
        });

        if POISONED.load(Ordering::SeqCst) {
            bug!("couldn't enable multi-threaded LLVM");
        }
    }
}

fn require_inited() {
    INIT.call_once(|| bug!("llvm is not initialized"));
    if POISONED.load(Ordering::SeqCst) {
        bug!("couldn't enable multi-threaded LLVM");
    }
}

unsafe fn configure_llvm(sess: &Session) {
    let mut llvm_c_strs = Vec::new();
    let mut llvm_args = Vec::new();

    {
        let mut add = |arg: &str| {
            let s = CString::new(arg).unwrap();
            llvm_args.push(s.as_ptr());
            llvm_c_strs.push(s);
        };
        add("rustc"); // fake program name
        if sess.time_llvm_passes() { add("-time-passes"); }
        if sess.print_llvm_passes() { add("-debug-pass=Structure"); }

        for arg in &sess.opts.cg.llvm_args {
            add(&(*arg));
        }
    }

    llvm::LLVMInitializePasses();

    llvm::initialize_available_targets();

    llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int,
                                 llvm_args.as_ptr());
}

// WARNING: the features after applying `to_llvm_feature` must be known
// to LLVM or the feature detection code will walk past the end of the feature
// array, leading to crashes.

const ARM_WHITELIST: &'static [&'static str] = &["neon", "v7", "vfp2", "vfp3", "vfp4"];

const AARCH64_WHITELIST: &'static [&'static str] = &["fp", "neon", "sve", "crc", "crypto",
                                                     "ras", "lse", "rdm", "fp16", "rcpc",
                                                     "dotprod", "v8.1a", "v8.2a", "v8.3a"];

const X86_WHITELIST: &'static [&'static str] = &["aes", "avx", "avx2", "avx512bw",
                                                 "avx512cd", "avx512dq", "avx512er",
                                                 "avx512f", "avx512ifma", "avx512pf",
                                                 "avx512vbmi", "avx512vl", "avx512vpopcntdq",
                                                 "bmi1", "bmi2", "fma", "fxsr",
                                                 "lzcnt", "mmx", "pclmulqdq",
                                                 "popcnt", "rdrand", "rdseed",
                                                 "sse", "sse2", "sse3", "sse4.1",
                                                 "sse4.2", "sse4a", "ssse3",
                                                 "tbm", "xsave", "xsavec",
                                                 "xsaveopt", "xsaves"];

const HEXAGON_WHITELIST: &'static [&'static str] = &["hvx", "hvx-double"];

const POWERPC_WHITELIST: &'static [&'static str] = &["altivec",
                                                     "power8-altivec", "power9-altivec",
                                                     "power8-vector", "power9-vector",
                                                     "vsx"];

const MIPS_WHITELIST: &'static [&'static str] = &["msa"];

pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str {
    let arch = if sess.target.target.arch == "x86_64" {
        "x86"
    } else {
        &*sess.target.target.arch
    };
    match (arch, s) {
        ("x86", "pclmulqdq") => "pclmul",
        ("x86", "rdrand") => "rdrnd",
        ("x86", "bmi1") => "bmi",
        ("aarch64", "fp16") => "fullfp16",
        (_, s) => s,
    }
}

pub fn target_features(sess: &Session) -> Vec<Symbol> {
    let target_machine = create_target_machine(sess);
    target_feature_whitelist(sess)
        .iter()
        .filter(|feature| {
            let llvm_feature = to_llvm_feature(sess, feature);
            let cstr = CString::new(llvm_feature).unwrap();
            unsafe { llvm::LLVMRustHasFeature(target_machine, cstr.as_ptr()) }
        })
        .map(|feature| Symbol::intern(feature)).collect()
}

pub fn target_feature_whitelist(sess: &Session) -> &'static [&'static str] {
    match &*sess.target.target.arch {
        "arm" => ARM_WHITELIST,
        "aarch64" => AARCH64_WHITELIST,
        "x86" | "x86_64" => X86_WHITELIST,
        "hexagon" => HEXAGON_WHITELIST,
        "mips" | "mips64" => MIPS_WHITELIST,
        "powerpc" | "powerpc64" => POWERPC_WHITELIST,
        _ => &[],
    }
}

pub fn print_version() {
    // Can be called without initializing LLVM
    unsafe {
        println!("LLVM version: {}.{}",
                 llvm::LLVMRustVersionMajor(), llvm::LLVMRustVersionMinor());
    }
}

pub fn print_passes() {
    // Can be called without initializing LLVM
    unsafe { llvm::LLVMRustPrintPasses(); }
}

pub(crate) fn print(req: PrintRequest, sess: &Session) {
    require_inited();
    let tm = create_target_machine(sess);
    unsafe {
        match req {
            PrintRequest::TargetCPUs => llvm::LLVMRustPrintTargetCPUs(tm),
            PrintRequest::TargetFeatures => llvm::LLVMRustPrintTargetFeatures(tm),
            _ => bug!("rustc_trans can't handle print request: {:?}", req),
        }
    }
}
<commit_msg>librustc_trans: add fp64 to mips features whitelist<commit_after>// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use syntax_pos::symbol::Symbol;
use back::write::create_target_machine;
use llvm;
use rustc::session::Session;
use rustc::session::config::PrintRequest;
use libc::c_int;
use std::ffi::CString;

use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Once;

static POISONED: AtomicBool = AtomicBool::new(false);
static INIT: Once = Once::new();

pub(crate) fn init(sess: &Session) {
    unsafe {
        // Before we touch LLVM, make sure that multithreading is enabled.
        INIT.call_once(|| {
            if llvm::LLVMStartMultithreaded() != 1 {
                // use an extra bool to make sure that all future usage of LLVM
                // cannot proceed despite the Once not running more than once.
                POISONED.store(true, Ordering::SeqCst);
            }

            configure_llvm(sess);
        });

        if POISONED.load(Ordering::SeqCst) {
            bug!("couldn't enable multi-threaded LLVM");
        }
    }
}

fn require_inited() {
    INIT.call_once(|| bug!("llvm is not initialized"));
    if POISONED.load(Ordering::SeqCst) {
        bug!("couldn't enable multi-threaded LLVM");
    }
}

unsafe fn configure_llvm(sess: &Session) {
    let mut llvm_c_strs = Vec::new();
    let mut llvm_args = Vec::new();

    {
        let mut add = |arg: &str| {
            let s = CString::new(arg).unwrap();
            llvm_args.push(s.as_ptr());
            llvm_c_strs.push(s);
        };
        add("rustc"); // fake program name
        if sess.time_llvm_passes() { add("-time-passes"); }
        if sess.print_llvm_passes() { add("-debug-pass=Structure"); }

        for arg in &sess.opts.cg.llvm_args {
            add(&(*arg));
        }
    }

    llvm::LLVMInitializePasses();

    llvm::initialize_available_targets();

    llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int,
                                 llvm_args.as_ptr());
}

// WARNING: the features after applying `to_llvm_feature` must be known
// to LLVM or the feature detection code will walk past the end of the feature
// array, leading to crashes.

const ARM_WHITELIST: &'static [&'static str] = &["neon", "v7", "vfp2", "vfp3", "vfp4"];

const AARCH64_WHITELIST: &'static [&'static str] = &["fp", "neon", "sve", "crc", "crypto",
                                                     "ras", "lse", "rdm", "fp16", "rcpc",
                                                     "dotprod", "v8.1a", "v8.2a", "v8.3a"];

const X86_WHITELIST: &'static [&'static str] = &["aes", "avx", "avx2", "avx512bw",
                                                 "avx512cd", "avx512dq", "avx512er",
                                                 "avx512f", "avx512ifma", "avx512pf",
                                                 "avx512vbmi", "avx512vl", "avx512vpopcntdq",
                                                 "bmi1", "bmi2", "fma", "fxsr",
                                                 "lzcnt", "mmx", "pclmulqdq",
                                                 "popcnt", "rdrand", "rdseed",
                                                 "sse", "sse2", "sse3", "sse4.1",
                                                 "sse4.2", "sse4a", "ssse3",
                                                 "tbm", "xsave", "xsavec",
                                                 "xsaveopt", "xsaves"];

const HEXAGON_WHITELIST: &'static [&'static str] = &["hvx", "hvx-double"];

const POWERPC_WHITELIST: &'static [&'static str] = &["altivec",
                                                     "power8-altivec", "power9-altivec",
                                                     "power8-vector", "power9-vector",
                                                     "vsx"];

const MIPS_WHITELIST: &'static [&'static str] = &["fp64", "msa"];

pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str {
    let arch = if sess.target.target.arch == "x86_64" {
        "x86"
    } else {
        &*sess.target.target.arch
    };
    match (arch, s) {
        ("x86", "pclmulqdq") => "pclmul",
        ("x86", "rdrand") => "rdrnd",
        ("x86", "bmi1") => "bmi",
        ("aarch64", "fp16") => "fullfp16",
        (_, s) => s,
    }
}

pub fn target_features(sess: &Session) -> Vec<Symbol> {
    let target_machine = create_target_machine(sess);
    target_feature_whitelist(sess)
        .iter()
        .filter(|feature| {
            let llvm_feature = to_llvm_feature(sess, feature);
            let cstr = CString::new(llvm_feature).unwrap();
            unsafe { llvm::LLVMRustHasFeature(target_machine, cstr.as_ptr()) }
        })
        .map(|feature| Symbol::intern(feature)).collect()
}

pub fn target_feature_whitelist(sess: &Session) -> &'static [&'static str] {
    match &*sess.target.target.arch {
        "arm" => ARM_WHITELIST,
        "aarch64" => AARCH64_WHITELIST,
        "x86" | "x86_64" => X86_WHITELIST,
        "hexagon" => HEXAGON_WHITELIST,
        "mips" | "mips64" => MIPS_WHITELIST,
        "powerpc" | "powerpc64" => POWERPC_WHITELIST,
        _ => &[],
    }
}

pub fn print_version() {
    // Can be called without initializing LLVM
    unsafe {
        println!("LLVM version: {}.{}",
                 llvm::LLVMRustVersionMajor(), llvm::LLVMRustVersionMinor());
    }
}

pub fn print_passes() {
    // Can be called without initializing LLVM
    unsafe { llvm::LLVMRustPrintPasses(); }
}

pub(crate) fn print(req: PrintRequest, sess: &Session) {
    require_inited();
    let tm = create_target_machine(sess);
    unsafe {
        match req {
            PrintRequest::TargetCPUs => llvm::LLVMRustPrintTargetCPUs(tm),
            PrintRequest::TargetFeatures => llvm::LLVMRustPrintTargetFeatures(tm),
            _ => bug!("rustc_trans can't handle print request: {:?}", req),
        }
    }
}
<|endoftext|>


<commit_before>import std::term;
import io::writer_util;
import codemap::span;

export emitter, emit;
export level, fatal, error, warning, note;
export span_handler, handler, mk_span_handler, mk_handler;
export codemap_span_handler, codemap_handler;
export ice_msg;

type emitter = fn@(cmsp: option<(codemap::codemap, span)>,
                   msg: str, lvl: level);

iface span_handler {
    fn span_fatal(sp: span, msg: str) -> !;
    fn span_err(sp: span, msg: str);
    fn span_warn(sp: span, msg: str);
    fn span_note(sp: span, msg: str);
    fn span_bug(sp: span, msg: str) -> !;
    fn span_unimpl(sp: span, msg: str) -> !;
    fn handler() -> handler;
}

iface handler {
    fn fatal(msg: str) -> !;
    fn err(msg: str);
    fn bump_err_count();
    fn has_errors() -> bool;
    fn abort_if_errors();
    fn warn(msg: str);
    fn note(msg: str);
    fn bug(msg: str) -> !;
    fn unimpl(msg: str) -> !;
    fn emit(cmsp: option<(codemap::codemap, span)>, msg: str, lvl: level);
}

type handler_t = @{
    mut err_count: uint,
    _emit: emitter
};

type codemap_t = @{
    handler: handler,
    cm: codemap::codemap
};

impl codemap_span_handler of span_handler for codemap_t {
    fn span_fatal(sp: span, msg: str) -> ! {
        self.handler.emit(some((self.cm, sp)), msg, fatal);
        fail;
    }
    fn span_err(sp: span, msg: str) {
        self.handler.emit(some((self.cm, sp)), msg, error);
        self.handler.bump_err_count();
    }
    fn span_warn(sp: span, msg: str) {
        self.handler.emit(some((self.cm, sp)), msg, warning);
    }
    fn span_note(sp: span, msg: str) {
        self.handler.emit(some((self.cm, sp)), msg, note);
    }
    fn span_bug(sp: span, msg: str) -> ! {
        self.span_fatal(sp, ice_msg(msg));
    }
    fn span_unimpl(sp: span, msg: str) -> ! {
        self.span_bug(sp, "unimplemented " + msg);
    }
    fn handler() -> handler {
        self.handler
    }
}

impl codemap_handler of handler for handler_t {
    fn fatal(msg: str) -> ! {
        self._emit(none, msg, fatal);
        fail;
    }
    fn err(msg: str) {
        self._emit(none, msg, error);
        self.bump_err_count();
    }
    fn bump_err_count() {
        self.err_count += 1u;
    }
    fn has_errors() -> bool { self.err_count > 0u }
    fn abort_if_errors() {
        if self.err_count > 0u {
            self.fatal("aborting due to previous errors");
        }
    }
    fn warn(msg: str) {
        self._emit(none, msg, warning);
    }
    fn note(msg: str) {
        self._emit(none, msg, note);
    }
    fn bug(msg: str) -> ! {
        self.fatal(ice_msg(msg));
    }
    fn unimpl(msg: str) -> ! { self.bug("unimplemented " + msg); }
    fn emit(cmsp: option<(codemap::codemap, span)>, msg: str, lvl: level) {
        self._emit(cmsp, msg, lvl);
    }
}

fn ice_msg(msg: str) -> str {
    #fmt["internal compiler error %s", msg]
}

fn mk_span_handler(handler: handler, cm: codemap::codemap) -> span_handler {
    @{ handler: handler, cm: cm } as span_handler
}

fn mk_handler(emitter: option<emitter>) -> handler {

    let emit = alt emitter {
      some(e) { e }
      none {
        let f = fn@(cmsp: option<(codemap::codemap, span)>,
            msg: str, t: level) {
            emit(cmsp, msg, t);
        };
        f
      }
    };

    @{
        mut err_count: 0u,
        _emit: emit
    } as handler
}

enum level {
    fatal,
    error,
    warning,
    note,
}

fn diagnosticstr(lvl: level) -> str {
    alt lvl {
      fatal { "error" }
      error { "error" }
      warning { "warning" }
      note { "note" }
    }
}

fn diagnosticcolor(lvl: level) -> u8 {
    alt lvl {
      fatal { term::color_bright_red }
      error { term::color_bright_red }
      warning { term::color_bright_yellow }
      note { term::color_bright_green }
    }
}

fn print_diagnostic(topic: str, lvl: level, msg: str) {
    if str::is_not_empty(topic) {
        io::stderr().write_str(#fmt["%s ", topic]);
    }
    if term::color_supported() {
        term::fg(io::stderr(), diagnosticcolor(lvl));
    }
    io::stderr().write_str(#fmt["%s:", diagnosticstr(lvl)]);
    if term::color_supported() {
        term::reset(io::stderr());
    }
    io::stderr().write_str(#fmt[" %s\n", msg]);
}

fn emit(cmsp: option<(codemap::codemap, span)>,
        msg: str, lvl: level) {
    alt cmsp {
      some((cm, sp)) {
        let sp = codemap::adjust_span(cm,sp);
        let ss = codemap::span_to_str(sp, cm);
        let lines = codemap::span_to_lines(sp, cm);
        print_diagnostic(ss, lvl, msg);
        highlight_lines(cm, sp, lines);
        print_macro_backtrace(cm, sp);
      }
      none {
        print_diagnostic("", lvl, msg);
      }
    }
}

fn highlight_lines(cm: codemap::codemap, sp: span,
                   lines: @codemap::file_lines) {

    let fm = lines.file;

    // arbitrarily only print up to six lines of the error
    let max_lines = 6u;
    let mut elided = false;
    let mut display_lines = lines.lines;
    if vec::len(display_lines) > max_lines {
        display_lines = vec::slice(display_lines, 0u, max_lines);
        elided = true;
    }
    // Print the offending lines
    for display_lines.each {|line|
        io::stderr().write_str(#fmt["%s:%u ", fm.name, line + 1u]);
        let s = codemap::get_line(fm, line as int) + "\n";
        io::stderr().write_str(s);
    }
    if elided {
        let last_line = display_lines[vec::len(display_lines) - 1u];
        let s = #fmt["%s:%u ", fm.name, last_line + 1u];
        let mut indent = str::len(s);
        let mut out = "";
        while indent > 0u { out += " "; indent -= 1u; }
        out += "...\n";
        io::stderr().write_str(out);
    }

    // If there's one line at fault we can easily point to the problem
    if vec::len(lines.lines) == 1u {
        let lo = codemap::lookup_char_pos(cm, sp.lo);
        let mut digits = 0u;
        let mut num = (lines.lines[0] + 1u) / 10u;

        // how many digits must be indent past?
        while num > 0u { num /= 10u; digits += 1u; }

        // indent past |name:## | and the 0-offset column location
        let mut left = str::len(fm.name) + digits + lo.col + 3u;
        let mut s = "";
        while left > 0u { str::push_char(s, ' '); left -= 1u; }

        s += "^";
        let hi = codemap::lookup_char_pos(cm, sp.hi);
        if hi.col != lo.col {
            // the ^ already takes up one space
            let mut width = hi.col - lo.col - 1u;
            while width > 0u { str::push_char(s, '~'); width -= 1u; }
        }
        io::stderr().write_str(s + "\n");
    }
}

fn print_macro_backtrace(cm: codemap::codemap, sp: span) {
    option::iter (sp.expn_info) {|ei|
        let ss = option::map_default(ei.callie.span, "",
                               bind codemap::span_to_str(_, cm));
        print_diagnostic(ss, note,
                         #fmt("in expansion of #%s", ei.callie.name));
        let ss = codemap::span_to_str(ei.call_site, cm);
        print_diagnostic(ss, note, "expansion site");
        print_macro_backtrace(cm, ei.call_site);
    }
}
<commit_msg>syntax: Cleanup in diagnostic<commit_after>import std::term;
import io::writer_util;
import codemap::span;

export emitter, emit;
export level, fatal, error, warning, note;
export span_handler, handler, mk_span_handler, mk_handler;
export codemap_span_handler, codemap_handler;
export ice_msg;

type emitter = fn@(cmsp: option<(codemap::codemap, span)>,
                   msg: str, lvl: level);

iface span_handler {
    fn span_fatal(sp: span, msg: str) -> !;
    fn span_err(sp: span, msg: str);
    fn span_warn(sp: span, msg: str);
    fn span_note(sp: span, msg: str);
    fn span_bug(sp: span, msg: str) -> !;
    fn span_unimpl(sp: span, msg: str) -> !;
    fn handler() -> handler;
}

iface handler {
    fn fatal(msg: str) -> !;
    fn err(msg: str);
    fn bump_err_count();
    fn has_errors() -> bool;
    fn abort_if_errors();
    fn warn(msg: str);
    fn note(msg: str);
    fn bug(msg: str) -> !;
    fn unimpl(msg: str) -> !;
    fn emit(cmsp: option<(codemap::codemap, span)>, msg: str, lvl: level);
}

type handler_t = @{
    mut err_count: uint,
    emit: emitter
};

type codemap_t = @{
    handler: handler,
    cm: codemap::codemap
};

impl codemap_span_handler of span_handler for codemap_t {
    fn span_fatal(sp: span, msg: str) -> ! {
        self.handler.emit(some((self.cm, sp)), msg, fatal);
        fail;
    }
    fn span_err(sp: span, msg: str) {
        self.handler.emit(some((self.cm, sp)), msg, error);
        self.handler.bump_err_count();
    }
    fn span_warn(sp: span, msg: str) {
        self.handler.emit(some((self.cm, sp)), msg, warning);
    }
    fn span_note(sp: span, msg: str) {
        self.handler.emit(some((self.cm, sp)), msg, note);
    }
    fn span_bug(sp: span, msg: str) -> ! {
        self.span_fatal(sp, ice_msg(msg));
    }
    fn span_unimpl(sp: span, msg: str) -> ! {
        self.span_bug(sp, "unimplemented " + msg);
    }
    fn handler() -> handler {
        self.handler
    }
}

impl codemap_handler of handler for handler_t {
    fn fatal(msg: str) -> ! {
        self.emit(none, msg, fatal);
        fail;
    }
    fn err(msg: str) {
        self.emit(none, msg, error);
        self.bump_err_count();
    }
    fn bump_err_count() {
        self.err_count += 1u;
    }
    fn has_errors() -> bool { self.err_count > 0u }
    fn abort_if_errors() {
        if self.err_count > 0u {
            self.fatal("aborting due to previous errors");
        }
    }
    fn warn(msg: str) {
        self.emit(none, msg, warning);
    }
    fn note(msg: str) {
        self.emit(none, msg, note);
    }
    fn bug(msg: str) -> ! {
        self.fatal(ice_msg(msg));
    }
    fn unimpl(msg: str) -> ! { self.bug("unimplemented " + msg); }
    fn emit(cmsp: option<(codemap::codemap, span)>, msg: str, lvl: level) {
        self.emit(cmsp, msg, lvl);
    }
}

fn ice_msg(msg: str) -> str {
    #fmt["internal compiler error %s", msg]
}

fn mk_span_handler(handler: handler, cm: codemap::codemap) -> span_handler {
    @{ handler: handler, cm: cm } as span_handler
}

fn mk_handler(emitter: option<emitter>) -> handler {

    let emit = alt emitter {
      some(e) { e }
      none {
        let f = fn@(cmsp: option<(codemap::codemap, span)>,
            msg: str, t: level) {
            emit(cmsp, msg, t);
        };
        f
      }
    };

    @{
        mut err_count: 0u,
        emit: emit
    } as handler
}

enum level {
    fatal,
    error,
    warning,
    note,
}

fn diagnosticstr(lvl: level) -> str {
    alt lvl {
      fatal { "error" }
      error { "error" }
      warning { "warning" }
      note { "note" }
    }
}

fn diagnosticcolor(lvl: level) -> u8 {
    alt lvl {
      fatal { term::color_bright_red }
      error { term::color_bright_red }
      warning { term::color_bright_yellow }
      note { term::color_bright_green }
    }
}

fn print_diagnostic(topic: str, lvl: level, msg: str) {
    if str::is_not_empty(topic) {
        io::stderr().write_str(#fmt["%s ", topic]);
    }
    if term::color_supported() {
        term::fg(io::stderr(), diagnosticcolor(lvl));
    }
    io::stderr().write_str(#fmt["%s:", diagnosticstr(lvl)]);
    if term::color_supported() {
        term::reset(io::stderr());
    }
    io::stderr().write_str(#fmt[" %s\n", msg]);
}

fn emit(cmsp: option<(codemap::codemap, span)>,
        msg: str, lvl: level) {
    alt cmsp {
      some((cm, sp)) {
        let sp = codemap::adjust_span(cm,sp);
        let ss = codemap::span_to_str(sp, cm);
        let lines = codemap::span_to_lines(sp, cm);
        print_diagnostic(ss, lvl, msg);
        highlight_lines(cm, sp, lines);
        print_macro_backtrace(cm, sp);
      }
      none {
        print_diagnostic("", lvl, msg);
      }
    }
}

fn highlight_lines(cm: codemap::codemap, sp: span,
                   lines: @codemap::file_lines) {

    let fm = lines.file;

    // arbitrarily only print up to six lines of the error
    let max_lines = 6u;
    let mut elided = false;
    let mut display_lines = lines.lines;
    if vec::len(display_lines) > max_lines {
        display_lines = vec::slice(display_lines, 0u, max_lines);
        elided = true;
    }
    // Print the offending lines
    for display_lines.each {|line|
        io::stderr().write_str(#fmt["%s:%u ", fm.name, line + 1u]);
        let s = codemap::get_line(fm, line as int) + "\n";
        io::stderr().write_str(s);
    }
    if elided {
        let last_line = display_lines[vec::len(display_lines) - 1u];
        let s = #fmt["%s:%u ", fm.name, last_line + 1u];
        let mut indent = str::len(s);
        let mut out = "";
        while indent > 0u { out += " "; indent -= 1u; }
        out += "...\n";
        io::stderr().write_str(out);
    }

    // If there's one line at fault we can easily point to the problem
    if vec::len(lines.lines) == 1u {
        let lo = codemap::lookup_char_pos(cm, sp.lo);
        let mut digits = 0u;
        let mut num = (lines.lines[0] + 1u) / 10u;

        // how many digits must be indent past?
        while num > 0u { num /= 10u; digits += 1u; }

        // indent past |name:## | and the 0-offset column location
        let mut left = str::len(fm.name) + digits + lo.col + 3u;
        let mut s = "";
        while left > 0u { str::push_char(s, ' '); left -= 1u; }

        s += "^";
        let hi = codemap::lookup_char_pos(cm, sp.hi);
        if hi.col != lo.col {
            // the ^ already takes up one space
            let mut width = hi.col - lo.col - 1u;
            while width > 0u { str::push_char(s, '~'); width -= 1u; }
        }
        io::stderr().write_str(s + "\n");
    }
}

fn print_macro_backtrace(cm: codemap::codemap, sp: span) {
    option::iter (sp.expn_info) {|ei|
        let ss = option::map_default(ei.callie.span, "",
                               bind codemap::span_to_str(_, cm));
        print_diagnostic(ss, note,
                         #fmt("in expansion of #%s", ei.callie.name));
        let ss = codemap::span_to_str(ei.call_site, cm);
        print_diagnostic(ss, note, "expansion site");
        print_macro_backtrace(cm, ei.call_site);
    }
}
<|endoftext|>


<commit_before>/// Maximum order of the fixed predictors permitted by the format.
pub const MAX_FIXED_ORDER: usize = 4;

/// Maximum LPC order permitted by the format.
pub const MAX_LPC_ORDER: usize   = 32;

/// A single channel of audio data.
pub struct SubFrame {
  /// Data containing one of the four different types of subframes.
  pub data: Data,
  /// Number of wasted bits within each sample.
  pub wasted_bits: u32,
}

/// General enum that holds all the different subframe data types.
#[derive(Debug, PartialEq, Eq)]
pub enum Data {
  /// A single value that represents a constant subframe.
  Constant(i32),
  /// An uncompressed subframe.
  Verbatim(Vec<i32>),
  /// Fixed linear prediction subframe.
  Fixed(Fixed),
  /// FIR linear prediction subframe.
  LPC(LPC),
}

/// Fixed linear prediction subframe.
#[derive(Debug, PartialEq, Eq)]
pub struct Fixed {
  /// Residual coding method.
  pub entropy_coding_method: EntropyCodingMethod,
  /// Polynomial order.
  pub order: u8,
  /// Samples used to warm up, or prime, the predictor.
  pub warmup: [i32; MAX_FIXED_ORDER],
  /// Remaining samples after the warm up samples.
  pub residual: Vec<i32>,
}

/// Finite Impulse Response (FIR) linear prediction subframe.
#[derive(Debug, PartialEq, Eq)]
pub struct LPC {
  /// Residual coding method.
  pub entropy_coding_method: EntropyCodingMethod,
  /// FIR order.
  pub order: u8,
  /// Quantized FIR filter coefficient precision in bits.
  pub qlp_coeff_precision: u8,
  /// Quantized linear predictor coefficient shift needed in bits.
  pub quantization_level: i8,
  /// FIR filter coefficients.
  pub qlp_coefficients: [i32; MAX_LPC_ORDER],
  /// Samples used to warm up, or prime, the predictor.
  pub warmup: [i32; MAX_LPC_ORDER],
  /// Remaining samples after the warm up samples.
  pub residual: Vec<i32>,
}

/// Header for the entropy coding method.
#[derive(Debug, PartialEq, Eq)]
pub struct EntropyCodingMethod {
  pub method_type: CodingMethod,
  pub data: PartitionedRice,
}

/// The available entropy coding methods.
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum CodingMethod {
  PartitionedRice,
  PartitionedRice2,
}

/// Header for a Rice partitioned residual.
#[derive(Debug, PartialEq, Eq)]
pub struct PartitionedRice {
  pub order: u32,
  pub contents: PartitionedRiceContents,
}

/// Contents of a Rice partitioned residual.
#[derive(Debug, PartialEq, Eq)]
pub struct PartitionedRiceContents {
  pub parameters: Vec<u32>,
  pub raw_bits: Vec<u32>,
}

impl PartitionedRiceContents {
  pub fn new(capacity: usize) -> PartitionedRiceContents {
    let mut parameters = Vec::with_capacity(capacity);
    let mut raw_bits   = Vec::with_capacity(capacity);

    unsafe {
      parameters.set_len(capacity);
      raw_bits.set_len(capacity);
    }

    PartitionedRiceContents {
      parameters: parameters,
      raw_bits: raw_bits,
    }
  }
}
<commit_msg>Add field documentation for `EntropyCodingMethod`<commit_after>/// Maximum order of the fixed predictors permitted by the format.
pub const MAX_FIXED_ORDER: usize = 4;

/// Maximum LPC order permitted by the format.
pub const MAX_LPC_ORDER: usize   = 32;

/// A single channel of audio data.
pub struct SubFrame {
  /// Data containing one of the four different types of subframes.
  pub data: Data,
  /// Number of wasted bits within each sample.
  pub wasted_bits: u32,
}

/// General enum that holds all the different subframe data types.
#[derive(Debug, PartialEq, Eq)]
pub enum Data {
  /// A single value that represents a constant subframe.
  Constant(i32),
  /// An uncompressed subframe.
  Verbatim(Vec<i32>),
  /// Fixed linear prediction subframe.
  Fixed(Fixed),
  /// FIR linear prediction subframe.
  LPC(LPC),
}

/// Fixed linear prediction subframe.
#[derive(Debug, PartialEq, Eq)]
pub struct Fixed {
  /// Residual coding method.
  pub entropy_coding_method: EntropyCodingMethod,
  /// Polynomial order.
  pub order: u8,
  /// Samples used to warm up, or prime, the predictor.
  pub warmup: [i32; MAX_FIXED_ORDER],
  /// Remaining samples after the warm up samples.
  pub residual: Vec<i32>,
}

/// Finite Impulse Response (FIR) linear prediction subframe.
#[derive(Debug, PartialEq, Eq)]
pub struct LPC {
  /// Residual coding method.
  pub entropy_coding_method: EntropyCodingMethod,
  /// FIR order.
  pub order: u8,
  /// Quantized FIR filter coefficient precision in bits.
  pub qlp_coeff_precision: u8,
  /// Quantized linear predictor coefficient shift needed in bits.
  pub quantization_level: i8,
  /// FIR filter coefficients.
  pub qlp_coefficients: [i32; MAX_LPC_ORDER],
  /// Samples used to warm up, or prime, the predictor.
  pub warmup: [i32; MAX_LPC_ORDER],
  /// Remaining samples after the warm up samples.
  pub residual: Vec<i32>,
}

/// Header for the entropy coding method.
#[derive(Debug, PartialEq, Eq)]
pub struct EntropyCodingMethod {
  /// The type of coding method being used.
  pub method_type: CodingMethod,
  /// Data for each entropy coding method partition.
  pub data: PartitionedRice,
}

/// The available entropy coding methods.
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum CodingMethod {
  PartitionedRice,
  PartitionedRice2,
}

/// Header for a Rice partitioned residual.
#[derive(Debug, PartialEq, Eq)]
pub struct PartitionedRice {
  pub order: u32,
  pub contents: PartitionedRiceContents,
}

/// Contents of a Rice partitioned residual.
#[derive(Debug, PartialEq, Eq)]
pub struct PartitionedRiceContents {
  pub parameters: Vec<u32>,
  pub raw_bits: Vec<u32>,
}

impl PartitionedRiceContents {
  pub fn new(capacity: usize) -> PartitionedRiceContents {
    let mut parameters = Vec::with_capacity(capacity);
    let mut raw_bits   = Vec::with_capacity(capacity);

    unsafe {
      parameters.set_len(capacity);
      raw_bits.set_len(capacity);
    }

    PartitionedRiceContents {
      parameters: parameters,
      raw_bits: raw_bits,
    }
  }
}
<|endoftext|>


<commit_before>
/// Settings for window behavior.
pub struct GameWindowSettings {
    /// Title of the window.
    pub title: String,
    /// The size of the window
    pub size: [u32, ..2],
    /// If true, the window is fullscreen.
    pub full_screen: bool,
    /// If true, exit when pressing Esc.
    pub exit_on_esc: bool,
}

impl GameWindowSettings {
    /// Gets default settings.
    ///
    /// This exits the window when pressing `Esc`.
    /// The background color is set to black.
    pub fn default() -> GameWindowSettings {
        GameWindowSettings {
            title: "Piston".to_string(),
            size: [640, 480],
            full_screen: false,
            exit_on_esc: true,
        }
    }
}

<commit_msg>Changed back to `fullscreen`<commit_after>
/// Settings for window behavior.
pub struct GameWindowSettings {
    /// Title of the window.
    pub title: String,
    /// The size of the window
    pub size: [u32, ..2],
    /// If true, the window is fullscreen.
    pub fullscreen: bool,
    /// If true, exit when pressing Esc.
    pub exit_on_esc: bool,
}

impl GameWindowSettings {
    /// Gets default settings.
    ///
    /// This exits the window when pressing `Esc`.
    /// The background color is set to black.
    pub fn default() -> GameWindowSettings {
        GameWindowSettings {
            title: "Piston".to_string(),
            size: [640, 480],
            fullscreen: false,
            exit_on_esc: true,
        }
    }
}

<|endoftext|>


<commit_before>use std::io::{File, Reader, BufferedReader};

pub struct Buffer {
    pub file_path: Option<Path>,
    pub lines: Vec<Line>,
}

impl Buffer {
    /// Create a new buffer instance
    pub fn new() -> Buffer {
        Buffer {
            file_path: None,
            lines: Vec::new(),
        }
    }

    /// Create a new buffer with a single line
    pub fn new_empty() -> Buffer {
        let mut buffer = Buffer::new();
        buffer.lines.push(Line::new(String::new(), 0));

        buffer
    }

    fn lines_from_reader<R: Reader>(reader: &mut BufferedReader<R>) -> Vec<Line> {
        let mut v = vec![];
        // for every line in the reader we add a corresponding line to the buffer
        for (index, line) in reader.lines().enumerate() {
            let mut data = line.unwrap();
            let last_index = data.len() - 1;
            if data.is_char_boundary(last_index) && data.char_at(last_index) == '\n' {
                data.pop();
            }
            v.push(Line::new(data.trim_right_chars('\n').into_string(), index));
        }
        v
    }

    pub fn new_from_reader<R: Reader>(reader: R) -> Buffer {
        let mut r = BufferedReader::new(reader);
        Buffer {
            lines: Buffer::lines_from_reader(&mut r),
            file_path: None
        }
    }

    /// Create a new buffer instance and load the given file
    pub fn new_from_file(path: Path) -> Buffer {
        let mut buffer = Buffer::new();

        if let Ok(file) = File::open(&path) {
            buffer.lines = Buffer::lines_from_reader(&mut BufferedReader::new(file));
        } else {
            buffer.lines.push(Line::new(String::new(), 0));
        }

        buffer.file_path = Some(path);
        buffer
    }

    pub fn get_status_text(&self) -> String {
        match self.file_path {
            Some(ref path) => format!("{}, lines: {}", path.display(), self.lines.len()),
            None => format!("untitled, lines: {}", self.lines.len())
        }
    }

    fn fix_linenums(&mut self) {
        for (index, line) in self.lines.iter_mut().enumerate() {
            line.linenum = index;
        }
    }

    pub fn insert_line(&mut self, offset: uint, mut line_num: uint) {
        // split the current line at the cursor position
        let (_, new_data) = self.split_line(offset, line_num);
        {
            // truncate the current line
            let line = self.get_line_at_mut(line_num);
            line.unwrap().data.truncate(offset);
        }

        line_num += 1;

        self.lines.insert(line_num, Line::new(new_data, line_num));

        self.fix_linenums();
    }

    /// Join the line identified by `line_num` with the one at `line_num - 1 `.
    pub fn join_line_with_previous(&mut self, offset: uint, line_num: uint) -> uint {
        // if the line_num is 0 (ie the first line), don't do anything
        if line_num == 0 { return offset }

        let mut current_line_data: String;
        {
            let current_line = match self.get_line_at(line_num) {
                Some(line) => line,
                None => return offset,
            };
            current_line_data = current_line.data.clone();
        }

        // update the previous line
        let new_cursor_offset = match self.get_line_at_mut(line_num -1) {
            None => offset,
            Some(line) => {
                let line_len = line.data.len();
                line.data.push_str(&*current_line_data);
                line_len
            }
        };

        self.lines.remove(line_num);
        self.fix_linenums();

        return new_cursor_offset
    }

    /// Split the line identified by `line_num` at `offset`
    fn split_line(&mut self, offset: uint, line_num: uint) -> (String, String) {
        let line = self.get_line_at(line_num).unwrap();

        let data = line.data.clone();
        let old_data = data.slice_to(offset);
        let new_data = data.slice_from(offset);

        let mut new = String::new(); new.push_str(new_data);
        let mut old = String::new(); old.push_str(old_data);

        return (old, new)
    }

    fn get_line_at(&self, line_num: uint) -> Option<&Line> {
        let num_lines = self.lines.len() -1;
        if line_num > num_lines { return None }
        Some(&self.lines[line_num])
    }

    fn get_line_at_mut(&mut self, line_num: uint) -> Option<&mut Line> {
        let num_lines = self.lines.len() -1;
        if line_num > num_lines { return None }
        Some(&mut self.lines[line_num])
    }

}

pub struct Line {
    pub data: String,
    pub linenum: uint,
}

impl Line {
    /// Create a new line instance
    pub fn new(data: String, line_num: uint) -> Line {
        Line{
            data: data,
            linenum: line_num,
        }
    }

    /// Get the length of the current line
    pub fn len(&self) -> uint {
        self.data.len()
    }
}

#[cfg(test)]
mod tests {

    use buffer::Buffer;
    use buffer::Line;
    use utils::data_from_str;

    fn setup_buffer() -> Buffer {
        let mut buffer = Buffer::new();
        buffer.file_path = Some(Path::new("/some/file.txt"));
        buffer.lines = vec!(
            Line::new(data_from_str("test"), 0),
            Line::new(String::new(), 1),
            Line::new(data_from_str("text file"), 2),
            Line::new(data_from_str("content"), 3),
        );
        buffer
    }

    #[test]
    fn test_get_status_text() {
        let buffer = setup_buffer();
        assert_eq!(buffer.get_status_text(), "/some/file.txt, lines: 4".to_string())
    }

    #[test]
    fn test_insert_line() {
        let mut buffer = setup_buffer();
        buffer.insert_line(0, 0);
        assert_eq!(buffer.lines.len(), 5);
    }

    #[test]
    fn test_insert_line_in_middle_of_other_line() {
        let mut buffer = setup_buffer();
        buffer.insert_line(1, 0);
        assert_eq!(buffer.lines.len(), 5);

        let ref line = buffer.lines[1];
        assert_eq!(line.data, data_from_str("est"));
    }

    #[test]
    fn test_line_numbers_are_fixed_after_adding_new_line() {
        let mut buffer = setup_buffer();
        buffer.insert_line(1, 2);
        assert_eq!(buffer.lines.len(), 5);

        // check that all linenums are sequential
        for (index, line) in buffer.lines.iter().enumerate() {
            assert_eq!(index, line.linenum);
        }
    }

    #[test]
    fn test_join_line_with_previous() {
        let mut buffer = setup_buffer();

        let offset = buffer.join_line_with_previous(0, 3);

        assert_eq!(buffer.lines.len(), 3);
        assert_eq!(buffer.lines[2].data, data_from_str("text filecontent"));
        assert_eq!(offset, 9);
    }

    #[test]
    fn join_line_with_previous_does_nothing_on_line_zero_offset_zero() {
        let mut buffer = setup_buffer();
        buffer.join_line_with_previous(0, 0);

        assert_eq!(buffer.lines.len(), 4);
        assert_eq!(buffer.lines[0].data, data_from_str("test"));
    }

    #[test]
    fn test_split_line() {
        let mut buffer = setup_buffer();
        let (old, new) = buffer.split_line(3, 3);

        assert_eq!(old, data_from_str("con"));
        assert_eq!(new, data_from_str("tent"));
    }

    #[test]
    fn joining_line_with_non_existant_next_line_does_nothing() {
        let mut buffer = setup_buffer();
        buffer.lines = vec!(Line::new(String::new(), 0));
        buffer.join_line_with_previous(0, 1);
    }

}

<commit_msg>Dont use clone when splitting a line<commit_after>use std::io::{File, Reader, BufferedReader};

pub struct Buffer {
    pub file_path: Option<Path>,
    pub lines: Vec<Line>,
}

impl Buffer {
    /// Create a new buffer instance
    pub fn new() -> Buffer {
        Buffer {
            file_path: None,
            lines: Vec::new(),
        }
    }

    /// Create a new buffer with a single line
    pub fn new_empty() -> Buffer {
        let mut buffer = Buffer::new();
        buffer.lines.push(Line::new(String::new(), 0));

        buffer
    }

    fn lines_from_reader<R: Reader>(reader: &mut BufferedReader<R>) -> Vec<Line> {
        let mut v = vec![];
        // for every line in the reader we add a corresponding line to the buffer
        for (index, line) in reader.lines().enumerate() {
            let mut data = line.unwrap();
            let last_index = data.len() - 1;
            if data.is_char_boundary(last_index) && data.char_at(last_index) == '\n' {
                data.pop();
            }
            v.push(Line::new(data.trim_right_chars('\n').into_string(), index));
        }
        v
    }

    pub fn new_from_reader<R: Reader>(reader: R) -> Buffer {
        let mut r = BufferedReader::new(reader);
        Buffer {
            lines: Buffer::lines_from_reader(&mut r),
            file_path: None
        }
    }

    /// Create a new buffer instance and load the given file
    pub fn new_from_file(path: Path) -> Buffer {
        let mut buffer = Buffer::new();

        if let Ok(file) = File::open(&path) {
            buffer.lines = Buffer::lines_from_reader(&mut BufferedReader::new(file));
        } else {
            buffer.lines.push(Line::new(String::new(), 0));
        }

        buffer.file_path = Some(path);
        buffer
    }

    pub fn get_status_text(&self) -> String {
        match self.file_path {
            Some(ref path) => format!("{}, lines: {}", path.display(), self.lines.len()),
            None => format!("untitled, lines: {}", self.lines.len())
        }
    }

    fn fix_linenums(&mut self) {
        for (index, line) in self.lines.iter_mut().enumerate() {
            line.linenum = index;
        }
    }

    pub fn insert_line(&mut self, offset: uint, mut line_num: uint) {
        // split the current line at the cursor position
        let (_, new_data) = self.split_line(offset, line_num);
        {
            // truncate the current line
            let line = self.get_line_at_mut(line_num);
            line.unwrap().data.truncate(offset);
        }

        line_num += 1;

        self.lines.insert(line_num, Line::new(new_data, line_num));

        self.fix_linenums();
    }

    /// Join the line identified by `line_num` with the one at `line_num - 1 `.
    pub fn join_line_with_previous(&mut self, offset: uint, line_num: uint) -> uint {
        // if the line_num is 0 (ie the first line), don't do anything
        if line_num == 0 { return offset }

        let mut current_line_data: String;
        {
            let current_line = match self.get_line_at(line_num) {
                Some(line) => line,
                None => return offset,
            };
            current_line_data = current_line.data.clone();
        }

        // update the previous line
        let new_cursor_offset = match self.get_line_at_mut(line_num -1) {
            None => offset,
            Some(line) => {
                let line_len = line.data.len();
                line.data.push_str(&*current_line_data);
                line_len
            }
        };

        self.lines.remove(line_num);
        self.fix_linenums();

        return new_cursor_offset
    }

    /// Split the line identified by `line_num` at `offset`
    fn split_line(&mut self, offset: uint, line_num: uint) -> (String, String) {
        let line = self.get_line_at(line_num).unwrap();

        let data = &line.data;
        let old_data = data.slice_to(offset);
        let new_data = data.slice_from(offset);

        let mut new = String::new(); new.push_str(new_data);
        let mut old = String::new(); old.push_str(old_data);

        return (old, new)
    }

    fn get_line_at(&self, line_num: uint) -> Option<&Line> {
        let num_lines = self.lines.len() -1;
        if line_num > num_lines { return None }
        Some(&self.lines[line_num])
    }

    fn get_line_at_mut(&mut self, line_num: uint) -> Option<&mut Line> {
        let num_lines = self.lines.len() -1;
        if line_num > num_lines { return None }
        Some(&mut self.lines[line_num])
    }

}

pub struct Line {
    pub data: String,
    pub linenum: uint,
}

impl Line {
    /// Create a new line instance
    pub fn new(data: String, line_num: uint) -> Line {
        Line{
            data: data,
            linenum: line_num,
        }
    }

    /// Get the length of the current line
    pub fn len(&self) -> uint {
        self.data.len()
    }
}

#[cfg(test)]
mod tests {

    use buffer::Buffer;
    use buffer::Line;
    use utils::data_from_str;

    fn setup_buffer() -> Buffer {
        let mut buffer = Buffer::new();
        buffer.file_path = Some(Path::new("/some/file.txt"));
        buffer.lines = vec!(
            Line::new(data_from_str("test"), 0),
            Line::new(String::new(), 1),
            Line::new(data_from_str("text file"), 2),
            Line::new(data_from_str("content"), 3),
        );
        buffer
    }

    #[test]
    fn test_get_status_text() {
        let buffer = setup_buffer();
        assert_eq!(buffer.get_status_text(), "/some/file.txt, lines: 4".to_string())
    }

    #[test]
    fn test_insert_line() {
        let mut buffer = setup_buffer();
        buffer.insert_line(0, 0);
        assert_eq!(buffer.lines.len(), 5);
    }

    #[test]
    fn test_insert_line_in_middle_of_other_line() {
        let mut buffer = setup_buffer();
        buffer.insert_line(1, 0);
        assert_eq!(buffer.lines.len(), 5);

        let ref line = buffer.lines[1];
        assert_eq!(line.data, data_from_str("est"));
    }

    #[test]
    fn test_line_numbers_are_fixed_after_adding_new_line() {
        let mut buffer = setup_buffer();
        buffer.insert_line(1, 2);
        assert_eq!(buffer.lines.len(), 5);

        // check that all linenums are sequential
        for (index, line) in buffer.lines.iter().enumerate() {
            assert_eq!(index, line.linenum);
        }
    }

    #[test]
    fn test_join_line_with_previous() {
        let mut buffer = setup_buffer();

        let offset = buffer.join_line_with_previous(0, 3);

        assert_eq!(buffer.lines.len(), 3);
        assert_eq!(buffer.lines[2].data, data_from_str("text filecontent"));
        assert_eq!(offset, 9);
    }

    #[test]
    fn join_line_with_previous_does_nothing_on_line_zero_offset_zero() {
        let mut buffer = setup_buffer();
        buffer.join_line_with_previous(0, 0);

        assert_eq!(buffer.lines.len(), 4);
        assert_eq!(buffer.lines[0].data, data_from_str("test"));
    }

    #[test]
    fn test_split_line() {
        let mut buffer = setup_buffer();
        let (old, new) = buffer.split_line(3, 3);

        assert_eq!(old, data_from_str("con"));
        assert_eq!(new, data_from_str("tent"));
    }

    #[test]
    fn joining_line_with_non_existant_next_line_does_nothing() {
        let mut buffer = setup_buffer();
        buffer.lines = vec!(Line::new(String::new(), 0));
        buffer.join_line_with_previous(0, 1);
    }

}

<|endoftext|>