Skip to content

Commit

Permalink
Add LSEQ
Browse files Browse the repository at this point in the history
  • Loading branch information
bluk committed Sep 5, 2019
1 parent 0306f96 commit 48a63f6
Show file tree
Hide file tree
Showing 15 changed files with 5,593 additions and 0 deletions.
8 changes: 8 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,13 @@ let package = Package(
name: "CRDTRegistersTests",
dependencies: ["CRDTRegisters"]
),
.target(
name: "LSEQ",
dependencies: []
),
.testTarget(
name: "LSEQTests",
dependencies: ["LSEQ"]
),
]
)
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ See the tests for more examples.

## Related Links

### CRDT Papers

* [Convergent and Commutative Replicated Data Types][crdt]
* [LSEQ, an Adaptive Structure for Sequences in Distributed Collaborative Editing][lseq]

### Other Projects

See other projects which have implementations for CRDTs:

* [rust-crdt][rust_crdt]
Expand All @@ -82,3 +89,4 @@ See other projects which have implementations for CRDTs:
[crdt]: https://hal.inria.fr/file/index/docid/555588/filename/techreport.pdf
[rust_crdt]: https://github.com/rust-crdt/rust-crdt
[java_crdt]: https://github.com/ajantis/java-crdt
[lseq]: https://hal.archives-ouvertes.fr/hal-00921633/document
84 changes: 84 additions & 0 deletions Sources/LSEQ/LSEQ.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright 2019 Bryant Luk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

public protocol LSEQ: Collection {
associatedtype PositionType

associatedtype Element

associatedtype Index

associatedtype ElementContainer where ElementContainer: LSEQElementContainer,
ElementContainer.PositionType == PositionType, ElementContainer.Element == Element

associatedtype Operation where Operation: LSEQOperation,
Operation.PositionType == PositionType, Operation.Element == Element

var boundary: PositionType.Segment.Identifier { get }
var source: PositionType.Segment.Source { get }
var startPosition: PositionType { get }
var endPosition: PositionType { get }
var clock: PositionType.Clock { get }
var storage: [ElementContainer] { get }

mutating func reserveCapacity(_ minimumCapacity: Int)

mutating func insert(_ newElement: Element, at index: Index)

mutating func insertAndMakeOperation(_ newElement: Element, at index: Index) -> Operation

@discardableResult
mutating func remove(at index: Index) -> Element

@discardableResult
mutating func removeAndMakeOperation(at index: Index) -> (Element, Operation)

mutating func apply(_ operation: Operation)

func makeDifferenceOperations(from other: Self) -> [Operation]
}

public protocol LSEQOperation {
associatedtype Kind
associatedtype PositionType where PositionType: Position
associatedtype Element

var kind: Kind { get }
var position: PositionType { get }
var element: Element? { get }
}

public protocol LSEQElementContainer {
associatedtype PositionType where PositionType: Position
associatedtype Element

var position: PositionType { get }
var element: Element { get }
}

internal extension RandomAccessCollection {
func insertionIndex(for predicate: (Element) -> Bool) -> Index {
var slice: SubSequence = self[...]

while !slice.isEmpty {
let middle = slice.index(slice.startIndex, offsetBy: slice.count / 2)
if predicate(slice[middle]) {
slice = slice[index(after: middle)...]
} else {
slice = slice[..<middle]
}
}
return slice.startIndex
}
}
Loading

0 comments on commit 48a63f6

Please sign in to comment.