<commit_before>use crate::cpp_ffi_data::{
    CppFfiArgumentMeaning, CppFfiFunctionKind, CppFfiType, CppFieldAccessorType,
    CppTypeConversionToFfi, QtSlotWrapper,
};
use crate::cpp_function::ReturnValueAllocationPlace;
use crate::cpp_type::CppType;
use itertools::Itertools;
use ritual_common::errors::{bail, Result};
use ritual_common::file_utils::{create_file, path_to_str};
use ritual_common::utils::get_command_output;
use ritual_common::utils::MapIfOk;

use crate::cpp_ffi_data::CppFfiFunction;
use crate::cpp_type::CppPointerLikeTypeKind;
use crate::database::CppFfiItem;
use crate::database::CppFfiItemKind;
use crate::rust_info::RustDatabase;
use crate::rust_info::RustItemKind;
use crate::rust_info::RustStructKind;
use std::io::Write;
use std::iter::once;
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;

/// Generates function name, return type and arguments list
/// as it appears in both function declaration and implementation.
fn function_signature(method: &CppFfiFunction) -> Result<String> {
    let mut arg_texts = Vec::new();
    for arg in &method.arguments {
        arg_texts.push(arg.to_cpp_code()?);
    }
    let name_with_args = format!("{}({})", method.path.to_cpp_code()?, arg_texts.join(", "));
    let return_type = &method.return_type.ffi_type;
    let r = if let CppType::FunctionPointer(..) = return_type {
        return_type.to_cpp_code(Some(&name_with_args))?
    } else {
        format!("{} {}", return_type.to_cpp_code(None)?, name_with_args)
    };
    Ok(r)
}

/// Generates code for a Qt slot wrapper
fn qt_slot_wrapper(wrapper: &QtSlotWrapper) -> Result<String> {
    let func_type = CppType::FunctionPointer(wrapper.function_type.clone());
    let method_args = wrapper
        .arguments
        .iter()
        .enumerate()
        .map_if_ok(|(num, t)| -> Result<_> {
            Ok(format!("{} arg{}", t.original_type.to_cpp_code(None)?, num))
        })?
        .join(", ");
    let func_args = once("m_data".to_string())
        .chain(
            wrapper
                .arguments
                .iter()
                .enumerate()
                .map_if_ok(|(num, t)| convert_type_to_ffi(t, format!("arg{}", num)))?,
        )
        .join(", ");
    Ok(format!(
        include_str!("../templates/c_lib/qt_slot_wrapper.h"),
        class_name = wrapper.class_path.to_cpp_code()?,
        func_arg = func_type.to_cpp_code(Some("func"))?,
        func_field = func_type.to_cpp_code(Some("m_func"))?,
        method_args = method_args,
        func_args = func_args
    ))
}

/// Generates code that wraps `expression` of type `type1.original_type` and
/// converts it to type `type1.ffi_type`
fn convert_type_to_ffi(type1: &CppFfiType, expression: String) -> Result<String> {
    Ok(match type1.conversion {
        CppTypeConversionToFfi::NoChange => expression,
        CppTypeConversionToFfi::ValueToPointer => format!(
            "new {}({})",
            type1.original_type.to_cpp_code(None)?,
            expression
        ),
        CppTypeConversionToFfi::ReferenceToPointer => format!("&{}", expression),
        CppTypeConversionToFfi::QFlagsToInt => format!("int({})", expression),
    })
}

/// Wraps `expression` returned by the original C++ method to
/// convert it to return type of the FFI method.
fn convert_return_type(method: &CppFfiFunction, expression: String) -> Result<String> {
    let mut result = expression;
    match method.return_type.conversion {
        CppTypeConversionToFfi::NoChange => {}
        CppTypeConversionToFfi::ValueToPointer => {
            match method.allocation_place {
                ReturnValueAllocationPlace::Stack => {
                    bail!("stack allocated wrappers are expected to return void");
                }
                ReturnValueAllocationPlace::NotApplicable => {
                    bail!("ValueToPointer conflicts with NotApplicable");
                }
                ReturnValueAllocationPlace::Heap => {
                    // constructors are said to return values in parse result,
                    // but in reality we use `new` which returns a pointer,
                    // so no conversion is necessary for constructors.
                    if !method
                        .kind
                        .cpp_function()
                        .map(|m| m.is_constructor())
                        .unwrap_or(false)
                    {
                        result = format!(
                            "new {}({})",
                            method.return_type.original_type.to_cpp_code(None)?,
                            result
                        );
                    }
                }
            }
        }
        CppTypeConversionToFfi::ReferenceToPointer => {
            result = format!("&{}", result);
        }
        CppTypeConversionToFfi::QFlagsToInt => {
            result = format!("int({})", result);
        }
    }

    if method.allocation_place == ReturnValueAllocationPlace::Stack
        && !method
            .kind
            .cpp_function()
            .map(|m| m.is_constructor())
            .unwrap_or(false)
    {
        if let Some(arg) = method
            .arguments
            .iter()
            .find(|x| x.meaning == CppFfiArgumentMeaning::ReturnValue)
        {
            let type1 = arg.argument_type.ffi_type.pointer_like_to_target()?;
            result = format!("new({}) {}({})", arg.name, type1.to_cpp_code(None)?, result);
        }
    }
    Ok(result)
}

/// Generates code for values passed to the original C++ method.
fn arguments_values(method: &CppFfiFunction) -> Result<String> {
    let r = method
        .arguments
        .iter()
        .filter(|arg| arg.meaning.is_argument())
        .map_if_ok(|argument| -> Result<_> {
            let mut result = argument.name.clone();
            match argument.argument_type.conversion {
                CppTypeConversionToFfi::ValueToPointer
                | CppTypeConversionToFfi::ReferenceToPointer => result = format!("*{}", result),
                CppTypeConversionToFfi::NoChange => {}
                CppTypeConversionToFfi::QFlagsToInt => {
                    let type_text = if let CppType::PointerLike {
                        kind,
                        is_const,
                        target,
                    } = &argument.argument_type.original_type
                    {
                        if *kind == CppPointerLikeTypeKind::Reference && *is_const {
                            target.to_cpp_code(None)?
                        } else {
                            bail!("Unsupported original type for QFlagsToUInt conversion");
                        }
                    } else {
                        argument.argument_type.original_type.to_cpp_code(None)?
                    };
                    result = format!("{}({})", type_text, result);
                }
            }
            Ok(result)
        })?;
    Ok(r.join(", "))
}

/// Generates code for the value returned by the FFI method.
#[allow(clippy::collapsible_if)]
fn returned_expression(method: &CppFfiFunction) -> Result<String> {
    let result = if method
        .kind
        .cpp_function()
        .map(|m| m.is_destructor())
        .unwrap_or(false)
    {
        if let Some(arg) = method
            .arguments
            .iter()
            .find(|x| x.meaning == CppFfiArgumentMeaning::This)
        {
            format!("c2r_call_destructor({})", arg.name)
        } else {
            bail!("no this arg in destructor");
        }
    } else {
        let result_without_args =
            if let Some(cpp_function) = method.kind.cpp_function().filter(|m| m.is_constructor()) {
                match method.allocation_place {
                    ReturnValueAllocationPlace::Stack => {
                        if let Some(arg) = method
                            .arguments
                            .iter()
                            .find(|x| x.meaning == CppFfiArgumentMeaning::ReturnValue)
                        {
                            format!(
                                "new({}) {}",
                                arg.name,
                                cpp_function.class_type()?.to_cpp_code()?
                            )
                        } else {
                            bail!("return value argument not found\n{:?}", method);
                        }
                    }
                    ReturnValueAllocationPlace::Heap => {
                        format!("new {}", cpp_function.class_type()?.to_cpp_code()?)
                    }
                    ReturnValueAllocationPlace::NotApplicable => {
                        bail!("NotApplicable in constructor");
                    }
                }
            } else {
                let path = match &method.kind {
                    CppFfiFunctionKind::Function { cpp_function, .. } => &cpp_function.path,
                    CppFfiFunctionKind::FieldAccessor { field, .. } => &field.path,
                };

                if let Some(arg) = method
                    .arguments
                    .iter()
                    .find(|x| x.meaning == CppFfiArgumentMeaning::This)
                {
                    format!("{}->{}", arg.name, path.last().to_cpp_code()?)
                } else {
                    path.to_cpp_code()?
                }
            };
        if let CppFfiFunctionKind::FieldAccessor { accessor_type, .. } = &method.kind {
            if accessor_type == &CppFieldAccessorType::Setter {
                format!("{} = {}", result_without_args, arguments_values(method)?)
            } else {
                result_without_args
            }
        } else {
            format!("{}({})", result_without_args, arguments_values(method)?)
        }
    };
    convert_return_type(method, result)
}

/// Generates body of the FFI method implementation.
fn source_body(method: &CppFfiFunction) -> Result<String> {
    if method
        .kind
        .cpp_function()
        .map(|m| m.is_destructor())
        .unwrap_or(false)
        && method.allocation_place == ReturnValueAllocationPlace::Heap
    {
        if let Some(arg) = method
            .arguments
            .iter()
            .find(|x| x.meaning == CppFfiArgumentMeaning::This)
        {
            Ok(format!("delete {};\n", arg.name))
        } else {
            panic!("Error: no this argument found\n{:?}", method);
        }
    } else {
        Ok(format!(
            "{}{};\n",
            if method.return_type.ffi_type.is_void() {
                ""
            } else {
                "return "
            },
            returned_expression(&method)?
        ))
    }
}

/// Generates implementation of the FFI method for the source file.
pub fn function_implementation(method: &CppFfiFunction) -> Result<String> {
    Ok(format!(
        "C2R_EXPORT {} {{\n  {}}}\n\n",
        function_signature(method)?,
        source_body(&method)?
    ))
}

