<commit_before>//! Define trait for vectors

use ndarray::{LinalgScalar, Array, Ix1};
use num_traits::float::Float;

/// Methods for vectors
pub trait Vector {
    type Scalar;
    /// L-2 norm
    fn norm(&self) -> Self::Scalar;
}

impl<A: Float + LinalgScalar> Vector for Array<A, Ix1> {
    type Scalar = A;
    fn norm(&self) -> Self::Scalar {
        self.dot(&self).sqrt()
    }
}
<commit_msg>Add norm_{l1,l2,max} in Vector crate<commit_after>//! Define trait for vectors

use std::iter::Sum;
use ndarray::{LinalgScalar, ArrayBase, Data, Dimension};
use num_traits::float::Float;

/// Methods for vectors
pub trait Vector {
    type Scalar;
    /// rename of norm_l2
    fn norm(&self) -> Self::Scalar {
        self.norm_l2()
    }
    /// L-1 norm
    fn norm_l1(&self) -> Self::Scalar;
    /// L-2 norm
    fn norm_l2(&self) -> Self::Scalar;
    /// maximum norm
    fn norm_max(&self) -> Self::Scalar;
}

impl<A, S, D, T> Vector for ArrayBase<S, D>
    where A: LinalgScalar + Squared<Output = T>,
          T: Float + Sum,
          S: Data<Elem = A>,
          D: Dimension
{
    type Scalar = T;
    fn norm_l1(&self) -> Self::Scalar {
        self.iter().map(|x| x.sq_abs()).sum()
    }
    fn norm_l2(&self) -> Self::Scalar {
        self.iter().map(|x| x.squared()).sum::<T>().sqrt()
    }
    fn norm_max(&self) -> Self::Scalar {
        self.iter().fold(T::zero(), |f, &val| {
            let v = val.sq_abs();
            if f > v { f } else { v }
        })
    }
}

pub trait Squared {
    type Output;
    fn squared(&self) -> Self::Output;
    fn sq_abs(&self) -> Self::Output;
}

