<commit_before>use std::error::Error;

use schema::*;
use diesel::*;

#[test]
fn test_updating_single_column() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    update(users).set(name.eq("Jim")).execute(&connection).unwrap();

    let expected_data = vec!["Jim".to_string(); 2];
    let data: Vec<String> = users.select(name).load(&connection).unwrap();
    assert_eq!(expected_data, data);
}

#[test]
fn test_updating_single_column_of_single_row() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);

    update(users.filter(id.eq(sean.id))).set(name.eq("Jim"))
        .execute(&connection).unwrap();

    let expected_data = vec!["Jim".to_string(), "Tess".to_string()];
    let data: Vec<String> = users.select(name).order(id).load(&connection).unwrap();
    assert_eq!(expected_data, data);
}

#[test]
fn test_updating_nullable_column() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);

    update(users.filter(id.eq(sean.id))).set(hair_color.eq(Some("black")))
        .execute(&connection).unwrap();

    let data: Option<String> = users.select(hair_color)
        .filter(id.eq(sean.id))
        .first(&connection)
        .unwrap();
    assert_eq!(Some("black".to_string()), data);

    update(users.filter(id.eq(sean.id))).set(hair_color.eq(None::<String>))
        .execute(&connection).unwrap();

    let data: QueryResult<Option<String>> = users.select(hair_color)
        .filter(id.eq(sean.id))
        .first(&connection);
    assert_eq!(Ok(None::<String>), data);
}

#[test]
fn test_updating_multiple_columns() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);

    update(users.filter(id.eq(sean.id))).set((
        name.eq("Jim"),
        hair_color.eq(Some("black")),
    )).execute(&connection).unwrap();

    let expected_user = User::with_hair_color(sean.id, "Jim", "black");
    let user = users.find(sean.id).first(&connection);
    assert_eq!(Ok(expected_user), user);
}

#[test]
#[cfg(not(feature="sqlite"))]
fn update_returning_struct() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    let user = update(users.filter(id.eq(sean.id))).set(hair_color.eq("black"))
        .get_result(&connection);
    let expected_user = User::with_hair_color(sean.id, "Sean", "black");

    assert_eq!(Ok(expected_user), user);
}

#[test]
#[cfg(not(feature="sqlite"))]
fn update_with_custom_returning_clause() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    let user = update(users.filter(id.eq(sean.id)))
        .set(hair_color.eq("black"))
        .returning((name, hair_color))
        .get_result::<(String, Option<String>)>(&connection);
    let expected_result = ("Sean".to_string(), Some("black".to_string()));

    assert_eq!(Ok(expected_result), user);
}

#[test]
fn update_with_struct_as_changes() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    let changes = NewUser::new("Jim", Some("blue"));

    update(users.filter(id.eq(sean.id))).set(&changes)
        .execute(&connection).unwrap();
    let user = users.find(sean.id).first(&connection);
    let expected_user = User::with_hair_color(sean.id, "Jim", "blue");

    assert_eq!(Ok(expected_user), user);
}

#[test]
fn update_with_struct_does_not_set_primary_key() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    let other_id = sean.id + 1;
    let changes = User::with_hair_color(other_id, "Jim", "blue");

    update(users.filter(id.eq(sean.id))).set(&changes)
        .execute(&connection).unwrap();
    let user = users.find(sean.id).first(&connection);
    let expected_user = User::with_hair_color(sean.id, "Jim", "blue");

    assert_eq!(Ok(expected_user), user);
}

#[test]
fn save_on_struct_with_primary_key_changes_that_struct() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    let user = User::with_hair_color(sean.id, "Jim", "blue").save_changes::<User>(&connection);

    let user_in_db = users.find(sean.id).first(&connection);

    assert_eq!(user, user_in_db);
}

#[test]
fn option_fields_on_structs_are_not_assigned() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    update(users.filter(id.eq(sean.id)))
        .set(hair_color.eq("black"))
        .execute(&connection).unwrap();
    let user = User::new(sean.id, "Jim").save_changes(&connection);

    let expected_user = User::with_hair_color(sean.id, "Jim", "black");
    assert_eq!(Ok(expected_user), user);
}

#[test]
fn sql_syntax_is_correct_when_option_field_comes_before_non_option() {
    #[derive(AsChangeset)]
    #[table_name="users"]
    struct Changes {
        hair_color: Option<String>,
        name: String,
    }

    let changes = Changes { hair_color: None, name: "Jim".into() };
    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    update(users::table.filter(users::id.eq(sean.id))).set(&changes)
        .execute(&connection).unwrap();
    let user = users::table.find(sean.id).first(&connection);

    let expected_user = User::new(sean.id, "Jim");
    assert_eq!(Ok(expected_user), user);
}

#[test]
fn sql_syntax_is_correct_when_option_field_comes_mixed_with_non_option() {
    #[derive(AsChangeset)]
    #[table_name="posts"]
    struct Changes {
        user_id: i32,
        title: Option<String>,
        body: String,
    }

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    let new_post = sean.new_post("Hello", Some("world"));
    insert(&new_post).into(posts::table).execute(&connection).unwrap();

    let changes = Changes { user_id: 1, title: None, body: "earth".into() };
    update(posts::table)
        .set(&changes)
        .execute(&connection)
        .unwrap();
    let post = posts::table.order(posts::id.desc()).first::<Post>(&connection).unwrap();

    let expected_post = Post::new(post.id, sean.id, "Hello".into(), Some("earth".into()));
    assert_eq!(expected_post, post);
}

#[test]
fn can_update_with_struct_containing_single_field() {
    #[derive(AsChangeset)]
    #[table_name="posts"]
    struct SetBody {
        body: String,
    }

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    let new_post = sean.new_post("Hello", Some("world"));
    insert(&new_post).into(posts::table).execute(&connection).unwrap();

    let changes = SetBody { body: "earth".into() };
    update(posts::table)
        .set(&changes)
        .execute(&connection)
        .unwrap();
    let post = posts::table.order(posts::id.desc()).first::<Post>(&connection).unwrap();

    let expected_post = Post::new(post.id, sean.id, "Hello".into(), Some("earth".into()));
    assert_eq!(expected_post, post);
}

#[test]
fn struct_with_option_fields_treated_as_null() {
    #[derive(Identifiable, AsChangeset)]
    #[table_name="posts"]
    #[changeset_options(treat_none_as_null="true")]
    struct UpdatePost {
        id: i32,
        title: String,
        body: Option<String>,
    }

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    let new_post = sean.new_post("Hello", Some("world"));
    insert(&new_post).into(posts::table)
        .execute(&connection).unwrap();
    let post = posts::table.order(posts::id.desc()).first::<Post>(&connection).unwrap();

    let changes = UpdatePost { id: post.id, title: "Hello again".into(), body: None };
    let expected_post = Post::new(post.id, sean.id, "Hello again".into(), None);
    let updated_post = changes.save_changes(&connection);
    let post_in_database = posts::table.find(post.id).first(&connection);

    assert_eq!(Ok(&expected_post), updated_post.as_ref());
    assert_eq!(Ok(&expected_post), post_in_database.as_ref());
}

#[test]
#[should_panic="There are no changes to save."]
fn update_with_no_changes() {
    #[derive(AsChangeset)]
    #[table_name="users"]
    struct Changes {
        name: Option<String>,
        hair_color: Option<String>,
    }

    let connection = connection();
    let changes = Changes { name: None, hair_color: None, };
    update(users::table).set(&changes).execute(&connection).unwrap();
}
<commit_msg>Fix invalid test<commit_after>use std::error::Error;

use schema::*;
use diesel::*;

#[test]
fn test_updating_single_column() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    update(users).set(name.eq("Jim")).execute(&connection).unwrap();

    let expected_data = vec!["Jim".to_string(); 2];
    let data: Vec<String> = users.select(name).load(&connection).unwrap();
    assert_eq!(expected_data, data);
}

#[test]
fn test_updating_single_column_of_single_row() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);

    update(users.filter(id.eq(sean.id))).set(name.eq("Jim"))
        .execute(&connection).unwrap();

    let expected_data = vec!["Jim".to_string(), "Tess".to_string()];
    let data: Vec<String> = users.select(name).order(id).load(&connection).unwrap();
    assert_eq!(expected_data, data);
}

#[test]
fn test_updating_nullable_column() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);

    update(users.filter(id.eq(sean.id))).set(hair_color.eq(Some("black")))
        .execute(&connection).unwrap();

    let data: Option<String> = users.select(hair_color)
        .filter(id.eq(sean.id))
        .first(&connection)
        .unwrap();
    assert_eq!(Some("black".to_string()), data);

    update(users.filter(id.eq(sean.id))).set(hair_color.eq(None::<String>))
        .execute(&connection).unwrap();

    let data: QueryResult<Option<String>> = users.select(hair_color)
        .filter(id.eq(sean.id))
        .first(&connection);
    assert_eq!(Ok(None::<String>), data);
}

#[test]
fn test_updating_multiple_columns() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);

    update(users.filter(id.eq(sean.id))).set((
        name.eq("Jim"),
        hair_color.eq(Some("black")),
    )).execute(&connection).unwrap();

    let expected_user = User::with_hair_color(sean.id, "Jim", "black");
    let user = users.find(sean.id).first(&connection);
    assert_eq!(Ok(expected_user), user);
}

#[test]
#[cfg(not(feature="sqlite"))]
fn update_returning_struct() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    let user = update(users.filter(id.eq(sean.id))).set(hair_color.eq("black"))
        .get_result(&connection);
    let expected_user = User::with_hair_color(sean.id, "Sean", "black");

    assert_eq!(Ok(expected_user), user);
}

#[test]
#[cfg(not(feature="sqlite"))]
fn update_with_custom_returning_clause() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    let user = update(users.filter(id.eq(sean.id)))
        .set(hair_color.eq("black"))
        .returning((name, hair_color))
        .get_result::<(String, Option<String>)>(&connection);
    let expected_result = ("Sean".to_string(), Some("black".to_string()));

    assert_eq!(Ok(expected_result), user);
}

#[test]
fn update_with_struct_as_changes() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    let changes = NewUser::new("Jim", Some("blue"));

    update(users.filter(id.eq(sean.id))).set(&changes)
        .execute(&connection).unwrap();
    let user = users.find(sean.id).first(&connection);
    let expected_user = User::with_hair_color(sean.id, "Jim", "blue");

    assert_eq!(Ok(expected_user), user);
}

#[test]
fn update_with_struct_does_not_set_primary_key() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    let other_id = sean.id + 1;
    let changes = User::with_hair_color(other_id, "Jim", "blue");

    update(users.filter(id.eq(sean.id))).set(&changes)
        .execute(&connection).unwrap();
    let user = users.find(sean.id).first(&connection);
    let expected_user = User::with_hair_color(sean.id, "Jim", "blue");

    assert_eq!(Ok(expected_user), user);
}

#[test]
fn save_on_struct_with_primary_key_changes_that_struct() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    let user = User::with_hair_color(sean.id, "Jim", "blue").save_changes::<User>(&connection);

    let user_in_db = users.find(sean.id).first(&connection);

    assert_eq!(user, user_in_db);
}

