<commit_before>use ide_db::{
    imports::import_assets::item_for_path_search, use_trivial_contructor::use_trivial_constructor,
};
use itertools::Itertools;
use stdx::format_to;
use syntax::ast::{self, AstNode, HasName, HasVisibility, StructKind};

use crate::{
    utils::{find_impl_block_start, find_struct_impl, generate_impl_text},
    AssistContext, AssistId, AssistKind, Assists,
};

// Assist: generate_new
//
// Adds a new inherent impl for a type.
//
// ```
// struct Ctx<T: Clone> {
//      data: T,$0
// }
// ```
// ->
// ```
// struct Ctx<T: Clone> {
//      data: T,
// }
//
// impl<T: Clone> Ctx<T> {
//     fn $0new(data: T) -> Self { Self { data } }
// }
// ```
pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
    let strukt = ctx.find_node_at_offset::<ast::Struct>()?;

    // We want to only apply this to non-union structs with named fields
    let field_list = match strukt.kind() {
        StructKind::Record(named) => named,
        _ => return None,
    };

    // Return early if we've found an existing new fn
    let impl_def = find_struct_impl(ctx, &ast::Adt::Struct(strukt.clone()), "new")?;

    let current_module = ctx.sema.scope(strukt.syntax())?.module();

    let target = strukt.syntax().text_range();
    acc.add(AssistId("generate_new", AssistKind::Generate), "Generate `new`", target, |builder| {
        let mut buf = String::with_capacity(512);

        if impl_def.is_some() {
            buf.push('\n');
        }

        let vis = strukt.visibility().map_or(String::new(), |v| format!("{} ", v));

        let trivial_constructors = field_list
            .fields()
            .map(|f| {
                let ty = ctx.sema.resolve_type(&f.ty()?)?;

                let item_in_ns = hir::ItemInNs::from(hir::ModuleDef::from(ty.as_adt()?));

                let type_path = current_module
                    .find_use_path(ctx.sema.db, item_for_path_search(ctx.sema.db, item_in_ns)?)?;

                let expr = use_trivial_constructor(
                    &ctx.sema.db,
                    ide_db::helpers::mod_path_to_ast(&type_path),
                    &ty,
                )?;

                Some(format!("{}: {}", f.name()?.syntax(), expr))
            })
            .collect::<Vec<_>>();

        let params = field_list
            .fields()
            .enumerate()
            .filter_map(|(i, f)| {
                if trivial_constructors[i].is_none() {
                    Some(format!("{}: {}", f.name()?.syntax(), f.ty()?.syntax()))
                } else {
                    None
                }
            })
            .format(", ");

        let fields = field_list
            .fields()
            .enumerate()
            .filter_map(|(i, f)| {
                let contructor = trivial_constructors[i].clone();
                if contructor.is_some() {
                    contructor
                } else {
                    Some(f.name()?.to_string())
                }
            })
            .format(", ");

        format_to!(buf, "    {}fn new({}) -> Self {{ Self {{ {} }} }}", vis, params, fields);

        let start_offset = impl_def
            .and_then(|impl_def| find_impl_block_start(impl_def, &mut buf))
            .unwrap_or_else(|| {
                buf = generate_impl_text(&ast::Adt::Struct(strukt.clone()), &buf);
                strukt.syntax().text_range().end()
            });

        match ctx.config.snippet_cap {
            None => builder.insert(start_offset, buf),
            Some(cap) => {
                buf = buf.replace("fn new", "fn $0new");
                builder.insert_snippet(cap, start_offset, buf);
            }
        }
    })
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};

    use super::*;

    #[test]
    fn test_generate_new_with_zst_fields() {
        check_assist(
            generate_new,
            r#"
struct Empty;

struct Foo { empty: Empty $0}
"#,
            r#"
struct Empty;

struct Foo { empty: Empty }

impl Foo {
    fn $0new() -> Self { Self { empty: Empty } }
}
"#,
        );
        check_assist(
            generate_new,
            r#"
struct Empty;

struct Foo { baz: String, empty: Empty $0}
"#,
            r#"
struct Empty;

struct Foo { baz: String, empty: Empty }

impl Foo {
    fn $0new(baz: String) -> Self { Self { baz, empty: Empty } }
}
"#,
        );
        check_assist(
            generate_new,
            r#"
enum Empty { Bar }

struct Foo { empty: Empty $0}
"#,
            r#"
enum Empty { Bar }

struct Foo { empty: Empty }

impl Foo {
    fn $0new() -> Self { Self { empty: Empty::Bar } }
}
"#,
        );

        // make sure the assist only works on unit variants
        check_assist(
            generate_new,
            r#"
struct Empty {}

struct Foo { empty: Empty $0}
"#,
            r#"
struct Empty {}

struct Foo { empty: Empty }

impl Foo {
    fn $0new(empty: Empty) -> Self { Self { empty } }
}
"#,
        );
        check_assist(
            generate_new,
            r#"
enum Empty { Bar {} }

struct Foo { empty: Empty $0}
"#,
            r#"
enum Empty { Bar {} }

struct Foo { empty: Empty }

impl Foo {
    fn $0new(empty: Empty) -> Self { Self { empty } }
}
"#,
        );
    }

    #[test]
    fn test_generate_new() {
        check_assist(
            generate_new,
            r#"
struct Foo {$0}
"#,
            r#"
struct Foo {}

impl Foo {
    fn $0new() -> Self { Self {  } }
}
"#,
        );
        check_assist(
            generate_new,
            r#"
struct Foo<T: Clone> {$0}
"#,
            r#"
struct Foo<T: Clone> {}

impl<T: Clone> Foo<T> {
    fn $0new() -> Self { Self {  } }
}
"#,
        );
        check_assist(
            generate_new,
            r#"
struct Foo<'a, T: Foo<'a>> {$0}
"#,
            r#"
struct Foo<'a, T: Foo<'a>> {}

impl<'a, T: Foo<'a>> Foo<'a, T> {
    fn $0new() -> Self { Self {  } }
}
"#,
        );
        check_assist(
            generate_new,
            r#"
struct Foo { baz: String $0}
"#,
            r#"
struct Foo { baz: String }

impl Foo {
    fn $0new(baz: String) -> Self { Self { baz } }
}
"#,
        );
        check_assist(
            generate_new,
            r#"
struct Foo { baz: String, qux: Vec<i32> $0}
"#,
            r#"
struct Foo { baz: String, qux: Vec<i32> }

impl Foo {
    fn $0new(baz: String, qux: Vec<i32>) -> Self { Self { baz, qux } }
}
"#,
        );
    }

    #[test]
    fn check_that_visibility_modifiers_dont_get_brought_in() {
        check_assist(
            generate_new,
            r#"
struct Foo { pub baz: String, pub qux: Vec<i32> $0}
"#,
            r#"
struct Foo { pub baz: String, pub qux: Vec<i32> }

impl Foo {
    fn $0new(baz: String, qux: Vec<i32>) -> Self { Self { baz, qux } }
}
"#,
        );
    }

    #[test]
    fn check_it_reuses_existing_impls() {
        check_assist(
            generate_new,
            r#"
struct Foo {$0}

impl Foo {}
"#,
            r#"
struct Foo {}

impl Foo {
    fn $0new() -> Self { Self {  } }
}
"#,
        );
        check_assist(
            generate_new,
            r#"
struct Foo {$0}

impl Foo {
    fn qux(&self) {}
}
"#,
            r#"
struct Foo {}

impl Foo {
    fn $0new() -> Self { Self {  } }

    fn qux(&self) {}
}
"#,
        );

        check_assist(
            generate_new,
            r#"
struct Foo {$0}

impl Foo {
    fn qux(&self) {}
    fn baz() -> i32 {
        5
    }
}
"#,
            r#"
struct Foo {}

impl Foo {
    fn $0new() -> Self { Self {  } }

    fn qux(&self) {}
    fn baz() -> i32 {
        5
    }
}
"#,
        );
    }

    #[test]
    fn check_visibility_of_new_fn_based_on_struct() {
        check_assist(
            generate_new,
            r#"
pub struct Foo {$0}
"#,
            r#"
pub struct Foo {}

impl Foo {
    pub fn $0new() -> Self { Self {  } }
}
"#,
        );
        check_assist(
            generate_new,
            r#"
pub(crate) struct Foo {$0}
"#,
            r#"
pub(crate) struct Foo {}

impl Foo {
    pub(crate) fn $0new() -> Self { Self {  } }
}
"#,
        );
    }

    #[test]
    fn generate_new_not_applicable_if_fn_exists() {
        check_assist_not_applicable(
            generate_new,
            r#"
struct Foo {$0}

impl Foo {
    fn new() -> Self {
        Self
    }
}
"#,
        );

        check_assist_not_applicable(
            generate_new,
            r#"
struct Foo {$0}

impl Foo {
    fn New() -> Self {
        Self
    }
}
"#,
        );
    }

    #[test]
    fn generate_new_target() {
        check_assist_target(
            generate_new,
            r#"
struct SomeThingIrrelevant;
/// Has a lifetime parameter
struct Foo<'a, T: Foo<'a>> {$0}
struct EvenMoreIrrelevant;
"#,
            "/// Has a lifetime parameter
struct Foo<'a, T: Foo<'a>> {}",
        );
    }

    #[test]
    fn test_unrelated_new() {
        check_assist(
            generate_new,
            r#"
pub struct AstId<N: AstNode> {
    file_id: HirFileId,
    file_ast_id: FileAstId<N>,
}

impl<N: AstNode> AstId<N> {
    pub fn new(file_id: HirFileId, file_ast_id: FileAstId<N>) -> AstId<N> {
        AstId { file_id, file_ast_id }
    }
}

pub struct Source<T> {
    pub file_id: HirFileId,$0
    pub ast: T,
}

impl<T> Source<T> {
    pub fn map<F: FnOnce(T) -> U, U>(self, f: F) -> Source<U> {
        Source { file_id: self.file_id, ast: f(self.ast) }
    }
}
"#,
            r#"
pub struct AstId<N: AstNode> {
    file_id: HirFileId,
    file_ast_id: FileAstId<N>,
}

impl<N: AstNode> AstId<N> {
    pub fn new(file_id: HirFileId, file_ast_id: FileAstId<N>) -> AstId<N> {
        AstId { file_id, file_ast_id }
    }
}

pub struct Source<T> {
    pub file_id: HirFileId,
    pub ast: T,
}

impl<T> Source<T> {
    pub fn $0new(file_id: HirFileId, ast: T) -> Self { Self { file_id, ast } }

    pub fn map<F: FnOnce(T) -> U, U>(self, f: F) -> Source<U> {
        Source { file_id: self.file_id, ast: f(self.ast) }
    }
}
"#,
        );
    }
}
<commit_msg>fix generate_new doc<commit_after>use ide_db::{
    imports::import_assets::item_for_path_search, use_trivial_contructor::use_trivial_constructor,
};
use itertools::Itertools;
use stdx::format_to;
use syntax::ast::{self, AstNode, HasName, HasVisibility, StructKind};

use crate::{
    utils::{find_impl_block_start, find_struct_impl, generate_impl_text},
    AssistContext, AssistId, AssistKind, Assists,
};