/// Generates a source file with the specified FFI methods.
pub fn generate_cpp_file(
    ffi_items: &[CppFfiItem],
    file_path: &Path,
    global_header_name: &str,
) -> Result<()> {
    let mut cpp_file = create_file(file_path)?;
    writeln!(cpp_file, "#include \"{}\"", global_header_name)?;

    let mut any_slot_wrappers = false;
    for ffi_item in ffi_items {
        if !ffi_item.checks.any_passed() {
            continue;
        }
        if let CppFfiItemKind::QtSlotWrapper(qt_slot_wrapper) = &ffi_item.kind {
            any_slot_wrappers = true;
            write!(cpp_file, "{}", self::qt_slot_wrapper(qt_slot_wrapper)?)?;
        }
    }

    writeln!(cpp_file, "extern \"C\" {{")?;
    for ffi_item in ffi_items {
        if !ffi_item.checks.any_passed() {
            continue;
        }
        if let CppFfiItemKind::Function(cpp_ffi_function) = &ffi_item.kind {
            writeln!(cpp_file, "{}", function_implementation(cpp_ffi_function)?)?;
        }
    }
    writeln!(cpp_file, "}} // extern \"C\"")?;

    if any_slot_wrappers {
        let moc_output = get_command_output(Command::new("moc").arg("-i").arg(file_path))?;
        writeln!(
            cpp_file,
            "// start of MOC generated code\n{}\n// end of MOC generated code",
            moc_output
        )?;
    }
    Ok(())
}

/// Generates a C++ program that determines sizes of target C++ types
/// on the current platform and outputs the Rust code for `sized_types.rs` module
/// to the standard output.
pub fn generate_cpp_type_size_requester(
    rust_database: &RustDatabase,
    include_directives: &[PathBuf],
    mut output: impl Write,
) -> Result<()> {
    for dir in include_directives {
        writeln!(output, "#include <{}>", path_to_str(dir)?)?;
    }
    writeln!(output, "#include <stdio.h>\n\nint main() {{")?;

    for item in &rust_database.items {
        if let RustItemKind::Struct(data) = &item.kind {
            if let RustStructKind::SizedType(cpp_path) = &data.kind {
                let cpp_path_code = cpp_path.to_cpp_code()?;

                writeln!(
                    output,
                    "printf(\"#[repr(C, align(%d))]\\n\", alignof({}));",
                    cpp_path_code
                )?;

                writeln!(
                    output,
                    "printf(\"pub struct {}([u8; %d]);\\n\\n\", sizeof({}));",
                    data.path.last(),
                    cpp_path_code
                )?;
            }
        }
    }

    writeln!(output, "}}")?;
    Ok(())
}
<commit_msg>fix printf type in type size requester<commit_after>use crate::cpp_ffi_data::{
    CppFfiArgumentMeaning, CppFfiFunctionKind, CppFfiType, CppFieldAccessorType,
    CppTypeConversionToFfi, QtSlotWrapper,
};
use crate::cpp_function::ReturnValueAllocationPlace;
use crate::cpp_type::CppType;
use itertools::Itertools;
use ritual_common::errors::{bail, Result};
use ritual_common::file_utils::{create_file, path_to_str};
use ritual_common::utils::get_command_output;
use ritual_common::utils::MapIfOk;

use crate::cpp_ffi_data::CppFfiFunction;
use crate::cpp_type::CppPointerLikeTypeKind;
use crate::database::CppFfiItem;
use crate::database::CppFfiItemKind;
use crate::rust_info::RustDatabase;
use crate::rust_info::RustItemKind;
use crate::rust_info::RustStructKind;
use std::io::Write;
use std::iter::once;
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;

/// Generates function name, return type and arguments list
/// as it appears in both function declaration and implementation.
fn function_signature(method: &CppFfiFunction) -> Result<String> {
    let mut arg_texts = Vec::new();
    for arg in &method.arguments {
        arg_texts.push(arg.to_cpp_code()?);
    }
    let name_with_args = format!("{}({})", method.path.to_cpp_code()?, arg_texts.join(", "));
    let return_type = &method.return_type.ffi_type;
    let r = if let CppType::FunctionPointer(..) = return_type {
        return_type.to_cpp_code(Some(&name_with_args))?
    } else {
        format!("{} {}", return_type.to_cpp_code(None)?, name_with_args)
    };
    Ok(r)
}

/// Generates code for a Qt slot wrapper
fn qt_slot_wrapper(wrapper: &QtSlotWrapper) -> Result<String> {
    let func_type = CppType::FunctionPointer(wrapper.function_type.clone());
    let method_args = wrapper
        .arguments
        .iter()
        .enumerate()
        .map_if_ok(|(num, t)| -> Result<_> {
            Ok(format!("{} arg{}", t.original_type.to_cpp_code(None)?, num))
        })?
        .join(", ");
    let func_args = once("m_data".to_string())
        .chain(
            wrapper
                .arguments
                .iter()
                .enumerate()
                .map_if_ok(|(num, t)| convert_type_to_ffi(t, format!("arg{}", num)))?,
        )
        .join(", ");
    Ok(format!(
        include_str!("../templates/c_lib/qt_slot_wrapper.h"),
        class_name = wrapper.class_path.to_cpp_code()?,
        func_arg = func_type.to_cpp_code(Some("func"))?,
        func_field = func_type.to_cpp_code(Some("m_func"))?,
        method_args = method_args,
        func_args = func_args
    ))
}

/// Generates code that wraps `expression` of type `type1.original_type` and
/// converts it to type `type1.ffi_type`
fn convert_type_to_ffi(type1: &CppFfiType, expression: String) -> Result<String> {
    Ok(match type1.conversion {
        CppTypeConversionToFfi::NoChange => expression,
        CppTypeConversionToFfi::ValueToPointer => format!(
            "new {}({})",
            type1.original_type.to_cpp_code(None)?,
            expression
        ),
        CppTypeConversionToFfi::ReferenceToPointer => format!("&{}", expression),
        CppTypeConversionToFfi::QFlagsToInt => format!("int({})", expression),
    })
}

/// Wraps `expression` returned by the original C++ method to
/// convert it to return type of the FFI method.
fn convert_return_type(method: &CppFfiFunction, expression: String) -> Result<String> {
    let mut result = expression;
    match method.return_type.conversion {
        CppTypeConversionToFfi::NoChange => {}
        CppTypeConversionToFfi::ValueToPointer => {
            match method.allocation_place {
                ReturnValueAllocationPlace::Stack => {
                    bail!("stack allocated wrappers are expected to return void");
                }
                ReturnValueAllocationPlace::NotApplicable => {
                    bail!("ValueToPointer conflicts with NotApplicable");
                }
                ReturnValueAllocationPlace::Heap => {
                    // constructors are said to return values in parse result,
                    // but in reality we use `new` which returns a pointer,
                    // so no conversion is necessary for constructors.
                    if !method
                        .kind
                        .cpp_function()
                        .map(|m| m.is_constructor())
                        .unwrap_or(false)
                    {
                        result = format!(
                            "new {}({})",
                            method.return_type.original_type.to_cpp_code(None)?,
                            result
                        );
                    }
                }
            }
        }
        CppTypeConversionToFfi::ReferenceToPointer => {
            result = format!("&{}", result);
        }
        CppTypeConversionToFfi::QFlagsToInt => {
            result = format!("int({})", result);
        }
    }

    if method.allocation_place == ReturnValueAllocationPlace::Stack
        && !method
            .kind
            .cpp_function()
            .map(|m| m.is_constructor())
            .unwrap_or(false)
    {
        if let Some(arg) = method
            .arguments
            .iter()
            .find(|x| x.meaning == CppFfiArgumentMeaning::ReturnValue)
        {
            let type1 = arg.argument_type.ffi_type.pointer_like_to_target()?;
            result = format!("new({}) {}({})", arg.name, type1.to_cpp_code(None)?, result);
        }
    }
    Ok(result)
}

/// Generates code for values passed to the original C++ method.
fn arguments_values(method: &CppFfiFunction) -> Result<String> {
    let r = method
        .arguments
        .iter()
        .filter(|arg| arg.meaning.is_argument())
        .map_if_ok(|argument| -> Result<_> {
            let mut result = argument.name.clone();
            match argument.argument_type.conversion {
                CppTypeConversionToFfi::ValueToPointer
                | CppTypeConversionToFfi::ReferenceToPointer => result = format!("*{}", result),
                CppTypeConversionToFfi::NoChange => {}
                CppTypeConversionToFfi::QFlagsToInt => {
                    let type_text = if let CppType::PointerLike {
                        kind,
                        is_const,
                        target,
                    } = &argument.argument_type.original_type
                    {
                        if *kind == CppPointerLikeTypeKind::Reference && *is_const {
                            target.to_cpp_code(None)?
                        } else {
                            bail!("Unsupported original type for QFlagsToUInt conversion");
                        }
                    } else {
                        argument.argument_type.original_type.to_cpp_code(None)?
                    };
                    result = format!("{}({})", type_text, result);
                }
            }
            Ok(result)
        })?;
    Ok(r.join(", "))
}