#[test]
fn option_fields_on_structs_are_not_assigned() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    update(users.filter(id.eq(sean.id)))
        .set(hair_color.eq("black"))
        .execute(&connection).unwrap();
    let user = User::new(sean.id, "Jim").save_changes(&connection);

    let expected_user = User::with_hair_color(sean.id, "Jim", "black");
    assert_eq!(Ok(expected_user), user);
}

#[test]
fn sql_syntax_is_correct_when_option_field_comes_before_non_option() {
    #[derive(AsChangeset)]
    #[table_name="users"]
    struct Changes {
        hair_color: Option<String>,
        name: String,
    }

    let changes = Changes { hair_color: None, name: "Jim".into() };
    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    update(users::table.filter(users::id.eq(sean.id))).set(&changes)
        .execute(&connection).unwrap();
    let user = users::table.find(sean.id).first(&connection);

    let expected_user = User::new(sean.id, "Jim");
    assert_eq!(Ok(expected_user), user);
}

#[test]
fn sql_syntax_is_correct_when_option_field_comes_mixed_with_non_option() {
    #[derive(AsChangeset)]
    #[table_name="posts"]
    struct Changes {
        user_id: i32,
        title: Option<String>,
        body: String,
    }

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    let new_post = sean.new_post("Hello", Some("world"));
    insert(&new_post).into(posts::table).execute(&connection).unwrap();

    let changes = Changes { user_id: 1, title: None, body: "earth".into() };
    update(posts::table)
        .set(&changes)
        .execute(&connection)
        .unwrap();
    let post = posts::table.order(posts::id.desc()).first::<Post>(&connection).unwrap();

    let expected_post = Post::new(post.id, sean.id, "Hello".into(), Some("earth".into()));
    assert_eq!(expected_post, post);
}

#[test]
fn can_update_with_struct_containing_single_field() {
    #[derive(AsChangeset)]
    #[table_name="posts"]
    struct SetBody {
        body: String,
    }

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    let new_post = sean.new_post("Hello", Some("world"));
    insert(&new_post).into(posts::table).execute(&connection).unwrap();

    let changes = SetBody { body: "earth".into() };
    update(posts::table)
        .set(&changes)
        .execute(&connection)
        .unwrap();
    let post = posts::table.order(posts::id.desc()).first::<Post>(&connection).unwrap();

    let expected_post = Post::new(post.id, sean.id, "Hello".into(), Some("earth".into()));
    assert_eq!(expected_post, post);
}

#[test]
fn struct_with_option_fields_treated_as_null() {
    #[derive(Identifiable, AsChangeset)]
    #[table_name="posts"]
    #[changeset_options(treat_none_as_null="true")]
    struct UpdatePost {
        id: i32,
        title: String,
        body: Option<String>,
    }

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    let new_post = sean.new_post("Hello", Some("world"));
    insert(&new_post).into(posts::table)
        .execute(&connection).unwrap();
    let post = posts::table.order(posts::id.desc()).first::<Post>(&connection).unwrap();

    let changes = UpdatePost { id: post.id, title: "Hello again".into(), body: None };
    let expected_post = Post::new(post.id, sean.id, "Hello again".into(), None);
    let updated_post = changes.save_changes(&connection);
    let post_in_database = posts::table.find(post.id).first(&connection);

    assert_eq!(Ok(&expected_post), updated_post.as_ref());
    assert_eq!(Ok(&expected_post), post_in_database.as_ref());
}

#[test]
#[should_panic(expected="There are no changes to save.")]
fn update_with_no_changes() {
    #[derive(AsChangeset)]
    #[table_name="users"]
    struct Changes {
        name: Option<String>,
        hair_color: Option<String>,
    }

    let connection = connection();
    let changes = Changes { name: None, hair_color: None, };
    update(users::table).set(&changes).execute(&connection).unwrap();
}
<|endoftext|>


<commit_before>use std::fmt;
use std::ops;
use std::ops::{Range, RangeFrom, RangeTo, RangeFull};
use std::iter;
use std::iter::FromIterator;

//
pub trait ArrayIx {
    fn to_idx_vec(&self, ax: usize, dims: &[usize]) -> Vec<usize>;
    fn size(&self, ax: usize, dims: &[usize]) -> usize {
        self.to_idx_vec(ax, dims).len()
    }
}

impl ArrayIx for RangeFull {
    fn to_idx_vec(&self, ax: usize, dims: &[usize]) -> Vec<usize> {
        assert!(dims.len() > ax, "ax must be in range");
        (0 .. dims[ax]).collect()
    }
}

macro_rules! impl_array_ix_for_range {
    ($typ:ty) => (
        impl ArrayIx for Range<$typ> {
            fn to_idx_vec(&self, ax: usize, dims: &[usize]) -> Vec<usize> {
                assert!(dims.len() > ax, "ax must be in range");
                assert!((self.start as usize) < dims[ax], "range start overflow");
                assert!((self.end as usize) < dims[ax], "range start overflow");
                (self.start as usize .. self.end as usize).map(|i| i as usize).collect()
            }
        }

        impl ArrayIx for RangeFrom<$typ> {
            fn to_idx_vec(&self, ax: usize, dims: &[usize]) -> Vec<usize> {
                assert!(dims.len() > ax, "ax must be in range");
                assert!((self.start as usize) < dims[ax], "range start overflow");
                (self.start as usize .. dims[ax]).collect()
            }
        }

        impl ArrayIx for RangeTo<$typ> {
            fn to_idx_vec(&self, ax: usize, dims: &[usize]) -> Vec<usize> {
                assert!(dims.len() > ax, "ax must be in range");
                assert!((self.end as usize) < dims[ax], "range start overflow");
                (0 .. self.end as usize).collect()
            }
        }
    )
}

impl_array_ix_for_range!(i32);
impl_array_ix_for_range!(usize);

impl ArrayIx for [usize] {
    fn to_idx_vec(&self, ax: usize, dims: &[usize]) -> Vec<usize> {
        assert!(self.iter().filter(|&&i| i >= dims[ax]).count() == 0, "ax must be in range");
        self.iter().map(|&i| i).collect()
    }
}

impl ArrayIx for [i32] {
    fn to_idx_vec(&self, _ax: usize, _dims: &[usize]) -> Vec<usize> {
        self.iter().map(|&i| i as usize).collect()
    }
}

macro_rules! impl_array_ix_for_fixed_size_array {
    ($typ:ty, $size:expr) => (
        impl ArrayIx for [$typ; $size] {
            fn to_idx_vec(&self, _ax: usize, _dims: &[usize]) -> Vec<usize> {
                self.iter().map(|&i| i as usize).collect()
            }
        }
    )
}

impl_array_ix_for_fixed_size_array!(i32, 1);
impl_array_ix_for_fixed_size_array!(i32, 2);
impl_array_ix_for_fixed_size_array!(i32, 3);
impl_array_ix_for_fixed_size_array!(i32, 4);
impl_array_ix_for_fixed_size_array!(i32, 5);
impl_array_ix_for_fixed_size_array!(i32, 6);
impl_array_ix_for_fixed_size_array!(i32, 7);
impl_array_ix_for_fixed_size_array!(i32, 8);

#[test]
fn test_index_ranges() {
    let dims = vec![4, 5, 6];

    assert_eq!((1..3).to_idx_vec(0, &dims), vec![1, 2]);
    assert_eq!((1..).to_idx_vec(0, &dims), vec![1, 2, 3]);
    assert_eq!((..2).to_idx_vec(0, &dims), vec![0, 1]);
    assert_eq!((..).to_idx_vec(0, &dims), vec![0, 1, 2, 3]);
}

// nd Array
#[derive(Clone, PartialEq, Debug)]
pub struct Array<T> {
    data: Vec<T>,
    shape: Vec<usize>
}

macro_rules! simple_impl_for_array {
    ($op:ty, $func:ident) => (
        impl
    )
}

impl<T: Copy> Array<T> {
    pub fn new(v: Vec<T>) -> Array<T> {
        let nelem = v.len();
        Array {
            data: v,
            shape: vec![nelem]
        }
    }

    pub fn shape(&self) -> Vec<usize> {
        self.shape.clone()
    }

    fn offset_of(&self, index: &[usize]) -> usize {
        index.iter().enumerate()
            .map(|(i, &ax)| {
                assert!(ax < self.shape[i]);
                self.shape.iter().skip(i+1).product::<usize>() * ax
            })
            .sum()
    }

    pub fn get<D: AsRef<[usize]>>(&self, index: D) -> T {
        self.data[self.offset_of(index.as_ref())]
    }

    pub fn get_mut<D: AsRef<[usize]>>(&mut self, index: D) -> &mut T {
        let offset = self.offset_of(index.as_ref());
        &mut self.data[offset]
    }

    pub fn reshape<D: AsRef<[usize]>>(&mut self, shape: D) {
        assert_eq!(self.data.len(), shape.as_ref().iter().product());
        self.shape = shape.as_ref().into()
    }

    pub fn slice<'a>(&'a self, ix: Vec<Box<ArrayIx>>) -> RefArray<'a, T> {
        RefArray {
            arr: self,
            open_mesh: ix
        }
    }
}

impl<A: Copy> FromIterator<A> for Array<A> {
    fn from_iter<T: IntoIterator<Item=A>>(iterator: T) -> Self {
        Array::new(iterator.into_iter().collect())
    }
}

impl<T: Copy, D: AsRef<[usize]>> ops::Index<D> for Array<T> {
    type Output = T;

    #[inline]
    fn index<'a>(&'a self, index: D) -> &'a T {
        &self.data[self.offset_of(index.as_ref())]
    }
}

impl<T: Copy, D: AsRef<[usize]>> ops::IndexMut<D> for Array<T> {
    #[inline]
    fn index_mut<'a>(&'a mut self, index: D) -> &'a mut T {
        let offset = self.offset_of(index.as_ref());
        &mut self.data[offset]
    }
}

// impl<T: Copy> ops::Index<(Range<usize>,)> for Array<T> {
//     type Output = T;

//     #[inline]
//     fn index<'a>(&'a self, index: (Range<usize,)) -> &'a T {

//         println!("start => {}", index.0.start());
//         println!("end => {}", index.0.start());
//         &self.data[0]
//     }
// }

// helper function for print an array
fn dump_data<T: Copy + fmt::Display>(a: &Array<T>, dims: &[usize], nd: usize, index: &[usize]) -> String {
    let mut ret = String::new();
    if nd == 0 {
        ret.push_str(&format!("{:4}", a[index]));
    } else {
        ret.push('[');
        for i in 0 .. dims[0] {
            let index = index.iter().map(|&i| i).chain(iter::once(i)).collect::<Vec<usize>>();
            ret.push_str(&dump_data(a, &dims[1..], nd-1, &index));
            if i < dims[0] - 1 {
                ret.push_str(", ");
            }
        }
        ret.push(']');
    }
    ret
}

impl<T: Copy + fmt::Display> fmt::Display for Array<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let ndim = self.shape.len();
        let dims = self.shape.clone();

        let ret = dump_data(self, &dims, ndim, &vec![]);
        // FIXME: adding line break's buggy format
        write!(f, "{}", ret.replace("],", "],\n"))
    }
}