// Assist: generate_new
//
// Adds a `fn new` for a type.
//
// ```
// struct Ctx<T: Clone> {
//      data: T,$0
// }
// ```
// ->
// ```
// struct Ctx<T: Clone> {
//      data: T,
// }
//
// impl<T: Clone> Ctx<T> {
//     fn $0new(data: T) -> Self { Self { data } }
// }
// ```
pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
    let strukt = ctx.find_node_at_offset::<ast::Struct>()?;

    // We want to only apply this to non-union structs with named fields
    let field_list = match strukt.kind() {
        StructKind::Record(named) => named,
        _ => return None,
    };

    // Return early if we've found an existing new fn
    let impl_def = find_struct_impl(ctx, &ast::Adt::Struct(strukt.clone()), "new")?;

    let current_module = ctx.sema.scope(strukt.syntax())?.module();

    let target = strukt.syntax().text_range();
    acc.add(AssistId("generate_new", AssistKind::Generate), "Generate `new`", target, |builder| {
        let mut buf = String::with_capacity(512);

        if impl_def.is_some() {
            buf.push('\n');
        }

        let vis = strukt.visibility().map_or(String::new(), |v| format!("{} ", v));

        let trivial_constructors = field_list
            .fields()
            .map(|f| {
                let ty = ctx.sema.resolve_type(&f.ty()?)?;

                let item_in_ns = hir::ItemInNs::from(hir::ModuleDef::from(ty.as_adt()?));

                let type_path = current_module
                    .find_use_path(ctx.sema.db, item_for_path_search(ctx.sema.db, item_in_ns)?)?;

                let expr = use_trivial_constructor(
                    &ctx.sema.db,
                    ide_db::helpers::mod_path_to_ast(&type_path),
                    &ty,
                )?;

                Some(format!("{}: {}", f.name()?.syntax(), expr))
            })
            .collect::<Vec<_>>();

        let params = field_list
            .fields()
            .enumerate()
            .filter_map(|(i, f)| {
                if trivial_constructors[i].is_none() {
                    Some(format!("{}: {}", f.name()?.syntax(), f.ty()?.syntax()))
                } else {
                    None
                }
            })
            .format(", ");

        let fields = field_list
            .fields()
            .enumerate()
            .filter_map(|(i, f)| {
                let contructor = trivial_constructors[i].clone();
                if contructor.is_some() {
                    contructor
                } else {
                    Some(f.name()?.to_string())
                }
            })
            .format(", ");

        format_to!(buf, "    {}fn new({}) -> Self {{ Self {{ {} }} }}", vis, params, fields);

        let start_offset = impl_def
            .and_then(|impl_def| find_impl_block_start(impl_def, &mut buf))
            .unwrap_or_else(|| {
                buf = generate_impl_text(&ast::Adt::Struct(strukt.clone()), &buf);
                strukt.syntax().text_range().end()
            });

        match ctx.config.snippet_cap {
            None => builder.insert(start_offset, buf),
            Some(cap) => {
                buf = buf.replace("fn new", "fn $0new");
                builder.insert_snippet(cap, start_offset, buf);
            }
        }
    })
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};

    use super::*;

    #[test]
    fn test_generate_new_with_zst_fields() {
        check_assist(
            generate_new,
            r#"
struct Empty;

struct Foo { empty: Empty $0}
"#,
            r#"
struct Empty;

struct Foo { empty: Empty }

impl Foo {
    fn $0new() -> Self { Self { empty: Empty } }
}
"#,
        );
        check_assist(
            generate_new,
            r#"
struct Empty;

struct Foo { baz: String, empty: Empty $0}
"#,
            r#"
struct Empty;

struct Foo { baz: String, empty: Empty }

impl Foo {
    fn $0new(baz: String) -> Self { Self { baz, empty: Empty } }
}
"#,
        );
        check_assist(
            generate_new,
            r#"
enum Empty { Bar }

struct Foo { empty: Empty $0}
"#,
            r#"
enum Empty { Bar }

struct Foo { empty: Empty }

impl Foo {
    fn $0new() -> Self { Self { empty: Empty::Bar } }
}
"#,
        );

        // make sure the assist only works on unit variants
        check_assist(
            generate_new,
            r#"
struct Empty {}

struct Foo { empty: Empty $0}
"#,
            r#"
struct Empty {}

struct Foo { empty: Empty }

impl Foo {
    fn $0new(empty: Empty) -> Self { Self { empty } }
}
"#,
        );
        check_assist(
            generate_new,
            r#"
enum Empty { Bar {} }

struct Foo { empty: Empty $0}
"#,
            r#"
enum Empty { Bar {} }

struct Foo { empty: Empty }

impl Foo {
    fn $0new(empty: Empty) -> Self { Self { empty } }
}
"#,
        );
    }

    #[test]
    fn test_generate_new() {
        check_assist(
            generate_new,
            r#"
struct Foo {$0}
"#,
            r#"
struct Foo {}

impl Foo {
    fn $0new() -> Self { Self {  } }
}
"#,
        );
        check_assist(
            generate_new,
            r#"
struct Foo<T: Clone> {$0}
"#,
            r#"
struct Foo<T: Clone> {}

impl<T: Clone> Foo<T> {
    fn $0new() -> Self { Self {  } }
}
"#,
        );
        check_assist(
            generate_new,
            r#"
struct Foo<'a, T: Foo<'a>> {$0}
"#,
            r#"
struct Foo<'a, T: Foo<'a>> {}

impl<'a, T: Foo<'a>> Foo<'a, T> {
    fn $0new() -> Self { Self {  } }
}
"#,
        );
        check_assist(
            generate_new,
            r#"
struct Foo { baz: String $0}
"#,
            r#"
struct Foo { baz: String }

impl Foo {
    fn $0new(baz: String) -> Self { Self { baz } }
}
"#,
        );
        check_assist(
            generate_new,
            r#"
struct Foo { baz: String, qux: Vec<i32> $0}
"#,
            r#"
struct Foo { baz: String, qux: Vec<i32> }

impl Foo {
    fn $0new(baz: String, qux: Vec<i32>) -> Self { Self { baz, qux } }
}
"#,
        );
    }

    #[test]
    fn check_that_visibility_modifiers_dont_get_brought_in() {
        check_assist(
            generate_new,
            r#"
struct Foo { pub baz: String, pub qux: Vec<i32> $0}
"#,
            r#"
struct Foo { pub baz: String, pub qux: Vec<i32> }

impl Foo {
    fn $0new(baz: String, qux: Vec<i32>) -> Self { Self { baz, qux } }
}
"#,
        );
    }

    #[test]
    fn check_it_reuses_existing_impls() {
        check_assist(
            generate_new,
            r#"
struct Foo {$0}

impl Foo {}
"#,
            r#"
struct Foo {}

impl Foo {
    fn $0new() -> Self { Self {  } }
}
"#,
        );
        check_assist(
            generate_new,
            r#"
struct Foo {$0}

impl Foo {
    fn qux(&self) {}
}
"#,
            r#"
struct Foo {}

impl Foo {
    fn $0new() -> Self { Self {  } }

    fn qux(&self) {}
}
"#,
        );

        check_assist(
            generate_new,
            r#"
struct Foo {$0}

impl Foo {
    fn qux(&self) {}
    fn baz() -> i32 {
        5
    }
}
"#,
            r#"
struct Foo {}

impl Foo {
    fn $0new() -> Self { Self {  } }

    fn qux(&self) {}
    fn baz() -> i32 {
        5
    }
}
"#,
        );
    }

    #[test]
    fn check_visibility_of_new_fn_based_on_struct() {
        check_assist(
            generate_new,
            r#"
pub struct Foo {$0}
"#,
            r#"
pub struct Foo {}

impl Foo {
    pub fn $0new() -> Self { Self {  } }
}
"#,
        );
        check_assist(
            generate_new,
            r#"
pub(crate) struct Foo {$0}
"#,
            r#"
pub(crate) struct Foo {}

impl Foo {
    pub(crate) fn $0new() -> Self { Self {  } }
}
"#,
        );
    }

    #[test]
    fn generate_new_not_applicable_if_fn_exists() {
        check_assist_not_applicable(
            generate_new,
            r#"
struct Foo {$0}

impl Foo {
    fn new() -> Self {
        Self
    }
}
"#,
        );

        check_assist_not_applicable(
            generate_new,
            r#"
struct Foo {$0}

impl Foo {
    fn New() -> Self {
        Self
    }
}
"#,
        );
    }

    #[test]
    fn generate_new_target() {
        check_assist_target(
            generate_new,
            r#"
struct SomeThingIrrelevant;
/// Has a lifetime parameter
struct Foo<'a, T: Foo<'a>> {$0}
struct EvenMoreIrrelevant;
"#,
            "/// Has a lifetime parameter
struct Foo<'a, T: Foo<'a>> {}",
        );
    }

    #[test]
    fn test_unrelated_new() {
        check_assist(
            generate_new,
            r#"
pub struct AstId<N: AstNode> {
    file_id: HirFileId,
    file_ast_id: FileAstId<N>,
}

impl<N: AstNode> AstId<N> {
    pub fn new(file_id: HirFileId, file_ast_id: FileAstId<N>) -> AstId<N> {
        AstId { file_id, file_ast_id }
    }
}

pub struct Source<T> {
    pub file_id: HirFileId,$0
    pub ast: T,
}

impl<T> Source<T> {
    pub fn map<F: FnOnce(T) -> U, U>(self, f: F) -> Source<U> {
        Source { file_id: self.file_id, ast: f(self.ast) }
    }
}
"#,
            r#"
pub struct AstId<N: AstNode> {
    file_id: HirFileId,
    file_ast_id: FileAstId<N>,
}

impl<N: AstNode> AstId<N> {
    pub fn new(file_id: HirFileId, file_ast_id: FileAstId<N>) -> AstId<N> {
        AstId { file_id, file_ast_id }
    }
}

pub struct Source<T> {
    pub file_id: HirFileId,
    pub ast: T,
}

impl<T> Source<T> {
    pub fn $0new(file_id: HirFileId, ast: T) -> Self { Self { file_id, ast } }

    pub fn map<F: FnOnce(T) -> U, U>(self, f: F) -> Source<U> {
        Source { file_id: self.file_id, ast: f(self.ast) }
    }
}
"#,
        );
    }
}
<|endoftext|>


<commit_before>
extern crate gitlab_api as gitlab;

use std::env;
use gitlab::GitLab;
use gitlab::Pagination;
use gitlab::projects;

fn main() {
    let hostname = match env::var("GITLAB_HOSTNAME") {
        Ok(val) => val,
        Err(_) => {
            let default = String::from("gitlab.com");
            println!("Please set environment variable 'GITLAB_HOSTNAME'. Using default '{}'.",
                     default);
            default
        }
    };

    let token = match env::var("GITLAB_TOKEN") {
        Ok(val) => val,
        Err(_) => {
            panic!("Please set environment variable 'GITLAB_TOKEN'. Take it from \
                    http://{}/profile/account",
                   hostname);
        }
    };

    let mut gl = GitLab::new_https(&hostname, &token);
    // for i in 1..82 {
    //     gl.set_pagination(Pagination{page: i, per_page: 1});
    //     println!("projects: {:?}", gl.projects().unwrap());
    // }
    // gl.set_pagination(Pagination {
    //     page: 1,
    //     per_page: 100,
    // });
    let projects = gl.projects(projects::Listing::new()).unwrap();
    println!("projects: {:?}", projects);
    // FIXME: Project's members are private
    // for project in projects {
    //     println!("{:?}", project.path_with_namespace);
    // }

    let projects = gl.projects_all(projects::all::Listing::new()).unwrap();
    println!("projects: {:?}", projects);

    let listing = projects::id::Listing::new(projects::id::ListingId::Id(10));
    let projects = gl.projects_id(listing).unwrap();
    println!("projects: {:?}", projects);
}
<commit_msg>Initialize env_logger in list_projects.<commit_after>
extern crate gitlab_api as gitlab;

use std::env;
#[macro_use]
extern crate log;
extern crate env_logger;

use gitlab::GitLab;
use gitlab::Pagination;
use gitlab::projects;

fn main() {
    env_logger::init().unwrap();
    info!("starting up");

    let hostname = match env::var("GITLAB_HOSTNAME") {
        Ok(val) => val,
        Err(_) => {
            let default = String::from("gitlab.com");
            println!("Please set environment variable 'GITLAB_HOSTNAME'. Using default '{}'.",
                     default);
            default
        }
    };

    let token = match env::var("GITLAB_TOKEN") {
        Ok(val) => val,
        Err(_) => {
            panic!("Please set environment variable 'GITLAB_TOKEN'. Take it from \
                    http://{}/profile/account",
                   hostname);
        }
    };

    let mut gl = GitLab::new_https(&hostname, &token);
    // for i in 1..82 {
    //     gl.set_pagination(Pagination{page: i, per_page: 1});
    //     println!("projects: {:?}", gl.projects().unwrap());
    // }
    // gl.set_pagination(Pagination {
    //     page: 1,
    //     per_page: 100,
    // });
    let projects = gl.projects(projects::Listing::new()).unwrap();
    println!("projects: {:?}", projects);
    // FIXME: Project's members are private
    // for project in projects {
    //     println!("{:?}", project.path_with_namespace);
    // }

    let projects = gl.projects_all(projects::all::Listing::new()).unwrap();
    println!("projects: {:?}", projects);

    let listing = projects::id::Listing::new(projects::id::ListingId::Id(10));
    let projects = gl.projects_id(listing).unwrap();
    println!("projects: {:?}", projects);
}
<|endoftext|>


<commit_before>//! An example that displays RDTSC frequency.
extern crate raw_cpuid;
extern crate x86;

use std::time;
use x86::time::rdtscp;

const MHZ_TO_HZ: u64 = 1000000;
const KHZ_TO_HZ: u64 = 1000;