/// Generates code for the value returned by the FFI method.
#[allow(clippy::collapsible_if)]
fn returned_expression(method: &CppFfiFunction) -> Result<String> {
    let result = if method
        .kind
        .cpp_function()
        .map(|m| m.is_destructor())
        .unwrap_or(false)
    {
        if let Some(arg) = method
            .arguments
            .iter()
            .find(|x| x.meaning == CppFfiArgumentMeaning::This)
        {
            format!("c2r_call_destructor({})", arg.name)
        } else {
            bail!("no this arg in destructor");
        }
    } else {
        let result_without_args =
            if let Some(cpp_function) = method.kind.cpp_function().filter(|m| m.is_constructor()) {
                match method.allocation_place {
                    ReturnValueAllocationPlace::Stack => {
                        if let Some(arg) = method
                            .arguments
                            .iter()
                            .find(|x| x.meaning == CppFfiArgumentMeaning::ReturnValue)
                        {
                            format!(
                                "new({}) {}",
                                arg.name,
                                cpp_function.class_type()?.to_cpp_code()?
                            )
                        } else {
                            bail!("return value argument not found\n{:?}", method);
                        }
                    }
                    ReturnValueAllocationPlace::Heap => {
                        format!("new {}", cpp_function.class_type()?.to_cpp_code()?)
                    }
                    ReturnValueAllocationPlace::NotApplicable => {
                        bail!("NotApplicable in constructor");
                    }
                }
            } else {
                let path = match &method.kind {
                    CppFfiFunctionKind::Function { cpp_function, .. } => &cpp_function.path,
                    CppFfiFunctionKind::FieldAccessor { field, .. } => &field.path,
                };

                if let Some(arg) = method
                    .arguments
                    .iter()
                    .find(|x| x.meaning == CppFfiArgumentMeaning::This)
                {
                    format!("{}->{}", arg.name, path.last().to_cpp_code()?)
                } else {
                    path.to_cpp_code()?
                }
            };
        if let CppFfiFunctionKind::FieldAccessor { accessor_type, .. } = &method.kind {
            if accessor_type == &CppFieldAccessorType::Setter {
                format!("{} = {}", result_without_args, arguments_values(method)?)
            } else {
                result_without_args
            }
        } else {
            format!("{}({})", result_without_args, arguments_values(method)?)
        }
    };
    convert_return_type(method, result)
}

/// Generates body of the FFI method implementation.
fn source_body(method: &CppFfiFunction) -> Result<String> {
    if method
        .kind
        .cpp_function()
        .map(|m| m.is_destructor())
        .unwrap_or(false)
        && method.allocation_place == ReturnValueAllocationPlace::Heap
    {
        if let Some(arg) = method
            .arguments
            .iter()
            .find(|x| x.meaning == CppFfiArgumentMeaning::This)
        {
            Ok(format!("delete {};\n", arg.name))
        } else {
            panic!("Error: no this argument found\n{:?}", method);
        }
    } else {
        Ok(format!(
            "{}{};\n",
            if method.return_type.ffi_type.is_void() {
                ""
            } else {
                "return "
            },
            returned_expression(&method)?
        ))
    }
}

/// Generates implementation of the FFI method for the source file.
pub fn function_implementation(method: &CppFfiFunction) -> Result<String> {
    Ok(format!(
        "C2R_EXPORT {} {{\n  {}}}\n\n",
        function_signature(method)?,
        source_body(&method)?
    ))
}

/// Generates a source file with the specified FFI methods.
pub fn generate_cpp_file(
    ffi_items: &[CppFfiItem],
    file_path: &Path,
    global_header_name: &str,
) -> Result<()> {
    let mut cpp_file = create_file(file_path)?;
    writeln!(cpp_file, "#include \"{}\"", global_header_name)?;

    let mut any_slot_wrappers = false;
    for ffi_item in ffi_items {
        if !ffi_item.checks.any_passed() {
            continue;
        }
        if let CppFfiItemKind::QtSlotWrapper(qt_slot_wrapper) = &ffi_item.kind {
            any_slot_wrappers = true;
            write!(cpp_file, "{}", self::qt_slot_wrapper(qt_slot_wrapper)?)?;
        }
    }

    writeln!(cpp_file, "extern \"C\" {{")?;
    for ffi_item in ffi_items {
        if !ffi_item.checks.any_passed() {
            continue;
        }
        if let CppFfiItemKind::Function(cpp_ffi_function) = &ffi_item.kind {
            writeln!(cpp_file, "{}", function_implementation(cpp_ffi_function)?)?;
        }
    }
    writeln!(cpp_file, "}} // extern \"C\"")?;

    if any_slot_wrappers {
        let moc_output = get_command_output(Command::new("moc").arg("-i").arg(file_path))?;
        writeln!(
            cpp_file,
            "// start of MOC generated code\n{}\n// end of MOC generated code",
            moc_output
        )?;
    }
    Ok(())
}

/// Generates a C++ program that determines sizes of target C++ types
/// on the current platform and outputs the Rust code for `sized_types.rs` module
/// to the standard output.
pub fn generate_cpp_type_size_requester(
    rust_database: &RustDatabase,
    include_directives: &[PathBuf],
    mut output: impl Write,
) -> Result<()> {
    for dir in include_directives {
        writeln!(output, "#include <{}>", path_to_str(dir)?)?;
    }
    writeln!(output, "#include <stdio.h>\n\nint main() {{")?;

    for item in &rust_database.items {
        if let RustItemKind::Struct(data) = &item.kind {
            if let RustStructKind::SizedType(cpp_path) = &data.kind {
                let cpp_path_code = cpp_path.to_cpp_code()?;

                writeln!(
                    output,
                    "printf(\"#[repr(C, align(%zu))]\\n\", alignof({}));",
                    cpp_path_code
                )?;

                writeln!(
                    output,
                    "printf(\"pub struct {}([u8; %zu]);\\n\\n\", sizeof({}));",
                    data.path.last(),
                    cpp_path_code
                )?;
            }
        }
    }

    writeln!(output, "}}")?;
    Ok(())
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(clippy)]

#![allow(dead_code)]
#![allow(single_match)]
#![allow(unused_variables, similar_names)]
#![deny(blacklisted_name)]

fn test(foo: ()) {}

fn main() {
    let foo = 42;
    let bar = 42;
    let baz = 42;

    let barb = 42;
    let barbaric = 42;

    match (42, Some(1337), Some(0)) {
        (foo, Some(bar), baz @ Some(_)) => (),

        _ => (),
    }
}
<commit_msg>clean tests/ui/blacklisted_name.rs<commit_after>#![feature(plugin)]
#![plugin(clippy)]

#![allow(dead_code)]
#![allow(single_match)]
#![allow(unused_variables, similar_names)]
#![deny(blacklisted_name)]

fn test(foo: ()) {}

fn main() {
    let foo = 42;
    let bar = 42;
    let baz = 42;

    let barb = 42;
    let barbaric = 42;

    match (42, Some(1337), Some(0)) {
        (foo, Some(bar), baz @ Some(_)) => (),
        _ => (),
    }
}
<|endoftext|>


<commit_before>use std::os::raw::c_void;
use std::ptr::null_mut;
use raw::{FunctionCallbackInfo, Env, Local};

use nodejs_sys as napi;

#[repr(C)]
pub struct CCallback {
    pub static_callback: *mut c_void,
    pub dynamic_callback: *mut c_void
}

impl Default for CCallback {
    fn default() -> Self {
        CCallback {
            static_callback: null_mut(),
            dynamic_callback: null_mut()
        }
    }
}

pub unsafe extern "C" fn set_return(_info: FunctionCallbackInfo, _value: Local) {

}

pub unsafe extern "C" fn get_isolate(info: FunctionCallbackInfo) -> Env { unimplemented!() }

// FIXME: Remove. This will never be implemented
pub unsafe extern "C" fn current_isolate() -> Env { panic!("current_isolate won't be implemented in n-api") }

pub unsafe extern "C" fn is_construct(_info: FunctionCallbackInfo) -> bool { unimplemented!() }

pub unsafe extern "C" fn this(env: Env, info: FunctionCallbackInfo, out: &mut Local) {
    let status = napi::napi_get_cb_info(
        env,
        info,
        null_mut(),
        null_mut(),
        out as *mut _,
        null_mut(),
    );
    assert_eq!(status, napi::napi_status::napi_ok);
}

/// Mutates the `out` argument provided to refer to the associated data value of the
/// `napi_callback_info`.
pub unsafe extern "C" fn data(env: Env, info: FunctionCallbackInfo, out: &mut *mut c_void) {
    let mut data = null_mut();
    let mut argc = 0usize;
    let status = napi::napi_get_cb_info(
        env,
        info,
        &mut argc as *mut _,
        null_mut(),
        null_mut(),
        &mut data as *mut _,
    );
    if status == napi::napi_status::napi_ok {
        *out = data;
    }
}

/// Gets the number of arguments passed to the function.
pub unsafe extern "C" fn len(env: Env, info: FunctionCallbackInfo) -> i32 {
    let mut argc = 0usize;
    let status = napi::napi_get_cb_info(
        env,
        info,
        &mut argc as *mut _,
        null_mut(),
        null_mut(),
        null_mut(),
    );
    assert_eq!(status, napi::napi_status::napi_ok);
    argc as i32
}

/// Mutates the `out` argument provided to refer to the `napi_value` of the `i`th argument
/// passed to the function.
pub unsafe extern "C" fn get(env: Env, info: FunctionCallbackInfo, i: i32, out: &mut Local) {
    // TODO make this not allocate
    // Instead, we can probably get all the arguments at once in `neon` itself?
    let mut args = vec![null_mut(); (i + 1) as usize];
    let mut num_args = args.len();

    let status = napi::napi_get_cb_info(
        env,
        info,
        &mut num_args as *mut _,
        args.as_mut_ptr(),
        null_mut(),
        null_mut(),
    );
    assert_eq!(status, napi::napi_status::napi_ok);
    assert!(num_args > i as usize);
    *out = args[i as usize];
}
<commit_msg>Remove unnecessary `argc` value from `neon_runtime::call::data()`.<commit_after>use std::os::raw::c_void;
use std::ptr::null_mut;
use raw::{FunctionCallbackInfo, Env, Local};

use nodejs_sys as napi;

#[repr(C)]
pub struct CCallback {
    pub static_callback: *mut c_void,
    pub dynamic_callback: *mut c_void
}

impl Default for CCallback {
    fn default() -> Self {
        CCallback {
            static_callback: null_mut(),
            dynamic_callback: null_mut()
        }
    }
}

pub unsafe extern "C" fn set_return(_info: FunctionCallbackInfo, _value: Local) {

}

pub unsafe extern "C" fn get_isolate(info: FunctionCallbackInfo) -> Env { unimplemented!() }

// FIXME: Remove. This will never be implemented
pub unsafe extern "C" fn current_isolate() -> Env { panic!("current_isolate won't be implemented in n-api") }