// RefArray
pub struct RefArray<'a, T: 'a> {
    arr: &'a Array<T>,
    // simulation of np.ix_ function?
    open_mesh: Vec<Box<ArrayIx + 'a>>
}

impl<'a, T: Copy> RefArray<'a, T> {
    pub fn shape(&self) -> Vec<usize> {
        self.open_mesh.iter().enumerate().map(|(i,v)| (*v).size(i, &self.arr.shape())).collect()
    }

    fn offset_translate(&self, index: &[usize]) -> usize {
        let mut ix = Vec::<usize>::new();
        for (i, &k) in index.iter().enumerate() {
            ix.push(self.open_mesh[i].to_idx_vec(i, &self.arr.shape())[k]);
        }
        self.arr.offset_of(&ix)
    }

    pub fn get<D: AsRef<[usize]>>(&self, index: D) -> T {
        self.arr.data[self.offset_translate(index.as_ref())]
    }

    // pub fn get_mut<D: AsRef<[usize]>>(&mut self, index: D) -> &mut T {
    //     let offset = self.offset_of(index.as_ref());
    //     &mut self.data[offset]
    // }
}

macro_rules! ix {
    ($($arg:expr),*) => (
        vec![$( Box::new($arg) as Box<ArrayIx> ),*]
    )
}

impl<'a, T: Copy + fmt::Display> fmt::Display for RefArray<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fn dump_ref_array_data<'b, T: Copy + fmt::Display>(a: &'b RefArray<T>, dims: &[usize], nd: usize, index: &[usize]) -> String {
            let mut ret = String::new();
            if nd == 0 {
                ret.push_str(&format!("{:4}", a.get(index)));
            } else {
                ret.push('[');
                for i in 0 .. dims[0] {
                    let index = index.iter().map(|&i| i).chain(iter::once(i)).collect::<Vec<usize>>();
                    ret.push_str(&dump_ref_array_data(a, &dims[1..], nd-1, &index));
                    if i < dims[0] - 1 {
                        ret.push_str(", ");
                    }
                }
                ret.push(']');
            }
            ret
        }

        let ndim = self.shape().len();
        let dims = self.shape();

        let ret = dump_ref_array_data(self, &dims, ndim, &vec![]);
        // FIXME: adding line break's buggy format
        write!(f, "{}", ret.replace("],", "],\n"))
    }
}

#[test]
fn test_array() {
    let mut v = Array::new(vec![ 0,  1,  2,  3,  4,  5,  6,  7,
                                 8,  9, 10, 11, 12, 13, 14, 15,
                                 16, 17, 18, 19, 20, 21, 22, 23]);

    v.reshape([2, 3, 4]);
    assert_eq!(v.get([1, 1, 2]), 18);

    v[[1,2,3]] = 100;
    println!("fuck {:?}", v[[1,1,2]]);

    let shape = vec![2, 3, 4];
    let s = dump_data(&v, &shape, 3, &vec![]);

    println!("DEBUG print => \n{}", v);
    println!("DEBUG print => \n{:?}", s);

    v.reshape([6, 4]);
    println!("DEBUG print => \n{}", v);

    let v2 = ix!([1, 2, 3], [2, 0]);
    let v3 = v.slice(v2);
    println!("debug => {:?}", v3.get([0,0]));

    println!("SUB[1,2,3; 2,0] => \n{}", v3);

    println!("SUB => \n{}", v.slice(ix!(3.., [2,0])));
}
<commit_msg>add array index iterator; add eye()/zeros(); add array concat()<commit_after>use std::fmt;
use std::ops;
use std::ops::{Range, RangeFrom, RangeTo, RangeFull};
use std::iter;
use std::iter::FromIterator;

use num::traits::{One, Zero};

//
pub trait ArrayIx {
    fn to_idx_vec(&self, ax: usize, dims: &[usize]) -> Vec<usize>;
    fn size(&self, ax: usize, dims: &[usize]) -> usize {
        self.to_idx_vec(ax, dims).len()
    }
}

impl ArrayIx for RangeFull {
    fn to_idx_vec(&self, ax: usize, dims: &[usize]) -> Vec<usize> {
        assert!(dims.len() > ax, "ax must be in range");
        (0 .. dims[ax]).collect()
    }
}

macro_rules! impl_array_ix_for_range {
    ($typ:ty) => (
        impl ArrayIx for Range<$typ> {
            fn to_idx_vec(&self, ax: usize, dims: &[usize]) -> Vec<usize> {
                assert!(dims.len() > ax, "ax must be in range");
                assert!((self.start as usize) < dims[ax], "range start overflow");
                assert!((self.end as usize) < dims[ax], "range start overflow");
                (self.start as usize .. self.end as usize).map(|i| i as usize).collect()
            }
        }

        impl ArrayIx for RangeFrom<$typ> {
            fn to_idx_vec(&self, ax: usize, dims: &[usize]) -> Vec<usize> {
                assert!(dims.len() > ax, "ax must be in range");
                assert!((self.start as usize) < dims[ax], "range start overflow");
                (self.start as usize .. dims[ax]).collect()
            }
        }

        impl ArrayIx for RangeTo<$typ> {
            fn to_idx_vec(&self, ax: usize, dims: &[usize]) -> Vec<usize> {
                assert!(dims.len() > ax, "ax must be in range");
                assert!((self.end as usize) < dims[ax], "range start overflow");
                (0 .. self.end as usize).collect()
            }
        }
    )
}

impl_array_ix_for_range!(i32);
impl_array_ix_for_range!(usize);

impl ArrayIx for [usize] {
    fn to_idx_vec(&self, ax: usize, dims: &[usize]) -> Vec<usize> {
        assert!(self.iter().filter(|&&i| i >= dims[ax]).count() == 0, "ax must be in range");
        self.iter().map(|&i| i).collect()
    }
}

impl ArrayIx for [i32] {
    fn to_idx_vec(&self, _ax: usize, _dims: &[usize]) -> Vec<usize> {
        self.iter().map(|&i| i as usize).collect()
    }
}

macro_rules! impl_array_ix_for_fixed_size_array {
    ($typ:ty, $size:expr) => (
        impl ArrayIx for [$typ; $size] {
            fn to_idx_vec(&self, _ax: usize, _dims: &[usize]) -> Vec<usize> {
                self.iter().map(|&i| i as usize).collect()
            }
        }
    )
}

impl_array_ix_for_fixed_size_array!(i32, 1);
impl_array_ix_for_fixed_size_array!(i32, 2);
impl_array_ix_for_fixed_size_array!(i32, 3);
impl_array_ix_for_fixed_size_array!(i32, 4);
impl_array_ix_for_fixed_size_array!(i32, 5);
impl_array_ix_for_fixed_size_array!(i32, 6);
impl_array_ix_for_fixed_size_array!(i32, 7);
impl_array_ix_for_fixed_size_array!(i32, 8);

#[test]
fn test_index_ranges() {
    let dims = vec![4, 5, 6];

    assert_eq!((1..3).to_idx_vec(0, &dims), vec![1, 2]);
    assert_eq!((1..).to_idx_vec(0, &dims), vec![1, 2, 3]);
    assert_eq!((..2).to_idx_vec(0, &dims), vec![0, 1]);
    assert_eq!((..).to_idx_vec(0, &dims), vec![0, 1, 2, 3]);
}

// nd Array
#[derive(Clone, PartialEq, Debug)]
pub struct Array<T> {
    data: Vec<T>,
    shape: Vec<usize>
}

macro_rules! simple_impl_for_array {
    ($op:ty, $func:ident) => (
        impl
    )
}

pub struct ArrayIndexIter<'a, T: 'a> {
    arr: &'a Array<T>,
    current: Vec<usize>,
    shape: Vec<usize>
}

impl<'a, T> Iterator for ArrayIndexIter<'a, T> {
    type Item = Vec<usize>;

    fn next(&mut self) -> Option<Self::Item> {
        let ndim = self.shape.len();
        if self.current[0] >= self.shape[0] {
            return None;
        }
        let old_current = self.current.clone();
        self.current.last_mut().map(|k| *k += 1);
        for i in (0 .. ndim).rev() {
            if self.current[i] == self.shape[i] && i > 0 {
                self.current[i] = 0;
                self.current[i-1] += 1;
            }
        }
        Some(old_current)
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let sz = self.shape.iter()
            .zip(self.current.iter())
            .map(|(&sz, &i)| (sz - i -1) * sz).product();
        (sz, Some(sz))
    }
}

impl<T: Copy> Array<T> {
    pub fn new<S: AsRef<[usize]>>(shape: S) -> Array<T> {
        let nelem = shape.as_ref().iter().product();
        let mut v = Vec::with_capacity(nelem);
        unsafe { v.set_len(nelem) };
        Array {
            data: v,
            shape: shape.as_ref().to_vec()
        }
    }

    pub fn iter_indices<'a>(&'a self) -> ArrayIndexIter<'a, T> {
        let shape = self.shape();
        let zeros = iter::repeat(0).take(shape.len()).collect();
        ArrayIndexIter {
            arr: self,
            current: zeros,
            shape: shape
        }
    }

    pub fn from_vec(v: Vec<T>) -> Array<T> {
        let nelem = v.len();
        Array {
            data: v,
            shape: vec![nelem]
        }
    }

    pub fn new_with_shape(v: Vec<T>, shape: Vec<usize>) -> Array<T> {
        assert!(shape.clone().iter().product::<usize>() == v.len());
        Array {
            data: v,
            shape: shape
        }
    }

    pub fn shape(&self) -> Vec<usize> {
        self.shape.clone()
    }

    fn offset_of(&self, index: &[usize]) -> usize {
        index.iter().enumerate()
            .map(|(i, &ax)| {
                assert!(ax < self.shape[i]);
                self.shape.iter().skip(i+1).product::<usize>() * ax
            })
            .sum()
    }

    pub fn get<D: AsRef<[usize]>>(&self, index: D) -> T {
        self.data[self.offset_of(index.as_ref())]
    }

    pub fn get_mut<D: AsRef<[usize]>>(&mut self, index: D) -> &mut T {
        let offset = self.offset_of(index.as_ref());
        &mut self.data[offset]
    }

    pub fn reshape<D: AsRef<[usize]>>(&mut self, shape: D) {
        assert_eq!(self.data.len(), shape.as_ref().iter().product());
        self.shape = shape.as_ref().into()
    }

    pub fn slice<'a>(&'a self, ix: Vec<Box<ArrayIx>>) -> RefArray<'a, T> {
        RefArray {
            arr: self,
            open_mesh: ix
        }
    }
}

impl<A: Copy> FromIterator<A> for Array<A> {
    fn from_iter<T: IntoIterator<Item=A>>(iterator: T) -> Self {
        Array::from_vec(iterator.into_iter().collect())
    }
}

impl<T: Copy, D: AsRef<[usize]>> ops::Index<D> for Array<T> {
    type Output = T;

    #[inline]
    fn index<'a>(&'a self, index: D) -> &'a T {
        &self.data[self.offset_of(index.as_ref())]
    }
}

