refactor the whole damn thing

This commit is contained in:
Kevin Jahns
2017-10-11 03:41:54 +02:00
parent d9ee67d2f3
commit 82015d5a37
43 changed files with 2194 additions and 4848 deletions

31
src/Struct/Delete.js Normal file
View File

@@ -0,0 +1,31 @@
import StructManager from '../Util/StructManager'
export default class Delete {
constructor () {
this._target = null
this._length = null
}
_fromBinary (y, decoder) {
this._targetID = decoder.readOpID()
this._length = decoder.readVarUint()
}
_toBinary (y, encoder) {
encoder.writeUint8(StructManager.getReference(this.constructor))
encoder.writeOpID(this._targetID)
encoder.writeVarUint(this._length)
}
_integrate (y) {
let items = y.os.getItems(this._target, this._length)
for (let i = items.length - 1; i >= 0; i--) {
items[i]._delete()
}
// TODO: only broadcast if created by local user or if y.connector._forwardAppliedStructs..
y.connector.broadcastStruct(this)
if (y.persistence !== null) {
y.persistence.saveOperations(this)
}
}
_logString () {
return `Delete - target: ${this._target}, len: ${this._length}`
}
}

159
src/Struct/Item.js Normal file
View File

@@ -0,0 +1,159 @@
import StructManager from '../Util/StructManager'
export default class Item {
constructor () {
this._id = null
this._origin = null
this._left = null
this._right = null
this._right_origin = null
this._parent = null
this._parentSub = null
this._deleted = false
}
get _length () {
return 1
}
_getDistanceToOrigin () {
if (this.left == null) {
return 0
} else {
var d = 0
var o = this.left
while (o !== null && !this.origin.equals(o.id)) {
d++
o = o.left
}
return d
}
}
_delete (y) {
this._deleted = true
y.ds.markDeleted(this._id, this._length)
}
/*
* - Integrate the struct so that other types/structs can see it
* - Add this struct to y.os
* - Check if this is struct deleted
*/
_integrate (y) {
if (this._id === null) {
this._id = y.ss.getNextID(this._length)
}
/*
# $this has to find a unique position between origin and the next known character
# case 1: $origin equals $o.origin: the $creator parameter decides if left or right
# let $OL= [o1,o2,o3,o4], whereby $this is to be inserted between o1 and o4
# o2,o3 and o4 origin is 1 (the position of o2)
# there is the case that $this.creator < o2.creator, but o3.creator < $this.creator
# then o2 knows o3. Since on another client $OL could be [o1,o3,o4] the problem is complex
# therefore $this would be always to the right of o3
# case 2: $origin < $o.origin
# if current $this insert_position > $o origin: $this ins
# else $insert_position will not change
# (maybe we encounter case 1 later, then this will be to the right of $o)
# case 3: $origin > $o.origin
# $this insert_position is to the left of $o (forever!)
*/
// handle conflicts
let o
// set o to the first conflicting item
if (this._left !== null) {
o = this._left._right
} else if (this._parentSub !== null) {
o = this._parent._map.get(this._parentSub)
} else {
o = this._parent._start
}
let conflictingItems = new Set()
let itemsBeforeOrigin = new Set()
// Let c in conflictingItems, b in itemsBeforeOrigin
// ***{origin}bbbb{this}{c,b}{c,b}{o}***
// Note that conflictingItems is a subset of itemsBeforeOrigin
while (o !== null && o !== this._right) {
itemsBeforeOrigin.add(o)
if (this.origin === o.origin) {
// case 1
if (o._id.user < this._id.user) {
this.left = o
conflictingItems = new Set()
}
} else if (itemsBeforeOrigin.has(o)) {
// case 2
if (conflictingItems.has(o)) {
this.left = o
conflictingItems = new Set()
}
} else {
break
}
o = o.right
}
y.os.set(this)
y.ds.checkIfDeleted(this)
if (y.connector._forwardAppliedStructs || this._id.user === y.userID) {
y.connector.broadcastStruct(this)
}
if (y.persistence !== null) {
y.persistence.saveOperations(this)
}
}
_toBinary (y, encoder) {
encoder.writeUint8(StructManager.getReference(this.constructor))
encoder.writeOpID(this._id)
encoder.writeOpID(this._parent._id)
encoder.writeVarString(this.parentSub === null ? '' : JSON.stringify(this.parentSub))
encoder.writeOpID(this._left === null ? null : this._left._id)
encoder.writeOpID(this._right_origin === null ? null : this._right_origin._id)
encoder.writeOpID(this._origin === null ? null : this._origin._id)
}
_fromBinary (y, decoder) {
let missing = []
this._id = decoder.readOpID()
let parent = decoder.readOpID()
let parentSub = decoder.readVarString()
if (parentSub.length > 0) {
this._parentSub = JSON.parse(parentSub)
}
let left = decoder.readOpID()
let right = decoder.readOpId()
let origin = decoder.readOpID()
if (parent !== null && this._parent === null) {
let _parent = y.os.get(parent)
if (_parent === null) {
missing.push(parent)
} else {
this._parent = _parent
}
}
if (origin !== null && this._origin === null) {
let _origin = y.os.getCleanStart(origin)
if (_origin === null) {
missing.push(origin)
} else {
this._origin = _origin
}
}
if (left !== null && this._left === null) {
let _left = y.os.getCleanEnd(left)
if (_left === null) {
// use origin instead
this._left = this._origin
} else {
this._left = _left
}
}
if (right !== null && this._right_origin === null) {
let _right = y.os.getCleanStart(right)
if (_right === null) {
missing.push(right)
} else {
this._right = _right
this._right_origin = _right
}
}
}
_logString () {
return `left: ${this._left}, origin: ${this._origin}, right: ${this._right}, parent: ${this._parent}, parentSub: ${this._parentSub}`
}
}