pub unsafe extern "C" fn is_construct(_info: FunctionCallbackInfo) -> bool { unimplemented!() }

pub unsafe extern "C" fn this(env: Env, info: FunctionCallbackInfo, out: &mut Local) {
    let status = napi::napi_get_cb_info(
        env,
        info,
        null_mut(),
        null_mut(),
        out as *mut _,
        null_mut(),
    );
    assert_eq!(status, napi::napi_status::napi_ok);
}

/// Mutates the `out` argument provided to refer to the associated data value of the
/// `napi_callback_info`.
pub unsafe extern "C" fn data(env: Env, info: FunctionCallbackInfo, out: &mut *mut c_void) {
    let mut data = null_mut();
    let status = napi::napi_get_cb_info(
        env,
        info,
        null_mut(),
        null_mut(),
        null_mut(),
        &mut data as *mut _,
    );
    if status == napi::napi_status::napi_ok {
        *out = data;
    }
}

/// Gets the number of arguments passed to the function.
pub unsafe extern "C" fn len(env: Env, info: FunctionCallbackInfo) -> i32 {
    let mut argc = 0usize;
    let status = napi::napi_get_cb_info(
        env,
        info,
        &mut argc as *mut _,
        null_mut(),
        null_mut(),
        null_mut(),
    );
    assert_eq!(status, napi::napi_status::napi_ok);
    argc as i32
}

/// Mutates the `out` argument provided to refer to the `napi_value` of the `i`th argument
/// passed to the function.
pub unsafe extern "C" fn get(env: Env, info: FunctionCallbackInfo, i: i32, out: &mut Local) {
    // TODO make this not allocate
    // Instead, we can probably get all the arguments at once in `neon` itself?
    let mut args = vec![null_mut(); (i + 1) as usize];
    let mut num_args = args.len();

    let status = napi::napi_get_cb_info(
        env,
        info,
        &mut num_args as *mut _,
        args.as_mut_ptr(),
        null_mut(),
        null_mut(),
    );
    assert_eq!(status, napi::napi_status::napi_ok);
    assert!(num_args > i as usize);
    *out = args[i as usize];
}
<|endoftext|>


<commit_before>/// Internal namespace.
pub( crate ) mod private
{
  use former::Former;
  use crate::string::split::*;
  use crate::string::isolate::isolate_right;
  use std::collections::HashMap;

  ///
  /// Wrapper types to make transformation.
  ///

  #[ derive( Debug, Clone, PartialEq ) ]
  pub enum OpType<T>
  {
    /// Wrapper over single element of type <T>.
    Primitive( T ),
    /// Wrapper over vector of elements of type <T>.
    Vector( Vec<T> ),
    /// Wrapper over hash map of elements of type <T>.
    Map( HashMap<String, T> ),
  }

  impl<T : Default> Default for OpType<T>
  {
    fn default() -> Self
    {
      OpType::Primitive( T::default() )
    }
  }

  impl<T> From<T> for OpType<T>
  {
    fn from( value: T ) -> Self
    {
      OpType::Primitive( value )
    }
  }

  impl<T> From<Vec<T>> for OpType<T>
  {
    fn from( value: Vec<T> ) -> Self
    {
      OpType::Vector( value )
    }
  }

  impl<T> Into<Vec<T>> for OpType<T>
  {
    fn into( self ) -> Vec<T>
    {
      match self
      {
        OpType::Vector( vec ) => vec,
        _ => unimplemented!( "not implemented" ),
      }
    }
  }

  impl<T : Clone> OpType<T>
  {
    /// Append item of OpType to current value. If current type is `Primitive`, then it will be converted to
    /// `Vector`.
    pub fn append( mut self, item : OpType<T> ) -> OpType<T>
    {
      let mut mut_item = item;
      match self
      {
        OpType::Primitive( value ) =>
        {
          match mut_item
          {
            OpType::Primitive( ins ) =>
            {
              let vector = vec![ value, ins ];
              OpType::Vector( vector )
            }
            OpType::Vector( ref mut vector ) =>
            {
              vector.insert( 0, value );
              mut_item
            },
            OpType::Map( _ ) => panic!( "Unexpected operation. Please, use method `insert` to insert item in hash map." ),
          }
        },
        OpType::Vector( ref mut vector ) =>
        {
          match mut_item
          {
            OpType::Primitive( ins ) =>
            {
              vector.push( ins );
              self
            }
            OpType::Vector( ref mut ins_vec ) =>
            {
              vector.append( ins_vec );
              self
            },
            OpType::Map( _ ) => panic!( "Unexpected operation. Please, use method `insert` to insert item in hash map." ),
          }
        },
        OpType::Map( _ ) => panic!( "Unexpected operation. Please, use method `insert` to insert item in hash map." ),
      }
    }

    /// Unwrap primitive value. Consumes self.
    pub fn primitive( self ) -> Option<T>
    {
      match self
      {
        OpType::Primitive( v ) => Some( v ),
        _ => None,
      }
    }

    /// Unwrap vector value. Consumes self.
    pub fn vector( self ) -> Option<Vec<T>>
    {
      match self
      {
        OpType::Vector( vec ) => Some( vec ),
        _ => None,
      }
    }
  }

  ///
  /// Parsed request data.
  ///

  #[ allow( dead_code ) ]
  #[ derive( Debug, Default, PartialEq ) ]
  pub struct Request< 'a >
  {
    /// Original request string.
    pub original : &'a str,
    /// Delimeter for pairs `key:value`.
    pub key_val_delimeter : &'a str,
    /// Delimeter for commands.
    pub commands_delimeter : &'a str,
    /// Parsed subject of first command.
    pub subject : String,
    /// All subjects of the commands in request.
    pub subjects : Vec<String>,
    /// Options map of first command.
    pub map : HashMap<String, OpType<String>>,
    /// All options maps of the commands in request.
    pub maps : Vec<HashMap<String, OpType<String>>>,
  }

  ///
  /// Options for parser.
  ///

  #[ derive( Debug ) ]
  #[ derive( Former ) ]
  #[ perform( fn parse( mut self ) -> Request< 'a > ) ]
  pub struct ParseOptions< 'a >
  {
    #[ default( "" ) ]
    src : &'a str,
    #[ default( ":" ) ]
    key_val_delimeter : &'a str,
    #[ default( ";" ) ]
    commands_delimeter : &'a str,
    #[ default( true ) ]
    quoting : bool,
    #[ default( true ) ]
    unquoting : bool,
    #[ default( true ) ]
    parsing_arrays : bool,
    #[ default( false ) ]
    several_values : bool,
    #[ default( false ) ]
    subject_win_paths_maybe : bool,
  }

  ///
  /// Adapter for ParseOptions.
  ///

  pub trait ParseOptionsAdapter< 'a >
  {
    /// A string to parse.
    fn src( &self ) -> &'a str;
    /// A delimeter for pairs `key:value`.
    fn key_val_delimeter( &self ) -> &'a str;
    /// Delimeter for commands.
    fn commands_delimeter( &self ) -> &'a str;
    /// Quoting of strings.
    fn quoting( &self ) -> bool;
    /// Unquoting of string.
    fn unquoting( &self ) -> bool;
    /// Parse arrays of values.
    fn parsing_arrays( &self ) -> bool;
    /// Append to a vector a values.
    fn several_values( &self ) -> bool;
    /// Parse subject on Windows taking into account colon in path.
    fn subject_win_paths_maybe( &self ) -> bool;

    /// Do parsing.
    fn parse( self ) -> Request< 'a >
    where
      Self : Sized,
    {
      Request::default()
    }
  }

  impl< 'a > ParseOptionsAdapter< 'a > for ParseOptions< 'a >
  {
    fn src( &self ) -> &'a str
    {
      self.src
    }
    fn key_val_delimeter( &self ) -> &'a str
    {
      self.key_val_delimeter
    }
    fn commands_delimeter( &self ) -> &'a str
    {
      self.commands_delimeter
    }
    fn quoting( &self ) -> bool
    {
      self.quoting
    }
    fn unquoting( &self ) -> bool
    {
      self.unquoting
    }
    fn parsing_arrays( &self ) -> bool
    {
      self.parsing_arrays
    }
    fn several_values( &self ) -> bool
    {
      self.several_values
    }
    fn subject_win_paths_maybe( &self ) -> bool
    {
      self.subject_win_paths_maybe
    }