impl<T: Copy, D: AsRef<[usize]>> ops::IndexMut<D> for Array<T> {
    #[inline]
    fn index_mut<'a>(&'a mut self, index: D) -> &'a mut T {
        let offset = self.offset_of(index.as_ref());
        &mut self.data[offset]
    }
}

impl<T: Copy + Zero> Array<T> {
    pub fn zeros(n: usize) -> Array<T> {
        let v = iter::repeat(Zero::zero()).take(n*n).collect::<Vec<T>>();
        Array::new_with_shape(v, vec![n, n])
    }
}

impl<T: Copy + One + Zero> Array<T> {
    pub fn eye(n: usize) -> Array<T> {
        let mut arr = Array::zeros(n);
        for i in 0 .. n {
            arr[[i,i]] = One::one();
        }
        arr
    }
}

pub fn concatenate<T: Copy, A: AsRef<[Array<T>]>>(arrs: A, axis: usize) -> Array<T> {
    let arrs = arrs.as_ref();
    assert!(arrs.len() > 1, "concatenation at least 2 array");
    assert!(arrs.iter().map(Array::shape)
            .zip(arrs.iter().skip(1).map(Array::shape))
            .all(|(as1, as2)| {
                as1[.. axis] == as2[.. axis] && as1[axis+1 ..] == as2[axis+1 ..]
            }),
            "all the input array dimensions except for the concatenation axis must match exactly"
            );
    let mut shape = arrs[0].shape();
    let dims = shape.len();

    shape[axis] = arrs.iter().map(|a| a.shape()[axis]).sum();

    let mut ret: Array<T> = Array::new(&shape);

    let mut ix_offset = 0;
    for arr in arrs.iter() {
        let mut idx: Vec<usize> = iter::repeat(0).take(dims).collect();

        for idx in arr.iter_indices() {
            let mut new_idx = idx.clone();
            new_idx[axis] += ix_offset;

            *ret.get_mut(new_idx) = arr.get(idx);
        }
        ix_offset += arr.shape()[axis];
    }

    ret
}

// impl<T: Copy> ops::Index<(Range<usize>,)> for Array<T> {
//     type Output = T;

//     #[inline]
//     fn index<'a>(&'a self, index: (Range<usize,)) -> &'a T {

//         println!("start => {}", index.0.start());
//         println!("end => {}", index.0.start());
//         &self.data[0]
//     }
// }

// helper function for print an array
fn dump_data<T: Copy + fmt::Display>(a: &Array<T>, dims: &[usize], nd: usize, index: &[usize]) -> String {
    let mut ret = String::new();
    if nd == 0 {
        ret.push_str(&format!("{:4}", a[index]));
    } else {
        ret.push('[');
        for i in 0 .. dims[0] {
            let index = index.iter().map(|&i| i).chain(iter::once(i)).collect::<Vec<usize>>();
            ret.push_str(&dump_data(a, &dims[1..], nd-1, &index));
            if i < dims[0] - 1 {
                ret.push_str(", ");
            }
        }
        ret.push(']');
    }
    ret
}

impl<T: Copy + fmt::Display> fmt::Display for Array<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let ndim = self.shape.len();
        let dims = self.shape.clone();

        let ret = dump_data(self, &dims, ndim, &vec![]);
        // FIXME: adding line break's buggy format
        write!(f, "{}", ret.replace("],", "],\n"))
    }
}

// RefArray
pub struct RefArray<'a, T: 'a> {
    arr: &'a Array<T>,
    // simulation of np.ix_ function?
    open_mesh: Vec<Box<ArrayIx + 'a>>
}

impl<'a, T: Copy> RefArray<'a, T> {
    pub fn shape(&self) -> Vec<usize> {
        self.open_mesh.iter().enumerate().map(|(i,v)| (*v).size(i, &self.arr.shape())).collect()
    }

    fn offset_translate(&self, index: &[usize]) -> usize {
        let mut ix = Vec::<usize>::new();
        for (i, &k) in index.iter().enumerate() {
            ix.push(self.open_mesh[i].to_idx_vec(i, &self.arr.shape())[k]);
        }
        self.arr.offset_of(&ix)
    }

    pub fn get<D: AsRef<[usize]>>(&self, index: D) -> T {
        self.arr.data[self.offset_translate(index.as_ref())]
    }

    // pub fn get_mut<D: AsRef<[usize]>>(&mut self, index: D) -> &mut T {
    //     let offset = self.offset_of(index.as_ref());
    //     &mut self.data[offset]
    // }
}

macro_rules! ix {
    ($($arg:expr),*) => (
        vec![$( Box::new($arg) as Box<ArrayIx> ),*]
    )
}

impl<'a, T: Copy + fmt::Display> fmt::Display for RefArray<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fn dump_ref_array_data<'b, T: Copy + fmt::Display>(a: &'b RefArray<T>, dims: &[usize], nd: usize, index: &[usize]) -> String {
            let mut ret = String::new();
            if nd == 0 {
                ret.push_str(&format!("{:4}", a.get(index)));
            } else {
                ret.push('[');
                for i in 0 .. dims[0] {
                    let index = index.iter().map(|&i| i).chain(iter::once(i)).collect::<Vec<usize>>();
                    ret.push_str(&dump_ref_array_data(a, &dims[1..], nd-1, &index));
                    if i < dims[0] - 1 {
                        ret.push_str(", ");
                    }
                }
                ret.push(']');
            }
            ret
        }

        let ndim = self.shape().len();
        let dims = self.shape();

        let ret = dump_ref_array_data(self, &dims, ndim, &vec![]);
        // FIXME: adding line break's buggy format
        write!(f, "{}", ret.replace("],", "],\n"))
    }
}

#[test]
fn test_array() {
    let mut v = Array::from_vec(vec![ 0,  1,  2,  3,  4,  5,  6,  7,
                                      8,  9, 10, 11, 12, 13, 14, 15,
                                      16, 17, 18, 19, 20, 21, 22, 23]);

    v.reshape([2, 3, 4]);
    assert_eq!(v.get([1, 1, 2]), 18);

    v[[1,2,3]] = 100;
    println!("fuck {:?}", v[[1,1,2]]);

    let shape = vec![2, 3, 4];
    let s = dump_data(&v, &shape, 3, &vec![]);

    println!("DEBUG print => \n{}", v);
    println!("DEBUG print => \n{:?}", s);

    v.reshape([6, 4]);
    println!("DEBUG print => \n{}", v);

    let v2 = ix!([1, 2, 3], [2, 0]);
    let v3 = v.slice(v2);
    println!("debug => {:?}", v3.get([0,0]));

    println!("SUB[1,2,3; 2,0] => \n{}", v3);

    println!("SUB => \n{}", v.slice(ix!(3.., [2,0])));
}

#[test]
fn test_array_eye() {
    println!("");
    let i = Array::<f64>::eye(5);
    println!("I => \n{}", i);
}

#[test]
fn test_array_concat() {
    let v1 = Array::new_with_shape(vec![0, 1,
                                        2, 3], vec![2, 2]);

    assert_eq!(v1.iter_indices().len(), 4);

    let v2 = Array::new_with_shape(vec![8, 9, 10,
                                        11, 9, 20], vec![2, 3]);

    let res = concatenate([v1, v2], 1);

    println!("Concat => \n{}", res);
}
<|endoftext|>


<commit_before>//! Utilities and parsers for dealing with ASCII data in `u8` format.

use std::ops::{Add, Mul};

use conv::{
    NoError,
    ValueFrom,
};
use conv::errors::UnwrapOk;

use types::{Buffer, Input};
use combinators::option;
use parsers::{
    SimpleResult,
    satisfy,
    take_while,
    take_while1,
};

/// Lowercase ASCII predicate.
#[inline]
pub fn is_lowercase(c: u8) -> bool {
    b'a' <= c && c <= b'z'
}

/// Uppercase ASCII character predicate.
#[inline]
pub fn is_uppercase(c: u8) -> bool {
    b'A' <= c && c <= b'Z'
}

/// ASCII whitespace predicate.
///
/// Includes:
///
/// * Horizontal tab (TAB)
/// * Line feed (LF)
/// * Vertical tab (VT)
/// * Form feed (FF)
/// * Carriage return (CR)
/// * Space
#[inline]
pub fn is_whitespace(c: u8) -> bool {
    9 <= c && c <= 13 || c == b' '
}

/// A predicate which matches either space (' ') or horizontal tab ('\t').
#[inline]
pub fn is_horizontal_space(c: u8) -> bool {
    c == b'\t' || c == b' '
}

/// A predicate matching eithr a newline ('\n') or a carriage return ('\r').
#[inline]
pub fn is_end_of_line(c: u8) -> bool {
    c == b'\n' || c == b'\r'
}

/// ASCII digit predicate.
#[inline]
pub fn is_digit(c: u8) -> bool {
    b'0' <= c && c <= b'9'
}

/// ASCII alphabetic predicate.
#[inline]
pub fn is_alpha(c: u8) -> bool {
    is_lowercase(c) || is_uppercase(c)
}

/// ASCII alphanumeric predicate.
#[inline]
pub fn is_alphanumeric(c: u8) -> bool {
    is_alpha(c) || is_digit(c)
}

/// Skips over whitespace.
///
/// Matches zero-length.
///
/// # Example
///
/// ```
/// use chomp::parse_only;
/// use chomp::ascii::skip_whitespace;
///
/// assert_eq!(parse_only(skip_whitespace, b" \t "), Ok(()));
/// ```
#[inline]
pub fn skip_whitespace<I: Input<Token=u8>>(i: I) -> SimpleResult<I, ()> {
    take_while(i, is_whitespace).map(|_| ())
}

/// Parses a single digit.
///
/// # Note
///
/// The result is the code of the digit, no conversion takes place.
///
/// # Example
///
/// ```
/// use chomp::parse_only;
/// use chomp::ascii::digit;
///
/// assert_eq!(parse_only(digit, b"1"), Ok(b'1'));
/// ```
#[inline]
pub fn digit<I: Input<Token=u8>>(i: I) -> SimpleResult<I, u8> {
    satisfy(i, is_digit)
}

/// Parses a number with an optional leading '+' or '-'.
///
/// # Note
///
/// The from `i8` bound here is usually smaller than the number parser requirement for signed
/// integers (usually the smallest possible signed is `i16`).
///
/// # Example
///
/// ```
/// use chomp::parse_only;
/// use chomp::ascii::{decimal, signed};
///
/// let r: Result<i16, _> = parse_only(|i| signed(i, decimal), b"-123");
///
/// assert_eq!(r, Ok(-123i16));
/// ```
#[inline]
pub fn signed<I: Input<Token=u8>, T, F>(i: I, f: F) -> SimpleResult<I, T>
  where T: Copy + ValueFrom<i8, Err=NoError> + Add<Output=T> + Mul<Output=T>,
        F: FnOnce(I) -> SimpleResult<I, T> {
    option(i,
           |i| satisfy(i, |c| c == b'-' || c == b'+')
               .map(|s| T::value_from(if s == b'+' { 1 } else { -1 }).unwrap_ok()),
           T::value_from(1).unwrap_ok())
        .bind(|i, sign| f(i).map(|num| sign * num))
}