fn main() {
    let cpuid = raw_cpuid::CpuId::new();
    let has_tsc = cpuid
        .get_feature_info()
        .map_or(false, |finfo| finfo.has_tsc());

    let has_invariant_tsc = cpuid
        .get_extended_function_info()
        .map_or(false, |efinfo| efinfo.has_invariant_tsc());

    let tsc_frequency_hz = cpuid.get_tsc_info().map(|tinfo| {
        if tinfo.nominal_frequency() != 0 {
            Some(tinfo.tsc_frequency())
        } else if tinfo.numerator() != 0 && tinfo.denominator() != 0 {
            // Skylake and Kabylake don't report the crystal clock, approximate with base frequency:
            cpuid
                .get_processor_frequency_info()
                .map(|pinfo| pinfo.processor_base_frequency() as u64 * MHZ_TO_HZ)
                .map(|cpu_base_freq_hz| {
                    let crystal_hz =
                        cpu_base_freq_hz * tinfo.denominator() as u64 / tinfo.numerator() as u64;
                    crystal_hz * tinfo.numerator() as u64 / tinfo.denominator() as u64
                })
        } else {
            None
        }
    });

    if has_tsc {
        println!(
            "TSC Frequency is: {} ({})",
            match tsc_frequency_hz {
                Some(x) => format!("{} Hz", x.unwrap_or(0)),
                None => String::from("unknown"),
            },
            if has_invariant_tsc {
                "invariant"
            } else {
                "TSC frequency varies with speed-stepping"
            }
        );
    }

    cpuid.get_hypervisor_info().map(|hv| {
        hv.tsc_frequency().map(|tsc_khz| {
            let virtual_tsc_frequency_hz = tsc_khz as u64 * KHZ_TO_HZ;
            println!(
                "Hypervisor reports TSC Frequency at: {} Hz",
                virtual_tsc_frequency_hz
            );
        })
    });

    let one_second = time::Duration::from_secs(1);
    unsafe {
        let now = time::Instant::now();
        let start = rdtscp();
        loop {
            if now.elapsed() >= one_second {
                break;
            }
        }
        let end = rdtscp();
        println!("Empirical measurement of TSC was: {} Hz", (end - start));
    }
}
<commit_msg>Make unsafe blocks small.<commit_after>//! An example that displays RDTSC frequency.
extern crate raw_cpuid;
extern crate x86;

use std::time;
use x86::time::rdtscp;

const MHZ_TO_HZ: u64 = 1000000;
const KHZ_TO_HZ: u64 = 1000;

fn main() {
    let cpuid = raw_cpuid::CpuId::new();
    let has_tsc = cpuid
        .get_feature_info()
        .map_or(false, |finfo| finfo.has_tsc());

    let has_invariant_tsc = cpuid
        .get_extended_function_info()
        .map_or(false, |efinfo| efinfo.has_invariant_tsc());

    let tsc_frequency_hz = cpuid.get_tsc_info().map(|tinfo| {
        if tinfo.nominal_frequency() != 0 {
            Some(tinfo.tsc_frequency())
        } else if tinfo.numerator() != 0 && tinfo.denominator() != 0 {
            // Skylake and Kabylake don't report the crystal clock, approximate with base frequency:
            cpuid
                .get_processor_frequency_info()
                .map(|pinfo| pinfo.processor_base_frequency() as u64 * MHZ_TO_HZ)
                .map(|cpu_base_freq_hz| {
                    let crystal_hz =
                        cpu_base_freq_hz * tinfo.denominator() as u64 / tinfo.numerator() as u64;
                    crystal_hz * tinfo.numerator() as u64 / tinfo.denominator() as u64
                })
        } else {
            None
        }
    });

    if has_tsc {
        println!(
            "TSC Frequency is: {} ({})",
            match tsc_frequency_hz {
                Some(x) => format!("{} Hz", x.unwrap_or(0)),
                None => String::from("unknown"),
            },
            if has_invariant_tsc {
                "invariant"
            } else {
                "TSC frequency varies with speed-stepping"
            }
        );
    }

    cpuid.get_hypervisor_info().map(|hv| {
        hv.tsc_frequency().map(|tsc_khz| {
            let virtual_tsc_frequency_hz = tsc_khz as u64 * KHZ_TO_HZ;
            println!(
                "Hypervisor reports TSC Frequency at: {} Hz",
                virtual_tsc_frequency_hz
            );
        })
    });

    let one_second = time::Duration::from_secs(1);
    let now = time::Instant::now();
    let start = unsafe { rdtscp() };
    loop {
        if now.elapsed() >= one_second {
            break;
        }
    }
    let end = unsafe { rdtscp() };
    println!("Empirical measurement of TSC was: {} Hz", (end - start));
}
<|endoftext|>


<commit_before>#[crate_id = "test#0.1"];

#[feature(globs)];
#[feature(macro_rules)];

#[link_args="-lwxc"];

extern crate native;
extern crate wx;

use libc::c_void;

use wx::_unsafe::*;
use wx::defs::*;
use wx::base::*;
use wx::core::*;

mod macros;

wxApp!(wx_main)

extern "C"
fn wx_main() {
    let frame = make_frame();
    frame.show();
    frame.raise();
}

fn make_frame() -> Frame {
    let frame = Frame::new(&Window::null(), ID_ANY, "Hello, wxRust!", -1, -1, -1, -1, DEFAULT_FRAME_STYLE);
    let menubar = make_menubar();
    frame.setMenuBar(&menubar);

    make_button(&frame);

    frame
}

fn make_menubar() -> MenuBar {
    let menubar = MenuBar::new(0);

    let fileMenu = Menu::new("", 0);
    let fileNew = MenuItem::newEx(ID_ANY, "New", "Create a new file.", 0, &Menu::null());
    fileMenu.appendItem(&fileNew);

    menubar.append(&fileMenu, "File");
    menubar
}

extern "C"
fn MyButton_clicked(fun: *mut c_void, data: *mut c_void, evt: *mut c_void) {
    if evt == 0 as *mut c_void {
        // Comes here when the target widget is destroyed.
        return;
    }

    println!("hello!");
    let parent = Window::from(data);
    let msgDlg = MessageDialog::new(&parent, "Pushed!!", "The Button", OK);
    msgDlg.showModal();
}

fn make_button<T: WindowMethods>(parent: &T) -> Button {
    let button = Button::new(parent, ID_ANY, "Push me!", 10, 10, 50, 30, 0);
    let closure = Closure::new(MyButton_clicked as *mut c_void, parent.ptr());
    unsafe {
        button.connect(ID_ANY, ID_ANY, expEVT_COMMAND_BUTTON_CLICKED(), closure.ptr());
    }

    button
}
<commit_msg>Fix build.<commit_after>#[crate_id = "test#0.1"];

#[feature(globs)];
#[feature(macro_rules)];

#[link_args="-lwxc"];

extern crate libc;
extern crate native;
extern crate wx;

use libc::c_void;

use wx::_unsafe::*;
use wx::defs::*;
use wx::base::*;
use wx::core::*;

mod macros;

wxApp!(wx_main)

extern "C"
fn wx_main() {
    let frame = make_frame();
    frame.show();
    frame.raise();
}

fn make_frame() -> Frame {
    let frame = Frame::new(&Window::null(), ID_ANY, "Hello, wxRust!", -1, -1, -1, -1, DEFAULT_FRAME_STYLE);
    let menubar = make_menubar();
    frame.setMenuBar(&menubar);

    make_button(&frame);

    frame
}

fn make_menubar() -> MenuBar {
    let menubar = MenuBar::new(0);

    let fileMenu = Menu::new("", 0);
    let fileNew = MenuItem::newEx(ID_ANY, "New", "Create a new file.", 0, &Menu::null());
    fileMenu.appendItem(&fileNew);

    menubar.append(&fileMenu, "File");
    menubar
}

extern "C"
fn MyButton_clicked(fun: *mut c_void, data: *mut c_void, evt: *mut c_void) {
    if evt == 0 as *mut c_void {
        // Comes here when the target widget is destroyed.
        return;
    }

    println!("hello!");
    let parent = Window::from(data);
    let msgDlg = MessageDialog::new(&parent, "Pushed!!", "The Button", OK);
    msgDlg.showModal();
}

fn make_button<T: WindowMethods>(parent: &T) -> Button {
    let button = Button::new(parent, ID_ANY, "Push me!", 10, 10, 50, 30, 0);
    let closure = Closure::new(MyButton_clicked as *mut c_void, parent.ptr());
    unsafe {
        button.connect(ID_ANY, ID_ANY, expEVT_COMMAND_BUTTON_CLICKED(), closure.ptr());
    }

    button
}
<|endoftext|>


<commit_before>extern crate rusqlite;
extern crate r2d2;
extern crate r2d2_sqlite;
extern crate tempdir;

use std::sync::mpsc;
use std::thread;

use r2d2::ManageConnection;
use tempdir::TempDir;

use r2d2_sqlite::SqliteConnectionManager;
use rusqlite::Connection;

#[test]
fn test_basic() {
    let manager = SqliteConnectionManager::file("file.db");
    let pool = r2d2::Pool::builder()
        .max_size(2)
        .build(manager)
        .unwrap();

    let (s1, r1) = mpsc::channel();
    let (s2, r2) = mpsc::channel();

    let pool1 = pool.clone();
    let t1 = thread::spawn(move || {
                               let conn = pool1.get().unwrap();
                               s1.send(()).unwrap();
                               r2.recv().unwrap();
                               drop(conn);
                           });

    let pool2 = pool.clone();
    let t2 = thread::spawn(move || {
                               let conn = pool2.get().unwrap();
                               s2.send(()).unwrap();
                               r1.recv().unwrap();
                               drop(conn);
                           });

    t1.join().unwrap();
    t2.join().unwrap();

    pool.get().unwrap();
}

#[test]
fn test_file() {
    let manager = SqliteConnectionManager::file("file.db");
    let pool = r2d2::Pool::builder()
        .max_size(2)
        .build(manager)
        .unwrap();

    let (s1, r1) = mpsc::channel();
    let (s2, r2) = mpsc::channel();

    let pool1 = pool.clone();
    let t1 = thread::spawn(move || {
                               let conn = pool1.get().unwrap();
                               let conn1: &Connection = &*conn;
                               s1.send(()).unwrap();
                               r2.recv().unwrap();
                               drop(conn1);
                           });

    let pool2 = pool.clone();
    let t2 = thread::spawn(move || {
                               let conn = pool2.get().unwrap();
                               s2.send(()).unwrap();
                               r1.recv().unwrap();
                               drop(conn);
                           });

    t1.join().unwrap();
    t2.join().unwrap();

    pool.get().unwrap();
}

#[test]
fn test_is_valid() {
    let manager = SqliteConnectionManager::file("file.db");
    let pool = r2d2::Pool::builder()
        .max_size(1)
        .test_on_check_out(true)
        .build(manager)
        .unwrap();

    pool.get().unwrap();
}

#[test]
fn test_error_handling() {
    //! We specify a directory as a database. This is bound to fail.
    let dir = TempDir::new("r2d2-sqlite").expect("Could not create temporary directory");
    let dirpath = dir.path().to_str().unwrap();
    let manager = SqliteConnectionManager::file(dirpath);
    assert!(manager.connect().is_err());
}
<commit_msg>Run rustfmt on tests/test.rs<commit_after>extern crate r2d2;
extern crate r2d2_sqlite;
extern crate rusqlite;
extern crate tempdir;

use std::sync::mpsc;
use std::thread;

use r2d2::ManageConnection;
use tempdir::TempDir;

use r2d2_sqlite::SqliteConnectionManager;
use rusqlite::Connection;

#[test]
fn test_basic() {
    let manager = SqliteConnectionManager::file("file.db");
    let pool = r2d2::Pool::builder().max_size(2).build(manager).unwrap();

    let (s1, r1) = mpsc::channel();
    let (s2, r2) = mpsc::channel();

    let pool1 = pool.clone();
    let t1 = thread::spawn(move || {
        let conn = pool1.get().unwrap();
        s1.send(()).unwrap();
        r2.recv().unwrap();
        drop(conn);
    });

    let pool2 = pool.clone();
    let t2 = thread::spawn(move || {
        let conn = pool2.get().unwrap();
        s2.send(()).unwrap();
        r1.recv().unwrap();
        drop(conn);
    });

    t1.join().unwrap();
    t2.join().unwrap();

    pool.get().unwrap();
}

#[test]
fn test_file() {
    let manager = SqliteConnectionManager::file("file.db");
    let pool = r2d2::Pool::builder().max_size(2).build(manager).unwrap();

    let (s1, r1) = mpsc::channel();
    let (s2, r2) = mpsc::channel();

    let pool1 = pool.clone();
    let t1 = thread::spawn(move || {
        let conn = pool1.get().unwrap();
        let conn1: &Connection = &*conn;
        s1.send(()).unwrap();
        r2.recv().unwrap();
        drop(conn1);
    });

    let pool2 = pool.clone();
    let t2 = thread::spawn(move || {
        let conn = pool2.get().unwrap();
        s2.send(()).unwrap();
        r1.recv().unwrap();
        drop(conn);
    });

    t1.join().unwrap();
    t2.join().unwrap();

    pool.get().unwrap();
}

#[test]
fn test_is_valid() {
    let manager = SqliteConnectionManager::file("file.db");
    let pool = r2d2::Pool::builder()
        .max_size(1)
        .test_on_check_out(true)
        .build(manager)
        .unwrap();

    pool.get().unwrap();
}