    fn parse( mut self ) -> Request< 'a >
    where
      Self : Sized,
    {
      let mut result = Request::default();

      result.original = self.src();
      result.key_val_delimeter = self.key_val_delimeter();
      result.commands_delimeter = self.commands_delimeter();

      self.src = self.src.trim();

      if self.src.is_empty()
      {
        return result;
      }

      let commands;
      if self.commands_delimeter.trim().is_empty()
      {
        commands = vec![ self.src().to_string() ];
      }
      else
      {
        let iter = split()
        .src( self.src() )
        .delimeter( self.commands_delimeter() )
        .quoting( self.quoting() )
        .stripping( true )
        .preserving_empty( false )
        .preserving_delimeters( false )
        .perform();
        commands = iter.map( | e | String::from( e ) ).collect::< Vec< _ > >();
      }

      for command in commands
      {
        let mut map_entries;
        if self.key_val_delimeter.trim().is_empty()
        {
          map_entries =  ( command.as_str(), None, "" );
        }
        else
        {
          map_entries = match command.split_once( self.key_val_delimeter )
          {
            Some( entries ) => ( entries.0, Some( self.key_val_delimeter ), entries.1 ),
            None => ( command.as_str(), None, "" ),
          };
        }

        let subject;
        let mut map : HashMap<String, OpType<String>> = HashMap::new();

        if map_entries.1.is_some()
        {
          let subject_and_key = isolate_right()
          .src( map_entries.0.trim() )
          .delimeter( " " )
          .none( true )
          .perform();
          subject = subject_and_key.0;
          map_entries.0 = subject_and_key.2;

          let mut join = String::from( map_entries.0 );
          join.push_str( map_entries.1.unwrap() );
          join.push_str( map_entries.2 );

          let mut splits = split()
          .src( join.as_str() )
          .delimeter( self.key_val_delimeter )
          .stripping( false )
          .quoting( self.quoting )
          .preserving_empty( true )
          .preserving_delimeters( true )
          .preserving_quoting( true )
          .perform()
          .map( | e | String::from( e ) ).collect::< Vec< _ > >();

          let mut pairs = vec![];
          for a in ( 0..splits.len() - 2 ).step_by( 2 )
          {
            let mut right = splits[ a + 2 ].clone();

            while a < ( splits.len() - 3 )
            {
              let cuts = isolate_right()
              .src( right.trim() )
              .delimeter( " " )
              .none( true )
              .perform();

              if cuts.1.is_none()
              {
                let mut joined = splits[ a + 2 ].clone();
                joined.push_str( splits[ a + 3 ].as_str() );
                joined.push_str( splits[ a + 4 ].as_str() );

                splits[ a + 2 ] = joined;
                right = splits[ a + 2 ].clone();
                splits.remove( a + 3 );
                splits.remove( a + 4 );
                continue;
              }

              splits[ a + 2 ] = cuts.2.to_string();
              right = cuts.0.to_string();
              break;
            }

            let left = splits[ a ].clone();
            let right = right.trim().to_string();
            if self.unquoting
            {
              if left.contains( "\"" ) || left.contains( "'" ) || right.contains( "\"" ) || right.contains( "'" )
              {
                unimplemented!( "not implemented" );
              }
              // left = str_unquote( left );
              // right = str_unquote( right );
            }

            pairs.push( left );
            pairs.push( right );
          }

          /* */

          let str_to_vec_maybe = | src : &str | -> Option<Vec<String>>
          {
            if !src.starts_with( '[' ) || !src.ends_with( ']' )
            {
              return None;
            }

            let splits = split()
            .src( &src[ 1..src.len() - 1 ] )
            .delimeter( "," )
            .stripping( true )
            .quoting( self.quoting )
            .preserving_empty( false )
            .preserving_delimeters( false )
            .preserving_quoting( false )
            .perform()
            .map( | e | String::from( e ).trim().to_owned() ).collect::< Vec<String> >();

            Some( splits )
          };

          /* */

          for a in ( 0..pairs.len() - 1 ).step_by( 2 )
          {
            let left = &pairs[ a ];
            let right_str = &pairs[ a + 1 ];
            let mut right = OpType::Primitive( pairs[ a + 1 ].to_string() );

            if self.parsing_arrays
            {
              if let Some( vector ) = str_to_vec_maybe( right_str )
              {
                right = OpType::Vector( vector );
              }
            }

            if self.several_values
            {
              if let Some( op ) = map.get( left )
              {
                let value = op.clone().append( right );
                map.insert( left.to_string(), value );
              }
              else
              {
                map.insert( left.to_string(), right );
              }
            }
            else
            {
              map.insert( left.to_string(), right );
            }
          }
        }
        else
        {
          subject = map_entries.0;
        }

        if self.unquoting
        {
          if subject.contains( "\"" ) || subject.contains( "'" )
          {
            unimplemented!( "not implemented" );
          }
          // subject = _.strUnquote( subject );
        }

        if self.subject_win_paths_maybe
        {
          unimplemented!( "not implemented" );
          // subject = win_path_subject_check( subject, map );
        }

        result.subjects.push( subject.to_string() );
        result.maps.push( map );
      }

      if result.subjects.len() > 0
      {
        result.subject = result.subjects[ 0 ].clone();
      }
      if result.maps.len() > 0
      {
        result.map = result.maps[ 0 ].clone();
      }

      result
    }
  }

  ///
  /// Function to parse a string with command request.
  ///
  /// It produces former. To convert former into options and run algorithm of splitting call `perform()`.
  ///

  pub fn request_parse<'a>() -> ParseOptionsFormer<'a>
  {
    ParseOptions::former()
  }
}

/// Protected namespace of the module.
pub mod protected
{
  pub use super::orphan::*;
  pub use super::private::
  {
    OpType,
    Request,
    ParseOptions,
    ParseOptionsAdapter,
    request_parse,
  };
}

#[ doc( inline ) ]
pub use protected::*;

/// Parented namespace of the module.
pub mod orphan
{
  pub use super::exposed::*;
}

/// Exposed namespace of the module.
pub mod exposed
{
  pub use super::private::
  {
    ParseOptionsAdapter,
    request_parse,
  };
}

/// Namespace of the module to include with `use module::*`.
pub mod prelude
{
  pub use super::private::ParseOptionsAdapter;
}
<commit_msg>Fix routine `split` of module `parse`, use valid option for isolate<commit_after>/// Internal namespace.
pub( crate ) mod private
{
  use former::Former;
  use crate::string::split::*;
  use crate::string::isolate::isolate_right;
  use std::collections::HashMap;

  ///
  /// Wrapper types to make transformation.
  ///

  #[ derive( Debug, Clone, PartialEq ) ]
  pub enum OpType<T>
  {
    /// Wrapper over single element of type <T>.
    Primitive( T ),
    /// Wrapper over vector of elements of type <T>.
    Vector( Vec<T> ),
    /// Wrapper over hash map of elements of type <T>.
    Map( HashMap<String, T> ),
  }

  impl<T : Default> Default for OpType<T>
  {
    fn default() -> Self
    {
      OpType::Primitive( T::default() )
    }
  }

  impl<T> From<T> for OpType<T>
  {
    fn from( value: T ) -> Self
    {
      OpType::Primitive( value )
    }
  }

  impl<T> From<Vec<T>> for OpType<T>
  {
    fn from( value: Vec<T> ) -> Self
    {
      OpType::Vector( value )
    }
  }

  impl<T> Into<Vec<T>> for OpType<T>
  {
    fn into( self ) -> Vec<T>
    {
      match self
      {
        OpType::Vector( vec ) => vec,
        _ => unimplemented!( "not implemented" ),
      }
    }
  }

  impl<T : Clone> OpType<T>
  {
    /// Append item of OpType to current value. If current type is `Primitive`, then it will be converted to
    /// `Vector`.
    pub fn append( mut self, item : OpType<T> ) -> OpType<T>
    {
      let mut mut_item = item;
      match self
      {
        OpType::Primitive( value ) =>
        {
          match mut_item
          {
            OpType::Primitive( ins ) =>
            {
              let vector = vec![ value, ins ];
              OpType::Vector( vector )
            }
            OpType::Vector( ref mut vector ) =>
            {
              vector.insert( 0, value );
              mut_item
            },
            OpType::Map( _ ) => panic!( "Unexpected operation. Please, use method `insert` to insert item in hash map." ),
          }
        },
        OpType::Vector( ref mut vector ) =>
        {
          match mut_item
          {
            OpType::Primitive( ins ) =>
            {
              vector.push( ins );
              self
            }
            OpType::Vector( ref mut ins_vec ) =>
            {
              vector.append( ins_vec );
              self
            },
            OpType::Map( _ ) => panic!( "Unexpected operation. Please, use method `insert` to insert item in hash map." ),
          }
        },
        OpType::Map( _ ) => panic!( "Unexpected operation. Please, use method `insert` to insert item in hash map." ),
      }
    }

    /// Unwrap primitive value. Consumes self.
    pub fn primitive( self ) -> Option<T>
    {
      match self
      {
        OpType::Primitive( v ) => Some( v ),
        _ => None,
      }
    }

    /// Unwrap vector value. Consumes self.
    pub fn vector( self ) -> Option<Vec<T>>
    {
      match self
      {
        OpType::Vector( vec ) => Some( vec ),
        _ => None,
      }
    }
  }

  ///
  /// Parsed request data.
  ///

  #[ allow( dead_code ) ]
  #[ derive( Debug, Default, PartialEq ) ]
  pub struct Request< 'a >
  {
    /// Original request string.
    pub original : &'a str,
    /// Delimeter for pairs `key:value`.
    pub key_val_delimeter : &'a str,
    /// Delimeter for commands.
    pub commands_delimeter : &'a str,
    /// Parsed subject of first command.
    pub subject : String,
    /// All subjects of the commands in request.
    pub subjects : Vec<String>,
    /// Options map of first command.
    pub map : HashMap<String, OpType<String>>,
    /// All options maps of the commands in request.
    pub maps : Vec<HashMap<String, OpType<String>>>,
  }

  ///
  /// Options for parser.
  ///

  #[ derive( Debug ) ]
  #[ derive( Former ) ]
  #[ perform( fn parse( mut self ) -> Request< 'a > ) ]
  pub struct ParseOptions< 'a >
  {
    #[ default( "" ) ]
    src : &'a str,
    #[ default( ":" ) ]
    key_val_delimeter : &'a str,
    #[ default( ";" ) ]
    commands_delimeter : &'a str,
    #[ default( true ) ]
    quoting : bool,
    #[ default( true ) ]
    unquoting : bool,
    #[ default( true ) ]
    parsing_arrays : bool,
    #[ default( false ) ]
    several_values : bool,
    #[ default( false ) ]
    subject_win_paths_maybe : bool,
  }

  ///
  /// Adapter for ParseOptions.
  ///

  pub trait ParseOptionsAdapter< 'a >
  {
    /// A string to parse.
    fn src( &self ) -> &'a str;
    /// A delimeter for pairs `key:value`.
    fn key_val_delimeter( &self ) -> &'a str;
    /// Delimeter for commands.
    fn commands_delimeter( &self ) -> &'a str;
    /// Quoting of strings.
    fn quoting( &self ) -> bool;
    /// Unquoting of string.
    fn unquoting( &self ) -> bool;
    /// Parse arrays of values.
    fn parsing_arrays( &self ) -> bool;
    /// Append to a vector a values.
    fn several_values( &self ) -> bool;
    /// Parse subject on Windows taking into account colon in path.
    fn subject_win_paths_maybe( &self ) -> bool;

