Skip to content

Commit

Permalink
Remove one type parameter in trait with associated type
Browse files Browse the repository at this point in the history
This patch removes one level of generic by transforming it to an
associated type.

This improves usability of the traits because of fewer generics.
Also, generic output values are problematic because every function which
wants to be generic over the trait has also to be generic over the
generic return type of the functions of the trait (see rust
documentation on associated types).

This patch improves this.
  • Loading branch information
matthiasbeyer committed Feb 1, 2018
1 parent 3490a35 commit c29b7eb
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 12 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# git-dit ChangeLog

## Next

Changes:
* Some traits in the library were refactored to not be generic over their
functions return types, but rather use associated types for that.

## v0.4.0 (2017-09-15)

### Binary
Expand Down
18 changes: 11 additions & 7 deletions lib/src/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,30 +123,34 @@ impl<'r> Iterator for Messages<'r> {
/// `Message`s which does not need to be part of `Messages` or another iterator.
///
pub trait MessagesExt {
type Output:
accumulation::MultiAccumulator +
FromIterator<(String, accumulation::ValueAccumulator)>;

/// Accumulate trailers according to the specification provided
///
/// This function accumulates all specified trailers from the messages
/// returned by the iterator.
///
fn accumulate_trailers<'a, A, I, J>(self, specs: I) -> A
where A: accumulation::MultiAccumulator + FromIterator<(String, accumulation::ValueAccumulator)>,
I: IntoIterator<Item = J>,
fn accumulate_trailers<'a, I, J>(self, specs: I) -> Self::Output
where I: IntoIterator<Item = J>,
J: Borrow<spec::TrailerSpec<'a>>;
}

impl<'a, I> MessagesExt for I
where I: Iterator<Item = git2::Commit<'a>>
{
fn accumulate_trailers<'b, A, J, K>(self, specs: J) -> A
where A: accumulation::MultiAccumulator + FromIterator<(String, accumulation::ValueAccumulator)>,
J: IntoIterator<Item = K>,
type Output = HashMap<String, accumulation::ValueAccumulator>;

fn accumulate_trailers<'b, J, K>(self, specs: J) -> Self::Output
where J: IntoIterator<Item = K>,
K: Borrow<spec::TrailerSpec<'b>>
{
use message::Message;
use trailer::accumulation::Accumulator;
use trailer::spec::ToMap;

let mut accumulator : A = specs.into_map();
let mut accumulator = specs.into_map();
accumulator.process_all(self.flat_map(|message| message.trailers()));
accumulator
}
Expand Down
11 changes: 6 additions & 5 deletions lib/src/trailer/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,19 +62,20 @@ pub const ISSUE_STATUS_SPEC: TrailerSpec = TrailerSpec {
/// specifications in a convenient way.
///
pub trait ToMap {
type Output: FromIterator<(String, ValueAccumulator)>;

/// Construct an accumulation map
///
fn into_map<M>(self) -> M
where M: FromIterator<(String, ValueAccumulator)>;
fn into_map(self) -> Self::Output;
}

impl<'s, I, J> ToMap for I
where I: IntoIterator<Item = J>,
J: Borrow<TrailerSpec<'s>>
{
fn into_map<M>(self) -> M
where M: FromIterator<(String, ValueAccumulator)>
{
type Output = ::std::collections::HashMap<String, ValueAccumulator>;

fn into_map(self) -> Self::Output {
self.into_iter()
.map(|spec| {
let s = spec.borrow();
Expand Down

0 comments on commit c29b7eb

Please sign in to comment.