impl<A: Float> Squared for A {
    type Output = A;
    fn squared(&self) -> A {
        *self * *self
    }
    fn sq_abs(&self) -> A {
        self.abs()
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate lazy_static;
extern crate typenum;
extern crate odds;

extern crate rex;

mod util;

use std::iter;
use std::fmt::Debug;
use std::path::Path;
use std::convert::{From, Into};
use std::io::{Cursor, Write, Seek, SeekFrom};

use odds::vec::VecExt;

use rex::frontend::{Event, KeyPress};

use util::mock_filesystem::{DefMockFilesystem, MockFilesystem};

fn assert_iter_eq<I, J>(one: I, other: J) where
    I: IntoIterator,
    J: IntoIterator,
    I::Item: PartialEq<J::Item> + Debug,
    J::Item: Debug,
{
    let mut one = one.into_iter();
    let mut other = other.into_iter();

    loop {
        match (one.next(), other.next()) {
            (None, None) => return,
            (Some(x), Some(y)) => assert_eq!(x, y),
            (a @ _, b @ _) => panic!("left is {:?}, right is {:?}", a, b)
        }
    }
}

#[test]
/// Test that basic copy/paste works
fn test_copy_paste() {
    let v : Vec<u8> = (0..0xff).into_iter().collect();
    let mut v_copy = v.clone();

    // let mut result_vec = vec![];
    let (mut edit, mut frontend) = util::simple_init_with_vec(v);

    // Add some junk data in the begining
    frontend.run_keys(&mut edit, vec![KeyPress::Insert]);
    frontend.run_str(&mut edit, "AABBCCDDEE");
    v_copy.splice(..0, vec![0xAA, 0xBB, 0xCC, 0xDD, 0xEE]);

    // Copy it
    frontend.run_keys(&mut edit, vec![KeyPress::Left, KeyPress::Shortcut(' '), KeyPress::Home, KeyPress::Shortcut('c')]);

    // Paste it in the middle
    frontend.run_keys(&mut edit, vec![KeyPress::Shortcut('g')]);
    frontend.run_str(&mut edit, "50");
    frontend.run_keys(&mut edit, vec![KeyPress::Enter, KeyPress::Shortcut('v')]);
    assert_eq!(edit.get_position(), 55);
    v_copy.splice(50..50, vec![0xAA, 0xBB, 0xCC, 0xDD, 0xEE]);

    // // Paste it in the end
    frontend.run_keys(&mut edit, vec![KeyPress::PageDown, KeyPress::PageDown, KeyPress::PageDown, KeyPress::Shortcut('v')]);
    let l = v_copy.len();
    v_copy.splice(l.., vec![0xAA, 0xBB, 0xCC, 0xDD, 0xEE]);

    edit.save(Path::new("test_copy_paste"));
    println!("result_vec = {:?}", v_copy);
    assert_iter_eq(v_copy.iter(), DefMockFilesystem::get_inner("test_copy_paste").iter());
}
<commit_msg>Small comment cleanup<commit_after>#[macro_use]
extern crate lazy_static;
extern crate typenum;
extern crate odds;

extern crate rex;

mod util;

use std::iter;
use std::fmt::Debug;
use std::path::Path;
use std::convert::{From, Into};
use std::io::{Cursor, Write, Seek, SeekFrom};

use odds::vec::VecExt;

use rex::frontend::{Event, KeyPress};

use util::mock_filesystem::{DefMockFilesystem, MockFilesystem};

fn assert_iter_eq<I, J>(one: I, other: J) where
    I: IntoIterator,
    J: IntoIterator,
    I::Item: PartialEq<J::Item> + Debug,
    J::Item: Debug,
{
    let mut one = one.into_iter();
    let mut other = other.into_iter();

    loop {
        match (one.next(), other.next()) {
            (None, None) => return,
            (Some(x), Some(y)) => assert_eq!(x, y),
            (a @ _, b @ _) => panic!("left is {:?}, right is {:?}", a, b)
        }
    }
}

#[test]
/// Test that basic copy/paste works
fn test_copy_paste() {
    let v : Vec<u8> = (0..0xff).into_iter().collect();
    let mut v_copy = v.clone();

    let (mut edit, mut frontend) = util::simple_init_with_vec(v);

    // Add some junk data in the begining
    frontend.run_keys(&mut edit, vec![KeyPress::Insert]);
    frontend.run_str(&mut edit, "AABBCCDDEE");
    v_copy.splice(..0, vec![0xAA, 0xBB, 0xCC, 0xDD, 0xEE]);

    // Copy it
    frontend.run_keys(&mut edit, vec![KeyPress::Left, KeyPress::Shortcut(' '), KeyPress::Home, KeyPress::Shortcut('c')]);

    // Paste it in the middle
    frontend.run_keys(&mut edit, vec![KeyPress::Shortcut('g')]);
    frontend.run_str(&mut edit, "50");
    frontend.run_keys(&mut edit, vec![KeyPress::Enter, KeyPress::Shortcut('v')]);
    assert_eq!(edit.get_position(), 55);
    v_copy.splice(50..50, vec![0xAA, 0xBB, 0xCC, 0xDD, 0xEE]);

    // Paste it in the end
    frontend.run_keys(&mut edit, vec![KeyPress::PageDown, KeyPress::PageDown, KeyPress::PageDown, KeyPress::Shortcut('v')]);
    let l = v_copy.len();
    v_copy.splice(l.., vec![0xAA, 0xBB, 0xCC, 0xDD, 0xEE]);

    edit.save(Path::new("test_copy_paste"));
    println!("result_vec = {:?}", v_copy);
    assert_iter_eq(v_copy.iter(), DefMockFilesystem::get_inner("test_copy_paste").iter());
}
<|endoftext|>


<commit_before>use crates_index_diff::Index;
use git_repository as git;
use git_testtools::tempfile::TempDir;
use std::path::PathBuf;
use std::sync::atomic::AtomicBool;

mod changes_between_commits;

const NUM_CHANGES_SINCE_EVER: usize = 3516;

#[test]
fn peek_changes() -> crate::Result {
    let mut index = index_ro()?;
    index.branch_name = "main";
    assert!(
        index.last_seen_reference().is_err(),
        "marker ref doesn't exist"
    );
    let (changes, last_seen_revision) =
        index.peek_changes_with_options2(git::progress::Discard, &AtomicBool::default())?;
    assert_eq!(
        changes.len(),
        NUM_CHANGES_SINCE_EVER,
        "all changes since the beginning of history"
    );

    let origin_main = index
        .repository()
        .find_reference("refs/remotes/origin/main")?;
    assert_eq!(
        last_seen_revision,
        origin_main.id(),
        "last seen reference should the latest state from the clone"
    );
    assert!(
        index.last_seen_reference().is_err(),
        "the last-seen reference has not been created"
    );
    Ok(())
}

#[test]
fn clone_if_needed() {
    let tmp = TempDir::new().unwrap();
    Index::from_path_or_cloned_with_options(tmp.path(), clone_options())
        .expect("successful clone to be created");
    Index::from_path_or_cloned_with_options(tmp.path(), clone_options())
        .expect("second instance re-uses existing clone");
}

#[test]
fn changes_since_last_fetch() -> crate::Result {
    let (mut index, _tmp) = index_rw()?;
    let repo = index.repository();
    assert!(index.last_seen_reference().is_err(), "no marker exists");
    let num_changes_since_first_commit = index.fetch_changes()?.len();
    assert_eq!(
        num_changes_since_first_commit, NUM_CHANGES_SINCE_EVER,
        "all changes since ever"
    );
    let mut marker = index
        .last_seen_reference()
        .expect("must be created/update now");
    let remote_main = repo.find_reference("refs/remotes/origin/main")?;
    assert_eq!(
        marker.target(),
        remote_main.target(),
        "we are updated to the most recent known version of the remote"
    );

    // reset to previous one
    marker
        .set_target_id(
            repo.rev_parse(format!("{}~1", index.seen_ref_name).as_str())?
                .single()
                .unwrap(),
            "resetting to previous commit",
        )
        .expect("reset success");
    let num_seen_after_reset = index.fetch_changes()?.len();
    assert_eq!(
        index.last_seen_reference()?.target(),
        remote_main.target(),
        "seen branch was updated again"
    );
    assert_eq!(
        num_seen_after_reset, 1,
        "normalization has no changes, but the commit before has one"
    );

    assert_eq!(
        index.fetch_changes()?.len(),
        0,
        "nothing if there was no change"
    );

    // now the remote has squashed their history, we should still be able to get the correct changes.
    git2::Repository::open(repo.git_dir())?.remote("local", repo.git_dir().to_str().unwrap())?;
    index.remote_name = Some("local");
    index
        .repository()
        .find_reference("refs/heads/main")?
        .set_target_id(
            index
                .repository()
                .rev_parse("origin/squashed")?
                .single()
                .unwrap(),
            "adjust to simulate remote with new squashed history",
        )?;
    let changes = index.fetch_changes()?;
    assert_eq!(changes.len(), 1);
    assert_eq!(
        changes
            .first()
            .and_then(|c| c.added().map(|v| (v.name.as_str(), v.version.as_str()))),
        Some(("git-repository", "1.0.0")),
        "there was just one actual changes compared to the previous state"
    );
    Ok(())
}

fn index_ro() -> crate::Result<Index> {
    let dir = fixture_dir()?;
    Ok(Index::from_path_or_cloned(dir.join("clone"))?)
}

fn index_rw() -> crate::Result<(Index, TempDir)> {
    let tmp = TempDir::new().unwrap();
    let mut index = Index::from_path_or_cloned_with_options(tmp.path(), clone_options())?;
    index.branch_name = "main";
    Ok((index, tmp))
}

fn fixture_dir() -> crate::Result<PathBuf> {
    git_testtools::scripted_fixture_repo_read_only_with_args(
        "make-index-from-parts.sh",
        std::env::current_dir()
            .ok()
            .map(|p| p.to_str().unwrap().to_owned()),
    )
}

fn clone_options() -> crates_index_diff::index::CloneOptions<'static> {
    crates_index_diff::index::CloneOptions {
        repository_url: fixture_dir().unwrap().join("base").display().to_string(),
        fetch_options: None,
    }
}
<commit_msg>use gitoxide based cloning on demand in tests, one failure<commit_after>use crates_index_diff::Index;
use git_repository as git;
use git_testtools::tempfile::TempDir;
use std::path::PathBuf;
use std::sync::atomic::AtomicBool;

mod changes_between_commits;

const NUM_CHANGES_SINCE_EVER: usize = 3516;

#[test]
fn peek_changes() -> crate::Result {
    let mut index = index_ro()?;
    index.branch_name = "main";
    assert!(
        index.last_seen_reference().is_err(),
        "marker ref doesn't exist"
    );
    let (changes, last_seen_revision) =
        index.peek_changes_with_options2(git::progress::Discard, &AtomicBool::default())?;
    assert_eq!(
        changes.len(),
        NUM_CHANGES_SINCE_EVER,
        "all changes since the beginning of history"
    );

    let origin_main = index
        .repository()
        .find_reference("refs/remotes/origin/main")?;
    assert_eq!(
        last_seen_revision,
        origin_main.id(),
        "last seen reference should the latest state from the clone"
    );
    assert!(
        index.last_seen_reference().is_err(),
        "the last-seen reference has not been created"
    );
    Ok(())
}

#[test]
fn clone_if_needed() {
    let tmp = TempDir::new().unwrap();
    let no_interrupt = &AtomicBool::default();
    Index::from_path_or_cloned_with_options2(
        tmp.path(),
        git::progress::Discard,
        no_interrupt,
        clone_options(),
    )
    .expect("successful clone to be created");
    Index::from_path_or_cloned_with_options2(
        tmp.path(),
        git::progress::Discard,
        no_interrupt,
        clone_options(),
    )
    .expect("second instance re-uses existing clone");
}

#[test]
#[ignore]
fn changes_since_last_fetch() -> crate::Result {
    let (mut index, _tmp) = index_rw()?;
    let repo = index.repository();
    assert!(index.last_seen_reference().is_err(), "no marker exists");
    let num_changes_since_first_commit = index.fetch_changes()?.len();
    assert_eq!(
        num_changes_since_first_commit, NUM_CHANGES_SINCE_EVER,
        "all changes since ever"
    );
    let mut marker = index
        .last_seen_reference()
        .expect("must be created/update now");
    let remote_main = repo.find_reference("refs/remotes/origin/main")?;
    assert_eq!(
        marker.target(),
        remote_main.target(),
        "we are updated to the most recent known version of the remote"
    );

    // reset to previous one
    marker
        .set_target_id(
            repo.rev_parse(format!("{}~1", index.seen_ref_name).as_str())?
                .single()
                .unwrap(),
            "resetting to previous commit",
        )
        .expect("reset success");
    let num_seen_after_reset = index.fetch_changes()?.len();
    assert_eq!(
        index.last_seen_reference()?.target(),
        remote_main.target(),
        "seen branch was updated again"
    );
    assert_eq!(
        num_seen_after_reset, 1,
        "normalization has no changes, but the commit before has one"
    );

    assert_eq!(
        index.fetch_changes()?.len(),
        0,
        "nothing if there was no change"
    );

    // now the remote has squashed their history, we should still be able to get the correct changes.
    git2::Repository::open(repo.git_dir())?.remote("local", repo.git_dir().to_str().unwrap())?;
    index.remote_name = Some("local");
    index
        .repository()
        .find_reference("refs/heads/main")?
        .set_target_id(
            index
                .repository()
                .rev_parse("origin/squashed")?
                .single()
                .unwrap(),
            "adjust to simulate remote with new squashed history",
        )?;
    let changes = index.fetch_changes()?;
    assert_eq!(changes.len(), 1);
    assert_eq!(
        changes
            .first()
            .and_then(|c| c.added().map(|v| (v.name.as_str(), v.version.as_str()))),
        Some(("git-repository", "1.0.0")),
        "there was just one actual changes compared to the previous state"
    );
    Ok(())
}

fn index_ro() -> crate::Result<Index> {
    let dir = fixture_dir()?;
    Ok(Index::from_path_or_cloned(dir.join("clone"))?)
}

fn index_rw() -> crate::Result<(Index, TempDir)> {
    let tmp = TempDir::new().unwrap();
    let mut index = Index::from_path_or_cloned_with_options2(
        tmp.path(),
        git::progress::Discard,
        &AtomicBool::default(),
        clone_options(),
    )?;
    index.branch_name = "main";
    Ok((index, tmp))
}

fn fixture_dir() -> crate::Result<PathBuf> {
    git_testtools::scripted_fixture_repo_read_only_with_args(
        "make-index-from-parts.sh",
        std::env::current_dir()
            .ok()
            .map(|p| p.to_str().unwrap().to_owned()),
    )
}

fn clone_options() -> crates_index_diff::index::CloneOptions2 {
    crates_index_diff::index::CloneOptions2 {
        url: fixture_dir().unwrap().join("base").display().to_string(),
    }
}
<|endoftext|>


<commit_before>use crate::grammar::ast::FuncCallExpression;
use crate::grammar::model::Fragment;
use crate::grammar::parsers::testing::setup;

fn test_call(s: &'static str, should_err: bool) {
    let (f, h) = setup(s);
    let fr = Fragment::new(&f, h);
    let r = FuncCallExpression::parse(fr);
    if should_err {
        assert!(r.is_err());
        r.map_err(|e| {
            e.map(|t| {
                let fr: Fragment = t.0;
                assert_eq!(fr.source(), s);
            })
        })
        .unwrap_err();
    } else {
        assert!(r.is_ok());
        let o = r.unwrap();
        assert_eq!(o.0.len(), 0);
        assert_eq!(o.1.frag.source(), s);
    }
}

#[test]
fn test_empty() {
    test_call("", true);
}

#[test]
fn test_underscore() {
    test_call("_()", true);
}

#[test]
fn test_true() {
    test_call("true()", false);
}

#[test]
fn test_calls() {
    [
        "abc()",
        "a_bc(1, \"abc\")",
        "n0(a, b, c)",
        "xd(e)",
        "foo(bar(baz), baz(bar(), foo), bar)",
        "a(b(), c(), d())",
    ]
    .iter()
    .for_each(|s| test_call(s, false))
}
<commit_msg>func call tests: make `true()` not valid<commit_after>use crate::grammar::ast::FuncCallExpression;
use crate::grammar::model::Fragment;
use crate::grammar::parsers::testing::setup;

fn test_call(s: &'static str, should_err: bool) {
    let (f, h) = setup(s);
    let fr = Fragment::new(&f, h);
    let r = FuncCallExpression::parse(fr);
    if should_err {
        assert!(r.is_err());
        r.map_err(|e| {
            e.map(|t| {
                let fr: Fragment = t.0;
                assert_eq!(fr.source(), s);
            })
        })
        .unwrap_err();
    } else {
        assert!(r.is_ok());
        let o = r.unwrap();
        assert_eq!(o.0.len(), 0);
        assert_eq!(o.1.frag.source(), s);
    }
}

#[test]
fn test_empty() {
    test_call("", true);
}

#[test]
fn test_underscore() {
    test_call("_()", true);
}

#[test]
fn test_true() {
    test_call("true()", true);
}

#[test]
fn test_calls() {
    [
        "abc()",
        "a_bc(1, \"abc\")",
        "n0(a, b, c)",
        "xd(e)",
        "foo(bar(baz), baz(bar(), foo), bar)",
        "a(b(), c(), d())",
    ]
    .iter()
    .for_each(|s| test_call(s, false))
}
<|endoftext|>


<commit_before>#[macro_use]
mod macros;

use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree};
use quote::quote;
use std::iter::FromIterator;
use syn::{Expr, ExprRange};