    /// Do parsing.
    fn parse( self ) -> Request< 'a >
    where
      Self : Sized,
    {
      Request::default()
    }
  }

  impl< 'a > ParseOptionsAdapter< 'a > for ParseOptions< 'a >
  {
    fn src( &self ) -> &'a str
    {
      self.src
    }
    fn key_val_delimeter( &self ) -> &'a str
    {
      self.key_val_delimeter
    }
    fn commands_delimeter( &self ) -> &'a str
    {
      self.commands_delimeter
    }
    fn quoting( &self ) -> bool
    {
      self.quoting
    }
    fn unquoting( &self ) -> bool
    {
      self.unquoting
    }
    fn parsing_arrays( &self ) -> bool
    {
      self.parsing_arrays
    }
    fn several_values( &self ) -> bool
    {
      self.several_values
    }
    fn subject_win_paths_maybe( &self ) -> bool
    {
      self.subject_win_paths_maybe
    }

    fn parse( mut self ) -> Request< 'a >
    where
      Self : Sized,
    {
      let mut result = Request::default();

      result.original = self.src();
      result.key_val_delimeter = self.key_val_delimeter();
      result.commands_delimeter = self.commands_delimeter();

      self.src = self.src.trim();

      if self.src.is_empty()
      {
        return result;
      }

      let commands;
      if self.commands_delimeter.trim().is_empty()
      {
        commands = vec![ self.src().to_string() ];
      }
      else
      {
        let iter = split()
        .src( self.src() )
        .delimeter( self.commands_delimeter() )
        .quoting( self.quoting() )
        .stripping( true )
        .preserving_empty( false )
        .preserving_delimeters( false )
        .perform();
        commands = iter.map( | e | String::from( e ) ).collect::< Vec< _ > >();
      }

      for command in commands
      {
        let mut map_entries;
        if self.key_val_delimeter.trim().is_empty()
        {
          map_entries =  ( command.as_str(), None, "" );
        }
        else
        {
          map_entries = match command.split_once( self.key_val_delimeter )
          {
            Some( entries ) => ( entries.0, Some( self.key_val_delimeter ), entries.1 ),
            None => ( command.as_str(), None, "" ),
          };
        }

        let subject;
        let mut map : HashMap<String, OpType<String>> = HashMap::new();

        if map_entries.1.is_some()
        {
          let subject_and_key = isolate_right()
          .src( map_entries.0.trim() )
          .delimeter( " " )
          .none( false )
          .perform();
          subject = subject_and_key.0;
          map_entries.0 = subject_and_key.2;

          let mut join = String::from( map_entries.0 );
          join.push_str( map_entries.1.unwrap() );
          join.push_str( map_entries.2 );

          let mut splits = split()
          .src( join.as_str() )
          .delimeter( self.key_val_delimeter )
          .stripping( false )
          .quoting( self.quoting )
          .preserving_empty( true )
          .preserving_delimeters( true )
          .preserving_quoting( true )
          .perform()
          .map( | e | String::from( e ) ).collect::< Vec< _ > >();

          let mut pairs = vec![];
          for a in ( 0..splits.len() - 2 ).step_by( 2 )
          {
            let mut right = splits[ a + 2 ].clone();

            while a < ( splits.len() - 3 )
            {
              let cuts = isolate_right()
              .src( right.trim() )
              .delimeter( " " )
              .none( false )
              .perform();

              if cuts.1.is_none()
              {
                let mut joined = splits[ a + 2 ].clone();
                joined.push_str( splits[ a + 3 ].as_str() );
                joined.push_str( splits[ a + 4 ].as_str() );

                splits[ a + 2 ] = joined;
                right = splits[ a + 2 ].clone();
                splits.remove( a + 3 );
                splits.remove( a + 4 );
                continue;
              }

              splits[ a + 2 ] = cuts.2.to_string();
              right = cuts.0.to_string();
              break;
            }

            let left = splits[ a ].clone();
            let right = right.trim().to_string();
            if self.unquoting
            {
              if left.contains( "\"" ) || left.contains( "'" ) || right.contains( "\"" ) || right.contains( "'" )
              {
                unimplemented!( "not implemented" );
              }
              // left = str_unquote( left );
              // right = str_unquote( right );
            }

            pairs.push( left );
            pairs.push( right );
          }

          /* */

          let str_to_vec_maybe = | src : &str | -> Option<Vec<String>>
          {
            if !src.starts_with( '[' ) || !src.ends_with( ']' )
            {
              return None;
            }

            let splits = split()
            .src( &src[ 1..src.len() - 1 ] )
            .delimeter( "," )
            .stripping( true )
            .quoting( self.quoting )
            .preserving_empty( false )
            .preserving_delimeters( false )
            .preserving_quoting( false )
            .perform()
            .map( | e | String::from( e ).trim().to_owned() ).collect::< Vec<String> >();

            Some( splits )
          };

          /* */

          for a in ( 0..pairs.len() - 1 ).step_by( 2 )
          {
            let left = &pairs[ a ];
            let right_str = &pairs[ a + 1 ];
            let mut right = OpType::Primitive( pairs[ a + 1 ].to_string() );

            if self.parsing_arrays
            {
              if let Some( vector ) = str_to_vec_maybe( right_str )
              {
                right = OpType::Vector( vector );
              }
            }

            if self.several_values
            {
              if let Some( op ) = map.get( left )
              {
                let value = op.clone().append( right );
                map.insert( left.to_string(), value );
              }
              else
              {
                map.insert( left.to_string(), right );
              }
            }
            else
            {
              map.insert( left.to_string(), right );
            }
          }
        }
        else
        {
          subject = map_entries.0;
        }

        if self.unquoting
        {
          if subject.contains( "\"" ) || subject.contains( "'" )
          {
            unimplemented!( "not implemented" );
          }
          // subject = _.strUnquote( subject );
        }

        if self.subject_win_paths_maybe
        {
          unimplemented!( "not implemented" );
          // subject = win_path_subject_check( subject, map );
        }

        result.subjects.push( subject.to_string() );
        result.maps.push( map );
      }

      if result.subjects.len() > 0
      {
        result.subject = result.subjects[ 0 ].clone();
      }
      if result.maps.len() > 0
      {
        result.map = result.maps[ 0 ].clone();
      }

      result
    }
  }

  ///
  /// Function to parse a string with command request.
  ///
  /// It produces former. To convert former into options and run algorithm of splitting call `perform()`.
  ///

  pub fn request_parse<'a>() -> ParseOptionsFormer<'a>
  {
    ParseOptions::former()
  }
}

/// Protected namespace of the module.
pub mod protected
{
  pub use super::orphan::*;
  pub use super::private::
  {
    OpType,
    Request,
    ParseOptions,
    ParseOptionsAdapter,
    request_parse,
  };
}

#[ doc( inline ) ]
pub use protected::*;

/// Parented namespace of the module.
pub mod orphan
{
  pub use super::exposed::*;
}

/// Exposed namespace of the module.
pub mod exposed
{
  pub use super::private::
  {
    ParseOptionsAdapter,
    request_parse,
  };
}

/// Namespace of the module to include with `use module::*`.
pub mod prelude
{
  pub use super::private::ParseOptionsAdapter;
}
<|endoftext|>


<commit_before>use scaly::memory::page::Page;
use scaly::memory::page::PAGE_SIZE;
use std::alloc::alloc;
use std::alloc::alloc_zeroed;
use std::alloc::dealloc;
use std::alloc::Layout;
use std::mem::size_of;
use std::ptr::null_mut;

const STACK_BUCKET_PAGES: usize = 0x100;

pub struct Region<'a> {
    page: &'a mut Page,
}

impl<'a> Region<'a> {
    pub fn create_from_page(page: &Page) -> Region<'a> {
        let our_page_address = StackBucket::new_page(page);
        Region {
            page: unsafe { &mut *(our_page_address as *mut Page) },
        }
    }
    pub fn create(region: &Region<'a>) -> Region<'a> {
        Region::create_from_page(region.page)
    }
}

impl<'a> Drop for Region<'a> {
    fn drop(&mut self) {
        self.page.deallocate_extensions();
    }
}

pub enum Bucket {
    Stack(StackBucket),
    Heap(HeapBucket),
}

pub struct HeapBucket {
    map: usize,
}

pub struct Pool {
    root_map: usize,
    maps: *mut usize,
    pointers: *mut HeapBucket,
}

const MAPS_SIZE: usize = size_of::<usize>() * 8 * size_of::<usize>();
const POINTERS_SIZE: usize = MAPS_SIZE * 8 * size_of::<usize>();

impl Pool {
    pub fn create() -> Pool {
        unsafe {
            let maps_memory = alloc_zeroed(Layout::from_size_align_unchecked(MAPS_SIZE, PAGE_SIZE));
            if maps_memory == null_mut() {
                panic!("Unable to allocate maps memory: Out of memory.");
            }
            let pointers_memory =
                alloc_zeroed(Layout::from_size_align_unchecked(POINTERS_SIZE, PAGE_SIZE));
            if pointers_memory == null_mut() {
                panic!("Unable to allocate maps memory: Out of memory.");
            }
            Pool {
                root_map: 0,
                maps: maps_memory as *mut usize,
                pointers: pointers_memory as *mut HeapBucket,
            }
        }
    }
}

impl Drop for Pool {
    fn drop(&mut self) {
        if self.root_map != 0 {
            panic!("Pool is not empty!")
        }
        unsafe {
            dealloc(
                self.maps as *mut u8,
                Layout::from_size_align_unchecked(MAPS_SIZE, PAGE_SIZE),
            );
            dealloc(
                self.pointers as *mut u8,
                Layout::from_size_align_unchecked(POINTERS_SIZE, PAGE_SIZE),
            );
        }
    }
}

pub struct StackBucket {
    next_bucket: *mut StackBucket,
    pool: *mut Pool,
}

