Skip to content

Commit

Permalink
DifferentiableSection is now inherited from Differentiable
Browse files Browse the repository at this point in the history
  • Loading branch information
ra1028 committed Aug 21, 2018
1 parent 2254970 commit 470ea34
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 24 deletions.
23 changes: 10 additions & 13 deletions Sources/Algorithm.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ public extension StagedChangeset where Collection: RangeReplaceableCollection, C
target: targetElements,
trackTargetIndexAsUpdated: false,
mapIndex: { ElementPath(element: $0, section: section) },
differentiable: { $0 },
remainedInTarget: { firstStageElements.append($0) }
)

Expand Down Expand Up @@ -124,7 +123,7 @@ public extension StagedChangeset where Collection: RangeReplaceableCollection, C
/// - Complexity: O(n)
public init(source: Collection, target: Collection) {
typealias Section = Collection.Element
typealias SectionIdentifier = Collection.Element.Model.DifferenceIdentifier
typealias SectionIdentifier = Collection.Element.DifferenceIdentifier
typealias Element = Collection.Element.Collection.Element
typealias ElementIdentifier = Collection.Element.Collection.Element.DifferenceIdentifier

Expand Down Expand Up @@ -161,8 +160,7 @@ public extension StagedChangeset where Collection: RangeReplaceableCollection, C
source: sourceSections,
target: targetSections,
trackTargetIndexAsUpdated: true,
mapIndex: { $0 },
differentiable: { $0.model }
mapIndex: { $0 }
)

// Calculate the element differences.
Expand Down Expand Up @@ -265,7 +263,7 @@ public extension StagedChangeset where Collection: RangeReplaceableCollection, C
offsetByDelete += 1
}

let section = Section(model: sourceSections[sourceSectionIndex].model, elements: firstStageElements)
let section = Section(source: sourceSections[sourceSectionIndex], elements: firstStageElements)
firstStageSections.append(section)
}

Expand All @@ -286,7 +284,7 @@ public extension StagedChangeset where Collection: RangeReplaceableCollection, C
let secondStageSection = firstStageSections[sourceSectionIndex - sectionDeleteOffset]
secondStageSections.append(secondStageSection)

let thirdStageSection = Section(model: secondStageSection.model, elements: targetElements)
let thirdStageSection = Section(source: secondStageSection, elements: targetElements)
thirdStageSections.append(thirdStageSection)