#[test]
fn test_expr_parse() {
    let tokens = quote!(..100u32);
    snapshot!(tokens as Expr, @r###"
    Expr::Range {
        limits: HalfOpen,
        to: Some(Expr::Lit {
            lit: 100u32,
        }),
    }
    "###);

    let tokens = quote!(..100u32);
    snapshot!(tokens as ExprRange, @r###"
    ExprRange {
        limits: HalfOpen,
        to: Some(Expr::Lit {
            lit: 100u32,
        }),
    }
    "###);
}

#[test]
fn test_await() {
    // Must not parse as Expr::Field.
    let tokens = quote!(fut.await);

    snapshot!(tokens as Expr, @r###"
    Expr::Await {
        base: Expr::Path {
            path: Path {
                segments: [
                    PathSegment {
                        ident: "fut",
                        arguments: None,
                    },
                ],
            },
        },
    }
    "###);
}

#[test]
fn test_tuple_multi_index() {
    for &input in &[
        "tuple.0.0",
        "tuple .0.0",
        "tuple. 0.0",
        "tuple.0 .0",
        "tuple.0. 0",
        "tuple . 0 . 0",
    ] {
        snapshot!(input as Expr, @r###"
        Expr::Field {
            base: Expr::Field {
                base: Expr::Path {
                    path: Path {
                        segments: [
                            PathSegment {
                                ident: "tuple",
                                arguments: None,
                            },
                        ],
                    },
                },
                member: Unnamed(Index {
                    index: 0,
                }),
            },
            member: Unnamed(Index {
                index: 0,
            }),
        }
        "###);
    }

    for tokens in vec![
        quote!(tuple.0.0),
        quote!(tuple .0.0),
        quote!(tuple. 0.0),
        quote!(tuple.0 .0),
        quote!(tuple.0. 0),
        quote!(tuple . 0 . 0),
    ] {
        snapshot!(tokens as Expr, @r###"
        Expr::Field {
            base: Expr::Field {
                base: Expr::Path {
                    path: Path {
                        segments: [
                            PathSegment {
                                ident: "tuple",
                                arguments: None,
                            },
                        ],
                    },
                },
                member: Unnamed(Index {
                    index: 0,
                }),
            },
            member: Unnamed(Index {
                index: 0,
            }),
        }
        "###);
    }
}

#[test]
fn test_macro_variable_func() {
    // mimics the token stream corresponding to `$fn()`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Group(Group::new(Delimiter::None, quote! { f })),
        TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())),
    ]);

    snapshot!(tokens as Expr, @r###"
    Expr::Call {
        func: Expr::Group {
            expr: Expr::Path {
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "f",
                            arguments: None,
                        },
                    ],
                },
            },
        },
    }
    "###);

    let tokens = TokenStream::from_iter(vec![
        TokenTree::Punct(Punct::new('#', Spacing::Alone)),
        TokenTree::Group(Group::new(Delimiter::Bracket, quote! { outside })),
        TokenTree::Group(Group::new(Delimiter::None, quote! { #[inside] f })),
        TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())),
    ]);

    snapshot!(tokens as Expr, @r###"
    Expr::Call {
        attrs: [
            Attribute {
                style: Outer,
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "outside",
                            arguments: None,
                        },
                    ],
                },
                tokens: TokenStream(``),
            },
        ],
        func: Expr::Group {
            expr: Expr::Path {
                attrs: [
                    Attribute {
                        style: Outer,
                        path: Path {
                            segments: [
                                PathSegment {
                                    ident: "inside",
                                    arguments: None,
                                },
                            ],
                        },
                        tokens: TokenStream(``),
                    },
                ],
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "f",
                            arguments: None,
                        },
                    ],
                },
            },
        },
    }
    "###);
}

#[test]
fn test_macro_variable_macro() {
    // mimics the token stream corresponding to `$macro!()`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Group(Group::new(Delimiter::None, quote! { m })),
        TokenTree::Punct(Punct::new('!', Spacing::Alone)),
        TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())),
    ]);

    snapshot!(tokens as Expr, @r###"
    Expr::Macro {
        mac: Macro {
            path: Path {
                segments: [
                    PathSegment {
                        ident: "m",
                        arguments: None,
                    },
                ],
            },
            delimiter: Paren,
            tokens: TokenStream(``),
        },
    }
    "###);
}

#[test]
fn test_macro_variable_struct() {
    // mimics the token stream corresponding to `$struct {}`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Group(Group::new(Delimiter::None, quote! { S })),
        TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())),
    ]);

    snapshot!(tokens as Expr, @r###"
    Expr::Struct {
        path: Path {
            segments: [
                PathSegment {
                    ident: "S",
                    arguments: None,
                },
            ],
        },
    }
    "###);
}

#[test]
fn test_macro_variable_match_arm() {
    // mimics the token stream corresponding to `match v { _ => $expr }`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Ident(Ident::new("match", Span::call_site())),
        TokenTree::Ident(Ident::new("v", Span::call_site())),
        TokenTree::Group(Group::new(
            Delimiter::Brace,
            TokenStream::from_iter(vec![
                TokenTree::Punct(Punct::new('_', Spacing::Alone)),
                TokenTree::Punct(Punct::new('=', Spacing::Joint)),
                TokenTree::Punct(Punct::new('>', Spacing::Alone)),
                TokenTree::Group(Group::new(Delimiter::None, quote! { #[a] () })),
            ]),
        )),
    ]);

    snapshot!(tokens as Expr, @r###"
    Expr::Match {
        expr: Expr::Path {
            path: Path {
                segments: [
                    PathSegment {
                        ident: "v",
                        arguments: None,
                    },
                ],
            },
        },
        arms: [
            Arm {
                pat: Pat::Wild,
                body: Expr::Group {
                    expr: Expr::Tuple {
                        attrs: [
                            Attribute {
                                style: Outer,
                                path: Path {
                                    segments: [
                                        PathSegment {
                                            ident: "a",
                                            arguments: None,
                                        },
                                    ],
                                },
                                tokens: TokenStream(``),
                            },
                        ],
                    },
                },
            },
        ],
    }
    "###);
}
<commit_msg>Stop rustfmt from mangling tuple multi-index test cases<commit_after>#[macro_use]
mod macros;

use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree};
use quote::quote;
use std::iter::FromIterator;
use syn::{Expr, ExprRange};

#[test]
fn test_expr_parse() {
    let tokens = quote!(..100u32);
    snapshot!(tokens as Expr, @r###"
    Expr::Range {
        limits: HalfOpen,
        to: Some(Expr::Lit {
            lit: 100u32,
        }),
    }
    "###);

    let tokens = quote!(..100u32);
    snapshot!(tokens as ExprRange, @r###"
    ExprRange {
        limits: HalfOpen,
        to: Some(Expr::Lit {
            lit: 100u32,
        }),
    }
    "###);
}

#[test]
fn test_await() {
    // Must not parse as Expr::Field.
    let tokens = quote!(fut.await);

    snapshot!(tokens as Expr, @r###"
    Expr::Await {
        base: Expr::Path {
            path: Path {
                segments: [
                    PathSegment {
                        ident: "fut",
                        arguments: None,
                    },
                ],
            },
        },
    }
    "###);
}

#[rustfmt::skip]
#[test]
fn test_tuple_multi_index() {
    for &input in &[
        "tuple.0.0",
        "tuple .0.0",
        "tuple. 0.0",
        "tuple.0 .0",
        "tuple.0. 0",
        "tuple . 0 . 0",
    ] {
        snapshot!(input as Expr, @r###"
        Expr::Field {
            base: Expr::Field {
                base: Expr::Path {
                    path: Path {
                        segments: [
                            PathSegment {
                                ident: "tuple",
                                arguments: None,
                            },
                        ],
                    },
                },
                member: Unnamed(Index {
                    index: 0,
                }),
            },
            member: Unnamed(Index {
                index: 0,
            }),
        }
        "###);
    }

    for tokens in vec![
        quote!(tuple.0.0),
        quote!(tuple .0.0),
        quote!(tuple. 0.0),
        quote!(tuple.0 .0),
        quote!(tuple.0. 0),
        quote!(tuple . 0 . 0),
    ] {
        snapshot!(tokens as Expr, @r###"
        Expr::Field {
            base: Expr::Field {
                base: Expr::Path {
                    path: Path {
                        segments: [
                            PathSegment {
                                ident: "tuple",
                                arguments: None,
                            },
                        ],
                    },
                },
                member: Unnamed(Index {
                    index: 0,
                }),
            },
            member: Unnamed(Index {
                index: 0,
            }),
        }
        "###);
    }
}

#[test]
fn test_macro_variable_func() {
    // mimics the token stream corresponding to `$fn()`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Group(Group::new(Delimiter::None, quote! { f })),
        TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())),
    ]);

    snapshot!(tokens as Expr, @r###"
    Expr::Call {
        func: Expr::Group {
            expr: Expr::Path {
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "f",
                            arguments: None,
                        },
                    ],
                },
            },
        },
    }
    "###);

    let tokens = TokenStream::from_iter(vec![
        TokenTree::Punct(Punct::new('#', Spacing::Alone)),
        TokenTree::Group(Group::new(Delimiter::Bracket, quote! { outside })),
        TokenTree::Group(Group::new(Delimiter::None, quote! { #[inside] f })),
        TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())),
    ]);

    snapshot!(tokens as Expr, @r###"
    Expr::Call {
        attrs: [
            Attribute {
                style: Outer,
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "outside",
                            arguments: None,
                        },
                    ],
                },
                tokens: TokenStream(``),
            },
        ],
        func: Expr::Group {
            expr: Expr::Path {
                attrs: [
                    Attribute {
                        style: Outer,
                        path: Path {
                            segments: [
                                PathSegment {
                                    ident: "inside",
                                    arguments: None,
                                },
                            ],
                        },
                        tokens: TokenStream(``),
                    },
                ],
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "f",
                            arguments: None,
                        },
                    ],
                },
            },
        },
    }
    "###);
}

#[test]
fn test_macro_variable_macro() {
    // mimics the token stream corresponding to `$macro!()`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Group(Group::new(Delimiter::None, quote! { m })),
        TokenTree::Punct(Punct::new('!', Spacing::Alone)),
        TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())),
    ]);

    snapshot!(tokens as Expr, @r###"
    Expr::Macro {
        mac: Macro {
            path: Path {
                segments: [
                    PathSegment {
                        ident: "m",
                        arguments: None,
                    },
                ],
            },
            delimiter: Paren,
            tokens: TokenStream(``),
        },
    }
    "###);
}

#[test]
fn test_macro_variable_struct() {
    // mimics the token stream corresponding to `$struct {}`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Group(Group::new(Delimiter::None, quote! { S })),
        TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())),
    ]);

    snapshot!(tokens as Expr, @r###"
    Expr::Struct {
        path: Path {
            segments: [
                PathSegment {
                    ident: "S",
                    arguments: None,
                },
            ],
        },
    }
    "###);
}

