diff --git a/src/iter/m_distinct.rs b/src/iter/m_distinct.rs index 48bc3a0..fc20878 100644 --- a/src/iter/m_distinct.rs +++ b/src/iter/m_distinct.rs @@ -1,17 +1,17 @@ #[derive(Clone)] pub struct DistinctIterator where - I::Item : Eq + std::hash::Hash + Copy, - I : Iterator + I::Item: Eq + std::hash::Hash + Copy, + I: Iterator, { - source : I, - hash_map : std::collections::HashSet + source: I, + hash_map: std::collections::HashSet, } impl Iterator for DistinctIterator where - I : Iterator, - I::Item : Eq + std::hash::Hash + Copy, + I: Iterator, + I::Item: Eq + std::hash::Hash + Copy, { type Item = I::Item; @@ -19,8 +19,7 @@ where loop { match self.source.next() { Some(item) => { - if self.hash_map.insert(item) - { + if self.hash_map.insert(item) { return Some(item); } } @@ -32,17 +31,14 @@ where } } - -pub fn distinct( - iter: I -) -> DistinctIterator +pub fn distinct(iter: I) -> DistinctIterator where - I : Iterator, - I::Item : Eq + std::hash::Hash + Copy, + I: Iterator, + I::Item: Eq + std::hash::Hash + Copy, { let hash_map = std::collections::HashSet::new(); DistinctIterator { - hash_map : hash_map, - source : iter + hash_map: hash_map, + source: iter, } } diff --git a/src/iter/m_enumerable.rs b/src/iter/m_enumerable.rs index 0c2f351..958872c 100644 --- a/src/iter/m_enumerable.rs +++ b/src/iter/m_enumerable.rs @@ -1,4 +1,4 @@ -use super::{m_builtin, m_method, m_order_by, m_select, m_distinct, m_union}; +use super::{m_builtin, m_distinct, m_method, m_order_by, m_select, m_union}; use m_builtin::{ConcateIterator, ReverseIterator, SelectIterator, WhereIterator}; use m_order_by::OrderedIterator; use m_select::{SelectManyIterator, SelectManySingleIterator}; @@ -166,12 +166,12 @@ pub trait Enumerable: Iterator { } /// Concatenates two sequences. - /// + /// /// # Examples - /// + /// /// ``` /// use linq::iter::Enumerable; - /// + /// /// let x = 0..100; /// let y = 100..200; /// let e = x.concate(y); @@ -186,12 +186,12 @@ pub trait Enumerable: Iterator { } /// Returns the first element of a sequence. - /// + /// /// # Examples - /// + /// /// ``` /// use linq::iter::Enumerable; - /// + /// /// assert!((0..0).first().is_none()); /// assert_eq!((0..2).first(), Some(0)); /// assert_eq!((0..1).first(), Some(0)); @@ -204,14 +204,14 @@ pub trait Enumerable: Iterator { } /// Returns the index-th element of the iterator. - /// + /// /// # Examples - /// + /// /// ``` /// use linq::iter::Enumerable; - /// + /// /// let a = [1, 2, 3]; - /// + /// /// assert_eq!(a.iter().element_at(0), Some(&1)); /// assert_eq!(a.iter().element_at(1), Some(&2)); /// assert_eq!(a.iter().element_at(2), Some(&3)); @@ -225,12 +225,12 @@ pub trait Enumerable: Iterator { } /// Returns the only element of a sequence. - /// + /// /// # Examples - /// + /// /// ``` /// use linq::iter::Enumerable; - /// + /// /// assert!((0..0).single().is_none()); /// assert!((0..2).single().is_none()); /// assert_eq!((0..1).single(), Some(0)); @@ -243,19 +243,19 @@ pub trait Enumerable: Iterator { } /// Inverts the order of the elements in a sequence. - /// + /// /// # Examples - /// + /// /// ``` /// use linq::iter::Enumerable; - /// + /// /// let a = [1, 2, 3]; /// let mut iter = a.iter().reverse(); - /// + /// /// assert_eq!(iter.next(), Some(&3)); /// assert_eq!(iter.next(), Some(&2)); /// assert_eq!(iter.next(), Some(&1)); - /// + /// /// assert_eq!(iter.next(), None); /// ``` fn reverse(self) -> ReverseIterator @@ -266,12 +266,12 @@ pub trait Enumerable: Iterator { } /// Determines whether a sequence contains a specified element by using the default equality comparer. - /// + /// /// # Examples - /// + /// /// ``` /// use linq::iter::Enumerable; - /// + /// /// let x = 0..10; /// assert!(x.clone().contains(&0)); /// assert!(x.clone().contains(&5)); @@ -286,12 +286,12 @@ pub trait Enumerable: Iterator { } /// Applies an accumulator function over a sequence. The specified seed value is used as the initial accumulator value. - /// + /// /// # Examples - /// + /// /// ``` /// use linq::iter::Enumerable; - /// + /// /// let x = 0..10; /// assert_eq!(x.clone().aggregate(1, |b, v| b * v), x.clone().product()); /// ``` @@ -311,7 +311,7 @@ pub trait Enumerable: Iterator { m_distinct::distinct(self) } - fn union(self, union_with : U) -> m_union::UnionIterator + fn union(self, union_with: U) -> m_union::UnionIterator where Self: Sized, Self::Item: Eq + std::hash::Hash + Copy, @@ -319,7 +319,6 @@ pub trait Enumerable: Iterator { { m_union::union(self, union_with) } - } impl Enumerable for I where I: Iterator {} diff --git a/src/iter/m_union.rs b/src/iter/m_union.rs index ce8c804..bbd006c 100644 --- a/src/iter/m_union.rs +++ b/src/iter/m_union.rs @@ -1,32 +1,30 @@ #[derive(Clone)] pub struct UnionIterator where - I::Item : Eq + std::hash::Hash + Copy, - I : Iterator, - U : Iterator, + I::Item: Eq + std::hash::Hash + Copy, + I: Iterator, + U: Iterator, { - first_source : I, - second_source : U, - was_first_source_consumed : bool, - hash_map : std::collections::HashSet + first_source: I, + second_source: U, + was_first_source_consumed: bool, + hash_map: std::collections::HashSet, } impl Iterator for UnionIterator where - I : Iterator, - U : Iterator, - I::Item : Eq + std::hash::Hash + Copy, + I: Iterator, + U: Iterator, + I::Item: Eq + std::hash::Hash + Copy, { type Item = I::Item; fn next(&mut self) -> Option { loop { - if !self.was_first_source_consumed - { + if !self.was_first_source_consumed { match self.first_source.next() { Some(item) => { - if self.hash_map.insert(item) - { + if self.hash_map.insert(item) { return Some(item); } } @@ -37,8 +35,7 @@ where } match self.second_source.next() { Some(item) => { - if self.hash_map.insert(item) - { + if self.hash_map.insert(item) { return Some(item); } } @@ -50,21 +47,17 @@ where } } - -pub fn union( - iter: I, - iter_union : U -) -> UnionIterator +pub fn union(iter: I, iter_union: U) -> UnionIterator where - I : Iterator, - U : Iterator, - I::Item : Eq + std::hash::Hash + Copy, + I: Iterator, + U: Iterator, + I::Item: Eq + std::hash::Hash + Copy, { let hash_map = std::collections::HashSet::new(); UnionIterator { - hash_map : hash_map, - first_source : iter, - second_source : iter_union, - was_first_source_consumed : false + hash_map: hash_map, + first_source: iter, + second_source: iter_union, + was_first_source_consumed: false, } } diff --git a/src/iter/mod.rs b/src/iter/mod.rs index eede593..505a277 100644 --- a/src/iter/mod.rs +++ b/src/iter/mod.rs @@ -1,11 +1,11 @@ //! Provide the implement of LINQ to Objects, based on `Iterator`. +mod m_builtin; +mod m_distinct; mod m_enumerable; +mod m_method; mod m_order_by; mod m_select; -mod m_builtin; -mod m_method; -mod m_distinct; mod m_union; pub use m_enumerable::*; diff --git a/src/lib.rs b/src/lib.rs index aab13bc..e0e13fc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -96,4 +96,4 @@ macro_rules! linq { } #[cfg(test)] -mod tests; \ No newline at end of file +mod tests; diff --git a/src/tests/iter_expr.rs b/src/tests/iter_expr.rs index dd30f87..b29c250 100644 --- a/src/tests/iter_expr.rs +++ b/src/tests/iter_expr.rs @@ -86,6 +86,8 @@ fn where_order() { fn distinct() { let x = [1, 2, 4, 2, 5, 6]; let y: Vec = x.iter().distinct().cloned().collect(); - let e: Vec = linq!(from p in x.iter(), select distinct p).cloned().collect(); + let e: Vec = linq!(from p in x.iter(), select distinct p) + .cloned() + .collect(); assert_eq!(e, y); -} \ No newline at end of file +} diff --git a/src/tests/iter_methods.rs b/src/tests/iter_methods.rs index 22ef523..3012cab 100644 --- a/src/tests/iter_methods.rs +++ b/src/tests/iter_methods.rs @@ -145,7 +145,7 @@ fn element_at() { #[test] fn distict() { let a = [1, 2, 3, 2, 3, 5]; - let mut iter = a.iter().distinct(); + let mut iter = a.iter().distinct(); assert_eq!(iter.next(), Some(&1)); assert_eq!(iter.next(), Some(&2)); assert_eq!(iter.next(), Some(&3)); @@ -158,7 +158,7 @@ fn distict() { fn union() { let a = [1, 2, 3, 2, 3, 4]; let b = [1, 2, 2, 5, 3, 6]; - let mut iter = a.iter().union(b.iter()); + let mut iter = a.iter().union(b.iter()); assert_eq!(iter.next(), Some(&1)); assert_eq!(iter.next(), Some(&2)); assert_eq!(iter.next(), Some(&3)); @@ -167,4 +167,4 @@ fn union() { assert_eq!(iter.next(), Some(&6)); assert_eq!(iter.next(), None); -} \ No newline at end of file +} diff --git a/src/tests/mod.rs b/src/tests/mod.rs index 1945444..2b51e3f 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -1,4 +1,10 @@ #[cfg(test)] - pub mod iter_expr; -pub mod iter_methods; \ No newline at end of file +pub mod iter_methods; +pub mod struct_methods_aggregate; +pub mod struct_methods_concate; +pub mod struct_methods_contains; +pub mod struct_methods_order_by; +pub mod struct_methods_select; +pub mod struct_methods_select_many; +pub mod struct_methods_where_by; diff --git a/src/tests/struct_methods_aggregate.rs b/src/tests/struct_methods_aggregate.rs new file mode 100644 index 0000000..b4d965f --- /dev/null +++ b/src/tests/struct_methods_aggregate.rs @@ -0,0 +1,17 @@ +use super::super::iter::Enumerable; + +#[derive(Clone, Debug, PartialEq)] +pub struct TestStruct { + pub value: i32, +} + +#[test] +fn aggregate_struct_vector_sum_of_first_ten_squares() { + let vector: Vec = (1..11).map(|i| TestStruct { value: i }).collect(); + + let actual = vector + .into_iter() + .aggregate(0, |val, next| val + next.value * next.value); + + assert_eq!(actual, 385); +} diff --git a/src/tests/struct_methods_concate.rs b/src/tests/struct_methods_concate.rs new file mode 100644 index 0000000..9a50370 --- /dev/null +++ b/src/tests/struct_methods_concate.rs @@ -0,0 +1,17 @@ +use super::super::iter::Enumerable; + +#[derive(Clone, Debug, PartialEq)] +pub struct TestStruct { + pub value: i32, +} + +#[test] +fn concate_struct_vector_with_struct_vector() { + let vector_a: Vec = (1..100).map(|i| TestStruct { value: i }).collect(); + let vector_b: Vec = (100..200).map(|i| TestStruct { value: i }).collect(); + + let expected: Vec = (1..200).map(|i| TestStruct { value: i }).collect(); + let actual: Vec = vector_a.into_iter().concate(vector_b.into_iter()).collect(); + + assert_eq!(actual, expected); +} diff --git a/src/tests/struct_methods_contains.rs b/src/tests/struct_methods_contains.rs new file mode 100644 index 0000000..6381db6 --- /dev/null +++ b/src/tests/struct_methods_contains.rs @@ -0,0 +1,68 @@ +use super::super::iter::Enumerable; + +#[derive(Clone, Debug, PartialEq)] +pub struct ParentTestStruct { + pub structs: Vec, +} + +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct TestStruct { + pub value: i32, +} + +#[test] +fn struct_vector_contains_vector() { + let vector: Vec = (1..5).map(|i| TestStruct { value: i }).collect(); + + let value = TestStruct { value: 3 }; + + let actual = vector.clone().into_iter().contains(&value); + + assert_eq!(true, actual); +} + +#[test] +fn struct_vector_not_contains_vector() { + let vector: Vec = (1..5).map(|i| TestStruct { value: i }).collect(); + + let value = TestStruct { value: 9 }; + + let actual = vector.into_iter().contains(&value); + + assert_eq!(false, actual); +} + +#[test] +fn parent_struct_vector_where_contains() { + let vector: Vec = (1..5) + .map(|i| ParentTestStruct { + structs: (0..i).map(|j| TestStruct { value: j }).collect(), + }) + .collect(); + + let value = TestStruct { value: 2 }; + + let expected: Vec = vec![ + ParentTestStruct { + structs: vec![ + TestStruct { value: 0 }, + TestStruct { value: 1 }, + TestStruct { value: 2 }, + ], + }, + ParentTestStruct { + structs: vec![ + TestStruct { value: 0 }, + TestStruct { value: 1 }, + TestStruct { value: 2 }, + TestStruct { value: 3 }, + ], + }, + ]; + let actual: Vec = vector + .into_iter() + .where_by(|p| p.structs.clone().into_iter().contains(&value)) + .collect(); + + assert_eq!(expected, actual); +} \ No newline at end of file diff --git a/src/tests/struct_methods_order_by.rs b/src/tests/struct_methods_order_by.rs new file mode 100644 index 0000000..4faaa4d --- /dev/null +++ b/src/tests/struct_methods_order_by.rs @@ -0,0 +1,27 @@ +use super::super::iter::Enumerable; + +#[derive(Clone, Debug, PartialEq)] +pub struct TestStruct { + pub value: i32, +} + +#[test] +fn struct_vector_order_by_i32_field() { + let vector_a: Vec = (1..100).map(|i| TestStruct { value: i }).collect(); + let vector_d: Vec = (1..100).rev().map(|i| TestStruct { value: i }).collect(); + + let actual: Vec = vector_d.into_iter().order_by(|s| s.value).collect(); + assert_eq!(vector_a, actual); +} + +#[test] +fn struct_vector_order_by_descending_i32_field() { + let vector_a: Vec = (1..100).map(|i| TestStruct { value: i }).collect(); + let vector_d: Vec = (1..100).rev().map(|i| TestStruct { value: i }).collect(); + + let actual: Vec = vector_a + .into_iter() + .order_by_descending(|s| s.value) + .collect(); + assert_eq!(vector_d, actual); +} diff --git a/src/tests/struct_methods_select.rs b/src/tests/struct_methods_select.rs new file mode 100644 index 0000000..e9e124e --- /dev/null +++ b/src/tests/struct_methods_select.rs @@ -0,0 +1,55 @@ +use super::super::iter::Enumerable; + +#[derive(Clone, Debug, PartialEq)] +pub struct TestStruct { + pub value: i32, +} + +#[derive(Clone, Debug, PartialEq)] +pub struct ResultStruct { + pub value: i32, +} + +#[test] +fn struct_vector_to_i32_vector() { + let vector: Vec = (1..100).map(|i| TestStruct { value: i }).collect(); + + let expected: Vec = (1..100).collect(); + let actual: Vec = vector.clone().into_iter().select(|s| s.value).collect(); + + assert_eq!(expected, actual); +} + +#[test] +fn struct_vector_to_i32_vector_with_multiplication() { + let vector: Vec = (1..100).map(|i| TestStruct { value: i }).collect(); + + let expected: Vec = (1..100).map(|i| i * 2).collect(); + let actual: Vec = vector.clone().into_iter().select(|s| s.value * 2).collect(); + + assert_eq!(expected, actual); +} + +#[test] +fn struct_vector_to_struct_vector() { + let vector: Vec = (1..100).map(|i| TestStruct { value: i }).collect(); + + let expected: Vec = vector.clone(); + let actual: Vec = vector.clone().into_iter().select(|s| s.clone()).collect(); + + assert_eq!(expected, actual); +} + +#[test] +fn select_struct_vector_to_different_struct_vector() { + let vector: Vec = (1..100).map(|i| TestStruct { value: i }).collect(); + + let expected: Vec = (1..100).map(|i| ResultStruct { value: i * 2 }).collect(); + let actual: Vec = vector + .clone() + .into_iter() + .select(|s| ResultStruct { value: s.value * 2 }) + .collect(); + + assert_eq!(expected, actual); +} diff --git a/src/tests/struct_methods_select_many.rs b/src/tests/struct_methods_select_many.rs new file mode 100644 index 0000000..27ead97 --- /dev/null +++ b/src/tests/struct_methods_select_many.rs @@ -0,0 +1,83 @@ +use super::super::iter::Enumerable; + +#[derive(Clone, Debug, PartialEq)] +pub struct ParentTestStruct { + pub structs: Vec, +} + +#[derive(Clone, Debug, PartialEq)] +pub struct TestStruct { + pub values: Vec, +} + +#[test] +fn struct_vector_to_i32_vector() { + let vector: Vec = (1..5) + .map(|i| TestStruct { + values: (0..i).collect(), + }) + .collect(); + + let expected: Vec = vec![0, 0, 1, 0, 1, 2, 0, 1, 2, 3]; + let actual: Vec = vector + .clone() + .into_iter() + .select_many_single(|s| s.values.clone().into_iter()) + .collect(); + + assert_eq!(expected, actual); +} + +#[test] +fn parent_struct_vector_to_struct_vector() { + let vector: Vec = (2..5) + .map(|i| ParentTestStruct { + structs: (1..i) + .map(|j| TestStruct { + values: (0..j).collect(), + }) + .collect(), + }) + .collect(); + + let expected: Vec = vec![ + TestStruct { values: vec![0] }, + TestStruct { values: vec![0] }, + TestStruct { values: vec![0, 1] }, + TestStruct { values: vec![0] }, + TestStruct { values: vec![0, 1] }, + TestStruct { + values: vec![0, 1, 2], + }, + ]; + let actual: Vec = vector + .clone() + .into_iter() + .select_many_single(|p| p.structs.clone().into_iter()) + .collect(); + + assert_eq!(expected, actual); +} + +#[test] +fn parent_struct_vector_to_struct_vector_to_i32_vector() { + let vector: Vec = (2..5) + .map(|i| ParentTestStruct { + structs: (1..i) + .map(|j| TestStruct { + values: (0..j).collect(), + }) + .collect(), + }) + .collect(); + + let expected: Vec = vec![0, 0, 0, 1, 0, 0, 1, 0, 1, 2]; + let actual: Vec = vector + .clone() + .into_iter() + .select_many_single(|p| p.structs.clone().into_iter()) + .select_many_single(|s| s.values.clone().into_iter()) + .collect(); + + assert_eq!(expected, actual); +} diff --git a/src/tests/struct_methods_where_by.rs b/src/tests/struct_methods_where_by.rs new file mode 100644 index 0000000..234bbbe --- /dev/null +++ b/src/tests/struct_methods_where_by.rs @@ -0,0 +1,36 @@ +use super::super::iter::Enumerable; + +#[derive(Clone, Debug, PartialEq)] +pub struct TestStruct { + pub value: i32, +} + +#[test] +fn struct_vector_where_by_i32_field() { + let vector: Vec = (1..100).map(|i| TestStruct { value: i }).collect(); + + let expected: Vec = (1..50).map(|i| TestStruct { value: i }).collect(); + let actual: Vec = vector + .clone() + .into_iter() + .where_by(|s| s.value < 50) + .collect(); + + assert_eq!(expected, actual); +} + +#[test] +fn struct_vector_where_by_struct() { + let vector: Vec = (1..100).map(|i| TestStruct { value: i }).collect(); + + let value = TestStruct { value: 20 }; + + let expected: Vec = vec![value.clone()]; + let actual: Vec = vector + .clone() + .into_iter() + .where_by(|s| s == &value) + .collect(); + + assert_eq!(expected, actual); +} diff --git a/tests/int_test.rs b/tests/int_test.rs index e20a4ec..378eb67 100644 --- a/tests/int_test.rs +++ b/tests/int_test.rs @@ -1,6 +1,5 @@ -use linq::linq; use linq::iter::Enumerable; - +use linq::linq; #[test] fn try_linq() {