for targetElementIndex in targetElements.indices {
Expand Down Expand Up @@ -381,12 +379,11 @@ public extension StagedChangeset where Collection: RangeReplaceableCollection, C

/// The shared algorithm to calculate differences between two linear collections.
@discardableResult
private func differentiate<E, D: Differentiable, I>(
private func differentiate<E: Differentiable, I>(
source: ContiguousArray<E>,
target: ContiguousArray<E>,
trackTargetIndexAsUpdated: Bool,
mapIndex: (Int) -> I,
differentiable: (E) -> D,
remainedInTarget: ((E) -> Void)? = nil
) -> DifferentiateResult<I> {
var deleted = [I]()
Expand All @@ -396,19 +393,19 @@ private func differentiate<E, D: Differentiable, I>(

var sourceTraces = ContiguousArray<Trace<Int>>()
var targetReferences = ContiguousArray<Int?>(repeating: nil, count: target.count)
var sourceIdentifiers = ContiguousArray<D.DifferenceIdentifier>()
var sourceIdentifiers = ContiguousArray<E.DifferenceIdentifier>()

sourceIdentifiers.reserveCapacity(source.count)
sourceTraces.reserveCapacity(source.count)

for sourceElement in source {
sourceTraces.append(Trace())
sourceIdentifiers.append(differentiable(sourceElement).differenceIdentifier)
sourceIdentifiers.append(sourceElement.differenceIdentifier)
}

sourceIdentifiers.withUnsafeBufferPointer { bufferPointer in
// The pointer and the table key are for optimization.
var sourceOccurrencesTable = [TableKey<D.DifferenceIdentifier>: Occurrence](minimumCapacity: source.count * 2)
var sourceOccurrencesTable = [TableKey<E.DifferenceIdentifier>: Occurrence](minimumCapacity: source.count * 2)

// Record the index where the element was found in source collection into occurrences table.
for sourceIndex in sourceIdentifiers.indices {
Expand All @@ -430,7 +427,7 @@ private func differentiate<E, D: Differentiable, I>(

// Record the target index and the source index that the element having the same identifier.
for targetIndex in target.indices {
var targetIdentifier = differentiable(target[targetIndex]).differenceIdentifier
var targetIdentifier = target[targetIndex].differenceIdentifier
let key = TableKey(pointer: &targetIdentifier)

switch sourceOccurrencesTable[key] {
Expand Down Expand Up @@ -481,7 +478,7 @@ private func differentiate<E, D: Differentiable, I>(
let sourceElement = source[sourceIndex]
let targetElement = target[targetIndex]

if !differentiable(targetElement).isContentEqual(to: differentiable(sourceElement)) {
if !targetElement.isContentEqual(to: sourceElement) {
updated.append(mapIndex(trackTargetIndexAsUpdated ? targetIndex : sourceIndex))
}

Expand Down
14 changes: 5 additions & 9 deletions Sources/DifferentiableSection.swift
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
/// Represents the section of collection that has model and elements that identified and can be compared to whether has updated.
public protocol DifferentiableSection {
/// A type representing the model for differentiated with other section.
associatedtype Model: Differentiable
public protocol DifferentiableSection: Differentiable {
/// A type representing the elements in section.
associatedtype Collection: Swift.Collection where Collection.Element: Differentiable

/// The model of section for differentiated with other section.
var model: Model { get }
/// The collection of element in the section.
var elements: Collection { get }

/// Creates a section from the model and the elements.
/// Creates a new section reproding the given source section with replacing the elements.
///
/// - Parameters:
/// - model: A model of section.
/// - elements: The collection of element in the section.
init<C: Swift.Collection>(model: Model, elements: C) where C.Element == Collection.Element
/// - source: A source section to reproduce.
/// - elements: The collection of elements for the new section.
init<C: Swift.Collection>(source: Self, elements: C) where C.Element == Collection.Element
}
30 changes: 29 additions & 1 deletion Sources/Section.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,43 @@ public struct Section<Model: Differentiable, Element: Differentiable>: Different
/// The array of element in the section.
public var elements: [Element]

/// An identifier value that of model for difference calculation.
public var differenceIdentifier: Model.DifferenceIdentifier {
return model.differenceIdentifier
}

/// Creates a section from the model and the elements.
///
/// - Parameters:
/// - model: A model of section.
/// - model: A differentiable model of section.
/// - elements: The collection of element in the section.
public init<C: Collection>(model: Model, elements: C) where C.Element == Element {
self.model = model
self.elements = Array(elements)
}

/// Creates a new section reproding the given source section with replacing the elements.
///
/// - Parameters:
/// - source: A source section to reproduce.
/// - elements: The collection of elements for the new section.
public init<C: Collection>(source: Section, elements: C) where C.Element == Element {
self.init(model: source.model, elements: elements)
}

/// Indicate whether the content of `self` is equals to the content of
/// the given source section.
///
/// - Note: It's compared by the model of `self` and the specified section.
///
/// - Parameters:
/// - source: A source section to compare.
///
/// - Returns: A Boolean value indicating whether the content of `self` is equals
/// to the content of the given source section.
public func isContentEqual(to source: Section) -> Bool {
return model.isContentEqual(to: source.model)
}
}

extension Section: Equatable where Model: Equatable, Element: Equatable {
Expand Down
2 changes: 1 addition & 1 deletion Tests/TestTools.swift
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ func XCTAssertReproducible<C: RangeReplaceableCollection & Equatable>(
elements.insert(element, at: targetElementIndex)
}

subject[targetSectionIndex] = Section(model: section.model, elements: elements)
subject[targetSectionIndex] = Section(source: section, elements: elements)
}

let reproduced = C(subject)
Expand Down

0 comments on commit 470ea34

Please sign in to comment.