#[test]
fn test_macro_variable_match_arm() {
    // mimics the token stream corresponding to `match v { _ => $expr }`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Ident(Ident::new("match", Span::call_site())),
        TokenTree::Ident(Ident::new("v", Span::call_site())),
        TokenTree::Group(Group::new(
            Delimiter::Brace,
            TokenStream::from_iter(vec![
                TokenTree::Punct(Punct::new('_', Spacing::Alone)),
                TokenTree::Punct(Punct::new('=', Spacing::Joint)),
                TokenTree::Punct(Punct::new('>', Spacing::Alone)),
                TokenTree::Group(Group::new(Delimiter::None, quote! { #[a] () })),
            ]),
        )),
    ]);

    snapshot!(tokens as Expr, @r###"
    Expr::Match {
        expr: Expr::Path {
            path: Path {
                segments: [
                    PathSegment {
                        ident: "v",
                        arguments: None,
                    },
                ],
            },
        },
        arms: [
            Arm {
                pat: Pat::Wild,
                body: Expr::Group {
                    expr: Expr::Tuple {
                        attrs: [
                            Attribute {
                                style: Outer,
                                path: Path {
                                    segments: [
                                        PathSegment {
                                            ident: "a",
                                            arguments: None,
                                        },
                                    ],
                                },
                                tokens: TokenStream(``),
                            },
                        ],
                    },
                },
            },
        ],
    }
    "###);
}
<|endoftext|>


<commit_before>extern crate unidecode;
use unidecode::unidecode;

// Tests that every character outputted by the unidecode() function is valid
// ASCII.
#[test]
fn test_all_ascii() {
    use std::char;

    let valid_unicode = (0x0..0xD7FF + 1).chain(0x0E000..0x10FFFF + 1);
    for i in valid_unicode {
        match char::from_u32(i) {
            Some(ch) => {
                for ascii_ch in unidecode(&ch.to_string()).chars() {
                    let x = ascii_ch as u32;
                    if x > 127 {
                        panic!(
                            "Data contains non-ASCII character (Dec: {})",
                            x
                        );
                    }
                }
            },
            None => panic!("Test written incorrectly; invalid unicode")
        }
    }
}

// These tests were ported directly from the original `Text::Unidecode` Perl
// module.
#[test]
fn test_conversion() {
    assert_eq!(unidecode("Æneid"), "AEneid");
    assert_eq!(unidecode("étude"), "etude");
    assert_eq!(unidecode("北亰"), "Bei Jing ");
    assert_eq!(unidecode("ᔕᓇᓇ"), "shanana");
    assert_eq!(unidecode("ᏔᎵᏆ"), "taliqua");
    assert_eq!(unidecode("ܦܛܽܐܺ"), "ptu'i");
    assert_eq!(unidecode("अभिजीत"), "abhijiit");
    assert_eq!(unidecode("অভিজীত"), "abhijiit");
    assert_eq!(unidecode("അഭിജീത"), "abhijiit");
    assert_eq!(unidecode("മലയാലമ്"), "mlyaalm");
    assert_eq!(unidecode("げんまい茶"), "genmaiCha ");
}
<commit_msg>fixed typo<commit_after>extern crate unidecode;
use unidecode::unidecode;

// Tests that every character outputted by the unidecode() function is valid
// ASCII.
#[test]
fn test_all_ascii() {
    use std::char;

    let valid_unicode = (0x0..0xD7FF + 1).chain(0x0E000..0x10FFFF + 1);
    for i in valid_unicode {
        match char::from_u32(i) {
            Some(ch) => {
                for ascii_ch in unidecode(&ch.to_string()).chars() {
                    let x = ascii_ch as u32;
                    if x > 127 {
                        panic!(
                            "Data contains non-ASCII character (Dec: {})",
                            x
                        );
                    }
                }
            },
            None => panic!("Test written incorrectly; invalid Unicode")
        }
    }
}

// These tests were ported directly from the original `Text::Unidecode` Perl
// module.
#[test]
fn test_conversion() {
    assert_eq!(unidecode("Æneid"), "AEneid");
    assert_eq!(unidecode("étude"), "etude");
    assert_eq!(unidecode("北亰"), "Bei Jing ");
    assert_eq!(unidecode("ᔕᓇᓇ"), "shanana");
    assert_eq!(unidecode("ᏔᎵᏆ"), "taliqua");
    assert_eq!(unidecode("ܦܛܽܐܺ"), "ptu'i");
    assert_eq!(unidecode("अभिजीत"), "abhijiit");
    assert_eq!(unidecode("অভিজীত"), "abhijiit");
    assert_eq!(unidecode("അഭിജീത"), "abhijiit");
    assert_eq!(unidecode("മലയാലമ്"), "mlyaalm");
    assert_eq!(unidecode("げんまい茶"), "genmaiCha ");
}
<|endoftext|>


<commit_before>#![feature(inclusive_range_syntax)]
//src: https://github.com/rustomax/rust-iterators#digging-deeper

fn main() {
    for j in 1...3 {
        for i in (1..11).map(|x| x +j) {
            print!("{} ", i);
        }
        println!("");
    }

    let v = vec![3, 5, 0, -2, 3, 4, 1];
//    let v:Vec<i32> = vec![];
    let max = v.iter().max();
    let min = v.iter().min();

    println!("max = {:?}, min = {:?}", max, min);

    // output: max = Some(5), min = Some(-2)
}
<commit_msg>impl Iterator<commit_after>#![feature(inclusive_range_syntax)]
//src: https://github.com/rustomax/rust-iterators#digging-deeper

fn main() {
    for j in 1...3 {
        for i in (1..11).map(|x| x +j) {
            print!("{} ", i);
        }
        println!("");
    }

    let v = vec![3, 5, 0, -2, 3, 4, 1];
    //    let v:Vec<i32> = vec![];
    //  let v:i32 = vec![];
    let max = v.iter().max();
    let min = v.iter().min();

    println!("max = {:?}, min = {:?}", max, min);

    // output: max = Some(5), min = Some(-2)

    // pass the starting temperature and step to the initializer function
    let ftc = FahrToCelc::new(0.0, 5.0);

    // produce the iterator table of first 5 values
    let temp_table = ftc.take(5);

    // print out the temperature table nicely
    for (f, c) in temp_table {
        println!("{:7.2} °F = {:7.2} °C", f, c);
    }
}

struct FahrToCelc {
    fahr: f32,
    step: f32,
}

impl FahrToCelc {
    fn new(fahr: f32, step: f32) -> FahrToCelc {
        FahrToCelc { fahr: fahr, step: step }
    }
}

impl Iterator for FahrToCelc {
    type Item = (f32, f32);

    fn next (&mut self) -> Option<(f32, f32)> {
        let curr_fahr = self.fahr;
        let curr_celc = (self.fahr - 32.0) / 1.8;
        self.fahr = self.fahr + self.step;
        Some((curr_fahr, curr_celc))
    }
}

<|endoftext|>


<commit_before>// Copyright (c) 2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

extern crate capnp;
extern crate capnp_futures;
extern crate futures;

pub mod addressbook_capnp {
  include!(concat!(env!("OUT_DIR"), "/addressbook_capnp.rs"));
}

#[cfg(test)]
mod tests {
    use crate::addressbook_capnp::{address_book, person};

    fn populate_address_book(address_book: address_book::Builder) {
        let mut people = address_book.init_people(2);
        {
            let mut alice = people.reborrow().get(0);
            alice.set_id(123);
            alice.set_name("Alice");
            alice.set_email("alice@example.com");
            {
                let mut alice_phones = alice.reborrow().init_phones(1);
                alice_phones.reborrow().get(0).set_number("555-1212");
                alice_phones.reborrow().get(0).set_type(person::phone_number::Type::Mobile);
            }
            alice.get_employment().set_school("MIT");
        }

        {
            let mut bob = people.get(1);
            bob.set_id(456);
            bob.set_name("Bob");
            bob.set_email("bob@example.com");
            {
                let mut bob_phones = bob.reborrow().init_phones(2);
                bob_phones.reborrow().get(0).set_number("555-4567");
                bob_phones.reborrow().get(0).set_type(person::phone_number::Type::Home);
                bob_phones.reborrow().get(1).set_number("555-7654");
                bob_phones.reborrow().get(1).set_type(person::phone_number::Type::Work);
            }
            bob.get_employment().set_unemployed(());
        }
    }

    fn read_address_book(address_book: address_book::Reader) {
        let people = address_book.get_people().unwrap();
        assert_eq!(people.len(), 2);
        let alice = people.get(0);
        assert_eq!(alice.get_id(), 123);
        assert_eq!(alice.get_name().unwrap(), "Alice");
        assert_eq!(alice.get_email().unwrap(), "alice@example.com");

        let bob = people.get(1);
        assert_eq!(bob.get_id(), 456);
        assert_eq!(bob.get_name().unwrap(), "Bob");
    }

    #[test]
    fn write_stream_and_read_queue() {
        use capnp;
        use capnp_futures;
        use futures::future::{FutureExt};
        use futures::stream::{StreamExt};

        use std::cell::Cell;
        use std::rc::Rc;

        let (s1, s2) = async_std::os::unix::net::UnixStream::pair().expect("socket pair");

        let (mut sender, write_queue) = capnp_futures::write_queue(s1);

        let read_stream = capnp_futures::ReadStream::new(s2, Default::default());

        let messages_read = Rc::new(Cell::new(0u32));
        let messages_read1 = messages_read.clone();

        let done_reading = read_stream.for_each(|m| {
            match m {
                Err(e) => panic!("read error: {:?}", e),
                Ok(msg) => {
                    let address_book = msg.get_root::<address_book::Reader>().unwrap();
                    read_address_book(address_book);
                    messages_read.set(messages_read.get() + 1);
                    futures::future::ready(())
                }
            }
        });

        let io = futures::future::join(done_reading, write_queue.map(|_| ()));

        let mut m = capnp::message::Builder::new_default();
        populate_address_book(m.init_root());
        async_std::task::block_on(async {
            async_std::task::spawn_local(sender.send(m).map(|_|()));
            drop(sender);
            io.await;
            assert_eq!(messages_read1.get(), 1);
        });
    }

    fn fill_and_send_message(mut message: capnp::message::Builder<capnp::message::HeapAllocator>) {
        use capnp_futures::serialize;
        use futures::{FutureExt, TryFutureExt};

        {
            let mut address_book = message.init_root::<address_book::Builder>();
            populate_address_book(address_book.reborrow());
            read_address_book(address_book.reborrow_as_reader());
        }

        let (stream0, stream1) = async_std::os::unix::net::UnixStream::pair().expect("socket pair");

        let f0 = serialize::write_message(stream0, message).map_err(|e| panic!("write error {:?}", e)).map(|_|());
        let f1 =
            serialize::read_message(stream1, capnp::message::ReaderOptions::new()).and_then(|maybe_message_reader| {
                match maybe_message_reader {
                    None => panic!("did not get message"),
                    Some(m) => {
                        let address_book = m.get_root::<address_book::Reader>().unwrap();
                        read_address_book(address_book);
                        futures::future::ready(Ok::<(),capnp::Error>(()))
                    }
                }
            });

        async_std::task::block_on(async {
            async_std::task::spawn_local(f0);
            f1.await
        }).expect("read task");
    }

    #[test]
    fn single_segment() {
        fill_and_send_message(capnp::message::Builder::new_default());
    }

    #[test]
    fn multi_segment() {
        let builder_options = capnp::message::HeapAllocator::new()
            .first_segment_words(1).allocation_strategy(capnp::message::AllocationStrategy::FixedSize);
        fill_and_send_message(capnp::message::Builder::new(builder_options));
    }

    #[test]
    fn static_lifetime_not_required_funcs() {
        use capnp::message;
        use capnp_futures::serialize;

        let (mut write, mut read) =
            async_std::os::unix::net::UnixStream::pair().expect("socket pair");
        serialize::read_message(&mut read, message::ReaderOptions::default());
        serialize::write_message(&mut write, message::Builder::new_default());
        drop(write);
        drop(read);
    }

    #[test]
    fn static_lifetime_not_required_on_highlevel() {
        use capnp::message;
        use capnp_futures;

        let (mut write, mut read) =
            async_std::os::unix::net::UnixStream::pair().expect("socket pair");
        capnp_futures::ReadStream::new(&mut read, message::ReaderOptions::default());
        capnp_futures::write_queue::<_, message::Builder<message::HeapAllocator>>(&mut write);
        drop(write);
        drop(read);
    }
}
<commit_msg>rm warnings from tests<commit_after>// Copyright (c) 2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

extern crate capnp;
extern crate capnp_futures;
extern crate futures;

pub mod addressbook_capnp {
  include!(concat!(env!("OUT_DIR"), "/addressbook_capnp.rs"));
}

#[cfg(test)]
mod tests {
    use crate::addressbook_capnp::{address_book, person};

    fn populate_address_book(address_book: address_book::Builder) {
        let mut people = address_book.init_people(2);
        {
            let mut alice = people.reborrow().get(0);
            alice.set_id(123);
            alice.set_name("Alice");
            alice.set_email("alice@example.com");
            {
                let mut alice_phones = alice.reborrow().init_phones(1);
                alice_phones.reborrow().get(0).set_number("555-1212");
                alice_phones.reborrow().get(0).set_type(person::phone_number::Type::Mobile);
            }
            alice.get_employment().set_school("MIT");
        }

        {
            let mut bob = people.get(1);
            bob.set_id(456);
            bob.set_name("Bob");
            bob.set_email("bob@example.com");
            {
                let mut bob_phones = bob.reborrow().init_phones(2);
                bob_phones.reborrow().get(0).set_number("555-4567");
                bob_phones.reborrow().get(0).set_type(person::phone_number::Type::Home);
                bob_phones.reborrow().get(1).set_number("555-7654");
                bob_phones.reborrow().get(1).set_type(person::phone_number::Type::Work);
            }
            bob.get_employment().set_unemployed(());
        }
    }

    fn read_address_book(address_book: address_book::Reader) {
        let people = address_book.get_people().unwrap();
        assert_eq!(people.len(), 2);
        let alice = people.get(0);
        assert_eq!(alice.get_id(), 123);
        assert_eq!(alice.get_name().unwrap(), "Alice");
        assert_eq!(alice.get_email().unwrap(), "alice@example.com");

        let bob = people.get(1);
        assert_eq!(bob.get_id(), 456);
        assert_eq!(bob.get_name().unwrap(), "Bob");
    }

    #[test]
    fn write_stream_and_read_queue() {
        use capnp;
        use capnp_futures;
        use futures::future::{FutureExt};
        use futures::stream::{StreamExt};

        use std::cell::Cell;
        use std::rc::Rc;

        let (s1, s2) = async_std::os::unix::net::UnixStream::pair().expect("socket pair");

        let (mut sender, write_queue) = capnp_futures::write_queue(s1);

        let read_stream = capnp_futures::ReadStream::new(s2, Default::default());

        let messages_read = Rc::new(Cell::new(0u32));
        let messages_read1 = messages_read.clone();

        let done_reading = read_stream.for_each(|m| {
            match m {
                Err(e) => panic!("read error: {:?}", e),
                Ok(msg) => {
                    let address_book = msg.get_root::<address_book::Reader>().unwrap();
                    read_address_book(address_book);
                    messages_read.set(messages_read.get() + 1);
                    futures::future::ready(())
                }
            }
        });

        let io = futures::future::join(done_reading, write_queue.map(|_| ()));

        let mut m = capnp::message::Builder::new_default();
        populate_address_book(m.init_root());
        async_std::task::block_on(async {
            async_std::task::spawn_local(sender.send(m).map(|_|()));
            drop(sender);
            io.await;
            assert_eq!(messages_read1.get(), 1);
        });
    }

    fn fill_and_send_message(mut message: capnp::message::Builder<capnp::message::HeapAllocator>) {
        use capnp_futures::serialize;
        use futures::{FutureExt, TryFutureExt};

        {
            let mut address_book = message.init_root::<address_book::Builder>();
            populate_address_book(address_book.reborrow());
            read_address_book(address_book.reborrow_as_reader());
        }

        let (stream0, stream1) = async_std::os::unix::net::UnixStream::pair().expect("socket pair");

        let f0 = serialize::write_message(stream0, message).map_err(|e| panic!("write error {:?}", e)).map(|_|());
        let f1 =
            serialize::read_message(stream1, capnp::message::ReaderOptions::new()).and_then(|maybe_message_reader| {
                match maybe_message_reader {
                    None => panic!("did not get message"),
                    Some(m) => {
                        let address_book = m.get_root::<address_book::Reader>().unwrap();
                        read_address_book(address_book);
                        futures::future::ready(Ok::<(),capnp::Error>(()))
                    }
                }
            });

        async_std::task::block_on(async {
            async_std::task::spawn_local(f0);
            f1.await
        }).expect("read task");
    }

    #[test]
    fn single_segment() {
        fill_and_send_message(capnp::message::Builder::new_default());
    }

    #[test]
    fn multi_segment() {
        let builder_options = capnp::message::HeapAllocator::new()
            .first_segment_words(1).allocation_strategy(capnp::message::AllocationStrategy::FixedSize);
        fill_and_send_message(capnp::message::Builder::new(builder_options));
    }

    #[test]
    fn static_lifetime_not_required_funcs() {
        use capnp::message;
        use capnp_futures::serialize;

        let (mut write, mut read) =
            async_std::os::unix::net::UnixStream::pair().expect("socket pair");
        let _ = serialize::read_message(&mut read, message::ReaderOptions::default());
        let _ = serialize::write_message(&mut write, message::Builder::new_default());
        drop(write);
        drop(read);
    }

    #[test]
    fn static_lifetime_not_required_on_highlevel() {
        use capnp::message;
        use capnp_futures;

        let (mut write, mut read) =
            async_std::os::unix::net::UnixStream::pair().expect("socket pair");
        let _ = capnp_futures::ReadStream::new(&mut read, message::ReaderOptions::default());
        let _ = capnp_futures::write_queue::<_, message::Builder<message::HeapAllocator>>(&mut write);
        drop(write);
        drop(read);
    }
}
<|endoftext|>


<commit_before><commit_msg>Correct failure indication<commit_after><|endoftext|>


<commit_before><commit_msg>Request IdP response_mode=form_post if supported<commit_after><|endoftext|>


<commit_before>use rusqlite::Connection;
use std::env;
use std::fs::create_dir_all;
use ::input::*;
use std::collections::HashSet;
use output::SearchResult;
use std::process;

/// A struct to represent a movie to be attached to actors or directors
#[derive(Debug)]
pub struct Movie {
    pub title: String,
    pub year: String,
}

#[derive(Debug)]
struct Res {
    pub field: i64,
}

#[derive(Debug)]
struct GenreResult {
    pub field: String,
}

/// Checks if a database already exists
pub fn db_exists() -> bool {
    let tmp = env::home_dir();
    let mut path_buf = tmp.unwrap();
    path_buf.push("Film-O-Mat");
    path_buf.push("database");
    path_buf.set_extension("db");
    path_buf.as_path().exists()
}

/// Returns a connection to existing database
fn get_connection() -> Connection {
    let tmp = env::home_dir();
    let mut path_buf = tmp.unwrap();
    path_buf.push("Film-O-Mat");
    path_buf.push("database");
    path_buf.set_extension("db");

    let conn = Connection::open(path_buf).unwrap();
    conn
}

/// Creates a database with movies and related information for movie suggestions
/// Movies: movie titles with associated release date and genre
/// Actors: names of all actors
/// Rankings: associates movie ID with IMDb ratings and number of ratings
/// Crew (actors and directors): associates actors/directors with their movies
pub fn create_database() {

    let tmp = env::home_dir();
    let mut path_buf = tmp.unwrap();
    path_buf.push("Film-O-Mat");

    // creates path if not existing
    if create_dir_all(&path_buf).is_err() {
        println!("Error while creating the Database at {:?}", path_buf);
        process::exit(1);
    }

    path_buf.push("database");
    path_buf.set_extension("db");

    let conn = Connection::open(path_buf).unwrap();

    conn.execute("CREATE TABLE IF NOT EXISTS movies (
                  id              INTEGER PRIMARY KEY,
                  title           TEXT NOT NULL,
                  year            TEXT NOT NULL,
                  rating          TEXT NOT NULL,
                  number          TEXT NOT NULL
                  )",
                 &[])
        .unwrap();

    conn.execute("CREATE TABLE IF NOT EXISTS genres (
                  movie_id        INTEGER NOT NULL,
                  genre           TEXT NOT NULL
            )",
                 &[])
        .unwrap();
}