/// Parses a series of digits and converts them to an integer.
///
/// # Note
///
/// The `T` type must be larger than `u8` if it is signed.
///
/// # Example
///
/// ```
/// use chomp::parse_only;
/// use chomp::ascii::decimal;
///
/// let r = parse_only(decimal::<_, u8>, b"123");
///
/// assert_eq!(r, Ok(123u8));
/// ```
#[inline]
pub fn decimal<I: Input<Token=u8>, T: Copy + ValueFrom<u8, Err=NoError> + Add<Output=T> + Mul<Output=T>>(i: I) -> SimpleResult<I, T> {
    take_while1(i, is_digit).map(to_decimal)
}

/// Internal function converting a `[u8]` to the given integer type `T`.
///
/// # Notes
///
/// * The slice must not contain any other characters besides 0 to 9.
/// * The `T` type must be larger than `u8` if it is signed.
#[inline]
fn to_decimal<T: Copy + ValueFrom<u8, Err=NoError> + Add<Output=T> + Mul<Output=T>, I: Buffer<Token=u8>>(iter: I) -> T {
    iter.fold(T::value_from(0).unwrap_ok(), |a, n| a * T::value_from(10).unwrap_ok() + T::value_from(n - b'0').unwrap_ok())
}

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

    macro_rules! test_to_decimal {
        ( $($n:ty),+ ) => { $(
            assert_eq!(to_decimal::<$n, _>(&b""[..]), 0);
            assert_eq!(to_decimal::<$n, _>(&b"0"[..]), 0);
            assert_eq!(to_decimal::<$n, _>(&b"1"[..]), 1);
            assert_eq!(to_decimal::<$n, _>(&b"2"[..]), 2);
            assert_eq!(to_decimal::<$n, _>(&b"10"[..]), 10);
            assert_eq!(to_decimal::<$n, _>(&b"20"[..]), 20);
            assert_eq!(to_decimal::<$n, _>(&b"25"[..]), 25);
        )+ }
    }

    #[test]
    fn test_to_decimal_u8() {
        test_to_decimal!(u8, u16, u32, u64, i16, i32, i64);
    }
}
<commit_msg>ascii::skip_whitespace: Use skip_while internally<commit_after>//! Utilities and parsers for dealing with ASCII data in `u8` format.

use std::ops::{Add, Mul};

use conv::{
    NoError,
    ValueFrom,
};
use conv::errors::UnwrapOk;

use types::{Buffer, Input};
use combinators::option;
use parsers::{
    SimpleResult,
    satisfy,
    skip_while,
    take_while1,
};

/// Lowercase ASCII predicate.
#[inline]
pub fn is_lowercase(c: u8) -> bool {
    b'a' <= c && c <= b'z'
}

/// Uppercase ASCII character predicate.
#[inline]
pub fn is_uppercase(c: u8) -> bool {
    b'A' <= c && c <= b'Z'
}

/// ASCII whitespace predicate.
///
/// Includes:
///
/// * Horizontal tab (TAB)
/// * Line feed (LF)
/// * Vertical tab (VT)
/// * Form feed (FF)
/// * Carriage return (CR)
/// * Space
#[inline]
pub fn is_whitespace(c: u8) -> bool {
    9 <= c && c <= 13 || c == b' '
}

/// A predicate which matches either space (' ') or horizontal tab ('\t').
#[inline]
pub fn is_horizontal_space(c: u8) -> bool {
    c == b'\t' || c == b' '
}

/// A predicate matching eithr a newline ('\n') or a carriage return ('\r').
#[inline]
pub fn is_end_of_line(c: u8) -> bool {
    c == b'\n' || c == b'\r'
}

/// ASCII digit predicate.
#[inline]
pub fn is_digit(c: u8) -> bool {
    b'0' <= c && c <= b'9'
}

/// ASCII alphabetic predicate.
#[inline]
pub fn is_alpha(c: u8) -> bool {
    is_lowercase(c) || is_uppercase(c)
}

/// ASCII alphanumeric predicate.
#[inline]
pub fn is_alphanumeric(c: u8) -> bool {
    is_alpha(c) || is_digit(c)
}

/// Skips over whitespace.
///
/// Matches zero-length.
///
/// # Example
///
/// ```
/// use chomp::parse_only;
/// use chomp::ascii::skip_whitespace;
///
/// assert_eq!(parse_only(skip_whitespace, b" \t "), Ok(()));
/// ```
#[inline]
pub fn skip_whitespace<I: Input<Token=u8>>(i: I) -> SimpleResult<I, ()> {
    skip_while(i, is_whitespace)
}

/// Parses a single digit.
///
/// # Note
///
/// The result is the code of the digit, no conversion takes place.
///
/// # Example
///
/// ```
/// use chomp::parse_only;
/// use chomp::ascii::digit;
///
/// assert_eq!(parse_only(digit, b"1"), Ok(b'1'));
/// ```
#[inline]
pub fn digit<I: Input<Token=u8>>(i: I) -> SimpleResult<I, u8> {
    satisfy(i, is_digit)
}

/// Parses a number with an optional leading '+' or '-'.
///
/// # Note
///
/// The from `i8` bound here is usually smaller than the number parser requirement for signed
/// integers (usually the smallest possible signed is `i16`).
///
/// # Example
///
/// ```
/// use chomp::parse_only;
/// use chomp::ascii::{decimal, signed};
///
/// let r: Result<i16, _> = parse_only(|i| signed(i, decimal), b"-123");
///
/// assert_eq!(r, Ok(-123i16));
/// ```
#[inline]
pub fn signed<I: Input<Token=u8>, T, F>(i: I, f: F) -> SimpleResult<I, T>
  where T: Copy + ValueFrom<i8, Err=NoError> + Add<Output=T> + Mul<Output=T>,
        F: FnOnce(I) -> SimpleResult<I, T> {
    option(i,
           |i| satisfy(i, |c| c == b'-' || c == b'+')
               .map(|s| T::value_from(if s == b'+' { 1 } else { -1 }).unwrap_ok()),
           T::value_from(1).unwrap_ok())
        .bind(|i, sign| f(i).map(|num| sign * num))
}

/// Parses a series of digits and converts them to an integer.
///
/// # Note
///
/// The `T` type must be larger than `u8` if it is signed.
///
/// # Example
///
/// ```
/// use chomp::parse_only;
/// use chomp::ascii::decimal;
///
/// let r = parse_only(decimal::<_, u8>, b"123");
///
/// assert_eq!(r, Ok(123u8));
/// ```
#[inline]
pub fn decimal<I: Input<Token=u8>, T: Copy + ValueFrom<u8, Err=NoError> + Add<Output=T> + Mul<Output=T>>(i: I) -> SimpleResult<I, T> {
    take_while1(i, is_digit).map(to_decimal)
}

/// Internal function converting a `[u8]` to the given integer type `T`.
///
/// # Notes
///
/// * The slice must not contain any other characters besides 0 to 9.
/// * The `T` type must be larger than `u8` if it is signed.
#[inline]
fn to_decimal<T: Copy + ValueFrom<u8, Err=NoError> + Add<Output=T> + Mul<Output=T>, I: Buffer<Token=u8>>(iter: I) -> T {
    iter.fold(T::value_from(0).unwrap_ok(), |a, n| a * T::value_from(10).unwrap_ok() + T::value_from(n - b'0').unwrap_ok())
}

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

    macro_rules! test_to_decimal {
        ( $($n:ty),+ ) => { $(
            assert_eq!(to_decimal::<$n, _>(&b""[..]), 0);
            assert_eq!(to_decimal::<$n, _>(&b"0"[..]), 0);
            assert_eq!(to_decimal::<$n, _>(&b"1"[..]), 1);
            assert_eq!(to_decimal::<$n, _>(&b"2"[..]), 2);
            assert_eq!(to_decimal::<$n, _>(&b"10"[..]), 10);
            assert_eq!(to_decimal::<$n, _>(&b"20"[..]), 20);
            assert_eq!(to_decimal::<$n, _>(&b"25"[..]), 25);
        )+ }
    }

    #[test]
    fn test_to_decimal_u8() {
        test_to_decimal!(u8, u16, u32, u64, i16, i32, i64);
    }
}
<|endoftext|>


<commit_before>//! # Serde
//!
//! Serde is a framework for ***ser***ializing and ***de***serializing Rust data
//! structures efficiently and generically.
//!
//! The Serde ecosystem consists of data structures that know how to serialize
//! and deserialize themselves along with data formats that know how to
//! serialize and deserialize other things. Serde provides the layer by which
//! these two groups interact with each other, allowing any supported data
//! structure to be serialized and deserialized using any supported data format.
//!
//! See the Serde website <https://serde.rs/> for additional documentation and
//! usage examples.
//!
//! ## Design
//!
//! Where many other languages rely on runtime reflection for serializing data,
//! Serde is instead built on Rust's powerful trait system. A data structure
//! that knows how to serialize and deserialize itself is one that implements
//! Serde's `Serialize` and `Deserialize` traits (or uses Serde's derive
//! attribute to automatically generate implementations at compile time). This
//! avoids any overhead of reflection or runtime type information. In fact in
//! many situations the interaction between data structure and data format can
//! be completely optimized away by the Rust compiler, leaving Serde
//! serialization to perform the same speed as a handwritten serializer for the
//! specific selection of data structure and data format.
//!
//! ## Data formats
//!
//! The following is a partial list of data formats that have been implemented
//! for Serde by the community.
//!
//! - [JSON], the ubiquitous JavaScript Object Notation used by many HTTP APIs.
//! - [Bincode], a compact binary format
//!   used for IPC within the Servo rendering engine.
//! - [CBOR], a Concise Binary Object Representation designed for small message
//!   size without the need for version negotiation.
//! - [YAML], a self-proclaimed human-friendly configuration language that ain't
//!   markup language.
//! - [MessagePack], an efficient binary format that resembles a compact JSON.
//! - [TOML], a minimal configuration format used by [Cargo].
//! - [Pickle], a format common in the Python world.
//! - [RON], a Rusty Object Notation.
//! - [BSON], the data storage and network transfer format used by MongoDB.
//! - [Avro], a binary format used within Apache Hadoop, with support for schema
//!   definition.
//! - [JSON5], a superset of JSON including some productions from ES5.
//! - [Postcard], a no\_std and embedded-systems friendly compact binary format.
//! - [URL] query strings, in the x-www-form-urlencoded format.
//! - [Envy], a way to deserialize environment variables into Rust structs.
//!   *(deserialization only)*
//! - [Envy Store], a way to deserialize [AWS Parameter Store] parameters into
//!   Rust structs. *(deserialization only)*
//! - [S-expressions], the textual representation of code and data used by the
//!   Lisp language family.
//! - [D-Bus]'s binary wire format.
//! - [FlexBuffers], the schemaless cousin of Google's FlatBuffers zero-copy serialization format.
//! - [DynamoDB Items], the format used by [rusoto_dynamodb] to transfer data to
//!   and from DynamoDB.
//!
//! [JSON]: https://github.com/serde-rs/json
//! [Bincode]: https://github.com/bincode-org/bincode
//! [CBOR]: https://github.com/enarx/ciborium
//! [YAML]: https://github.com/dtolnay/serde-yaml
//! [MessagePack]: https://github.com/3Hren/msgpack-rust
//! [TOML]: https://github.com/alexcrichton/toml-rs
//! [Pickle]: https://github.com/birkenfeld/serde-pickle
//! [RON]: https://github.com/ron-rs/ron
//! [BSON]: https://github.com/mongodb/bson-rust
//! [Avro]: https://github.com/flavray/avro-rs
//! [JSON5]: https://github.com/callum-oakley/json5-rs
//! [Postcard]: https://github.com/jamesmunns/postcard
//! [URL]: https://docs.rs/serde_qs
//! [Envy]: https://github.com/softprops/envy
//! [Envy Store]: https://github.com/softprops/envy-store
//! [Cargo]: https://doc.rust-lang.org/cargo/reference/manifest.html
//! [AWS Parameter Store]: https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html
//! [S-expressions]: https://github.com/rotty/lexpr-rs
//! [D-Bus]: https://docs.rs/zvariant
//! [FlexBuffers]: https://github.com/google/flatbuffers/tree/master/rust/flexbuffers
//! [DynamoDB Items]: https://docs.rs/serde_dynamo
//! [rusoto_dynamodb]: https://docs.rs/rusoto_dynamodb

