Skip to content

Commit

Permalink
Adds documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
wokalski committed Nov 21, 2016
1 parent 3df6660 commit 539761d
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 22 deletions.
2 changes: 1 addition & 1 deletion Diff.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,8 @@
isa = PBXGroup;
children = (
C9EE87821CCFFB68006BD90E /* Diff.swift */,
C9278ADD1DE32B88009CE846 /* Diff+UIKit.swift */,
C9B03FBF1DE1CA7500BC6F2A /* ExtendedDiff.swift */,
C9278ADD1DE32B88009CE846 /* Diff+UIKit.swift */,
C9EE87831CCFFB68006BD90E /* Patch.swift */,
C99118971DDB4C3000067A60 /* Patch+Sort.swift */,
C99118AD1DDDAFEA00067A60 /* ExtendedPatch.swift */,
Expand Down
12 changes: 12 additions & 0 deletions Sources/Diff+UIKit.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ struct BatchUpdate {
}

public extension UITableView {

/// Animates rows which changed between oldData and newData.
///
/// - parameter oldData: Data which reflects the previous state of UITableView
/// - parameter newData: Data which reflects the current state of UITableView
/// - parameter deletionAnimation: Animation type for deletions
/// - parameter insertionAnimation: Animation type for insertions
public func animateRowChanges<T: Collection>(
oldData: T,
newData: T,
Expand All @@ -48,6 +55,11 @@ public extension UITableView {
}

public extension UICollectionView {

/// Animates items which changed between oldData and newData.
///
/// - parameter oldData: Data which reflects the previous state of UITableView
/// - parameter newData: Data which reflects the current state of UITableView
public func animateItemChanges<T: Collection>(
oldData: T,
newData: T
Expand Down
48 changes: 42 additions & 6 deletions Sources/Diff.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ public protocol DiffProtocol: Collection, Sequence {
var elements: [DiffElementType] { get }
}

/**
A sequence of deletions and insertions where deletions point to locations in the source and insertions point to locations in the output.
Examples:
"12" -> "": D(0)D(1)
"" -> "12": I(0)I(1)

SeeAlso: Diff
*/
public struct Diff: DiffProtocol {

public enum Element {
Expand All @@ -22,7 +30,8 @@ public struct Diff: DiffProtocol {
public func index(after i: Int) -> Int {
return i + 1
}


/// An array of particular diff operations
public let elements: [Diff.Element]
}

Expand Down Expand Up @@ -59,16 +68,18 @@ public func ==(l: Point, r: Point) -> Bool {
return (l.x == r.x) && (l.y == r.y)
}


/// A data structure representing single trace produced by the diff algorithm. See the [paper](http://www.xmailserver.org/diff2.pdf) for more information on traces.
public struct Trace {
public let from: Point
public let to: Point
public let D: Int
}

extension Trace: Equatable {}

public func ==(l: Trace, r: Trace) -> Bool {
return (l.from == r.from) && (l.to == r.to)
extension Trace: Equatable {
static public func ==(l: Trace, r: Trace) -> Bool {
return (l.from == r.from) && (l.to == r.to)
}
}

enum TraceType {
Expand All @@ -94,13 +105,26 @@ extension Trace {
}

public extension String {


/// Creates a diff between the calee and `to` string
///
/// - parameter to: a string to compare the calee to.
/// - complexity: O((N+M)*D)
/// - returns: a Diff between the calee and `to` string
public func diff(to: String) -> Diff {
if self == to {
return Diff(elements: [])
}
return characters.diff(to.characters)
}


/// Creates an extended diff (includes insertions, deletions, and moves) between the calee and `other` string
///
/// - parameter other: a string to compare the calee to.
/// - complexity: O((N+M)*D)
/// - returns: an ExtendedDiff between the calee and `other` string
public func extendedDiff(_ other: String) -> ExtendedDiff {
if self == other {
return ExtendedDiff(
Expand Down Expand Up @@ -133,10 +157,22 @@ struct TraceStep {

public extension Collection where Iterator.Element : Equatable {


/// Creates a diff between the calee and `other` collection
///
/// - parameter other: a collection to compare the calee to
/// - complexity: O((N+M)*D)
/// - returns: a Diff between the calee and `other` collection
public func diff(_ other: Self) -> Diff {
return findPath(diffTraces(to: other), n: Int(self.count.toIntMax()), m: Int(other.count.toIntMax()))
}



/// Generates all traces required to create an output diff. See the [paper](http://www.xmailserver.org/diff2.pdf) for more information on traces.
///
/// - parameter to: other collection
///
/// - returns: all traces required to create an output diff
public func diffTraces(to: Self) -> [Trace] {
if (self.count == 0 && to.count == 0) {
return []
Expand Down
27 changes: 23 additions & 4 deletions Sources/ExtendedDiff.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@

/**
A sequence of deletions, insertions, and moves where deletions point to locations in the source and insertions point to locations in the output.
Examples:
"12" -> "": D(0)D(1)
"" -> "12": I(0)I(1)

SeeAlso: Diff
*/
public struct ExtendedDiff: DiffProtocol {

public enum Element {
Expand All @@ -16,13 +24,18 @@ public struct ExtendedDiff: DiffProtocol {
return i + 1
}


/// Diff used to compute an instance
public let source: Diff
/// An array which holds indices of diff elements in the source diff (i.e. diff without moves).
public let sourceIndex: [Int]
let sourceIndex: [Int]
/// An array which holds indices of diff elements in a diff where move's subelements (deletion and insertion) are ordered accordingly
public let reorderedIndex: [Int]
let reorderedIndex: [Int]


/// An array of particular diff operations
public let elements: [ExtendedDiff.Element]
public let moveIndices: Set<Int>
let moveIndices: Set<Int>
}

extension ExtendedDiff.Element {
Expand All @@ -38,11 +51,17 @@ extension ExtendedDiff.Element {

public extension Collection where Iterator.Element : Equatable {


/// Creates an extended diff between the calee and `other` collection
///
/// - parameter other: a collection to compare the calee to
/// - complexity: O((N+M)*D). There's additional cost of O(D^2) to compute the moves.
/// - returns: ExtendedDiff between the calee and `other` collection
public func extendedDiff(_ other: Self) -> ExtendedDiff {
return extendedDiffFrom(diff(other), other: other)
}

fileprivate func extendedDiffFrom(_ diff: Diff, other: Self) -> ExtendedDiff {
private func extendedDiffFrom(_ diff: Diff, other: Self) -> ExtendedDiff {


var elements: [ExtendedDiff.Element] = []
Expand Down
25 changes: 25 additions & 0 deletions Sources/ExtendedPatch.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,27 @@ enum BoxedDiffAndPatchElement<T> {
}
}

/// Single step in a patch sequence.
///
/// - insertion: A single patch step containing an insertion index and an element to be inserted
/// - deletion: A single patch step containing a deletion index
/// - move: A single patch step containing the origin and target of a move
public enum ExtendedPatch<Element> {
case insertion(index: Int, element: Element)
case deletion(index: Int)
case move(from: Int, to: Int)
}

/**
Generates a patch sequence. It is a list of steps to be applied to obtain the `to` collection from the `from` one.
The sorting function lets you sort the output e.g. you might want the output patch to have insertions first.

- parameter from: The source collection
- parameter to: The target collection
- parameter sort: A sorting function
- complexity: O((N+M)*D)
- returns: Arbitrarly sorted sequence of steps to obtain `to` collection from the `from` one.
*/
public func extendedPatch<T: Collection>(
from: T,
to: T,
Expand All @@ -37,6 +52,16 @@ public func extendedPatch<T: Collection>(
extension ExtendedDiff {
public typealias OrderedBefore = (_ fst: ExtendedDiff.Element, _ snd: ExtendedDiff.Element) -> Bool

/**
Generates a patch sequence based on the callee. It is a list of steps to be applied to obtain the `to` collection from the `from` one.
The sorting function lets you sort the output e.g. you might want the output patch to have insertions first.

- parameter from: The source collection (usually the source collecetion of the callee)
- parameter to: The target collection (usually the target collecetion of the callee)
- parameter sort: A sorting function
- complexity: O(D^2)
- returns: Arbitrarly sorted sequence of steps to obtain `to` collection from the `from` one.
*/
public func patch<T: Collection>(
from: T,
to: T,
Expand Down
43 changes: 32 additions & 11 deletions Sources/Patch+Sort.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@

/**
Generates arbitrarly sorted patch sequence. It is a list of steps to be applied to obtain the `to` collection from the `from` one.
The sorting function lets you sort the output e.g. you might want the output patch to have insertions first.

- parameter from: The source collection
- parameter to: The target collection
- parameter sort: A sorting function
- complexity: O((N+M)*D)
- returns: Arbitrarly sorted sequence of steps to obtain `to` collection from the `from` one.
*/
public func patch<T: Collection>(
from: T,
to: T,
Expand All @@ -11,6 +21,28 @@ public extension Diff {

public typealias OrderedBefore = (_ fst: Diff.Element, _ snd: Diff.Element) -> Bool

/**
Generates arbitrarly sorted patch sequence based on the callee. It is a list of steps to be applied to obtain the `to` collection from the `from` one.
The sorting function lets you sort the output e.g. you might want the output patch to have insertions first.

- parameter from: The source collection (usually the source collecetion of the callee)
- parameter to: The target collection (usually the target collecetion of the callee)
- parameter sort: A sorting function
- complexity: O(D^2)
- returns: Arbitrarly sorted sequence of steps to obtain `to` collection from the `from` one.
*/
public func patch<T: Collection>(
from: T,
to: T,
sort: OrderedBefore
) -> [Patch<T.Iterator.Element>] where T.Iterator.Element : Equatable {
let shiftedPatch = patch(from: from, to: to)
return shiftedPatchElements(from: sortedPatchElements(
from: shiftedPatch,
sortBy: sort
)).map { $0.value }
}

private func sortedPatchElements<T>(from source: [Patch<T>], sortBy areInIncreasingOrder: OrderedBefore) -> [SortedPatchElement<T>] {
let sorted = indices.map { (self[$0], $0) }
.sorted { areInIncreasingOrder($0.0, $1.0) }
Expand All @@ -25,15 +57,4 @@ public extension Diff {
})
}

public func patch<T: Collection>(
from: T,
to: T,
sort: OrderedBefore
) -> [Patch<T.Iterator.Element>] where T.Iterator.Element : Equatable {
let shiftedPatch = patch(from: from, to: to)
return shiftedPatchElements(from: sortedPatchElements(
from: shiftedPatch,
sortBy: sort
)).map { $0.value }
}
}
20 changes: 20 additions & 0 deletions Sources/Patch.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@


/// Single step in a patch sequence.
public enum Patch<Element> {
/// A single patch step containing an insertion index and an element to be inserted
case insertion(index: Int, element: Element)
/// A single patch step containing a deletion index
case deletion(index: Int)

func index() -> Int {
Expand All @@ -15,6 +19,14 @@ public enum Patch<Element> {

public extension Diff {

/**
Generates a patch sequence based on a diff. It is a list of steps to be applied to obtain the `to` collection from the `from` one.

- parameter from: The source collection (usually the source collecetion of the callee)
- parameter to: The target collection (usually the target collecetion of the callee)
- complexity: O(N)
- returns: A sequence of steps to obtain `to` collection from the `from` one.
*/
public func patch<T: Collection>(
from: T,
to: T
Expand All @@ -33,6 +45,14 @@ public extension Diff {
}
}

/**
Generates a patch sequence. It is a list of steps to be applied to obtain the `to` collection from the `from` one.

- parameter from: The source collection
- parameter to: The target collection
- complexity: O((N+M)*D)
- returns: A sequence of steps to obtain `to` collection from the `from` one.
*/
public func patch<T: Collection>(
from: T,
to: T
Expand Down

0 comments on commit 539761d

Please sign in to comment.