32
src/Struct/ItemJSON.js Normal file
View File

@@ -0,0 +1,32 @@
import Item from './Item'
export default class ItemJSON extends Item {
constructor () {
super()
this._content = null
}
get _length () {
return this._content.length
}
_fromBinary (y, decoder) {
let missing = super._fromBinary(y, decoder)
let len = decoder.readVarUint()
this._content = new Array(len)
for (let i = 0; i < len; i++) {
this._content[i] = JSON.parse(decoder.readVarString())
}
return missing
}
_toBinary (y, encoder) {
super._toBinary(y, encoder)
let len = this._content.length
encoder.writeVarUint(len)
for (let i = 0; i < len; i++) {
encoder.writeVarString(JSON.stringify(this._content[i]))
}
}
_logString () {
let s = super._logString()
return 'ItemJSON: ' + s
}
}

24
src/Struct/ItemString.js Normal file
View File

@@ -0,0 +1,24 @@
import Item from './Item'
export default class ItemString extends Item {
constructor () {
super()
this._content = null
}
get _length () {
return this._content.length
}
_fromBinary (y, decoder) {
let missing = super._fromBinary(y, decoder)
this._content = decoder.readVarString()
return missing
}
_toBinary (y, encoder) {
super._toBinary(y, encoder)
encoder.writeVarString(this._content)
}
_logString () {
let s = super._logString()
return 'ItemString: ' + s
}
}

26
src/Struct/Type.js Normal file
View File

@@ -0,0 +1,26 @@
import Item from './Item'
export default class Type extends Item {
constructor () {
super()
this._map = new Map()
this._start = null
}
_delete (y) {
super._delete(y)
// delete map types
for (let value of this._map.values()) {
if (value instanceof Item && !value._deleted) {
value._delete()
}
}
// delete array types
let t = this._start
while (t !== null) {
if (!t._deleted) {
t._delete()
}
t = t._right
}
}
}