////////////////////////////////////////////////////////////////////////////////

// Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.136")]
// Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)]
// Unstable functionality only if the user asks for it. For tracking and
// discussion of these features please refer to this issue:
//
//    https://github.com/serde-rs/serde/issues/812
#![cfg_attr(feature = "unstable", feature(never_type))]
#![allow(unknown_lints, bare_trait_objects, deprecated)]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
// Ignored clippy and clippy_pedantic lints
#![cfg_attr(
    feature = "cargo-clippy",
    allow(
        // clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704
        unnested_or_patterns,
        // clippy bug: https://github.com/rust-lang/rust-clippy/issues/7768
        semicolon_if_nothing_returned,
        // not available in our oldest supported compiler
        checked_conversions,
        empty_enum,
        redundant_field_names,
        redundant_static_lifetimes,
        type_repetition_in_bounds, // https://github.com/rust-lang/rust-clippy/issues/8772
        // integer and float ser/de requires these sorts of casts
        cast_possible_truncation,
        cast_possible_wrap,
        cast_sign_loss,
        // things are often more readable this way
        cast_lossless,
        module_name_repetitions,
        option_if_let_else,
        single_match_else,
        type_complexity,
        use_self,
        zero_prefixed_literal,
        // correctly used
        enum_glob_use,
        let_underscore_drop,
        map_err_ignore,
        result_unit_err,
        wildcard_imports,
        // not practical
        needless_pass_by_value,
        similar_names,
        too_many_lines,
        // preference
        doc_markdown,
        unseparated_literal_suffix,
        // false positive
        needless_doctest_main,
        // noisy
        missing_errors_doc,
        must_use_candidate,
    )
)]
// Rustc lints.
#![deny(missing_docs, unused_imports)]

////////////////////////////////////////////////////////////////////////////////

#[cfg(feature = "alloc")]
extern crate alloc;

/// A facade around all the types we need from the `std`, `core`, and `alloc`
/// crates. This avoids elaborate import wrangling having to happen in every
/// module.
mod lib {
    mod core {
        #[cfg(not(feature = "std"))]
        pub use core::*;
        #[cfg(feature = "std")]
        pub use std::*;
    }

    pub use self::core::{cmp, iter, mem, num, ptr, slice, str};
    pub use self::core::{f32, f64};
    pub use self::core::{i16, i32, i64, i8, isize};
    pub use self::core::{u16, u32, u64, u8, usize};

    pub use self::core::cell::{Cell, RefCell};
    pub use self::core::clone::{self, Clone};
    pub use self::core::convert::{self, From, Into};
    pub use self::core::default::{self, Default};
    pub use self::core::fmt::{self, Debug, Display};
    pub use self::core::marker::{self, PhantomData};
    pub use self::core::num::Wrapping;
    pub use self::core::ops::Range;
    pub use self::core::option::{self, Option};
    pub use self::core::result::{self, Result};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::borrow::{Cow, ToOwned};
    #[cfg(feature = "std")]
    pub use std::borrow::{Cow, ToOwned};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::string::{String, ToString};
    #[cfg(feature = "std")]
    pub use std::string::{String, ToString};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::vec::Vec;
    #[cfg(feature = "std")]
    pub use std::vec::Vec;

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::boxed::Box;
    #[cfg(feature = "std")]
    pub use std::boxed::Box;

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::rc::{Rc, Weak as RcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::rc::{Rc, Weak as RcWeak};

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::sync::{Arc, Weak as ArcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::sync::{Arc, Weak as ArcWeak};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
    #[cfg(feature = "std")]
    pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};

    #[cfg(feature = "std")]
    pub use std::{error, net};

    #[cfg(feature = "std")]
    pub use std::collections::{HashMap, HashSet};
    #[cfg(feature = "std")]
    pub use std::ffi::{CStr, CString, OsStr, OsString};
    #[cfg(feature = "std")]
    pub use std::hash::{BuildHasher, Hash};
    #[cfg(feature = "std")]
    pub use std::io::Write;
    #[cfg(feature = "std")]
    pub use std::path::{Path, PathBuf};
    #[cfg(feature = "std")]
    pub use std::sync::{Mutex, RwLock};
    #[cfg(feature = "std")]
    pub use std::time::{SystemTime, UNIX_EPOCH};

    #[cfg(all(feature = "std", not(no_collections_bound), no_ops_bound))]
    pub use std::collections::Bound;

    #[cfg(not(no_core_reverse))]
    pub use self::core::cmp::Reverse;

    #[cfg(not(no_ops_bound))]
    pub use self::core::ops::Bound;

    #[cfg(not(no_range_inclusive))]
    pub use self::core::ops::RangeInclusive;

    #[cfg(all(feature = "std", not(no_std_atomic)))]
    pub use std::sync::atomic::{
        AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU8,
        AtomicUsize, Ordering,
    };
    #[cfg(all(feature = "std", not(no_std_atomic64)))]
    pub use std::sync::atomic::{AtomicI64, AtomicU64};

    #[cfg(any(feature = "std", not(no_core_duration)))]
    pub use self::core::time::Duration;
}

////////////////////////////////////////////////////////////////////////////////

#[macro_use]
mod macros;

#[macro_use]
mod integer128;

pub mod de;
pub mod ser;

#[doc(inline)]
pub use de::{Deserialize, Deserializer};
#[doc(inline)]
pub use ser::{Serialize, Serializer};

// Used by generated code and doc tests. Not public API.
#[doc(hidden)]
#[path = "private/mod.rs"]
pub mod __private;

#[allow(unused_imports)]
use self::__private as export;
#[allow(unused_imports)]
use self::__private as private;

#[path = "de/seed.rs"]
mod seed;

#[cfg(not(feature = "std"))]
mod std_error;

// Re-export #[derive(Serialize, Deserialize)].
//
// The reason re-exporting is not enabled by default is that disabling it would
// be annoying for crates that provide handwritten impls or data formats. They
// would need to disable default features and then explicitly re-enable std.
#[cfg(feature = "serde_derive")]
#[allow(unused_imports)]
#[macro_use]
extern crate serde_derive;
#[cfg(feature = "serde_derive")]
#[doc(hidden)]
pub use serde_derive::*;

#[cfg(all(not(no_serde_derive), any(feature = "std", feature = "alloc")))]
mod actually_private {
    pub struct T;
}
<commit_msg>Clean up clippy allows which are superseded by msrv in clippy.toml<commit_after>//! # Serde
//!
//! Serde is a framework for ***ser***ializing and ***de***serializing Rust data
//! structures efficiently and generically.
//!
//! The Serde ecosystem consists of data structures that know how to serialize
//! and deserialize themselves along with data formats that know how to
//! serialize and deserialize other things. Serde provides the layer by which
//! these two groups interact with each other, allowing any supported data
//! structure to be serialized and deserialized using any supported data format.
//!
//! See the Serde website <https://serde.rs/> for additional documentation and
//! usage examples.
//!
//! ## Design
//!
//! Where many other languages rely on runtime reflection for serializing data,
//! Serde is instead built on Rust's powerful trait system. A data structure
//! that knows how to serialize and deserialize itself is one that implements
//! Serde's `Serialize` and `Deserialize` traits (or uses Serde's derive
//! attribute to automatically generate implementations at compile time). This
//! avoids any overhead of reflection or runtime type information. In fact in
//! many situations the interaction between data structure and data format can
//! be completely optimized away by the Rust compiler, leaving Serde
//! serialization to perform the same speed as a handwritten serializer for the
//! specific selection of data structure and data format.
//!
//! ## Data formats
//!
//! The following is a partial list of data formats that have been implemented
//! for Serde by the community.
//!
//! - [JSON], the ubiquitous JavaScript Object Notation used by many HTTP APIs.
//! - [Bincode], a compact binary format
//!   used for IPC within the Servo rendering engine.
//! - [CBOR], a Concise Binary Object Representation designed for small message
//!   size without the need for version negotiation.
//! - [YAML], a self-proclaimed human-friendly configuration language that ain't
//!   markup language.
//! - [MessagePack], an efficient binary format that resembles a compact JSON.
//! - [TOML], a minimal configuration format used by [Cargo].
//! - [Pickle], a format common in the Python world.
//! - [RON], a Rusty Object Notation.
//! - [BSON], the data storage and network transfer format used by MongoDB.
//! - [Avro], a binary format used within Apache Hadoop, with support for schema
//!   definition.
//! - [JSON5], a superset of JSON including some productions from ES5.
//! - [Postcard], a no\_std and embedded-systems friendly compact binary format.
//! - [URL] query strings, in the x-www-form-urlencoded format.
//! - [Envy], a way to deserialize environment variables into Rust structs.
//!   *(deserialization only)*
//! - [Envy Store], a way to deserialize [AWS Parameter Store] parameters into
//!   Rust structs. *(deserialization only)*
//! - [S-expressions], the textual representation of code and data used by the
//!   Lisp language family.
//! - [D-Bus]'s binary wire format.
//! - [FlexBuffers], the schemaless cousin of Google's FlatBuffers zero-copy serialization format.
//! - [DynamoDB Items], the format used by [rusoto_dynamodb] to transfer data to
//!   and from DynamoDB.
//!
//! [JSON]: https://github.com/serde-rs/json
//! [Bincode]: https://github.com/bincode-org/bincode
//! [CBOR]: https://github.com/enarx/ciborium
//! [YAML]: https://github.com/dtolnay/serde-yaml
//! [MessagePack]: https://github.com/3Hren/msgpack-rust
//! [TOML]: https://github.com/alexcrichton/toml-rs
//! [Pickle]: https://github.com/birkenfeld/serde-pickle
//! [RON]: https://github.com/ron-rs/ron
//! [BSON]: https://github.com/mongodb/bson-rust
//! [Avro]: https://github.com/flavray/avro-rs
//! [JSON5]: https://github.com/callum-oakley/json5-rs
//! [Postcard]: https://github.com/jamesmunns/postcard
//! [URL]: https://docs.rs/serde_qs
//! [Envy]: https://github.com/softprops/envy
//! [Envy Store]: https://github.com/softprops/envy-store
//! [Cargo]: https://doc.rust-lang.org/cargo/reference/manifest.html
//! [AWS Parameter Store]: https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html
//! [S-expressions]: https://github.com/rotty/lexpr-rs
//! [D-Bus]: https://docs.rs/zvariant
//! [FlexBuffers]: https://github.com/google/flatbuffers/tree/master/rust/flexbuffers
//! [DynamoDB Items]: https://docs.rs/serde_dynamo
//! [rusoto_dynamodb]: https://docs.rs/rusoto_dynamodb

////////////////////////////////////////////////////////////////////////////////

// Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.136")]
// Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)]
// Unstable functionality only if the user asks for it. For tracking and
// discussion of these features please refer to this issue:
//
//    https://github.com/serde-rs/serde/issues/812
#![cfg_attr(feature = "unstable", feature(never_type))]
#![allow(unknown_lints, bare_trait_objects, deprecated)]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
// Ignored clippy and clippy_pedantic lints
#![cfg_attr(
    feature = "cargo-clippy",
    allow(
        // clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704
        unnested_or_patterns,
        // clippy bug: https://github.com/rust-lang/rust-clippy/issues/7768
        semicolon_if_nothing_returned,
        // not available in our oldest supported compiler
        empty_enum,
        type_repetition_in_bounds, // https://github.com/rust-lang/rust-clippy/issues/8772
        // integer and float ser/de requires these sorts of casts
        cast_possible_truncation,
        cast_possible_wrap,
        cast_sign_loss,
        // things are often more readable this way
        cast_lossless,
        module_name_repetitions,
        option_if_let_else,
        single_match_else,
        type_complexity,
        use_self,
        zero_prefixed_literal,
        // correctly used
        enum_glob_use,
        let_underscore_drop,
        map_err_ignore,
        result_unit_err,
        wildcard_imports,
        // not practical
        needless_pass_by_value,
        similar_names,
        too_many_lines,
        // preference
        doc_markdown,
        unseparated_literal_suffix,
        // false positive
        needless_doctest_main,
        // noisy
        missing_errors_doc,
        must_use_candidate,
    )
)]
// Rustc lints.
#![deny(missing_docs, unused_imports)]