/// List of movies with their year of release
pub fn import_movie(title: &str, year: &str, rating: &str, number: &str) {
    let conn = get_connection();

    println!("{}", title.replace("'", "").as_str());
    println!("{:?}", year);
    println!("{:?}", rating);
    println!("{:?}", number);

    conn.execute(&format!("INSERT INTO movies (title, year, rating, number) VALUES ('{}', '{}', \
                           '{}', '{}')",
                          title.replace("'", "''").as_str(),
                          year,
                          rating,
                          number),
                 &[])
        .unwrap();
}

/// Genre information is added to the movie list
pub fn add_genres(title: &str, year: &str, genre: &str) {
    let conn = get_connection();

    let mut stm = conn.prepare(&format!("SELECT id FROM movies WHERE title = '{}' AND year = '{}'",
                          title.replace("'", "''").as_str(),
                          year))
        .unwrap();

    let res = stm.query_map(&[], |x| Res { field: x.get(0) })
        .unwrap();

    let mut existent = false;
    let mut movie_id = 0;

    for tmp in res {
        existent = true;
        movie_id = tmp.unwrap().field;
    }

    if existent {
        conn.execute(&format!("INSERT INTO genres (movie_id, genre) VALUES ('{}', '{}')",
                              movie_id,
                              genre),
                     &[])
            .unwrap();
    }
}