impl StackBucket {
    pub fn new_page(page: &Page) -> *mut Page {
        let page_address = page as *const Page as usize;
        let stack_bucket_page_address = page_address & !(PAGE_SIZE * STACK_BUCKET_PAGES - 1);
        let overflowed_page_address = stack_bucket_page_address + PAGE_SIZE * STACK_BUCKET_PAGES;
        let our_page_address = page_address + PAGE_SIZE;
        if overflowed_page_address == our_page_address {
            let stack_bucket = (stack_bucket_page_address + size_of::<Page>()) as *mut StackBucket;
            unsafe { (*stack_bucket).get_page_from_next_bucket() }
        } else {
            our_page_address as *mut Page
        }
    }

    fn get_page_from_next_bucket(self: &mut StackBucket) -> *mut Page {
        if self.next_bucket == null_mut() {
            self.next_bucket = StackBucket::create(self.pool);
        }
        Page::get_page(self.next_bucket as usize)
    }

    fn create(pool: *mut Pool) -> *mut StackBucket {
        unsafe {
            let memory = alloc(Layout::from_size_align_unchecked(
                PAGE_SIZE * STACK_BUCKET_PAGES,
                PAGE_SIZE * STACK_BUCKET_PAGES,
            ));
            if memory == null_mut() {
                panic!("Unable to crete a new stack bucket: Out of memory.");
            }
            let page = &mut *(memory as *mut Page);
            page.reset();
            let bucket = page.allocate(StackBucket {
                next_bucket: null_mut(),
                pool: pool,
            });
            bucket
        }
    }

    pub fn deallocate(&self) {
        let mut bucket = self as *const StackBucket;
        unsafe {
            while !(*bucket).next_bucket.is_null() {
                let next_bucket = (*bucket).next_bucket;
                let page = Page::get_page(bucket as usize);
                dealloc(
                    page as *mut u8,
                    Layout::from_size_align_unchecked(
                        PAGE_SIZE * STACK_BUCKET_PAGES,
                        PAGE_SIZE * STACK_BUCKET_PAGES,
                    ),
                );

                bucket = next_bucket;
            }
        }
    }
}

impl Drop for StackBucket {
    fn drop(&mut self) {
        self.deallocate();
    }
}

#[test]
fn test_region() {
    unsafe {
        let mut pool = Pool::create();
        let root_stack_bucket = StackBucket::create(&mut pool);
        let r1 = Region::create_from_page(&*Page::get_page(root_stack_bucket as usize));
        {
            let r2 = Region::create(&r1);
            {
                let _ = Region::create(&r2);
            }
        }
        (*root_stack_bucket).deallocate();
    }
    unsafe {
        let mut pool = Pool::create();
        let root_stack_bucket = StackBucket::create(&mut pool);

        let mut r = Region::create_from_page(&*Page::get_page(root_stack_bucket as usize));
        for _ in 1..STACK_BUCKET_PAGES * 2 {
            r = Region::create(&r);
        }

        (*root_stack_bucket).deallocate();
    }
}
<commit_msg>Converted StackBucket.Pool to a mutable refernce<commit_after>use scaly::memory::page::Page;
use scaly::memory::page::PAGE_SIZE;
use std::alloc::alloc;
use std::alloc::alloc_zeroed;
use std::alloc::dealloc;
use std::alloc::Layout;
use std::mem::size_of;
use std::ptr::null_mut;

const STACK_BUCKET_PAGES: usize = 0x100;

pub struct Region<'a> {
    page: &'a mut Page,
}

impl<'a> Region<'a> {
    pub fn create_from_page(page: &Page) -> Region<'a> {
        let our_page_address = StackBucket::new_page(page);
        Region {
            page: unsafe { &mut *(our_page_address as *mut Page) },
        }
    }
    pub fn create(region: &Region<'a>) -> Region<'a> {
        Region::create_from_page(region.page)
    }
}

impl<'a> Drop for Region<'a> {
    fn drop(&mut self) {
        self.page.deallocate_extensions();
    }
}

pub enum Bucket<'a> {
    Stack(StackBucket<'a>),
    Heap(HeapBucket),
}

pub struct HeapBucket {
    map: usize,
}

pub struct Pool {
    root_map: usize,
    maps: *mut usize,
    pointers: *mut HeapBucket,
}

const MAPS_SIZE: usize = size_of::<usize>() * 8 * size_of::<usize>();
const POINTERS_SIZE: usize = MAPS_SIZE * 8 * size_of::<usize>();

impl Pool {
    pub fn create() -> Pool {
        unsafe {
            let maps_memory = alloc_zeroed(Layout::from_size_align_unchecked(MAPS_SIZE, PAGE_SIZE));
            if maps_memory == null_mut() {
                panic!("Unable to allocate maps memory: Out of memory.");
            }
            let pointers_memory =
                alloc_zeroed(Layout::from_size_align_unchecked(POINTERS_SIZE, PAGE_SIZE));
            if pointers_memory == null_mut() {
                panic!("Unable to allocate maps memory: Out of memory.");
            }
            Pool {
                root_map: 0,
                maps: maps_memory as *mut usize,
                pointers: pointers_memory as *mut HeapBucket,
            }
        }
    }
}

impl Drop for Pool {
    fn drop(&mut self) {
        if self.root_map != 0 {
            panic!("Pool is not empty!")
        }
        unsafe {
            dealloc(
                self.maps as *mut u8,
                Layout::from_size_align_unchecked(MAPS_SIZE, PAGE_SIZE),
            );
            dealloc(
                self.pointers as *mut u8,
                Layout::from_size_align_unchecked(POINTERS_SIZE, PAGE_SIZE),
            );
        }
    }
}

pub struct StackBucket<'a> {
    next_bucket: *mut StackBucket<'a>,
    pool: &'a mut Pool,
}

impl<'a> StackBucket<'a> {
    pub fn new_page(page: &Page) -> *mut Page {
        let page_address = page as *const Page as usize;
        let stack_bucket_page_address = page_address & !(PAGE_SIZE * STACK_BUCKET_PAGES - 1);
        let overflowed_page_address = stack_bucket_page_address + PAGE_SIZE * STACK_BUCKET_PAGES;
        let our_page_address = page_address + PAGE_SIZE;
        if overflowed_page_address == our_page_address {
            let stack_bucket = (stack_bucket_page_address + size_of::<Page>()) as *mut StackBucket;
            unsafe { (*stack_bucket).get_page_from_next_bucket() }
        } else {
            our_page_address as *mut Page
        }
    }

    fn get_page_from_next_bucket(self: &'a mut StackBucket<'a>) -> *mut Page {
        if self.next_bucket == null_mut() {
            self.next_bucket = StackBucket::create(self.pool);
        }
        Page::get_page(self.next_bucket as usize)
    }

    fn create(pool: &'a mut Pool) -> *mut StackBucket<'a> {
        unsafe {
            let memory = alloc(Layout::from_size_align_unchecked(
                PAGE_SIZE * STACK_BUCKET_PAGES,
                PAGE_SIZE * STACK_BUCKET_PAGES,
            ));
            if memory == null_mut() {
                panic!("Unable to crete a new stack bucket: Out of memory.");
            }
            let page = &mut *(memory as *mut Page);
            page.reset();
            let bucket = page.allocate(StackBucket {
                next_bucket: null_mut(),
                pool: pool,
            });
            bucket
        }
    }

    pub fn deallocate(&self) {
        let mut bucket = self as *const StackBucket;
        unsafe {
            while !(*bucket).next_bucket.is_null() {
                let next_bucket = (*bucket).next_bucket;
                let page = Page::get_page(bucket as usize);
                dealloc(
                    page as *mut u8,
                    Layout::from_size_align_unchecked(
                        PAGE_SIZE * STACK_BUCKET_PAGES,
                        PAGE_SIZE * STACK_BUCKET_PAGES,
                    ),
                );

                bucket = next_bucket;
            }
        }
    }
}

impl<'a> Drop for StackBucket<'a> {
    fn drop(&mut self) {
        self.deallocate();
    }
}

#[test]
fn test_region() {
    unsafe {
        let mut pool = Pool::create();
        let root_stack_bucket = StackBucket::create(&mut pool);
        let r1 = Region::create_from_page(&*Page::get_page(root_stack_bucket as usize));
        {
            let r2 = Region::create(&r1);
            {
                let _ = Region::create(&r2);
            }
        }
        (*root_stack_bucket).deallocate();
    }
    unsafe {
        let mut pool = Pool::create();
        let root_stack_bucket = StackBucket::create(&mut pool);

        let mut r = Region::create_from_page(&*Page::get_page(root_stack_bucket as usize));
        for _ in 1..STACK_BUCKET_PAGES * 2 {
            r = Region::create(&r);
        }

        (*root_stack_bucket).deallocate();
    }
}
<|endoftext|>


<commit_before>use quick_csv::Csv;
use rustc_serialize;
use utilities::abs_standard_deviation;

pub trait Record {
    fn record_len() -> usize;
    fn data_at(&self, index: usize) -> f32;
    fn standarize_field(&mut self, index: usize, asd_median: &(f32, f32));
}

#[derive(Debug, RustcDecodable)]
pub struct MpgRecord {
    class: u32,
    values: [f32; 5],
}

impl Record for MpgRecord {
    fn record_len() -> usize {
        5
    }

    fn data_at(&self, index: usize) -> f32 {
        self.values[index]
    }

    fn standarize_field(&mut self, index: usize, asd_median: &(f32, f32)) {
        self.values[index] = (self.values[index] - asd_median.1) / asd_median.0;
    }
}

#[derive(Debug, RustcDecodable)]
pub struct IrisRecord {
    class: String,
    values: [f32; 4],
}

impl Record for IrisRecord {
    fn record_len() -> usize {
        4
    }

    fn data_at(&self, index: usize) -> f32 {
        self.values[index]
    }