////////////////////////////////////////////////////////////////////////////////

#[cfg(feature = "alloc")]
extern crate alloc;

/// A facade around all the types we need from the `std`, `core`, and `alloc`
/// crates. This avoids elaborate import wrangling having to happen in every
/// module.
mod lib {
    mod core {
        #[cfg(not(feature = "std"))]
        pub use core::*;
        #[cfg(feature = "std")]
        pub use std::*;
    }

    pub use self::core::{cmp, iter, mem, num, ptr, slice, str};
    pub use self::core::{f32, f64};
    pub use self::core::{i16, i32, i64, i8, isize};
    pub use self::core::{u16, u32, u64, u8, usize};

    pub use self::core::cell::{Cell, RefCell};
    pub use self::core::clone::{self, Clone};
    pub use self::core::convert::{self, From, Into};
    pub use self::core::default::{self, Default};
    pub use self::core::fmt::{self, Debug, Display};
    pub use self::core::marker::{self, PhantomData};
    pub use self::core::num::Wrapping;
    pub use self::core::ops::Range;
    pub use self::core::option::{self, Option};
    pub use self::core::result::{self, Result};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::borrow::{Cow, ToOwned};
    #[cfg(feature = "std")]
    pub use std::borrow::{Cow, ToOwned};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::string::{String, ToString};
    #[cfg(feature = "std")]
    pub use std::string::{String, ToString};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::vec::Vec;
    #[cfg(feature = "std")]
    pub use std::vec::Vec;

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::boxed::Box;
    #[cfg(feature = "std")]
    pub use std::boxed::Box;

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::rc::{Rc, Weak as RcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::rc::{Rc, Weak as RcWeak};

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::sync::{Arc, Weak as ArcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::sync::{Arc, Weak as ArcWeak};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
    #[cfg(feature = "std")]
    pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};

    #[cfg(feature = "std")]
    pub use std::{error, net};

    #[cfg(feature = "std")]
    pub use std::collections::{HashMap, HashSet};
    #[cfg(feature = "std")]
    pub use std::ffi::{CStr, CString, OsStr, OsString};
    #[cfg(feature = "std")]
    pub use std::hash::{BuildHasher, Hash};
    #[cfg(feature = "std")]
    pub use std::io::Write;
    #[cfg(feature = "std")]
    pub use std::path::{Path, PathBuf};
    #[cfg(feature = "std")]
    pub use std::sync::{Mutex, RwLock};
    #[cfg(feature = "std")]
    pub use std::time::{SystemTime, UNIX_EPOCH};

    #[cfg(all(feature = "std", not(no_collections_bound), no_ops_bound))]
    pub use std::collections::Bound;

    #[cfg(not(no_core_reverse))]
    pub use self::core::cmp::Reverse;

    #[cfg(not(no_ops_bound))]
    pub use self::core::ops::Bound;

    #[cfg(not(no_range_inclusive))]
    pub use self::core::ops::RangeInclusive;

    #[cfg(all(feature = "std", not(no_std_atomic)))]
    pub use std::sync::atomic::{
        AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU8,
        AtomicUsize, Ordering,
    };
    #[cfg(all(feature = "std", not(no_std_atomic64)))]
    pub use std::sync::atomic::{AtomicI64, AtomicU64};

    #[cfg(any(feature = "std", not(no_core_duration)))]
    pub use self::core::time::Duration;
}

////////////////////////////////////////////////////////////////////////////////

#[macro_use]
mod macros;

#[macro_use]
mod integer128;

pub mod de;
pub mod ser;

#[doc(inline)]
pub use de::{Deserialize, Deserializer};
#[doc(inline)]
pub use ser::{Serialize, Serializer};

// Used by generated code and doc tests. Not public API.
#[doc(hidden)]
#[path = "private/mod.rs"]
pub mod __private;

#[allow(unused_imports)]
use self::__private as export;
#[allow(unused_imports)]
use self::__private as private;

#[path = "de/seed.rs"]
mod seed;

#[cfg(not(feature = "std"))]
mod std_error;

// Re-export #[derive(Serialize, Deserialize)].
//
// The reason re-exporting is not enabled by default is that disabling it would
// be annoying for crates that provide handwritten impls or data formats. They
// would need to disable default features and then explicitly re-enable std.
#[cfg(feature = "serde_derive")]
#[allow(unused_imports)]
#[macro_use]
extern crate serde_derive;
#[cfg(feature = "serde_derive")]
#[doc(hidden)]
pub use serde_derive::*;

#[cfg(all(not(no_serde_derive), any(feature = "std", feature = "alloc")))]
mod actually_private {
    pub struct T;
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Anatoly Ikorsky
//
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

use byteorder::LittleEndian as LE;
use byteorder::WriteBytesExt;
use consts;
use errors::*;
use io::Stream;
use lib_futures::Async::Ready;
use lib_futures::Future;
use lib_futures::Poll;
use tokio::io::write_all;
use tokio::io::WriteAll;

/// Future that writes packet to a `Stream` and resolves to a pair of `Stream` and MySql's sequence
/// id.
pub struct WritePacket {
    future: WriteAll<Stream, Vec<u8>>,
    seq_id: u8,
}

pub fn new(stream: Stream, data: Vec<u8>, mut seq_id: u8) -> WritePacket {
    let data = {
        let mut last_was_max = false;
        let capacity = data.len() + 4 * (data.len() / consts::MAX_PAYLOAD_LEN + 2);
        let mut out = Vec::with_capacity(capacity);
        for chunk in data.chunks(consts::MAX_PAYLOAD_LEN) {
            out.write_uint::<LE>(chunk.len() as u64, 3).unwrap();
            out.write_u8(seq_id).unwrap();
            out.extend_from_slice(chunk);
            seq_id += 1;
            last_was_max = chunk.len() == consts::MAX_PAYLOAD_LEN;
        }
        if last_was_max {
            out.extend_from_slice(&[0, 0, 0, seq_id][..]);
            seq_id += 1;
        }
        out
    };
    WritePacket {
        future: write_all(stream, data),
        seq_id: seq_id,
    }
}

impl Future for WritePacket {
    type Item = (Stream, u8);
    type Error = Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        match try_ready!(self.future.poll()) {
            (stream, _) => Ok(Ready((stream, self.seq_id))),
        }
    }
}
<commit_msg>Fix WritePacket implementation<commit_after>// Copyright (c) 2016 Anatoly Ikorsky
//
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

use byteorder::LittleEndian as LE;
use byteorder::WriteBytesExt;
use consts;
use errors::*;
use io::Stream;
use lib_futures::Async::Ready;
use lib_futures::Future;
use lib_futures::Poll;
use tokio::io::write_all;
use tokio::io::WriteAll;

/// Future that writes packet to a `Stream` and resolves to a pair of `Stream` and MySql's sequence
/// id.
pub struct WritePacket {
    future: WriteAll<Stream, Vec<u8>>,
    seq_id: u8,
}

pub fn new(stream: Stream, data: Vec<u8>, mut seq_id: u8) -> WritePacket {
    let data = {
        if data.len() == 0 {
            let out = vec![0, 0, 0, seq_id];
            seq_id = seq_id.wrapping_add(1);
            out
        } else {
            let mut last_was_max = false;
            let capacity = data.len() + 4 * (data.len() / consts::MAX_PAYLOAD_LEN + 2);
            let mut out = Vec::with_capacity(capacity);
            for chunk in data.chunks(consts::MAX_PAYLOAD_LEN) {
                out.write_uint::<LE>(chunk.len() as u64, 3).unwrap();
                out.write_u8(seq_id).unwrap();
                out.extend_from_slice(chunk);
                seq_id = seq_id.wrapping_add(1);
                last_was_max = chunk.len() == consts::MAX_PAYLOAD_LEN;
            }
            if last_was_max {
                out.extend_from_slice(&[0, 0, 0, seq_id][..]);
                seq_id = seq_id.wrapping_add(1);
            }
            out
        }
    };

    WritePacket {
        future: write_all(stream, data),
        seq_id: seq_id,
    }
}

impl Future for WritePacket {
    type Item = (Stream, u8);
    type Error = Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        match try_ready!(self.future.poll()) {
            (stream, _) => Ok(Ready((stream, self.seq_id))),
        }
    }
}
<|endoftext|>


<commit_before>use nom::{le_u32};

use blocks;
use util;