/// List of ratings with information of user ratings
pub fn add_rating(title: &str, year: &str, rank: &str, votes: &str) {
    let conn = get_connection();

    conn.execute(&format!("INSERT INTO rankings (movie_id, score, number) VALUES ((SELECT id \
                           FROM movies WHERE title = '{}' AND year = '{}'), '{}', '{}')",
                          title,
                          year,
                          rank,
                          votes),
                 &[])
        .unwrap();
}

pub fn execute(search_params: SearchParams) -> Vec<SearchResult> {
    // println!("{:?}", search_params);
    let conn = get_connection();
    let mut query = String::new();

    query.push_str("SELECT * FROM movies JOIN (SELECT movie_id FROM genres JOIN (SELECT movie_id \
                    as m_id, COUNT(movie_id) AS ctr FROM (SELECT * FROM genres WHERE ");

    let mut genres_string = String::new();
    let mut genres: HashSet<String> = HashSet::new();

    if !search_params.get_movies().is_empty() {
        let mut movie_query = String::new();
        movie_query.push_str("SELECT genre FROM movies JOIN genres ON id = movie_id WHERE");

        let mut tmp = String::new();

        for movie in search_params.get_movies() {
            if tmp.is_empty() {
                tmp.push_str(format!(" title = '{}'", movie.replace("'", "''")).as_str());
            } else {
                tmp.push_str(format!(" OR title = '{}'", movie.replace("'", "''")).as_str());
            }
        }

        movie_query.push_str(tmp.as_str());

        let mut stm = conn.prepare(movie_query.as_str()).unwrap();

        let res = stm.query_map(&[], |x| GenreResult { field: x.get(0) }).unwrap();

        for genre in res {
            genres.insert(genre.unwrap().field);
        }
    }

    for genre in search_params.get_genres() {
        genres.insert(genre);
    }

    for genre in &genres {
        if genres_string.is_empty() {
            genres_string.push_str(format!("genre = '{}'", genre).as_str());
        } else {
            genres_string.push_str(format!(" OR genre = '{}'", genre).as_str());
        }
    }

    query.push_str(genres_string.as_str());

    query.push_str(format!(") GROUP BY m_id) ON movie_id = m_id WHERE ctr >= {} GROUP BY \
                            movie_id) ON id = movie_id WHERE rating > {} ORDER BY rating DESC",
                           genres.len(),
                           search_params.get_rating())
        .as_str());

    let mut stm = conn.prepare(query.as_str()).unwrap();
    let res = stm.query_map(&[], |x| {
        SearchResult {
            title: x.get(1),
            score: x.get(3),
            number: x.get(4),
            year: x.get(2),
            genres: Vec::new(),
        }
    });

    let mut tmp = Vec::new();
    for movie in res.unwrap() {
        let mut mov = movie.unwrap().clone();

        let mut stm =
            conn.prepare(format!("SELECT genre FROM genres WHERE movie_id = (SELECT id FROM \
                                  movies WHERE title = '{}' AND year = '{}') GROUP BY genre \
                                  ORDER BY genre ASC",
                                 mov.title,
                                 mov.year)
                    .as_str())
                .unwrap();
        let genres = stm.query_map(&[], |x| GenreResult { field: x.get(0) }).unwrap();
        let mut genre = Vec::new();
        for g in genres {
            genre.push(g.unwrap().field);
        }
        mov.genres = genre;
        tmp.push(mov);
    }

    tmp

}
<commit_msg>removed useless code<commit_after>use rusqlite::Connection;
use std::env;
use std::fs::create_dir_all;
use ::input::*;
use std::collections::HashSet;
use output::SearchResult;
use std::process;

/// A struct to represent a movie to be attached to actors or directors
#[derive(Debug)]
pub struct Movie {
    pub title: String,
    pub year: String,
}

#[derive(Debug)]
struct Res {
    pub field: i64,
}

#[derive(Debug)]
struct GenreResult {
    pub field: String,
}

/// Checks if a database already exists
pub fn db_exists() -> bool {
    let tmp = env::home_dir();
    let mut path_buf = tmp.unwrap();
    path_buf.push("Film-O-Mat");
    path_buf.push("database");
    path_buf.set_extension("db");
    path_buf.as_path().exists()
}

/// Returns a connection to existing database
fn get_connection() -> Connection {
    let tmp = env::home_dir();
    let mut path_buf = tmp.unwrap();
    path_buf.push("Film-O-Mat");
    path_buf.push("database");
    path_buf.set_extension("db");

    let conn = Connection::open(path_buf).unwrap();
    conn
}

/// Creates a database with movies and related information for movie suggestions
/// Movies: movie titles with associated release date and genre
/// Actors: names of all actors
/// Rankings: associates movie ID with IMDb ratings and number of ratings
/// Crew (actors and directors): associates actors/directors with their movies
pub fn create_database() {

    let tmp = env::home_dir();
    let mut path_buf = tmp.unwrap();
    path_buf.push("Film-O-Mat");

    // creates path if not existing
    if create_dir_all(&path_buf).is_err() {
        println!("Error while creating the Database at {:?}", path_buf);
        process::exit(1);
    }

    path_buf.push("database");
    path_buf.set_extension("db");

    let conn = Connection::open(path_buf).unwrap();

    conn.execute("CREATE TABLE IF NOT EXISTS movies (
                  id              INTEGER PRIMARY KEY,
                  title           TEXT NOT NULL,
                  year            TEXT NOT NULL,
                  rating          TEXT NOT NULL,
                  number          TEXT NOT NULL
                  )",
                 &[])
        .unwrap();

    conn.execute("CREATE TABLE IF NOT EXISTS genres (
                  movie_id        INTEGER NOT NULL,
                  genre           TEXT NOT NULL
            )",
                 &[])
        .unwrap();
}

/// List of movies with their year of release
pub fn import_movie(title: &str, year: &str, rating: &str, number: &str) {
    let conn = get_connection();

    conn.execute(&format!("INSERT INTO movies (title, year, rating, number) VALUES ('{}', '{}', \
                           '{}', '{}')",
                          title.replace("'", "''").as_str(),
                          year,
                          rating,
                          number),
                 &[])
        .unwrap();
}

/// Genre information is added to the movie list
pub fn add_genres(title: &str, year: &str, genre: &str) {
    let conn = get_connection();

    let mut stm = conn.prepare(&format!("SELECT id FROM movies WHERE title = '{}' AND year = '{}'",
                          title.replace("'", "''").as_str(),
                          year))
        .unwrap();

    let res = stm.query_map(&[], |x| Res { field: x.get(0) })
        .unwrap();

    let mut existent = false;
    let mut movie_id = 0;

    for tmp in res {
        existent = true;
        movie_id = tmp.unwrap().field;
    }

    if existent {
        conn.execute(&format!("INSERT INTO genres (movie_id, genre) VALUES ('{}', '{}')",
                              movie_id,
                              genre),
                     &[])
            .unwrap();
    }
}

/// List of ratings with information of user ratings
pub fn add_rating(title: &str, year: &str, rank: &str, votes: &str) {
    let conn = get_connection();

    conn.execute(&format!("INSERT INTO rankings (movie_id, score, number) VALUES ((SELECT id \
                           FROM movies WHERE title = '{}' AND year = '{}'), '{}', '{}')",
                          title,
                          year,
                          rank,
                          votes),
                 &[])
        .unwrap();
}

pub fn execute(search_params: SearchParams) -> Vec<SearchResult> {
    // println!("{:?}", search_params);
    let conn = get_connection();
    let mut query = String::new();

    query.push_str("SELECT * FROM movies JOIN (SELECT movie_id FROM genres JOIN (SELECT movie_id \
                    as m_id, COUNT(movie_id) AS ctr FROM (SELECT * FROM genres WHERE ");

    let mut genres_string = String::new();
    let mut genres: HashSet<String> = HashSet::new();

    if !search_params.get_movies().is_empty() {
        let mut movie_query = String::new();
        movie_query.push_str("SELECT genre FROM movies JOIN genres ON id = movie_id WHERE");

        let mut tmp = String::new();

        for movie in search_params.get_movies() {
            if tmp.is_empty() {
                tmp.push_str(format!(" title = '{}'", movie.replace("'", "''")).as_str());
            } else {
                tmp.push_str(format!(" OR title = '{}'", movie.replace("'", "''")).as_str());
            }
        }

        movie_query.push_str(tmp.as_str());

        let mut stm = conn.prepare(movie_query.as_str()).unwrap();

        let res = stm.query_map(&[], |x| GenreResult { field: x.get(0) }).unwrap();

        for genre in res {
            genres.insert(genre.unwrap().field);
        }
    }

    for genre in search_params.get_genres() {
        genres.insert(genre);
    }

    for genre in &genres {
        if genres_string.is_empty() {
            genres_string.push_str(format!("genre = '{}'", genre).as_str());
        } else {
            genres_string.push_str(format!(" OR genre = '{}'", genre).as_str());
        }
    }

    query.push_str(genres_string.as_str());

    query.push_str(format!(") GROUP BY m_id) ON movie_id = m_id WHERE ctr >= {} GROUP BY \
                            movie_id) ON id = movie_id WHERE rating > {} ORDER BY rating DESC",
                           genres.len(),
                           search_params.get_rating())
        .as_str());

    let mut stm = conn.prepare(query.as_str()).unwrap();
    let res = stm.query_map(&[], |x| {
        SearchResult {
            title: x.get(1),
            score: x.get(3),
            number: x.get(4),
            year: x.get(2),
            genres: Vec::new(),
        }
    });

    let mut tmp = Vec::new();
    for movie in res.unwrap() {
        let mut mov = movie.unwrap().clone();

        let mut stm =
            conn.prepare(format!("SELECT genre FROM genres WHERE movie_id = (SELECT id FROM \
                                  movies WHERE title = '{}' AND year = '{}') GROUP BY genre \
                                  ORDER BY genre ASC",
                                 mov.title,
                                 mov.year)
                    .as_str())
                .unwrap();
        let genres = stm.query_map(&[], |x| GenreResult { field: x.get(0) }).unwrap();
        let mut genre = Vec::new();
        for g in genres {
            genre.push(g.unwrap().field);
        }
        mov.genres = genre;
        tmp.push(mov);
    }

    tmp

}
<|endoftext|>


<commit_before>use header::Tag;