    fn standarize_field(&mut self, index: usize, asd_median: &(f32, f32)) {
        self.values[index] = (self.values[index] - asd_median.1) / asd_median.0;
    }
}

#[derive(Debug)]
pub struct Database<T> {
    data: Vec<T>,
    abs_sd: Vec<(f32, f32)>,
}

impl<T> Database<T>
    where T: rustc_serialize::Decodable + ::std::fmt::Debug + Record
{
    pub fn new() -> Database<T> {
        Database {
            data: Vec::new(),
            abs_sd: Vec::new(),
        }
    }

    pub fn from_file(path: &str) -> Database<T> {
        let rdr = Csv::from_file(path).unwrap().has_header(true);
        let mut data: Vec<T> = Vec::new();
        for row in rdr.into_iter() {
            match row.unwrap().decode::<T>() {
                Ok(cols) => data.push(cols),
                Err(error) => println!("{}", error),
            }
        }

        Database {
            data: data,
            abs_sd: Vec::new(),
        }
    }

    pub fn add_file(&mut self, path: &str) {
        let rdr = Csv::from_file(path).unwrap();
        for row in rdr.into_iter() {
            match row.unwrap().decode::<T>() {
                Ok(cols) => self.data.push(cols),
                Err(error) => println!("{}", error),
            }
        }
    }

    pub fn standarize(&mut self) {
        println!("Standarizing DB...");
        let record_len = T::record_len();
        let mut mult_feat_vec = vec![Vec::<f32>::new(); record_len];

        for rcrd in self.data.iter() {
            for i in 0..record_len {
                mult_feat_vec[i].push(rcrd.data_at(i));
            }
        }

        let mut i = 0;
        for feat_vec in mult_feat_vec.iter() {
            let asd_median_tup = abs_standard_deviation(&feat_vec);
            println!("\t{}> asd: {}\tmedian: {}",
                     i,
                     asd_median_tup.0,
                     asd_median_tup.1);

            for rcrd in self.data.iter_mut() {
                rcrd.standarize_field(i, &asd_median_tup);
            }

            self.abs_sd.push(asd_median_tup);
            i += 1;
        }
    }

    // pub fn cross_validation(training_path: &str, n: usize, prefix: &str) {
    //     let mut precision = 0.0;

    //     for j in 1..n + 1 {
    //         let mut db = MpgDatabase::new();

    //         for i in 1..n + 1 {
    //             if i != j {
    //                 let path = format!("../../data/cross-validation/{}-{number:>0width$}",
    //                                    prefix,
    //                                    number = i,
    //                                    width = 2);
    //                 db.add_file(path.as_ref());
    //             }
    //         }

    //         db.standarize();
    //         let path = format!("../../data/cross-validation/{}-{number:>0width$}",
    //                            prefix,
    //                            number = j,
    //                            width = 2);
    //         let mut rdr = csv::Reader::from_file(path)
    //             .unwrap()
    //             .delimiter(b'\t')
    //             .has_headers(false);

    //         let mut n_correct = 0;
    //         let mut n_incorrect = 0;
    //         let mut count = 0;
    //         for record in rdr.decode() {
    //             let mut rcrd: (MpgRecord, String) = record.unwrap();
    //             let pred = db.predict(rcrd.0.cylinders,
    //                                   rcrd.0.ci,
    //                                   rcrd.0.hp,
    //                                   rcrd.0.weight,
    //                                   rcrd.0.secs);

    //             db.standarize_record(&mut rcrd.0);

    //             if rcrd.0.mpg == pred.mpg {
    //                 n_correct += 1;
    //             } else {
    //                 n_incorrect += 1;
    //             }
    //             count += 1;
    //         }

    //         println!("Correct: {}%\nIncorrect: {}%\n",
    //                  n_correct as f32 * 100.0 / count as f32,
    //                  n_incorrect as f32 * 100.0 / count as f32);

    //         presition += n_correct as f32 * 100.0 / count as f32;
    //     }

    //     presition /= n as f32;
    //     println!("Avg pres: {}%", presition);
    // }
}
<commit_msg>Before merge<commit_after>use quick_csv::Csv;
use rustc_serialize;
use utilities::abs_standard_deviation;

pub trait Record {
    fn record_len() -> usize;
    fn data_at(&self, index: usize) -> f32;
    fn standarize_field(&mut self, index: usize, asd_median: &(f32, f32));
    fn values(&self) -> Vec<f32>;
}

#[derive(Debug, RustcDecodable)]
pub struct MpgRecord {
    class: u32,
    values: [f32; 5],
}

impl Record for MpgRecord {
    fn record_len() -> usize {
        5
    }

    fn data_at(&self, index: usize) -> f32 {
        self.values[index]
    }

    fn standarize_field(&mut self, index: usize, asd_median: &(f32, f32)) {
        self.values[index] = (self.values[index] - asd_median.1) / asd_median.0;
    }

    fn values(&self) -> Vec<f32> {
        self.values.to_vec()
    }
}

#[derive(Debug, RustcDecodable)]
pub struct IrisRecord {
    class: String,
    values: [f32; 4],
}

impl Record for IrisRecord {
    fn record_len() -> usize {
        4
    }

    fn data_at(&self, index: usize) -> f32 {
        self.values[index]
    }

    fn standarize_field(&mut self, index: usize, asd_median: &(f32, f32)) {
        self.values[index] = (self.values[index] - asd_median.1) / asd_median.0;
    }

    fn values(&self) -> Vec<f32> {
        self.values.to_vec()
    }
}

#[derive(Debug)]
pub struct Database<T> {
    data: Vec<T>,
    abs_sd: Vec<(f32, f32)>,
}

impl<T> Database<T>
    where T: rustc_serialize::Decodable + ::std::fmt::Debug + Record
{
    pub fn new() -> Database<T> {
        Database {
            data: Vec::new(),
            abs_sd: Vec::new(),
        }
    }

    pub fn from_file(path: &str) -> Database<T> {
        let rdr = Csv::from_file(path).unwrap().has_header(true);
        let mut data: Vec<T> = Vec::new();
        for row in rdr.into_iter() {
            match row.unwrap().decode::<T>() {
                Ok(cols) => data.push(cols),
                Err(error) => println!("{}", error),
            }
        }

        Database {
            data: data,
            abs_sd: Vec::new(),
        }
    }

    pub fn add_file(&mut self, path: &str) {
        let rdr = Csv::from_file(path).unwrap();
        for row in rdr.into_iter() {
            match row.unwrap().decode::<T>() {
                Ok(cols) => self.data.push(cols),
                Err(error) => println!("{}", error),
            }
        }
    }

    pub fn standarize(&mut self) {
        println!("Standarizing DB...");
        let record_len = T::record_len();
        let mut mult_feat_vec = vec![Vec::<f32>::new(); record_len];

        for rcrd in self.data.iter() {
            for i in 0..record_len {
                mult_feat_vec[i].push(rcrd.data_at(i));
            }
        }

        let mut i = 0;
        for feat_vec in mult_feat_vec.iter() {
            let asd_median_tup = abs_standard_deviation(&feat_vec);
            println!("\t{}> asd: {}\tmedian: {}", i, asd_median_tup.0, asd_median_tup.1);

            for rcrd in self.data.iter_mut() {
                rcrd.standarize_field(i, &asd_median_tup);
            }

            self.abs_sd.push(asd_median_tup);
            i += 1;
        }
    }

    fn nearest_neighbors(&self, rcrd: &T, func: fn(&Vec<f32>, &Vec<f32>) -> f32) -> Vec<usize> {
        let mut distances: Vec<(f32, usize)> = Vec::new();
        let mut i = 0;
        for record in self.data.iter() {
            distances.push((func(&rcrd.values(), &record.values()), i));
            i += 1;
        }
        distances.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap());

        let indexes = distances.into_iter().map(|x| x.1).collect();
        indexes
    }

    pub fn predict(&self, vals: Vec<f32>) -> T {
        let record_len = T::record_len();
        if val
        let mut record = T::new();
        record.set_values(vals.as_ref());
        for i in 0..record_len {
            rcrd.standarize_field(i, self.abs_sd[i]);
        }
        record.set_class()
    }

    // pub fn cross_validation(training_path: &str, n: usize, prefix: &str) {
    //     let mut precision = 0.0;

    //     for j in 1..n + 1 {
    //         let mut db = MpgDatabase::new();

    //         for i in 1..n + 1 {
    //             if i != j {
    //                 let path = format!("../../data/cross-validation/{}-{number:>0width$}",
    //                                    prefix,
    //                                    number = i,
    //                                    width = 2);
    //                 db.add_file(path.as_ref());
    //             }
    //         }

    //         db.standarize();
    //         let path = format!("../../data/cross-validation/{}-{number:>0width$}",
    //                            prefix,
    //                            number = j,
    //                            width = 2);
    //         let mut rdr = csv::Reader::from_file(path)
    //             .unwrap()
    //             .delimiter(b'\t')
    //             .has_headers(false);

    //         let mut n_correct = 0;
    //         let mut n_incorrect = 0;
    //         let mut count = 0;
    //         for record in rdr.decode() {
    //             let mut rcrd: (MpgRecord, String) = record.unwrap();
    //             let pred = db.predict(rcrd.0.cylinders,
    //                                   rcrd.0.ci,
    //                                   rcrd.0.hp,
    //                                   rcrd.0.weight,
    //                                   rcrd.0.secs);

    //             db.standarize_record(&mut rcrd.0);

    //             if rcrd.0.mpg == pred.mpg {
    //                 n_correct += 1;
    //             } else {
    //                 n_incorrect += 1;
    //             }
    //             count += 1;
    //         }

    //         println!("Correct: {}%\nIncorrect: {}%\n",
    //                  n_correct as f32 * 100.0 / count as f32,
    //                  n_incorrect as f32 * 100.0 / count as f32);

    //         presition += n_correct as f32 * 100.0 / count as f32;
    //     }

    //     presition /= n as f32;
    //     println!("Avg pres: {}%", presition);
    // }
}
<|endoftext|>