#[derive(Debug)]
pub enum Block<'a> {
    SectionHeader(blocks::SectionHeader<'a>),
    EnhancedPacket(blocks::EnhancedPacket<'a>),
    InterfaceDescription(blocks::InterfaceDescription<'a>),
}

/// Public representation of a parsed block
#[derive(Debug)]
pub struct RawBlock<'a> {
    //  0                   1                   2                   3
    //  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    //  |                          Block Type                           |
    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    //  |                      Block Total Length                       |
    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    //  /                          Block Body                           /
    //  /          /* variable length, aligned to 32 bits */            /
    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    //  |                      Block Total Length                       |
    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    pub ty: u32,
    pub block_length: u32,
    pub body: &'a [u8],
    pub check_length: u32,
}

impl<'a> RawBlock<'a> {
    pub fn parse(self) -> Option<Block<'a>> {
        let block = match self.ty {
            blocks::section_header::TY => Block::SectionHeader(blocks::section_header::parse(self)),
            blocks::enhanced_packet::TY => Block::EnhancedPacket(blocks::enhanced_packet::parse(self)),
            blocks::interface_description::TY => Block::InterfaceDescription(blocks::interface_description::parse(self)),

            _ => return None,

        };

        return Some(block);
    }
}

named!(pub parse_block< &[u8],RawBlock >,
       chain!(
           ty: le_u32 ~
           block_length: le_u32 ~
           body: take!((block_length - 12) as usize) ~
           take!(util::pad_to_32bits((block_length - 12) as usize)) ~
           check_length: le_u32 ,

           ||{ RawBlock {
               ty: ty,
               block_length: block_length,
               body: body,
               check_length: check_length
           } }
           )
      );

named!(pub parse_blocks< &[u8],Vec<RawBlock> >,
       many1!(parse_block)
       );

#[cfg(test)]
use nom::IResult;

#[test]
fn test_parse_block() {
    let input = b"\n\r\r\n\x1c\x00\x00\x00M<+\x1a\x01\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x1c\x00\x00\x00";
    match parse_block(input) {
        IResult::Done(left, RawBlock { ty, block_length, body, check_length }) => {
            // Ignored because we do not currently parse the whole block
            assert_eq!(left, b"");
            assert_eq!(ty, 0x0A0D0D0A);
            assert_eq!(block_length, 28);
            assert_eq!(body, b"M<+\x1a\x01\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff");
            assert_eq!(check_length, 28);
        },
        _ => {
            assert_eq!(1, 2);
        },
    }
}

#[test]
fn test_parse_blocks() {
    let input = b"\n\r\r\n\x1c\x00\x00\x00M<+\x1a\x01\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x1c\x00\x00\x00\
    \n\r\r\n\x1c\x00\x00\x00M<+\x1a\x01\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x1c\x00\x00\x00";
    match parse_blocks(input) {
        IResult::Done(left, blocks) => {
            assert_eq!(blocks.len(), 2);
            for i in blocks {
                let RawBlock { ty, block_length, body, check_length } = i;
                // Ignored because we do not currently parse the whole block
                assert_eq!(left, b"");
                assert_eq!(ty, 0x0A0D0D0A);
                assert_eq!(block_length, 28);
                assert_eq!(body, b"M<+\x1a\x01\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff");
                assert_eq!(check_length, 28);
            }
        },
        _ => {
            assert_eq!(1, 2);
        },
    }
}

#[test]
fn test_parse_weird_length_block() {
    let input = b"\n\r\r\n\x1b\x00\x00\x00<+\x1a\x01\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x1b\x00\x00\x00";
    match parse_block(input) {
        IResult::Done(left, RawBlock { ty, block_length, body, check_length }) => {
            // Ignored because we do not currently parse the whole block
            assert_eq!(left, b"");
            assert_eq!(ty, 0x0A0D0D0A);
            assert_eq!(27, block_length);
            assert_eq!(body.len() + 12, block_length as usize);
            assert_eq!(body, b"<+\x1a\x01\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff");
            assert_eq!(body.len() + 12, check_length as usize);
        },
        _ => {
            unreachable!("Couldn't parse the block");
        },
    }
}

#[test]
fn test_multiple_options() {
    let input = b"\x0a\x0d\x0d\x0a\x40\x00\x00\x00\x4d\x3c\x2b\x1a\x01\x00\x00\x00\
                \xff\xff\xff\xff\xff\xff\xff\xff\x03\x00\x0b\x00\x57\x69\x6e\x64\
                \x6f\x77\x73\x20\x58\x50\x00\x00\x04\x00\x0c\x00\x54\x65\x73\x74\
                \x30\x30\x34\x2e\x65\x78\x65\x00\x00\x00\x00\x00\x40\x00\x00\x00";
    match parse_block(input) {
        IResult::Done(left, block) => {
            assert_eq!(left, b"");
            if let Some(Block::SectionHeader(blk)) = block.parse() {
                if let Some(opts) = blk.options {
                    assert_eq!(opts.options.len(), 3);

                    let o = &opts.options[0];
                    assert_eq!(o.code, 0x03);
                    assert_eq!(o.length, 0x0b);
                    assert_eq!(&o.value[..], b"Windows XP\x00");

                    let o = &opts.options[1];
                    assert_eq!(o.code, 0x04);
                    assert_eq!(o.length, 0x0c);
                    assert_eq!(&o.value[..], b"Test004.exe\x00");

                    let o = &opts.options[2];
                    assert_eq!(o.code, 0x00);
                    assert_eq!(o.length, 0x00);
                    assert_eq!(&o.value[..], b"");
                } else {
                    unreachable!();
                }
            } else {
                unreachable!();
            }
        },
        _ => {
            panic!("Hit a codepath we shouldn't have");
        },
    }
}
<commit_msg>return the unknown block from parse<commit_after>use nom::{le_u32};

use blocks;
use util;

#[derive(Debug)]
pub enum Block<'a> {
    SectionHeader(blocks::SectionHeader<'a>),
    EnhancedPacket(blocks::EnhancedPacket<'a>),
    InterfaceDescription(blocks::InterfaceDescription<'a>),
    UnknownBlock(RawBlock<'a>),
}

/// Public representation of a parsed block
#[derive(Debug)]
pub struct RawBlock<'a> {
    //  0                   1                   2                   3
    //  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    //  |                          Block Type                           |
    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    //  |                      Block Total Length                       |
    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    //  /                          Block Body                           /
    //  /          /* variable length, aligned to 32 bits */            /
    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    //  |                      Block Total Length                       |
    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    pub ty: u32,
    pub block_length: u32,
    pub body: &'a [u8],
    pub check_length: u32,
}

impl<'a> RawBlock<'a> {
    pub fn parse(self) -> Block<'a> {
        match self.ty {
            blocks::section_header::TY => Block::SectionHeader(blocks::section_header::parse(self)),
            blocks::enhanced_packet::TY => Block::EnhancedPacket(blocks::enhanced_packet::parse(self)),
            blocks::interface_description::TY => Block::InterfaceDescription(blocks::interface_description::parse(self)),

            _ => Block::UnknownBlock(self),

        }
    }
}

named!(pub parse_block< &[u8],RawBlock >,
       chain!(
           ty: le_u32 ~
           block_length: le_u32 ~
           body: take!((block_length - 12) as usize) ~
           take!(util::pad_to_32bits((block_length - 12) as usize)) ~
           check_length: le_u32 ,

           ||{ RawBlock {
               ty: ty,
               block_length: block_length,
               body: body,
               check_length: check_length
           } }
           )
      );

named!(pub parse_blocks< &[u8],Vec<RawBlock> >,
       many1!(parse_block)
       );

#[cfg(test)]
use nom::IResult;

#[test]
fn test_parse_block() {
    let input = b"\n\r\r\n\x1c\x00\x00\x00M<+\x1a\x01\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x1c\x00\x00\x00";
    match parse_block(input) {
        IResult::Done(left, RawBlock { ty, block_length, body, check_length }) => {
            // Ignored because we do not currently parse the whole block
            assert_eq!(left, b"");
            assert_eq!(ty, 0x0A0D0D0A);
            assert_eq!(block_length, 28);
            assert_eq!(body, b"M<+\x1a\x01\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff");
            assert_eq!(check_length, 28);
        },
        _ => {
            assert_eq!(1, 2);
        },
    }
}

#[test]
fn test_parse_blocks() {
    let input = b"\n\r\r\n\x1c\x00\x00\x00M<+\x1a\x01\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x1c\x00\x00\x00\
    \n\r\r\n\x1c\x00\x00\x00M<+\x1a\x01\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x1c\x00\x00\x00";
    match parse_blocks(input) {
        IResult::Done(left, blocks) => {
            assert_eq!(blocks.len(), 2);
            for i in blocks {
                let RawBlock { ty, block_length, body, check_length } = i;
                // Ignored because we do not currently parse the whole block
                assert_eq!(left, b"");
                assert_eq!(ty, 0x0A0D0D0A);
                assert_eq!(block_length, 28);
                assert_eq!(body, b"M<+\x1a\x01\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff");
                assert_eq!(check_length, 28);
            }
        },
        _ => {
            assert_eq!(1, 2);
        },
    }
}

#[test]
fn test_parse_weird_length_block() {
    let input = b"\n\r\r\n\x1b\x00\x00\x00<+\x1a\x01\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x1b\x00\x00\x00";
    match parse_block(input) {
        IResult::Done(left, RawBlock { ty, block_length, body, check_length }) => {
            // Ignored because we do not currently parse the whole block
            assert_eq!(left, b"");
            assert_eq!(ty, 0x0A0D0D0A);
            assert_eq!(27, block_length);
            assert_eq!(body.len() + 12, block_length as usize);
            assert_eq!(body, b"<+\x1a\x01\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff");
            assert_eq!(body.len() + 12, check_length as usize);
        },
        _ => {
            unreachable!("Couldn't parse the block");
        },
    }
}

#[test]
fn test_multiple_options() {
    let input = b"\x0a\x0d\x0d\x0a\x40\x00\x00\x00\x4d\x3c\x2b\x1a\x01\x00\x00\x00\
                \xff\xff\xff\xff\xff\xff\xff\xff\x03\x00\x0b\x00\x57\x69\x6e\x64\
                \x6f\x77\x73\x20\x58\x50\x00\x00\x04\x00\x0c\x00\x54\x65\x73\x74\
                \x30\x30\x34\x2e\x65\x78\x65\x00\x00\x00\x00\x00\x40\x00\x00\x00";
    match parse_block(input) {
        IResult::Done(left, block) => {
            assert_eq!(left, b"");
            if let Block::SectionHeader(blk) = block.parse() {
                if let Some(opts) = blk.options {
                    assert_eq!(opts.options.len(), 3);

                    let o = &opts.options[0];
                    assert_eq!(o.code, 0x03);
                    assert_eq!(o.length, 0x0b);
                    assert_eq!(&o.value[..], b"Windows XP\x00");

                    let o = &opts.options[1];
                    assert_eq!(o.code, 0x04);
                    assert_eq!(o.length, 0x0c);
                    assert_eq!(&o.value[..], b"Test004.exe\x00");

                    let o = &opts.options[2];
                    assert_eq!(o.code, 0x00);
                    assert_eq!(o.length, 0x00);
                    assert_eq!(&o.value[..], b"");
                } else {
                    unreachable!();
                }
            } else {
                unreachable!();
            }
        },
        _ => {
            panic!("Hit a codepath we shouldn't have");
        },
    }
}
<|endoftext|>