/// This tag contains section header table from an ELF kernel.
///
/// The sections iterator is provided via the `sections` method.
#[derive(Debug)]
pub struct ElfSectionsTag {
    inner: *const ElfSectionsTagInner,
    offset: usize,
}

pub unsafe fn elf_sections_tag(tag: &Tag, offset: usize) -> ElfSectionsTag {
    assert_eq!(9, tag.typ);
    let es = ElfSectionsTag {
        inner: (tag as *const Tag).offset(1) as *const ElfSectionsTagInner,
        offset,
    };
    assert!((es.get().entry_size * es.get().shndx) <= tag.size);
    es
}

#[derive(Clone, Copy, Debug)]
#[repr(C, packed)] // only repr(C) would add unwanted padding at the end
struct ElfSectionsTagInner {
    number_of_sections: u32,
    entry_size: u32,
    shndx: u32, // string table
}

impl ElfSectionsTag {
    /// Get an iterator of loaded ELF sections.
    ///
    /// # Examples
    ///
    /// ```ignore
    /// if let Some(elf_tag) = boot_info.elf_sections_tag() {
    ///     let mut total = 0;
    ///     for section in elf_tag.sections() {
    ///         println!("Section: {:?}", section);
    ///         total += 1;
    ///     }
    /// }
    /// ```
    pub fn sections(&self) -> ElfSectionIter {
        let string_section_offset = (self.get().shndx * self.get().entry_size) as isize;
        let string_section_ptr = unsafe {
            self.first_section().offset(string_section_offset) as *const _
        };
        ElfSectionIter {
            current_section: self.first_section(),
            remaining_sections: self.get().number_of_sections,
            entry_size: self.get().entry_size,
            string_section: string_section_ptr,
            offset: self.offset,
        }
    }

    fn first_section(&self) -> *const u8 {
        (unsafe { self.inner.offset(1) }) as *const _
    }

    fn get(&self) -> &ElfSectionsTagInner {
        unsafe { &*self.inner }
    }
}

/// An iterator over some ELF sections.
#[derive(Clone, Debug)]
pub struct ElfSectionIter {
    current_section: *const u8,
    remaining_sections: u32,
    entry_size: u32,
    string_section: *const u8,
    offset: usize,
}

impl Iterator for ElfSectionIter {
    type Item = ElfSection;

    fn next(&mut self) -> Option<ElfSection> {
        while self.remaining_sections != 0 {
            let section = ElfSection {
                inner: self.current_section,
                string_section: self.string_section,
                entry_size: self.entry_size,
                offset: self.offset,
            };

            self.current_section = unsafe { self.current_section.offset(self.entry_size as isize) };
            self.remaining_sections -= 1;

            if section.section_type() != ElfSectionType::Unused {
                return Some(section);
            }
        }
        None
    }
}

/// A single generic ELF Section.
#[derive(Debug)]
pub struct ElfSection {
    inner: *const u8,
    string_section: *const u8,
    entry_size: u32,
    offset: usize,
}

#[derive(Clone, Copy, Debug)]
#[repr(C, packed)]
struct ElfSectionInner32 {
    name_index: u32,
    typ: u32,
    flags: u32,
    addr: u32,
    offset: u32,
    size: u32,
    link: u32,
    info: u32,
    addralign: u32,
    entry_size: u32,
}

#[derive(Clone, Copy, Debug)]
#[repr(C, packed)]
struct ElfSectionInner64 {
    name_index: u32,
    typ: u32,
    flags: u64,
    addr: u64,
    offset: u64,
    size: u64,
    link: u32,
    info: u32,
    addralign: u64,
    entry_size: u64,
}

impl ElfSection {
    /// Get the section type as a `ElfSectionType` enum variant.
    pub fn section_type(&self) -> ElfSectionType {
        match self.get().typ() {
            0 => ElfSectionType::Unused,
            1 => ElfSectionType::ProgramSection,
            2 => ElfSectionType::LinkerSymbolTable,
            3 => ElfSectionType::StringTable,
            4 => ElfSectionType::RelaRelocation,
            5 => ElfSectionType::SymbolHashTable,
            6 => ElfSectionType::DynamicLinkingTable,
            7 => ElfSectionType::Note,
            8 => ElfSectionType::Uninitialized,
            9 => ElfSectionType::RelRelocation,
            10 => ElfSectionType::Reserved,
            11 => ElfSectionType::DynamicLoaderSymbolTable,
            0x6000_0000...0x6FFF_FFFF => ElfSectionType::EnvironmentSpecific,
            0x7000_0000...0x7FFF_FFFF => ElfSectionType::ProcessorSpecific,
            _ => panic!(),
        }
    }

    /// Get the "raw" section type as a `u32`
    pub fn section_type_raw(&self) -> u32 {
        self.get().typ()
    }

    /// Read the name of the section.
    pub fn name(&self) -> &str {
        use core::{str, slice};

        let name_ptr = unsafe {
            self.string_table().offset(self.get().name_index() as isize)
        };
        let strlen = {
            let mut len = 0;
            while unsafe { *name_ptr.offset(len) } != 0 {
                len += 1;
            }
            len as usize
        };

        str::from_utf8(unsafe { slice::from_raw_parts(name_ptr, strlen) }).unwrap()
    }

    /// Get the physical start address of the section.
    pub fn start_address(&self) -> u64 {
        self.get().addr()
    }

    /// Get the physical end address of the section.
    ///
    /// This is the same as doing `section.start_address() + section.size()`
    pub fn end_address(&self) -> u64 {
        self.get().addr() + self.get().size()
    }

    /// Get the section's size in bytes.
    pub fn size(&self) -> u64 {
        self.get().size()
    }

    /// Get the section's address alignment constraints.
    ///
    /// That is, the value of `start_address` must be congruent to 0,
    /// modulo the value of `addrlign`. Currently, only 0 and positive
    /// integral powers of two are allowed. Values 0 and 1 mean the section has no
    /// alignment constraints.
    pub fn addralign(&self) -> u64 {
        self.get().addralign()
    }

    /// Get the section's flags.
    pub fn flags(&self) -> ElfSectionFlags {
        ElfSectionFlags::from_bits_truncate(self.get().flags())
    }

    /// Check if the `ALLOCATED` flag is set in the section flags.
    pub fn is_allocated(&self) -> bool {
        self.flags().contains(ElfSectionFlags::ALLOCATED)
    }

    fn get(&self) -> &ElfSectionInner {
        match self.entry_size {
            40 => unsafe { &*(self.inner as *const ElfSectionInner32) },
            64 => unsafe { &*(self.inner as *const ElfSectionInner64) },
            _ => panic!(),
        }
    }

    unsafe fn string_table(&self) -> *const u8 {
        let addr = match self.entry_size {
            40 => (*(self.string_section as *const ElfSectionInner32)).addr as usize,
            64 => (*(self.string_section as *const ElfSectionInner64)).addr as usize,
            _ => panic!(),
        };
        (addr + self.offset) as *const _
    }
}

trait ElfSectionInner {
    fn name_index(&self) -> u32;

    fn typ(&self) -> u32;

    fn flags(&self) -> u64;

    fn addr(&self) -> u64;

    fn size(&self) -> u64;

    fn addralign(&self) -> u64;
}

impl ElfSectionInner for ElfSectionInner32 {
    fn name_index(&self) -> u32 {
        self.name_index
    }

    fn typ(&self) -> u32 {
        self.typ
    }

    fn flags(&self) -> u64 {
        self.flags.into()
    }

    fn addr(&self) -> u64 {
        self.addr.into()
    }

    fn size(&self) -> u64 {
        self.size.into()
    }

    fn addralign(&self) -> u64 {
        self.addralign.into()
    }
}

impl ElfSectionInner for ElfSectionInner64 {
    fn name_index(&self) -> u32 {
        self.name_index
    }

    fn typ(&self) -> u32 {
        self.typ
    }

    fn flags(&self) -> u64 {
        self.flags
    }

    fn addr(&self) -> u64 {
        self.addr
    }

    fn size(&self) -> u64 {
        self.size
    }

    fn addralign(&self) -> u64 {
        self.addralign.into()
    }
}

/// An enum abstraction over raw ELF section types.
#[derive(PartialEq, Eq, Debug, Copy, Clone)]
#[repr(u32)]
pub enum ElfSectionType {
    /// This value marks the section header as inactive; it does not have an
    /// associated section. Other members of the section header have undefined
    /// values.
    Unused = 0,

    /// The section holds information defined by the program, whose format and
    /// meaning are determined solely by the program.
    ProgramSection = 1,

    /// This section holds a linker symbol table.
    LinkerSymbolTable = 2,

    /// The section holds a string table.
    StringTable = 3,

    /// The section holds relocation entries with explicit addends, such as type
    /// Elf32_Rela for the 32-bit class of object files. An object file may have
    /// multiple relocation sections.
    RelaRelocation = 4,

    /// The section holds a symbol hash table.
    SymbolHashTable = 5,

    /// The section holds dynamic linking tables.
    DynamicLinkingTable = 6,

    /// This section holds information that marks the file in some way.
    Note = 7,

    /// A section of this type occupies no space in the file but otherwise resembles
    /// `ProgramSection`. Although this section contains no bytes, the
    /// sh_offset member contains the conceptual file offset.
    Uninitialized = 8,

    /// The section holds relocation entries without explicit addends, such as type
    /// Elf32_Rel for the 32-bit class of object files. An object file may have
    /// multiple relocation sections.
    RelRelocation = 9,

    /// This section type is reserved but has unspecified semantics.
    Reserved = 10,

    /// This section holds a dynamic loader symbol table.
    DynamicLoaderSymbolTable = 11,

    /// Values in this inclusive range (`[0x6000_0000, 0x6FFF_FFFF)`) are
    /// reserved for environment-specific semantics.
    EnvironmentSpecific = 0x6000_0000,

    /// Values in this inclusive range (`[0x7000_0000, 0x7FFF_FFFF)`) are
    /// reserved for processor-specific semantics.
    ProcessorSpecific = 0x7000_0000,
}

bitflags! {
    /// ELF Section bitflags.
    pub struct ElfSectionFlags: u64 {
        /// The section contains data that should be writable during program execution.
        const WRITABLE = 0x1;

        /// The section occupies memory during the process execution.
        const ALLOCATED = 0x2;

        /// The section contains executable machine instructions.
        const EXECUTABLE = 0x4;
        // plus environment-specific use at 0x0F000000
        // plus processor-specific use at 0xF0000000
    }
}
<commit_msg>Fix a few warnings<commit_after>use header::Tag;