#[test]
fn test_error_handling() {
    //! We specify a directory as a database. This is bound to fail.
    let dir = TempDir::new("r2d2-sqlite").expect("Could not create temporary directory");
    let dirpath = dir.path().to_str().unwrap();
    let manager = SqliteConnectionManager::file(dirpath);
    assert!(manager.connect().is_err());
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use std::env;

fn main() {
    let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let target_dir = env::var("CARGO_TARGET_DIR").unwrap();
    let profile_dir = env::var("PROFILE").unwrap();
    let dest = format!("{}/{}/{}", target_dir, profile_dir, "simpleservo.h");
    cbindgen::Builder::new()
        .with_crate(crate_dir)
        .with_language(cbindgen::Language::C)
        .generate()
        .expect("Unable to generate bindings")
        .write_to_file(dest);
}
<commit_msg>Do not include useless symbols to simpleservo.h<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use std::env;

fn main() {
    let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let target_dir = env::var("CARGO_TARGET_DIR").unwrap();
    let profile_dir = env::var("PROFILE").unwrap();
    let dest = format!("{}/{}/{}", target_dir, profile_dir, "simpleservo.h");
    cbindgen::Builder::new()
        .with_crate(crate_dir)
        .with_language(cbindgen::Language::C)
        .exclude_item("OutputDebugStringA")
        .generate()
        .expect("Unable to generate bindings")
        .write_to_file(dest);
}
<|endoftext|>


<commit_before>use ::internal_prelude::works_everywhere::*;
use std::sync::atomic::{AtomicU64, Ordering, ATOMIC_U64_INIT};

static NEXT_FLUENT_NODE_ID: AtomicU64 = ATOMIC_U64_INIT;

pub fn fluently() -> FluentNode {
    FluentNode::empty()
}

#[derive(Clone,Debug)]
pub struct FluentNode {
    input: Option<Box<FluentNode>>,
    canvas: Option<Box<FluentNode>>,
    data: Option<s::Node>,
    uid: u64,
}

impl FluentNode {
    fn next_uid() -> u64 {
        NEXT_FLUENT_NODE_ID.fetch_add(1, Ordering::SeqCst)
    }
    fn new(node: s::Node,
           input_node: Option<FluentNode>,
           canvas_node: Option<FluentNode>)
           -> FluentNode {
        FluentNode {
            input: input_node.and_then(|v| match v.is_empty() {
                true => None,
                false => Some(Box::new(v)),
            }),
            canvas: canvas_node.and_then(|v| match v.is_empty() {
                true => None,
                false => Some(Box::new(v)),
            }),
            data: Some(node),
            uid: FluentNode::next_uid(),
        }
    }
    pub fn empty() -> FluentNode {
        FluentNode {
            input: None,
            canvas: None,
            data: None,
            uid: FluentNode::next_uid(),
        }
    }

    pub fn is_empty(&self) -> bool {
        self.data.is_none()
    }

    pub fn to(self, v: s::Node) -> FluentNode {
        FluentNode::new(v, Some(self), None)
    }
    pub fn to_canvas(self, canvas: FluentNode, v: s::Node) -> FluentNode {
        FluentNode::new(v, Some(self), Some(canvas))
    }
    pub fn branch(&self) -> FluentNode {
        self.clone()
    }
    pub fn builder(self) -> FluentGraphBuilder {
        FluentGraphBuilder::new_with(self)
    }

    /// Injects placeholders
    pub fn to_build_0_1(self) -> s::Build001{
        self.builder().to_framewise().wrap_in_build_0_1()
    }

    pub fn constrain_within(self, w: Option<u32>, h: Option<u32>, resampling_hints: Option<s::ConstraintResamplingHints>) -> FluentNode{
        self.to(s::Node::Constrain(s::Constraint::Within{ w: w, h: h, hints: resampling_hints}))
    }

    pub fn canvas_bgra32(self,
                         w: usize,
                         // camelCased: #[serde(rename="fromY")]
                         h: usize,
                         color: s::Color)
                         -> FluentNode {
        self.to(s::Node::CreateCanvas {
            w: w,
            h: h,
            format: s::PixelFormat::Bgra32,
            color: color,
        })
    }

    pub fn create_canvas(self,
                         w: usize,
                         // camelCased: #[serde(rename="fromY")]
                         h: usize,
                         format: s::PixelFormat,
                         color: s::Color)
                         -> FluentNode {
        self.to(s::Node::CreateCanvas {
            w: w,
            h: h,
            format: format,
            color: color,
        })
    }

    pub fn decode(self, io_id: i32) -> FluentNode {
        self.to(s::Node::Decode {
            io_id: io_id,
            commands: None,
        })
    }
    pub fn encode(self, io_id: i32, preset: s::EncoderPreset) -> FluentNode {
        self.to(s::Node::Encode {
            io_id: io_id,
            preset: preset
        })
    }

    pub fn flip_vertical(self) -> FluentNode {
        self.to(s::Node::FlipV)
    }

    pub fn flip_horizontal(self) -> FluentNode {
        self.to(s::Node::FlipH)
    }

    pub fn rotate_90(self) -> FluentNode {
        self.to(s::Node::Rotate90)
    }
    pub fn rotate_180(self) -> FluentNode {
        self.to(s::Node::Rotate180)
    }
    pub fn rotate_270(self) -> FluentNode {
        self.to(s::Node::Rotate270)
    }

    pub fn transpose(self) -> FluentNode {
        self.to(s::Node::Transpose)
    }
    pub fn copy_rect_from(self,
                          from: FluentNode,
                          from_x: u32,
                          // camelCased: #[serde(rename="fromY")]
                          from_y: u32,
                          width: u32,
                          height: u32,
                          x: u32,
                          y: u32)
                          -> FluentNode {
        from.to_canvas(self,
                       s::Node::CopyRectToCanvas {
                           from_x: from_x,
                           from_y: from_y,
                           width: width,
                           height: height,
                           x: x,
                           y: y,
                       })
    }
}
impl PartialEq for FluentNode {
    fn eq(&self, other: &FluentNode) -> bool {
        self.uid == other.uid
    }
}

pub struct FluentGraphBuilder {
    output_nodes: Vec<Box<FluentNode>>,
}

impl FluentGraphBuilder {
    pub fn new() -> FluentGraphBuilder {
        FluentGraphBuilder { output_nodes: vec![] }
    }
    pub fn new_with(n: FluentNode) -> FluentGraphBuilder {
        FluentGraphBuilder { output_nodes: vec![Box::new(n)] }
    }

    pub fn with(self, n: FluentNode) -> FluentGraphBuilder {
        let mut new_vec = self.output_nodes.clone();
        new_vec.push(Box::new(n));
        FluentGraphBuilder { output_nodes: new_vec }
    }

    fn collect_unique(&self) -> Vec<&Box<FluentNode>> {
        let mut set = HashSet::new();
        let mut todo = Vec::new();
        let mut unique = Vec::new();
        for end in self.output_nodes.as_slice().iter() {
            todo.push(end);
        }

        loop {
            if todo.len() == 0 {
                break;
            }
            let next = todo.pop().unwrap();
            if !set.contains(&next.uid) {
                set.insert(next.uid);
                unique.push(next);
                if let Some(ref c) = next.canvas {
                    todo.push(&c);
                }
                if let Some(ref c) = next.input {
                    todo.push(&c);
                }
            }
        }

        unique
    }

    fn collect_edges(&self, for_nodes: &[&Box<FluentNode>]) -> Vec<(u64, u64, s::EdgeKind)> {
        let mut edges = vec![];
        for n in for_nodes {
            if let Some(ref parent) = n.canvas {
                edges.push((parent.uid, n.uid, s::EdgeKind::Canvas));
            }
            if let Some(ref parent) = n.input {
                edges.push((parent.uid, n.uid, s::EdgeKind::Input));
            }
        }
        edges
    }
    fn lowest_uid(for_nodes: &[&Box<FluentNode>]) -> Option<u64> {
        for_nodes.iter().map(|n| n.uid).min()
    }
    pub fn to_framewise(&self) -> s::Framewise {
        let nodes = self.collect_unique();
        let lowest_uid = FluentGraphBuilder::lowest_uid(&nodes).unwrap_or(0);
        let edges = self.collect_edges(&nodes);
        let framewise_edges = edges.into_iter()
            .map(|(from, to, kind)| {
                s::Edge {
                    from: (from - lowest_uid) as i32,
                    to: (to - lowest_uid) as i32,
                    kind: kind,
                }
            })
            .collect::<Vec<s::Edge>>();
        let mut framewise_nodes = HashMap::new();
        for n in nodes {
            let _ =
                framewise_nodes.insert((n.uid - lowest_uid).to_string(), n.data.clone().unwrap());
        }
        s::Framewise::Graph(s::Graph {
            edges: framewise_edges,
            nodes: framewise_nodes,
        })
    }

    //    pub fn to_graph(&self) -> ::Graph {
    //        let mut uid_map = HashMap::new();
    //        let from_list = self.collect_unique();
    //
    //        let mut g = ::Graph::with_capacity(from_list.len(), from_list.len() + 8);
    //        for n in from_list.as_slice(){
    //            if let Some(ref data) = n.data {
    //                let ix = g.add_node(::flow::definitions::Node::from(data.clone()));
    //                uid_map.insert(n.uid, ix);
    //            }
    //        }
    //
    //        for n in from_list.as_slice(){
    //            if let Some(ref parent) = n.canvas{
    //                g.add_edge(uid_map[&parent.uid], uid_map[&n.uid],::ffi::EdgeKind::Canvas).unwrap();
    //            }
    //            if let Some(ref parent) = n.input{
    //                g.add_edge(uid_map[&parent.uid], uid_map[&n.uid],::ffi::EdgeKind::Input).unwrap();
    //            }
    //        }
    //        g
    //    }
}

#[test]
fn test_graph_builder() {

    // let d = fluently().decode(0).flip_horizontal().rotate_90().
    let a = fluently()
        .to(s::Node::CreateCanvas {
            w: 200,
            h: 200,
            format: s::PixelFormat::Bgra32,
            color: s::Color::Black,
        })
        .to(s::Node::FlipV);
    let b = a.branch().to(s::Node::Encode {
        preset: s::EncoderPreset::libjpegturbo(),
        io_id: 0,
    });
    let c = a.branch()
        .to(s::Node::Resample2D {
            w: 100,
            h: 100,
            down_filter: None,
            up_filter: None,
            hints: None,
        })
        .to(s::Node::Encode {
            preset: s::EncoderPreset::libpng32(),
            io_id: 1,
        });
    b.builder().with(c).to_framewise();
}
<commit_msg>feat(fluent): use framewise steps when possible for simpler json<commit_after>use ::internal_prelude::works_everywhere::*;
use std::sync::atomic::{AtomicU64, Ordering, ATOMIC_U64_INIT};

static NEXT_FLUENT_NODE_ID: AtomicU64 = ATOMIC_U64_INIT;

pub fn fluently() -> FluentNode {
    FluentNode::empty()
}

#[derive(Clone,Debug)]
pub struct FluentNode {
    input: Option<Box<FluentNode>>,
    canvas: Option<Box<FluentNode>>,
    data: Option<s::Node>,
    uid: u64,
}

impl FluentNode {
    fn next_uid() -> u64 {
        NEXT_FLUENT_NODE_ID.fetch_add(1, Ordering::SeqCst)
    }
    fn new(node: s::Node,
           input_node: Option<FluentNode>,
           canvas_node: Option<FluentNode>)
           -> FluentNode {
        FluentNode {
            input: input_node.and_then(|v| match v.is_empty() {
                true => None,
                false => Some(Box::new(v)),
            }),
            canvas: canvas_node.and_then(|v| match v.is_empty() {
                true => None,
                false => Some(Box::new(v)),
            }),
            data: Some(node),
            uid: FluentNode::next_uid(),
        }
    }
    pub fn empty() -> FluentNode {
        FluentNode {
            input: None,
            canvas: None,
            data: None,
            uid: FluentNode::next_uid(),
        }
    }

    pub fn is_empty(&self) -> bool {
        self.data.is_none()
    }

    pub fn to(self, v: s::Node) -> FluentNode {
        FluentNode::new(v, Some(self), None)
    }
    pub fn to_canvas(self, canvas: FluentNode, v: s::Node) -> FluentNode {
        FluentNode::new(v, Some(self), Some(canvas))
    }
    pub fn branch(&self) -> FluentNode {
        self.clone()
    }
    pub fn builder(self) -> FluentGraphBuilder {
        FluentGraphBuilder::new_with(self)
    }

    /// Injects placeholders
    pub fn to_build_0_1(self) -> s::Build001{
        self.builder().to_framewise().wrap_in_build_0_1()
    }

    pub fn constrain_within(self, w: Option<u32>, h: Option<u32>, resampling_hints: Option<s::ConstraintResamplingHints>) -> FluentNode{
        self.to(s::Node::Constrain(s::Constraint::Within{ w: w, h: h, hints: resampling_hints}))
    }

    pub fn canvas_bgra32(self,
                         w: usize,
                         // camelCased: #[serde(rename="fromY")]
                         h: usize,
                         color: s::Color)
                         -> FluentNode {
        self.to(s::Node::CreateCanvas {
            w: w,
            h: h,
            format: s::PixelFormat::Bgra32,
            color: color,
        })
    }

    pub fn create_canvas(self,
                         w: usize,
                         // camelCased: #[serde(rename="fromY")]
                         h: usize,
                         format: s::PixelFormat,
                         color: s::Color)
                         -> FluentNode {
        self.to(s::Node::CreateCanvas {
            w: w,
            h: h,
            format: format,
            color: color,
        })
    }

    pub fn decode(self, io_id: i32) -> FluentNode {
        self.to(s::Node::Decode {
            io_id: io_id,
            commands: None,
        })
    }
    pub fn encode(self, io_id: i32, preset: s::EncoderPreset) -> FluentNode {
        self.to(s::Node::Encode {
            io_id: io_id,
            preset: preset
        })
    }

    pub fn flip_vertical(self) -> FluentNode {
        self.to(s::Node::FlipV)
    }

    pub fn flip_horizontal(self) -> FluentNode {
        self.to(s::Node::FlipH)
    }

    pub fn rotate_90(self) -> FluentNode {
        self.to(s::Node::Rotate90)
    }
    pub fn rotate_180(self) -> FluentNode {
        self.to(s::Node::Rotate180)
    }
    pub fn rotate_270(self) -> FluentNode {
        self.to(s::Node::Rotate270)
    }

    pub fn transpose(self) -> FluentNode {
        self.to(s::Node::Transpose)
    }
    pub fn copy_rect_from(self,
                          from: FluentNode,
                          from_x: u32,
                          // camelCased: #[serde(rename="fromY")]
                          from_y: u32,
                          width: u32,
                          height: u32,
                          x: u32,
                          y: u32)
                          -> FluentNode {
        from.to_canvas(self,
                       s::Node::CopyRectToCanvas {
                           from_x: from_x,
                           from_y: from_y,
                           width: width,
                           height: height,
                           x: x,
                           y: y,
                       })
    }
}
impl PartialEq for FluentNode {
    fn eq(&self, other: &FluentNode) -> bool {
        self.uid == other.uid
    }
}

pub struct FluentGraphBuilder {
    output_nodes: Vec<Box<FluentNode>>,
}

impl FluentGraphBuilder {
    pub fn new() -> FluentGraphBuilder {
        FluentGraphBuilder { output_nodes: vec![] }
    }
    pub fn new_with(n: FluentNode) -> FluentGraphBuilder {
        FluentGraphBuilder { output_nodes: vec![Box::new(n)] }
    }

    pub fn with(self, n: FluentNode) -> FluentGraphBuilder {
        let mut new_vec = self.output_nodes.clone();
        new_vec.push(Box::new(n));
        FluentGraphBuilder { output_nodes: new_vec }
    }

    fn collect_unique(&self) -> Vec<&Box<FluentNode>> {
        let mut set = HashSet::new();
        let mut todo = Vec::new();
        let mut unique = Vec::new();
        for end in self.output_nodes.as_slice().iter() {
            todo.push(end);
        }

        loop {
            if todo.len() == 0 {
                break;
            }
            let next = todo.pop().unwrap();
            if !set.contains(&next.uid) {
                set.insert(next.uid);
                unique.push(next);
                if let Some(ref c) = next.canvas {
                    todo.push(&c);
                }
                if let Some(ref c) = next.input {
                    todo.push(&c);
                }
            }
        }

        unique
    }

    fn collect_edges(&self, for_nodes: &[&Box<FluentNode>]) -> Vec<(u64, u64, s::EdgeKind)> {
        let mut edges = vec![];
        for n in for_nodes {
            if let Some(ref parent) = n.canvas {
                edges.push((parent.uid, n.uid, s::EdgeKind::Canvas));
            }
            if let Some(ref parent) = n.input {
                edges.push((parent.uid, n.uid, s::EdgeKind::Input));
            }
        }
        edges
    }
    fn lowest_uid(for_nodes: &[&Box<FluentNode>]) -> Option<u64> {
        for_nodes.iter().map(|n| n.uid).min()
    }
    pub fn to_framewise(&self) -> s::Framewise {
        let mut nodes = self.collect_unique();
        if self.output_nodes.len() == 1 && nodes.as_slice().iter().all(|n| n.canvas == None) {
            nodes.sort_by(|a,b|a.uid.cmp(&b.uid));
            s::Framewise::Steps(nodes.into_iter().map(|b| b.data.clone().unwrap()).collect::<Vec<s::Node>>())
        }else{
            self.to_framewise_graph()
        }
    }
    pub fn to_framewise_graph(&self) -> s::Framewise {
        let nodes = self.collect_unique();
        let lowest_uid = FluentGraphBuilder::lowest_uid(&nodes).unwrap_or(0);
        let edges = self.collect_edges(&nodes);
        let framewise_edges = edges.into_iter()
            .map(|(from, to, kind)| {
                s::Edge {
                    from: (from - lowest_uid) as i32,
                    to: (to - lowest_uid) as i32,
                    kind: kind,
                }
            })
            .collect::<Vec<s::Edge>>();
        let mut framewise_nodes = HashMap::new();
        for n in nodes {
            let _ =
                framewise_nodes.insert((n.uid - lowest_uid).to_string(), n.data.clone().unwrap());
        }
        s::Framewise::Graph(s::Graph {
            edges: framewise_edges,
            nodes: framewise_nodes,
        })
    }

    //    pub fn to_graph(&self) -> ::Graph {
    //        let mut uid_map = HashMap::new();
    //        let from_list = self.collect_unique();
    //
    //        let mut g = ::Graph::with_capacity(from_list.len(), from_list.len() + 8);
    //        for n in from_list.as_slice(){
    //            if let Some(ref data) = n.data {
    //                let ix = g.add_node(::flow::definitions::Node::from(data.clone()));
    //                uid_map.insert(n.uid, ix);
    //            }
    //        }
    //
    //        for n in from_list.as_slice(){
    //            if let Some(ref parent) = n.canvas{
    //                g.add_edge(uid_map[&parent.uid], uid_map[&n.uid],::ffi::EdgeKind::Canvas).unwrap();
    //            }
    //            if let Some(ref parent) = n.input{
    //                g.add_edge(uid_map[&parent.uid], uid_map[&n.uid],::ffi::EdgeKind::Input).unwrap();
    //            }
    //        }
    //        g
    //    }
}

#[test]
fn test_graph_builder() {

    // let d = fluently().decode(0).flip_horizontal().rotate_90().
    let a = fluently()
        .to(s::Node::CreateCanvas {
            w: 200,
            h: 200,
            format: s::PixelFormat::Bgra32,
            color: s::Color::Black,
        })
        .to(s::Node::FlipV);
    let b = a.branch().to(s::Node::Encode {
        preset: s::EncoderPreset::libjpegturbo(),
        io_id: 0,
    });
    let c = a.branch()
        .to(s::Node::Resample2D {
            w: 100,
            h: 100,
            down_filter: None,
            up_filter: None,
            hints: None,
        })
        .to(s::Node::Encode {
            preset: s::EncoderPreset::libpng32(),
            io_id: 1,
        });
    b.builder().with(c).to_framewise();
}
<|endoftext|>


<commit_before>#[doc = "Rust TNetStrings serialization library."];

use std;
import option::{some, none};
import std::map;
import std::map::hashmap;
import std::rand;

import io::writer_util;
import io::reader_util;

export t;
export str;
export int;
export float;
export bool;
export null;
export map;
export vec;
export to_writer;
export to_bytes;
export to_str;
export from_reader;
export from_bytes;
export from_str;

#[doc = "Represents a tnetstring value."]
enum t {
    #[doc = "str"]
    str([u8]),
    #[doc = "int"]
    int(int),
    #[doc = "floating"]
    float(float),
    #[doc = "boolean"]
    bool(bool),
    #[doc = "null"]
    null,
    #[doc = "map"]
    map(map::hashmap<[u8], t>),
    #[doc = "list"]
    vec([t]),
}

#[doc = "Serializes a tnetstring value into a io::writer."]
fn to_writer(writer: io::writer, t: t) {
    alt t {
        str(s) {
            writer.write_str(#fmt("%u:", vec::len(s)));
            writer.write(s);
            writer.write_char(',');
        }
        int(i) {
            let s = int::str(i);
            writer.write_str(#fmt("%u:%s#", str::len(s), s));
        }
        float(f) {
            let s = float::to_str(f, 6u);
            writer.write_str(#fmt("%u:%s^", str::len(s), s));
        }
        bool(b) {
            let s = bool::to_str(b);
            writer.write_str(#fmt("%u:%s!", str::len(s), s));
        }
        map(m) {
            let buf = io::mem_buffer();
            let wr = io::mem_buffer_writer(buf);
            for m.each { |key, value|
                to_writer(wr, str(key));
                to_writer(wr, value);
            }
            let payload = io::mem_buffer_buf(buf);
            writer.write_str(#fmt("%u:", vec::len(payload)));
            writer.write(payload);
            writer.write_char('}');
        }
        vec(l) {
            let buf = io::mem_buffer();
            let wr = io::mem_buffer_writer(buf);
            vec::iter(l, {|e| to_writer(wr, e) });
            let payload = io::mem_buffer_buf(buf);
            writer.write_str(#fmt("%u:", vec::len(payload)));
            writer.write(payload);
            writer.write_char(']');
        }
        null {
            writer.write_str("0:~");
        }
    }
}

#[doc = "Serializes a tnetstring value into a byte string."]
fn to_bytes(t: t) -> [u8] {
    let buf = io::mem_buffer();
    let wr = io::mem_buffer_writer(buf);
    to_writer(wr, t);
    io::mem_buffer_buf(buf)
}

#[doc = "Serializes a tnetstring value into a string."]
fn to_str(t: t) -> str {
    let buf = io::mem_buffer();
    let wr = io::mem_buffer_writer(buf);
    to_writer(wr, t);
    io::mem_buffer_str(buf)
}

#[doc = "Deserializes a tnetstring value from an io::reader."]
fn from_reader(reader: io::reader) -> option<t> {
    assert !reader.eof();

    let mut c = reader.read_byte();
    let mut len = 0u;

    // Note that netstring spec explicitly forbids padding zeros.
    // If the first char is zero, it must be the only char.
    if c < '0' as int || c > '9' as int {
        fail "Not a tnetstring: invalid or missing length prefix";
    } else if c == '0' as int {
        c = reader.read_byte();
    } else {
        do {
            len = (10u * len) + ((c as uint) - ('0' as uint));

            if reader.eof() {
                fail "Not a tnetstring: invalid or missing length prefix";
            }
            c = reader.read_byte();
        } while c >= '0' as int && c <= '9' as int;
    }

    // Validate end-of-length-prefix marker.
    if c != ':' as int {
        fail "Not a tnetstring: missing length prefix";
    }

    // Read the data plus terminating type tag.
    let payload = reader.read_bytes(len);

    if vec::len(payload) != len {
        fail "Not a tnetstring: invalid length prefix";
    }

    if reader.eof() {
        fail "Not a tnetstring: missing type tag";
    }

    alt reader.read_byte() as char {
      '#' {
        let s = unsafe { str::unsafe::from_bytes(payload) };
        option::chain(int::from_str(s)) {|v| some(int(v)) }
      }
      '}' { some(map(parse_map(payload))) }
      ']' { some(vec(parse_vec(payload))) }
      '!' {
        let s = unsafe { str::unsafe::from_bytes(payload) };
        option::chain(bool::from_str(s)) {|v| some(bool(v)) }
      }
      '^' {
        let s = unsafe { str::unsafe::from_bytes(payload) };
        option::chain(float::from_str(s)) {|v| some(float(v)) }
      }
      '~' {
        assert vec::len(payload) == 0u;
        some(null)
      }
      ',' { some(str(payload)) }
      c {
        let s = str::from_char(c);
        fail #fmt("Invalid payload type: %?", s)
      }
    }
}

fn parse_vec(data: [u8]) -> [t] {
    if vec::len(data) == 0u { ret []; }

    let reader = io::bytes_reader(data);

    let value = from_reader(reader);
    assert option::is_some(value);
    let mut result = [option::get(value)];

    while !reader.eof() {
        let value = from_reader(reader);
        assert option::is_some(value);
        vec::push(result, option::get(value));
    }

    ret result;
}

fn parse_pair(reader: io::reader) -> ([u8], t) {
    let key = from_reader(reader);
    assert option::is_some(key);
    assert !reader.eof();

    let key = alt option::get(key) {
        str(key) { key }
        _ { fail "Keys can only be strings." }
    };

    let value = from_reader(reader);
    assert option::is_some(value);

    ret (key, option::get(value));
}

fn parse_map(data: [u8]) -> map::hashmap<[u8], t> {
    if vec::len(data) == 0u { ret map::bytes_hash(); }

    let reader = io::bytes_reader(data);
    let (key, value) = parse_pair(reader);

    let result = map::bytes_hash();
    result.insert(key, value);

    while !reader.eof() {
        let (key, value) = parse_pair(reader);
        result.insert(key, value);
    }

    ret result;
}

#[doc = "Deserializes a tnetstring value from a byte string."]
fn from_bytes(data: [u8]) -> (option<t>, [u8]) {
    let rdr = io::bytes_reader(data);
    let tnetstring = from_reader(rdr);
    (tnetstring, rdr.read_whole_stream())
}

#[doc = "Deserializes a tnetstring value from a string."]
fn from_str(data: str) -> (option<t>, str) {
    io::with_str_reader(data) {|rdr|
        let tnetstring = from_reader(rdr);
        let bytes = rdr.read_whole_stream();
        (tnetstring, str::from_bytes(bytes))
    }

}

#[doc = "Test the equality between two tnetstring values"]
fn eq(t0: t, t1: t) -> bool {
    alt (t0, t1) {
        (str(s0), str(s1)) { s0 == s1 }
        (int(i0), int(i1)) { i0 == i1 }
        (float(f0), float(f1)) { f0 == f1 }
        (bool(b0), bool(b1)) { b0 == b1 }
        (null, null) { true }
        (map(d0), map(d1)) {
          if d0.size() == d1.size() {
              for d0.each() { |k, v|
                  if !d1.contains_key(k) || !eq(d1.get(k), v) {
                      ret false;
                  }
              }
              true
          } else {
              false
          }
        }
        (vec(l0), vec(l1)) { vec::all2(l0, l1, eq) }
        _ { false }
    }
}

#[cfg(test)]
mod tests {
    // Tests inspired by https://github.com/rfk/tnetstring.

    fn test(string: str, expected: t) {
        let (actual, rest) = from_str(string);
        assert option::is_some(actual);
        assert rest == "";

        let actual = option::get(actual);
        assert eq(actual, expected);
        assert to_str(expected) == string;
    }

    #[test]
    fn test_format() {
        test("11:hello world,", str(str::bytes("hello world")));
        test("0:}", map(map::bytes_hash()));
        test("0:]", vec([]));

        let d = map::bytes_hash();
        d.insert(str::bytes("hello"),
                vec([
                    int(12345678901),
                    str(str::bytes("this")),
                    bool(true),
                    null,
                    str(str::bytes("\x00\x00\x00\x00"))]));

        test("51:5:hello,39:11:12345678901#4:this,4:true!0:~4:\x00\x00\x00" +
            "\x00,]}", map(d));

        test("5:12345#", int(12345));
        test("12:this is cool,", str(str::bytes("this is cool")));
        test("0:,", str(str::bytes("")));
        test("0:~", null);
        test("4:true!", bool(true));
        test("5:false!", bool(false));
        test("10:\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00,",
            str(str::bytes("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")));
        test("24:5:12345#5:67890#5:xxxxx,]",
            vec(
                [int(12345),
                int(67890),
                str(str::bytes("xxxxx"))]));
        test("18:3:0.1^3:0.2^3:0.4^]",
           vec([float(0.1), float(0.2), float(0.4)]));
        test("243:238:233:228:223:218:213:208:203:198:193:188:183:178:173:" +
            "168:163:158:153:148:143:138:133:128:123:118:113:108:103:99:95:" +
            "91:87:83:79:75:71:67:63:59:55:51:47:43:39:35:31:27:23:19:15:" +
            "11:hello-there,]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]" +
            "]]]]",
            vec(
                [vec([vec([vec([vec([vec([vec([vec([vec(
                [vec([vec([vec([vec([vec([vec([vec([vec(
                [vec([vec([vec([vec([vec([vec([vec([vec(
                [vec([vec([vec([vec([vec([vec([vec([vec(
                [vec([vec([vec([vec([vec([vec([vec([vec(
                [vec([vec([vec([vec([vec([vec([vec([vec(
                [vec([vec([
                    str(str::bytes("hello-there"))
                ])])])])])])])])])])])])])])])])])])])])])])])])])])])])
                ])])])])])])])])])])])])])])])])])])])])])])]));
    }

    #[test]
    fn test_random() {
        fn randint(rng: rand::rng, a: u32, b: u32) -> u32 {
            (rng.next() % (b - a + 1u32)) + a
        }

        fn get_random_object(rng: rand::rng, depth: u32) -> t {
            if randint(rng, depth, 10u32) <= 4u32 {
                if randint(rng, 0u32, 1u32) == 0u32 {
                    let n = randint(rng, 0u32, 10u32);
                    vec(vec::from_fn(n as uint) { |_i|
                        get_random_object(rng, depth + 1u32)
                    })
                } else {
                    let d = map::bytes_hash();

                    let mut i = randint(rng, 0u32, 10u32);
                    while i != 0u32 {
                        let s = rng.gen_bytes(randint(rng, 0u32, 100u32) as uint);
                        d.insert(s, get_random_object(rng, depth + 1u32));
                        i -= 1u32;
                    }
                    map(d)
                }
            } else {
                alt randint(rng, 0u32, 5u32) {
                  0u32 { null }
                  1u32 { bool(true) }
                  2u32 { bool(false) }
                  3u32 {
                    if randint(rng, 0u32, 1u32) == 0u32 {
                        int(rng.next() as int)
                    } else {
                        int(-rng.next() as int)
                    }
                  }
                  4u32 {
                    let mut f = rng.next_float();

                    // Generate a float that can be exactly converted to
                    // and from a string.
                    while true {
                        alt float::from_str(float::to_str(f, 6u)) {
                          some(f1) {
                            if f == f1 { break; }
                            f = f1;
                          }
                          none { fail }
                        }
                    }

                    if randint(rng, 0u32, 1u32) == 0u32 {
                        float(f)
                    } else {
                        float(-f)
                    }
                  }
                  5u32 {
                    str(rng.gen_bytes(randint(rng, 0u32, 100u32) as uint))
                  }
                  _ { fail }
                }
            }
        }

        let rng = rand::rng();

        let mut i = 500u;
        while i != 0u {
            let v0 = get_random_object(rng, 0u32);

            alt from_bytes(to_bytes(v0)) {
                (some(v1), rest) if rest == [] {
                    assert eq(v0, v1);
                }
                _ { fail; }
            }
            i -= 1u;
        }
    }
}
<commit_msg>Update to rust a6b9fa.<commit_after>#[doc = "Rust TNetStrings serialization library."];

use std;
import option::{some, none};
import std::map;
import std::map::hashmap;
import std::rand;

import io::writer_util;
import io::reader_util;

export t;
export str;
export int;
export float;
export bool;
export null;
export map;
export vec;
export to_writer;
export to_bytes;
export to_str;
export from_reader;
export from_bytes;
export from_str;

#[doc = "Represents a tnetstring value."]
enum t {
    #[doc = "str"]
    str([u8]),
    #[doc = "int"]
    int(int),
    #[doc = "floating"]
    float(float),
    #[doc = "boolean"]
    bool(bool),
    #[doc = "null"]
    null,
    #[doc = "map"]
    map(map::hashmap<[u8], t>),
    #[doc = "list"]
    vec([t]),
}

#[doc = "Serializes a tnetstring value into a io::writer."]
fn to_writer(writer: io::writer, t: t) {
    alt t {
        str(s) {
            writer.write_str(#fmt("%u:", vec::len(s)));
            writer.write(s);
            writer.write_char(',');
        }
        int(i) {
            let s = int::str(i);
            writer.write_str(#fmt("%u:%s#", str::len(s), s));
        }
        float(f) {
            let s = float::to_str(f, 6u);
            writer.write_str(#fmt("%u:%s^", str::len(s), s));
        }
        bool(b) {
            let s = bool::to_str(b);
            writer.write_str(#fmt("%u:%s!", str::len(s), s));
        }
        map(m) {
            let buf = io::mem_buffer();
            let wr = io::mem_buffer_writer(buf);
            for m.each { |key, value|
                to_writer(wr, str(key));
                to_writer(wr, value);
            }
            let payload = io::mem_buffer_buf(buf);
            writer.write_str(#fmt("%u:", vec::len(payload)));
            writer.write(payload);
            writer.write_char('}');
        }
        vec(l) {
            let buf = io::mem_buffer();
            let wr = io::mem_buffer_writer(buf);
            vec::iter(l, {|e| to_writer(wr, e) });
            let payload = io::mem_buffer_buf(buf);
            writer.write_str(#fmt("%u:", vec::len(payload)));
            writer.write(payload);
            writer.write_char(']');
        }
        null {
            writer.write_str("0:~");
        }
    }
}

#[doc = "Serializes a tnetstring value into a byte string."]
fn to_bytes(t: t) -> [u8] {
    let buf = io::mem_buffer();
    let wr = io::mem_buffer_writer(buf);
    to_writer(wr, t);
    io::mem_buffer_buf(buf)
}

#[doc = "Serializes a tnetstring value into a string."]
fn to_str(t: t) -> str {
    let buf = io::mem_buffer();
    let wr = io::mem_buffer_writer(buf);
    to_writer(wr, t);
    io::mem_buffer_str(buf)
}

#[doc = "Deserializes a tnetstring value from an io::reader."]
fn from_reader(reader: io::reader) -> option<t> {
    assert !reader.eof();

    let mut c = reader.read_byte();
    let mut len = 0u;

    // Note that netstring spec explicitly forbids padding zeros.
    // If the first char is zero, it must be the only char.
    if c < '0' as int || c > '9' as int {
        fail "Not a tnetstring: invalid or missing length prefix";
    } else if c == '0' as int {
        c = reader.read_byte();
    } else {
        loop {
            len = (10u * len) + ((c as uint) - ('0' as uint));

            if reader.eof() {
                fail "Not a tnetstring: invalid or missing length prefix";
            }
            c = reader.read_byte();

            if c < '0' as int || c > '9' as int {
                break;
            }
        }
    }

    // Validate end-of-length-prefix marker.
    if c != ':' as int {
        fail "Not a tnetstring: missing length prefix";
    }

    // Read the data plus terminating type tag.
    let payload = reader.read_bytes(len);

    if vec::len(payload) != len {
        fail "Not a tnetstring: invalid length prefix";
    }

    if reader.eof() {
        fail "Not a tnetstring: missing type tag";
    }

    alt reader.read_byte() as char {
      '#' {
        let s = unsafe { str::unsafe::from_bytes(payload) };
        option::chain(int::from_str(s)) {|v| some(int(v)) }
      }
      '}' { some(map(parse_map(payload))) }
      ']' { some(vec(parse_vec(payload))) }
      '!' {
        let s = unsafe { str::unsafe::from_bytes(payload) };
        option::chain(bool::from_str(s)) {|v| some(bool(v)) }
      }
      '^' {
        let s = unsafe { str::unsafe::from_bytes(payload) };
        option::chain(float::from_str(s)) {|v| some(float(v)) }
      }
      '~' {
        assert vec::len(payload) == 0u;
        some(null)
      }
      ',' { some(str(payload)) }
      c {
        let s = str::from_char(c);
        fail #fmt("Invalid payload type: %?", s)
      }
    }
}

fn parse_vec(data: [u8]) -> [t] {
    if vec::len(data) == 0u { ret []; }

    let reader = io::bytes_reader(data);

    let value = from_reader(reader);
    assert option::is_some(value);
    let mut result = [option::get(value)];

    while !reader.eof() {
        let value = from_reader(reader);
        assert option::is_some(value);
        vec::push(result, option::get(value));
    }

    ret result;
}

fn parse_pair(reader: io::reader) -> ([u8], t) {
    let key = from_reader(reader);
    assert option::is_some(key);
    assert !reader.eof();

    let key = alt option::get(key) {
        str(key) { key }
        _ { fail "Keys can only be strings." }
    };

    let value = from_reader(reader);
    assert option::is_some(value);

    ret (key, option::get(value));
}

fn parse_map(data: [u8]) -> map::hashmap<[u8], t> {
    if vec::len(data) == 0u { ret map::bytes_hash(); }

    let reader = io::bytes_reader(data);
    let (key, value) = parse_pair(reader);

    let result = map::bytes_hash();
    result.insert(key, value);

    while !reader.eof() {
        let (key, value) = parse_pair(reader);
        result.insert(key, value);
    }

    ret result;
}

#[doc = "Deserializes a tnetstring value from a byte string."]
fn from_bytes(data: [u8]) -> (option<t>, [u8]) {
    let rdr = io::bytes_reader(data);
    let tnetstring = from_reader(rdr);
    (tnetstring, rdr.read_whole_stream())
}

#[doc = "Deserializes a tnetstring value from a string."]
fn from_str(data: str) -> (option<t>, str) {
    io::with_str_reader(data) {|rdr|
        let tnetstring = from_reader(rdr);
        let bytes = rdr.read_whole_stream();
        (tnetstring, str::from_bytes(bytes))
    }

}

#[doc = "Test the equality between two tnetstring values"]
fn eq(t0: t, t1: t) -> bool {
    alt (t0, t1) {
        (str(s0), str(s1)) { s0 == s1 }
        (int(i0), int(i1)) { i0 == i1 }
        (float(f0), float(f1)) { f0 == f1 }
        (bool(b0), bool(b1)) { b0 == b1 }
        (null, null) { true }
        (map(d0), map(d1)) {
          if d0.size() == d1.size() {
              for d0.each() { |k, v|
                  if !d1.contains_key(k) || !eq(d1.get(k), v) {
                      ret false;
                  }
              }
              true
          } else {
              false
          }
        }
        (vec(l0), vec(l1)) { vec::all2(l0, l1, eq) }
        _ { false }
    }
}

#[cfg(test)]
mod tests {
    // Tests inspired by https://github.com/rfk/tnetstring.

    fn test(string: str, expected: t) {
        let (actual, rest) = from_str(string);
        assert option::is_some(actual);
        assert rest == "";

        let actual = option::get(actual);
        assert eq(actual, expected);
        assert to_str(expected) == string;
    }

    #[test]
    fn test_format() {
        test("11:hello world,", str(str::bytes("hello world")));
        test("0:}", map(map::bytes_hash()));
        test("0:]", vec([]));

        let d = map::bytes_hash();
        d.insert(str::bytes("hello"),
                vec([
                    int(12345678901),
                    str(str::bytes("this")),
                    bool(true),
                    null,
                    str(str::bytes("\x00\x00\x00\x00"))]));

        test("51:5:hello,39:11:12345678901#4:this,4:true!0:~4:\x00\x00\x00" +
            "\x00,]}", map(d));

        test("5:12345#", int(12345));
        test("12:this is cool,", str(str::bytes("this is cool")));
        test("0:,", str(str::bytes("")));
        test("0:~", null);
        test("4:true!", bool(true));
        test("5:false!", bool(false));
        test("10:\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00,",
            str(str::bytes("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")));
        test("24:5:12345#5:67890#5:xxxxx,]",
            vec(
                [int(12345),
                int(67890),
                str(str::bytes("xxxxx"))]));
        test("18:3:0.1^3:0.2^3:0.4^]",
           vec([float(0.1), float(0.2), float(0.4)]));
        test("243:238:233:228:223:218:213:208:203:198:193:188:183:178:173:" +
            "168:163:158:153:148:143:138:133:128:123:118:113:108:103:99:95:" +
            "91:87:83:79:75:71:67:63:59:55:51:47:43:39:35:31:27:23:19:15:" +
            "11:hello-there,]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]" +
            "]]]]",
            vec(
                [vec([vec([vec([vec([vec([vec([vec([vec(
                [vec([vec([vec([vec([vec([vec([vec([vec(
                [vec([vec([vec([vec([vec([vec([vec([vec(
                [vec([vec([vec([vec([vec([vec([vec([vec(
                [vec([vec([vec([vec([vec([vec([vec([vec(
                [vec([vec([vec([vec([vec([vec([vec([vec(
                [vec([vec([
                    str(str::bytes("hello-there"))
                ])])])])])])])])])])])])])])])])])])])])])])])])])])])])
                ])])])])])])])])])])])])])])])])])])])])])])]));
    }

    #[test]
    fn test_random() {
        fn randint(rng: rand::rng, a: u32, b: u32) -> u32 {
            (rng.next() % (b - a + 1u32)) + a
        }

        fn get_random_object(rng: rand::rng, depth: u32) -> t {
            if randint(rng, depth, 10u32) <= 4u32 {
                if randint(rng, 0u32, 1u32) == 0u32 {
                    let n = randint(rng, 0u32, 10u32);
                    vec(vec::from_fn(n as uint) { |_i|
                        get_random_object(rng, depth + 1u32)
                    })
                } else {
                    let d = map::bytes_hash();

                    let mut i = randint(rng, 0u32, 10u32);
                    while i != 0u32 {
                        let s = rng.gen_bytes(randint(rng, 0u32, 100u32) as uint);
                        d.insert(s, get_random_object(rng, depth + 1u32));
                        i -= 1u32;
                    }
                    map(d)
                }
            } else {
                alt randint(rng, 0u32, 5u32) {
                  0u32 { null }
                  1u32 { bool(true) }
                  2u32 { bool(false) }
                  3u32 {
                    if randint(rng, 0u32, 1u32) == 0u32 {
                        int(rng.next() as int)
                    } else {
                        int(-rng.next() as int)
                    }
                  }
                  4u32 {
                    let mut f = rng.next_float();

                    // Generate a float that can be exactly converted to
                    // and from a string.
                    loop {
                        alt float::from_str(float::to_str(f, 6u)) {
                          some(f1) {
                            if f == f1 { break; }
                            f = f1;
                          }
                          none { fail }
                        }
                    }

                    if randint(rng, 0u32, 1u32) == 0u32 {
                        float(f)
                    } else {
                        float(-f)
                    }
                  }
                  5u32 {
                    str(rng.gen_bytes(randint(rng, 0u32, 100u32) as uint))
                  }
                  _ { fail }
                }
            }
        }

        let rng = rand::rng();

        let mut i = 500u;
        while i != 0u {
            let v0 = get_random_object(rng, 0u32);

            alt from_bytes(to_bytes(v0)) {
                (some(v1), rest) if rest == [] {
                    assert eq(v0, v1);
                }
                _ { fail; }
            }
            i -= 1u;
        }
    }
}
<|endoftext|>


<commit_before>extern crate log_domain;
extern crate rustomata;

use log_domain::LogDomain;

use rustomata::approximation::ApproximationStrategy;
use rustomata::approximation::equivalence_classes::EquivalenceRelation;
use rustomata::approximation::relabel::RlbElement;
use rustomata::cfg::*;
use rustomata::push_down_automaton::*;
use rustomata::recognisable::*;

#[test]
fn test_relabel_pushdown() {
    //create (and test) initial push down automata
    let r0_string = "S → [Nt A] # 1";
    let r1_string = "A → [T a, Nt A, Nt B  ] # 0.6";
    let r2_string = "A → [T a              ] # 0.4";
    let r3_string = "B → [T b, Nt B, Nt A  ] # 0.3";
    let r4_string = "B → [T b              ] # 0.7";

    let mut g_string = String::from("initial: [S, B]\n\n");
    g_string.push_str(r0_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r1_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r2_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r3_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r4_string.clone());

    let g: CFG<String, String, LogDomain<f64>> = g_string.parse().unwrap();

    let a = PushDownAutomaton::from(g);

    let mut e_string = String::from("S [S]\n");
    e_string.push_str("N [A, B]\n");
    e_string.push_str("R [*]\n");

    let e: EquivalenceRelation<String, String> = e_string.parse().unwrap();

    let f = |ps: &PushState<_, _>| ps.map(|nt| e.project(nt));
    let rlb = RlbElement::new(&f);

    let (b, _) = rlb.approximate_automaton(&a);

    assert_ne!(None, b.recognise(vec!["a".to_string() ]).next());
    assert_eq!(None, b.recognise(vec!["a".to_string(), "a".to_string(), "a".to_string(), "b".to_string() ]).next());
    assert_ne!(None, b.recognise(vec!["a".to_string(), "a".to_string(), "a".to_string(), "b".to_string(), "b".to_string(), "b".to_string(), "a".to_string() ]).next());
    assert_ne!(None, b.recognise(vec!["a".to_string(), "a".to_string(), "a".to_string(), "b".to_string(), "b".to_string() ]).next());

    assert_ne!(None, b.recognise(vec!["a".to_string(), "a".to_string(), "a".to_string(), "a".to_string(), "a".to_string() ]).next());
}

#[test]
fn test_relabel_check() {
    //create (and test) initial push down automata
    let r0_string = "S → [Nt A] # 1";
    let r1_string = "A → [T a, Nt A, Nt B  ] # 0.6";
    let r2_string = "A → [T a              ] # 0.4";
    let r3_string = "B → [T b, Nt B, Nt A  ] # 0.3";
    let r4_string = "B → [T b              ] # 0.7";

    let mut g_string = String::from("initial: [S, B]\n\n");
    g_string.push_str(r0_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r1_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r2_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r3_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r4_string.clone());

    let g: CFG<String, String, LogDomain<f64>> = g_string.parse().unwrap();

    let a = PushDownAutomaton::from(g);

    let mut e_string = String::from("S [S]\n");
    e_string.push_str("N [A, B]\n");
    e_string.push_str("R *\n");

    let e: EquivalenceRelation<String, String> = e_string.parse().unwrap();

    let f = |ps: &PushState<_, _>| ps.map(|nt| e.project(nt));
    let rlb = RlbElement::new(&f);

    let (b, _) = rlb.approximate_automaton(&a);

    let itemb = b.recognise(vec!["a".to_string(), "a".to_string(), "a".to_string(), "a".to_string(), "a".to_string() ]).next();
    assert_ne!(None, itemb);
}
<commit_msg>tests/cfg.rs: fixed test_relabel_pushdown()<commit_after>extern crate log_domain;
extern crate rustomata;

use log_domain::LogDomain;

use rustomata::approximation::ApproximationStrategy;
use rustomata::approximation::equivalence_classes::EquivalenceRelation;
use rustomata::approximation::relabel::RlbElement;
use rustomata::cfg::*;
use rustomata::push_down_automaton::*;
use rustomata::recognisable::*;

#[test]
fn test_relabel_pushdown() {
    //create (and test) initial push down automata
    let r0_string = "S → [Nt A] # 1";
    let r1_string = "A → [T a, Nt A, Nt B  ] # 0.6";
    let r2_string = "A → [T a              ] # 0.4";
    let r3_string = "B → [T b, Nt B, Nt A  ] # 0.3";
    let r4_string = "B → [T b              ] # 0.7";

    let mut g_string = String::from("initial: [S, B]\n\n");
    g_string.push_str(r0_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r1_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r2_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r3_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r4_string.clone());

    let g: CFG<String, String, LogDomain<f64>> = g_string.parse().unwrap();

    let a = PushDownAutomaton::from(g);

    let mut e_string = String::from("S [S]\n");
    e_string.push_str("N [A, B]\n");
    e_string.push_str("R *\n");

    let e: EquivalenceRelation<String, String> = e_string.parse().unwrap();

    let f = |ps: &PushState<_, _>| ps.map(|nt| e.project(nt));
    let rlb = RlbElement::new(&f);

    let (b, _) = rlb.approximate_automaton(&a);

    assert_ne!(None, b.recognise(vec!["a".to_string() ]).next());
    assert_eq!(None, b.recognise(vec!["a".to_string(), "a".to_string(), "a".to_string(), "b".to_string() ]).next());
    assert_ne!(None, b.recognise(vec!["a".to_string(), "a".to_string(), "a".to_string(), "b".to_string(), "b".to_string(), "b".to_string(), "a".to_string() ]).next());
    assert_ne!(None, b.recognise(vec!["a".to_string(), "a".to_string(), "a".to_string(), "b".to_string(), "b".to_string() ]).next());

    assert_ne!(None, b.recognise(vec!["a".to_string(), "a".to_string(), "a".to_string(), "a".to_string(), "a".to_string() ]).next());
}

#[test]
fn test_relabel_check() {
    //create (and test) initial push down automata
    let r0_string = "S → [Nt A] # 1";
    let r1_string = "A → [T a, Nt A, Nt B  ] # 0.6";
    let r2_string = "A → [T a              ] # 0.4";
    let r3_string = "B → [T b, Nt B, Nt A  ] # 0.3";
    let r4_string = "B → [T b              ] # 0.7";

    let mut g_string = String::from("initial: [S, B]\n\n");
    g_string.push_str(r0_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r1_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r2_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r3_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r4_string.clone());

    let g: CFG<String, String, LogDomain<f64>> = g_string.parse().unwrap();

    let a = PushDownAutomaton::from(g);

    let mut e_string = String::from("S [S]\n");
    e_string.push_str("N [A, B]\n");
    e_string.push_str("R *\n");

    let e: EquivalenceRelation<String, String> = e_string.parse().unwrap();

    let f = |ps: &PushState<_, _>| ps.map(|nt| e.project(nt));
    let rlb = RlbElement::new(&f);

    let (b, _) = rlb.approximate_automaton(&a);

    let itemb = b.recognise(vec!["a".to_string(), "a".to_string(), "a".to_string(), "a".to_string(), "a".to_string() ]).next();
    assert_ne!(None, itemb);
}
<|endoftext|>


<commit_before>mod support;

use support::{assert, exe, fixture};

#[test]
fn test_help() {
    let out = exe::run(&["--help"]);

    assert::exit_ok(&out);
    assert::stdout_includes(&out, "USAGE");
}

#[test]
fn test_positional() {
    let path = &fixture::path("all_numeric_lines");

    assert::exit_fail(&exe::run(&[]));
    assert::exit_ok(&exe::run(&[path]));
    assert::exit_ok(&exe::run(&[path, path]));
    assert::exit_ok(&exe::run(&[path, path, path]));
}

#[test]
fn test_stdin() {
    let file = fixture::file("all_numeric_lines");
    let out = exe::run_with_stdin(file, &["-s"]);

    assert::exit_ok(&out);
}

#[test]
fn test_lax() {
    {
        let path = &fixture::path("all_numeric_lines");
        assert::exit_ok(&exe::run(&[path]));
        assert::exit_ok(&exe::run(&[path, "--lax"]));
    }
    {
        let path = &fixture::path("bad_lines");
        assert::exit_fail(&exe::run(&[path]));
        assert::exit_ok(&exe::run(&[path, "--lax"]));
    }
    {
        let path = &fixture::path("empty_lines");
        assert::exit_ok(&exe::run(&[path]));
        assert::exit_ok(&exe::run(&[path, "--lax"]));
    }
    {
        let path = &fixture::path("trailing_empty_lines");
        assert::exit_ok(&exe::run(&[path]));
        assert::exit_ok(&exe::run(&[path, "--lax"]));
    }
}

#[test]
fn test_comparison() {
    let path = &fixture::path("all_numeric_lines");
    let out = exe::run(&[path, path]);

    assert::exit_ok(&out);
    assert::stderr_is_empty(&out);
    assert::stdout_eq_file(&out, "comparison.out");
}

#[test]
fn test_comparison_plot() {
    let path1 = &fixture::path("normal_0_1");
    let path2 = &fixture::path("normal_5_2");
    let out = exe::run(&["-p", "-w", "90", path1, path2]);

    assert::exit_ok(&out);
    assert::stderr_is_empty(&out);
    assert::stdout_eq_file(&out, "comparison_plot.out");
}

#[test]
fn test_plot_one() {
    let path = &fixture::path("normal_0_1");
    let out = exe::run(&["-p", "-w", "90", path]);

    assert::exit_ok(&out);
    assert::stderr_is_empty(&out);
    assert::stdout_eq_file(&out, "plot_one.out");
}

#[test]
fn test_plot_one_long() {
    let path = &fixture::path("normal_0_1");
    let out = exe::run(&["--plot", "-w", "90", path]);

    assert::exit_ok(&out);
    assert::stderr_is_empty(&out);
    assert::stdout_eq_file(&out, "plot_one.out");
}

#[test]
fn test_plot_many() {
    let paths = vec![
        fixture::path("normal_0_1"),
        fixture::path("normal_5_2"),
        fixture::path("normal_3_1"),
    ];
    let out = exe::run(&["-p", "-w", "90", &paths[0], &paths[1], &paths[2]]);

    assert::exit_ok(&out);
    assert::stderr_is_empty(&out);
    assert::stdout_eq_file(&out, "plot_many.out");
}

#[test]
fn test_plot_far_apart() {
    let paths = vec![
        fixture::path("near_0"),
        fixture::path("near_1000"),
    ];
    let out = exe::run(&["-p", "-w", "90", &paths[0], &paths[1]]);

    assert::exit_ok(&out);
    assert::stderr_is_empty(&out);
    assert::stdout_eq_file(&out, "far_apart.out");
}
<commit_msg>Remove redundant test<commit_after>mod support;

use support::{assert, exe, fixture};

#[test]
fn test_help() {
    let out = exe::run(&["--help"]);

    assert::exit_ok(&out);
    assert::stdout_includes(&out, "USAGE");
}

#[test]
fn test_positional() {
    let path = &fixture::path("all_numeric_lines");

    assert::exit_fail(&exe::run(&[]));
    assert::exit_ok(&exe::run(&[path]));
    assert::exit_ok(&exe::run(&[path, path]));
    assert::exit_ok(&exe::run(&[path, path, path]));
}

#[test]
fn test_stdin() {
    let file = fixture::file("all_numeric_lines");
    let out = exe::run_with_stdin(file, &["-s"]);

    assert::exit_ok(&out);
}

#[test]
fn test_lax() {
    {
        let path = &fixture::path("all_numeric_lines");
        assert::exit_ok(&exe::run(&[path]));
        assert::exit_ok(&exe::run(&[path, "--lax"]));
    }
    {
        let path = &fixture::path("bad_lines");
        assert::exit_fail(&exe::run(&[path]));
        assert::exit_ok(&exe::run(&[path, "--lax"]));
    }
    {
        let path = &fixture::path("empty_lines");
        assert::exit_ok(&exe::run(&[path]));
        assert::exit_ok(&exe::run(&[path, "--lax"]));
    }
    {
        let path = &fixture::path("trailing_empty_lines");
        assert::exit_ok(&exe::run(&[path]));
        assert::exit_ok(&exe::run(&[path, "--lax"]));
    }
}

#[test]
fn test_comparison() {
    let path = &fixture::path("all_numeric_lines");
    let out = exe::run(&[path, path]);

    assert::exit_ok(&out);
    assert::stderr_is_empty(&out);
    assert::stdout_eq_file(&out, "comparison.out");
}

#[test]
fn test_comparison_plot() {
    let path1 = &fixture::path("normal_0_1");
    let path2 = &fixture::path("normal_5_2");
    let out = exe::run(&["-p", "-w", "90", path1, path2]);

    assert::exit_ok(&out);
    assert::stderr_is_empty(&out);
    assert::stdout_eq_file(&out, "comparison_plot.out");
}

#[test]
fn test_plot_one() {
    let path = &fixture::path("normal_0_1");
    let out = exe::run(&["-p", "-w", "90", path]);

    assert::exit_ok(&out);
    assert::stderr_is_empty(&out);
    assert::stdout_eq_file(&out, "plot_one.out");
}

#[test]
fn test_plot_many() {
    let paths = vec![
        fixture::path("normal_0_1"),
        fixture::path("normal_5_2"),
        fixture::path("normal_3_1"),
    ];
    let out = exe::run(&["-p", "-w", "90", &paths[0], &paths[1], &paths[2]]);

    assert::exit_ok(&out);
    assert::stderr_is_empty(&out);
    assert::stdout_eq_file(&out, "plot_many.out");
}

#[test]
fn test_plot_far_apart() {
    let paths = vec![
        fixture::path("near_0"),
        fixture::path("near_1000"),
    ];
    let out = exe::run(&["-p", "-w", "90", &paths[0], &paths[1]]);

    assert::exit_ok(&out);
    assert::stderr_is_empty(&out);
    assert::stdout_eq_file(&out, "far_apart.out");
}
<|endoftext|>


<commit_before>extern crate num_traits;
extern crate ndarray;
#[macro_use]
extern crate rula;
extern crate lapack;

use ndarray::prelude::*;
use rula::prelude::*;
use lapack::{c32, c64};
use ndarray::{Ix2};
use num_traits::{One, Zero, ToPrimitive};

/// Identity matrix SVD
pub fn svd_test_identity<SV: SingularValue, T: SVD<SV> + One + Zero>() {
    const N: usize = 100;
    let m: Array<T, Ix2> = Array::eye(N);
    let solution = SVD::compute(&m, false, false);
    assert!(solution.is_ok());
    let values  = solution.unwrap();

    let truth =  Array::from_vec(vec![SV::one(); N]);
    assert_in_tol!(&values.values, &truth, 1e-5);
}

#[test]
pub fn svd_test_identity_f32() {
    svd_test_identity::<f32, f32>();
}
#[test]
pub fn svd_test_identity_f64() {
    svd_test_identity::<f64, f64>();
}
#[test]
pub fn svd_test_identity_c32() {
    svd_test_identity::<f32, c32>();
}
#[test]
pub fn svd_test_identity_c64() {
    svd_test_identity::<f64, c64>();
}

/// SVD for linear set of singular values
macro_rules! stlf {
    ($name: ident, $float_type:ty) => (
        #[test]
        pub fn $name() {
            const N: usize = 100;
            let mut m: Array<$float_type, Ix2> = Array::zeros((N, N));
            let svs = Array::linspace(100.0 as $float_type, 1.0 as $float_type, N);

            m.diag_mut().assign(&svs);

            let solution = SVD::compute(&m, false, false);
            let values = match solution {
                Err(_) => { assert!(false); return },
                Ok(x) => x.values
            };

            let truth = Array::linspace(100.0, 1.0, N);
            assert_in_tol!(&values, &truth, 1e-5);
        }
    )
}

stlf!(svd_test_linspace_f32, f32);
stlf!(svd_test_linspace_f64, f64);

/// SVD for linear set of singular values
macro_rules! stlc {
    ($name: ident, $c_type:ty, $sv:ty) => (
        #[test]
        pub fn $name() {
            const N: usize = 100;
            let mut m: Array<$c_type, Ix2> = Array::zeros((N, N));
            let mut svs = Array::default(N);
            for i in 0..N {
                svs[i] = ((N - i) as $sv).into();
            }

            m.diag_mut().assign(&svs);

            let solution = SVD::compute(&m, false, false);
            let values = match solution {
                Err(_) => { assert!(false); return },
                Ok(x) => x.values
            };

            let truth = Array::linspace(100.0 as $sv, 1.0, N);
            assert_in_tol!(&values, &truth, 1e-5);
        }
    )
}

stlc!(svd_test_linspace_c32, c32, f32);
stlc!(svd_test_linspace_c64, c64, f64);
<commit_msg>Fix SVD test (impl Magnitude)<commit_after>extern crate num_traits;
extern crate ndarray;
#[macro_use]
extern crate rula;
extern crate lapack;

use ndarray::prelude::*;
use rula::prelude::*;
use lapack::{c32, c64};
use ndarray::{Ix2};
use num_traits::{One, Zero, ToPrimitive};

/// Identity matrix SVD
pub fn svd_test_identity<SV: SingularValue + Magnitude, T: SVD<SV> + One + Zero>() {
    const N: usize = 100;
    let m: Array<T, Ix2> = Array::eye(N);
    let solution = SVD::compute(&m, false, false);
    assert!(solution.is_ok());
    let values  = solution.unwrap();

    let truth =  Array::from_vec(vec![SV::one(); N]);
    assert_in_tol!(&values.values, &truth, 1e-5);
}

#[test]
pub fn svd_test_identity_f32() {
    svd_test_identity::<f32, f32>();
}
#[test]
pub fn svd_test_identity_f64() {
    svd_test_identity::<f64, f64>();
}
#[test]
pub fn svd_test_identity_c32() {
    svd_test_identity::<f32, c32>();
}
#[test]
pub fn svd_test_identity_c64() {
    svd_test_identity::<f64, c64>();
}

/// SVD for linear set of singular values
macro_rules! stlf {
    ($name: ident, $float_type:ty) => (
        #[test]
        pub fn $name() {
            const N: usize = 100;
            let mut m: Array<$float_type, Ix2> = Array::zeros((N, N));
            let svs = Array::linspace(100.0 as $float_type, 1.0 as $float_type, N);

            m.diag_mut().assign(&svs);

            let solution = SVD::compute(&m, false, false);
            let values = match solution {
                Err(_) => { assert!(false); return },
                Ok(x) => x.values
            };

            let truth = Array::linspace(100.0, 1.0, N);
            assert_in_tol!(&values, &truth, 1e-5);
        }
    )
}

stlf!(svd_test_linspace_f32, f32);
stlf!(svd_test_linspace_f64, f64);

/// SVD for linear set of singular values
macro_rules! stlc {
    ($name: ident, $c_type:ty, $sv:ty) => (
        #[test]
        pub fn $name() {
            const N: usize = 100;
            let mut m: Array<$c_type, Ix2> = Array::zeros((N, N));
            let mut svs = Array::default(N);
            for i in 0..N {
                svs[i] = ((N - i) as $sv).into();
            }

            m.diag_mut().assign(&svs);

            let solution = SVD::compute(&m, false, false);
            let values = match solution {
                Err(_) => { assert!(false); return },
                Ok(x) => x.values
            };

            let truth = Array::linspace(100.0 as $sv, 1.0, N);
            assert_in_tol!(&values, &truth, 1e-5);
        }
    )
}

stlc!(svd_test_linspace_c32, c32, f32);
stlc!(svd_test_linspace_c64, c64, f64);
<|endoftext|>