/// This tag contains section header table from an ELF kernel.
///
/// The sections iterator is provided via the `sections` method.
#[derive(Debug)]
pub struct ElfSectionsTag {
    inner: *const ElfSectionsTagInner,
    offset: usize,
}

pub unsafe fn elf_sections_tag(tag: &Tag, offset: usize) -> ElfSectionsTag {
    assert_eq!(9, tag.typ);
    let es = ElfSectionsTag {
        inner: (tag as *const Tag).offset(1) as *const ElfSectionsTagInner,
        offset,
    };
    assert!((es.get().entry_size * es.get().shndx) <= tag.size);
    es
}

#[derive(Clone, Copy, Debug)]
#[repr(C, packed)] // only repr(C) would add unwanted padding at the end
struct ElfSectionsTagInner {
    number_of_sections: u32,
    entry_size: u32,
    shndx: u32, // string table
}

impl ElfSectionsTag {
    /// Get an iterator of loaded ELF sections.
    ///
    /// # Examples
    ///
    /// ```ignore
    /// if let Some(elf_tag) = boot_info.elf_sections_tag() {
    ///     let mut total = 0;
    ///     for section in elf_tag.sections() {
    ///         println!("Section: {:?}", section);
    ///         total += 1;
    ///     }
    /// }
    /// ```
    pub fn sections(&self) -> ElfSectionIter {
        let string_section_offset = (self.get().shndx * self.get().entry_size) as isize;
        let string_section_ptr =
            unsafe { self.first_section().offset(string_section_offset) as *const _ };
        ElfSectionIter {
            current_section: self.first_section(),
            remaining_sections: self.get().number_of_sections,
            entry_size: self.get().entry_size,
            string_section: string_section_ptr,
            offset: self.offset,
        }
    }

    fn first_section(&self) -> *const u8 {
        (unsafe { self.inner.offset(1) }) as *const _
    }

    fn get(&self) -> &ElfSectionsTagInner {
        unsafe { &*self.inner }
    }
}

/// An iterator over some ELF sections.
#[derive(Clone, Debug)]
pub struct ElfSectionIter {
    current_section: *const u8,
    remaining_sections: u32,
    entry_size: u32,
    string_section: *const u8,
    offset: usize,
}

impl Iterator for ElfSectionIter {
    type Item = ElfSection;

    fn next(&mut self) -> Option<ElfSection> {
        while self.remaining_sections != 0 {
            let section = ElfSection {
                inner: self.current_section,
                string_section: self.string_section,
                entry_size: self.entry_size,
                offset: self.offset,
            };

            self.current_section = unsafe { self.current_section.offset(self.entry_size as isize) };
            self.remaining_sections -= 1;

            if section.section_type() != ElfSectionType::Unused {
                return Some(section);
            }
        }
        None
    }
}

/// A single generic ELF Section.
#[derive(Debug)]
pub struct ElfSection {
    inner: *const u8,
    string_section: *const u8,
    entry_size: u32,
    offset: usize,
}

#[derive(Clone, Copy, Debug)]
#[repr(C, packed)]
struct ElfSectionInner32 {
    name_index: u32,
    typ: u32,
    flags: u32,
    addr: u32,
    offset: u32,
    size: u32,
    link: u32,
    info: u32,
    addralign: u32,
    entry_size: u32,
}

#[derive(Clone, Copy, Debug)]
#[repr(C, packed)]
struct ElfSectionInner64 {
    name_index: u32,
    typ: u32,
    flags: u64,
    addr: u64,
    offset: u64,
    size: u64,
    link: u32,
    info: u32,
    addralign: u64,
    entry_size: u64,
}

impl ElfSection {
    /// Get the section type as a `ElfSectionType` enum variant.
    pub fn section_type(&self) -> ElfSectionType {
        match self.get().typ() {
            0 => ElfSectionType::Unused,
            1 => ElfSectionType::ProgramSection,
            2 => ElfSectionType::LinkerSymbolTable,
            3 => ElfSectionType::StringTable,
            4 => ElfSectionType::RelaRelocation,
            5 => ElfSectionType::SymbolHashTable,
            6 => ElfSectionType::DynamicLinkingTable,
            7 => ElfSectionType::Note,
            8 => ElfSectionType::Uninitialized,
            9 => ElfSectionType::RelRelocation,
            10 => ElfSectionType::Reserved,
            11 => ElfSectionType::DynamicLoaderSymbolTable,
            0x6000_0000..=0x6FFF_FFFF => ElfSectionType::EnvironmentSpecific,
            0x7000_0000..=0x7FFF_FFFF => ElfSectionType::ProcessorSpecific,
            _ => panic!(),
        }
    }

    /// Get the "raw" section type as a `u32`
    pub fn section_type_raw(&self) -> u32 {
        self.get().typ()
    }

    /// Read the name of the section.
    pub fn name(&self) -> &str {
        use core::{slice, str};

        let name_ptr = unsafe { self.string_table().offset(self.get().name_index() as isize) };
        let strlen = {
            let mut len = 0;
            while unsafe { *name_ptr.offset(len) } != 0 {
                len += 1;
            }
            len as usize
        };

        str::from_utf8(unsafe { slice::from_raw_parts(name_ptr, strlen) }).unwrap()
    }

    /// Get the physical start address of the section.
    pub fn start_address(&self) -> u64 {
        self.get().addr()
    }

    /// Get the physical end address of the section.
    ///
    /// This is the same as doing `section.start_address() + section.size()`
    pub fn end_address(&self) -> u64 {
        self.get().addr() + self.get().size()
    }

    /// Get the section's size in bytes.
    pub fn size(&self) -> u64 {
        self.get().size()
    }

    /// Get the section's address alignment constraints.
    ///
    /// That is, the value of `start_address` must be congruent to 0,
    /// modulo the value of `addrlign`. Currently, only 0 and positive
    /// integral powers of two are allowed. Values 0 and 1 mean the section has no
    /// alignment constraints.
    pub fn addralign(&self) -> u64 {
        self.get().addralign()
    }

    /// Get the section's flags.
    pub fn flags(&self) -> ElfSectionFlags {
        ElfSectionFlags::from_bits_truncate(self.get().flags())
    }

    /// Check if the `ALLOCATED` flag is set in the section flags.
    pub fn is_allocated(&self) -> bool {
        self.flags().contains(ElfSectionFlags::ALLOCATED)
    }

    fn get(&self) -> &dyn ElfSectionInner {
        match self.entry_size {
            40 => unsafe { &*(self.inner as *const ElfSectionInner32) },
            64 => unsafe { &*(self.inner as *const ElfSectionInner64) },
            _ => panic!(),
        }
    }

    unsafe fn string_table(&self) -> *const u8 {
        let addr = match self.entry_size {
            40 => (*(self.string_section as *const ElfSectionInner32)).addr as usize,
            64 => (*(self.string_section as *const ElfSectionInner64)).addr as usize,
            _ => panic!(),
        };
        (addr + self.offset) as *const _
    }
}

trait ElfSectionInner {
    fn name_index(&self) -> u32;

    fn typ(&self) -> u32;

    fn flags(&self) -> u64;

    fn addr(&self) -> u64;

    fn size(&self) -> u64;

    fn addralign(&self) -> u64;
}

impl ElfSectionInner for ElfSectionInner32 {
    fn name_index(&self) -> u32 {
        self.name_index
    }

    fn typ(&self) -> u32 {
        self.typ
    }

    fn flags(&self) -> u64 {
        self.flags.into()
    }

    fn addr(&self) -> u64 {
        self.addr.into()
    }

    fn size(&self) -> u64 {
        self.size.into()
    }

    fn addralign(&self) -> u64 {
        self.addralign.into()
    }
}

impl ElfSectionInner for ElfSectionInner64 {
    fn name_index(&self) -> u32 {
        self.name_index
    }

    fn typ(&self) -> u32 {
        self.typ
    }

    fn flags(&self) -> u64 {
        self.flags
    }

    fn addr(&self) -> u64 {
        self.addr
    }

    fn size(&self) -> u64 {
        self.size
    }

    fn addralign(&self) -> u64 {
        self.addralign.into()
    }
}

/// An enum abstraction over raw ELF section types.
#[derive(PartialEq, Eq, Debug, Copy, Clone)]
#[repr(u32)]
pub enum ElfSectionType {
    /// This value marks the section header as inactive; it does not have an
    /// associated section. Other members of the section header have undefined
    /// values.
    Unused = 0,

    /// The section holds information defined by the program, whose format and
    /// meaning are determined solely by the program.
    ProgramSection = 1,

    /// This section holds a linker symbol table.
    LinkerSymbolTable = 2,

    /// The section holds a string table.
    StringTable = 3,

    /// The section holds relocation entries with explicit addends, such as type
    /// Elf32_Rela for the 32-bit class of object files. An object file may have
    /// multiple relocation sections.
    RelaRelocation = 4,

    /// The section holds a symbol hash table.
    SymbolHashTable = 5,

    /// The section holds dynamic linking tables.
    DynamicLinkingTable = 6,

    /// This section holds information that marks the file in some way.
    Note = 7,

    /// A section of this type occupies no space in the file but otherwise resembles
    /// `ProgramSection`. Although this section contains no bytes, the
    /// sh_offset member contains the conceptual file offset.
    Uninitialized = 8,

    /// The section holds relocation entries without explicit addends, such as type
    /// Elf32_Rel for the 32-bit class of object files. An object file may have
    /// multiple relocation sections.
    RelRelocation = 9,

    /// This section type is reserved but has unspecified semantics.
    Reserved = 10,

    /// This section holds a dynamic loader symbol table.
    DynamicLoaderSymbolTable = 11,

    /// Values in this inclusive range (`[0x6000_0000, 0x6FFF_FFFF)`) are
    /// reserved for environment-specific semantics.
    EnvironmentSpecific = 0x6000_0000,

    /// Values in this inclusive range (`[0x7000_0000, 0x7FFF_FFFF)`) are
    /// reserved for processor-specific semantics.
    ProcessorSpecific = 0x7000_0000,
}

bitflags! {
    /// ELF Section bitflags.
    pub struct ElfSectionFlags: u64 {
        /// The section contains data that should be writable during program execution.
        const WRITABLE = 0x1;

        /// The section occupies memory during the process execution.
        const ALLOCATED = 0x2;

        /// The section contains executable machine instructions.
        const EXECUTABLE = 0x4;
        // plus environment-specific use at 0x0F000000
        // plus processor-specific use at 0xF0000000
    }
}
<|endoftext|>