refactor read/write of structs
This commit is contained in:
@@ -14,7 +14,10 @@ import {
|
||||
findRootTypeKey,
|
||||
compareIDs,
|
||||
getItem,
|
||||
StructStore, ID, AbstractType, Y, Transaction // eslint-disable-line
|
||||
getItemType,
|
||||
getItemCleanEnd,
|
||||
getItemCleanStart,
|
||||
YEvent, StructStore, ID, AbstractType, Y, Transaction // eslint-disable-line
|
||||
} from '../internals.js'
|
||||
|
||||
import * as error from 'lib0/error.js'
|
||||
@@ -67,19 +70,10 @@ export class AbstractItem extends AbstractStruct {
|
||||
* @param {ID | null} origin
|
||||
* @param {AbstractItem | null} right
|
||||
* @param {ID | null} rightOrigin
|
||||
* @param {AbstractType<any> | null} parent
|
||||
* @param {AbstractType<any>} parent
|
||||
* @param {string | null} parentSub
|
||||
*/
|
||||
constructor (id, left, origin, right, rightOrigin, parent, parentSub) {
|
||||
if (left !== null) {
|
||||
parent = left.parent
|
||||
parentSub = left.parentSub
|
||||
} else if (right !== null) {
|
||||
parent = right.parent
|
||||
parentSub = right.parentSub
|
||||
} else if (parent === null) {
|
||||
throw error.unexpectedCase()
|
||||
}
|
||||
super(id)
|
||||
/**
|
||||
* The item that was originally to the left of this item.
|
||||
@@ -575,3 +569,49 @@ export const changeItemRefOffset = (item, offset) => {
|
||||
item.id = createID(item.id.client, item.id.clock + offset)
|
||||
item.left = createID(item.id.client, item.id.clock - 1)
|
||||
}
|
||||
|
||||
/**
|
||||
* Outsourcing some of the logic of computing the item params from a received struct.
|
||||
* If parent === null, it is expected to gc the read struct. Otherwise apply it.
|
||||
*
|
||||
* @param {Y} y
|
||||
* @param {StructStore} store
|
||||
* @param {ID|null} leftid
|
||||
* @param {ID|null} rightid
|
||||
* @param {ID|null} parentid
|
||||
* @param {string|null} parentSub
|
||||
* @param {string|null} parentYKey
|
||||
* @return {{left:AbstractItem?,right:AbstractItem?,parent:AbstractType<YEvent>?,parentSub:string?}}
|
||||
*/
|
||||
export const computeItemParams = (y, store, leftid, rightid, parentid, parentSub, parentYKey) => {
|
||||
const left = leftid === null ? null : getItemCleanEnd(store, leftid)
|
||||
const right = rightid === null ? null : getItemCleanStart(store, rightid)
|
||||
let parent = null
|
||||
if (parentid !== null) {
|
||||
const parentItem = getItemType(store, parentid)
|
||||
switch (parentItem.constructor) {
|
||||
case ItemDeleted:
|
||||
case GC:
|
||||
break
|
||||
default:
|
||||
parent = parentItem.type
|
||||
}
|
||||
} else if (parentYKey !== null) {
|
||||
parent = y.get(parentYKey)
|
||||
} else if (left !== null) {
|
||||
if (left.constructor !== GC) {
|
||||
parent = left.parent
|
||||
parentSub = left.parentSub
|
||||
}
|
||||
} else if (right !== null) {
|
||||
if (right.constructor !== GC) {
|
||||
parent = right.parent
|
||||
parentSub = right.parentSub
|
||||
}
|
||||
} else {
|
||||
throw error.unexpectedCase()
|
||||
}
|
||||
return {
|
||||
left, right, parent, parentSub
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
import {
|
||||
ID, Transaction // eslint-disable-line
|
||||
Y, StructStore, ID, Transaction // eslint-disable-line
|
||||
} from '../internals.js'
|
||||
|
||||
import * as encoding from 'lib0/encoding.js' // eslint-disable-line
|
||||
@@ -76,11 +76,12 @@ export class AbstractRef {
|
||||
return this._missing
|
||||
}
|
||||
/**
|
||||
* @param {Transaction} transaction
|
||||
* @param {Y} y
|
||||
* @param {StructStore} store
|
||||
* @param {number} offset
|
||||
* @return {AbstractStruct}
|
||||
*/
|
||||
toStruct (transaction, offset) {
|
||||
toStruct (y, store, offset) {
|
||||
throw error.methodUnimplemented()
|
||||
}
|
||||
/**
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
createID,
|
||||
writeID,
|
||||
addStruct,
|
||||
Transaction, ID // eslint-disable-line
|
||||
Y, StructStore, Transaction, ID // eslint-disable-line
|
||||
} from '../internals.js'
|
||||
|
||||
import * as decoding from 'lib0/decoding.js'
|
||||
@@ -89,11 +89,12 @@ export class GCRef extends AbstractRef {
|
||||
]
|
||||
}
|
||||
/**
|
||||
* @param {Transaction} transaction
|
||||
* @param {Y} y
|
||||
* @param {StructStore} store
|
||||
* @param {number} offset
|
||||
* @return {GC}
|
||||
*/
|
||||
toStruct (transaction, offset) {
|
||||
toStruct (y, store, offset) {
|
||||
if (offset > 0) {
|
||||
// @ts-ignore
|
||||
this.id = createID(this.id.client, this.id.clock + offset)
|
||||
|
||||
@@ -7,12 +7,9 @@
|
||||
import {
|
||||
AbstractItem,
|
||||
AbstractItemRef,
|
||||
getItemCleanEnd,
|
||||
getItemCleanStart,
|
||||
getItemType,
|
||||
computeItemParams,
|
||||
GC,
|
||||
ItemDeleted,
|
||||
Transaction, ID, AbstractType // eslint-disable-line
|
||||
StructStore, Y, AbstractType, ID, YEvent // eslint-disable-line
|
||||
} from '../internals.js'
|
||||
|
||||
import * as encoding from 'lib0/encoding.js'
|
||||
@@ -74,37 +71,24 @@ export class ItemBinaryRef extends AbstractItemRef {
|
||||
this.content = decoding.readPayload(decoder)
|
||||
}
|
||||
/**
|
||||
* @param {Transaction} transaction
|
||||
* @param {Y} y
|
||||
* @param {StructStore} store
|
||||
* @param {number} offset
|
||||
* @return {ItemBinary|GC}
|
||||
*/
|
||||
toStruct (transaction, offset) {
|
||||
const y = transaction.y
|
||||
const store = y.store
|
||||
|
||||
let parent
|
||||
if (this.parent !== null) {
|
||||
const parentItem = getItemType(store, this.parent)
|
||||
switch (parentItem.constructor) {
|
||||
case ItemDeleted:
|
||||
case GC:
|
||||
return new GC(this.id, 1)
|
||||
}
|
||||
parent = parentItem.type
|
||||
} else {
|
||||
// @ts-ignore
|
||||
parent = y.get(this.parentYKey)
|
||||
}
|
||||
|
||||
return new ItemBinary(
|
||||
this.id,
|
||||
this.left === null ? null : getItemCleanEnd(store, this.left),
|
||||
this.left,
|
||||
this.right === null ? null : getItemCleanStart(store, this.right),
|
||||
this.right,
|
||||
parent,
|
||||
this.parentSub,
|
||||
this.content
|
||||
)
|
||||
toStruct (y, store, offset) {
|
||||
const { left, right, parent, parentSub } = computeItemParams(y, store, this.left, this.right, this.parent, this.parentSub, this.parentYKey)
|
||||
return parent === null
|
||||
? new GC(this.id, this.length)
|
||||
: new ItemBinary(
|
||||
this.id,
|
||||
left,
|
||||
this.left,
|
||||
right,
|
||||
this.right,
|
||||
parent,
|
||||
parentSub,
|
||||
this.content
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,14 +7,12 @@
|
||||
import {
|
||||
AbstractItem,
|
||||
AbstractItemRef,
|
||||
getItemCleanEnd,
|
||||
getItemCleanStart,
|
||||
getItemType,
|
||||
computeItemParams,
|
||||
changeItemRefOffset,
|
||||
GC,
|
||||
splitItem,
|
||||
addToDeleteSet,
|
||||
StructStore, Transaction, ID, AbstractType // eslint-disable-line
|
||||
Y, StructStore, Transaction, ID, AbstractType // eslint-disable-line
|
||||
} from '../internals.js'
|
||||
|
||||
import * as encoding from 'lib0/encoding.js'
|
||||
@@ -112,41 +110,29 @@ export class ItemDeletedRef extends AbstractItemRef {
|
||||
return this.len
|
||||
}
|
||||
/**
|
||||
* @param {Transaction} transaction
|
||||
* @param {Y} y
|
||||
* @param {StructStore} store
|
||||
* @param {number} offset
|
||||
* @return {ItemDeleted|GC}
|
||||
*/
|
||||
toStruct (transaction, offset) {
|
||||
const y = transaction.y
|
||||
const store = y.store
|
||||
toStruct (y, store, offset) {
|
||||
if (offset > 0) {
|
||||
changeItemRefOffset(this, offset)
|
||||
this.len = this.len - offset
|
||||
}
|
||||
|
||||
let parent
|
||||
if (this.parent !== null) {
|
||||
const parentItem = getItemType(store, this.parent)
|
||||
switch (parentItem.constructor) {
|
||||
case ItemDeleted:
|
||||
case GC:
|
||||
return new GC(this.id, 1)
|
||||
}
|
||||
parent = parentItem.type
|
||||
} else {
|
||||
// @ts-ignore
|
||||
parent = y.get(this.parentYKey)
|
||||
}
|
||||
|
||||
return new ItemDeleted(
|
||||
this.id,
|
||||
this.left === null ? null : getItemCleanEnd(store, this.left),
|
||||
this.left,
|
||||
this.right === null ? null : getItemCleanStart(store, this.right),
|
||||
this.right,
|
||||
parent,
|
||||
this.parentSub,
|
||||
this.len
|
||||
)
|
||||
const { left, right, parent, parentSub } = computeItemParams(y, store, this.left, this.right, this.parent, this.parentSub, this.parentYKey)
|
||||
return parent === null
|
||||
? new GC(this.id, this.length)
|
||||
: new ItemDeleted(
|
||||
this.id,
|
||||
left,
|
||||
this.left,
|
||||
right,
|
||||
this.right,
|
||||
parent,
|
||||
parentSub,
|
||||
this.len
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,12 +5,9 @@
|
||||
import {
|
||||
AbstractItem,
|
||||
AbstractItemRef,
|
||||
getItemCleanEnd,
|
||||
getItemCleanStart,
|
||||
getItemType,
|
||||
ItemDeleted,
|
||||
computeItemParams,
|
||||
GC,
|
||||
Transaction, ID, AbstractType // eslint-disable-line
|
||||
Y, StructStore, ID, AbstractType // eslint-disable-line
|
||||
} from '../internals.js'
|
||||
|
||||
import * as encoding from 'lib0/encoding.js'
|
||||
@@ -69,37 +66,24 @@ export class ItemEmbedRef extends AbstractItemRef {
|
||||
this.embed = JSON.parse(decoding.readVarString(decoder))
|
||||
}
|
||||
/**
|
||||
* @param {Transaction} transaction
|
||||
* @param {Y} y
|
||||
* @param {StructStore} store
|
||||
* @param {number} offset
|
||||
* @return {ItemEmbed|GC}
|
||||
*/
|
||||
toStruct (transaction, offset) {
|
||||
const y = transaction.y
|
||||
const store = y.store
|
||||
|
||||
let parent
|
||||
if (this.parent !== null) {
|
||||
const parentItem = getItemType(store, this.parent)
|
||||
switch (parentItem.constructor) {
|
||||
case ItemDeleted:
|
||||
case GC:
|
||||
return new GC(this.id, 1)
|
||||
}
|
||||
parent = parentItem.type
|
||||
} else {
|
||||
// @ts-ignore
|
||||
parent = y.get(this.parentYKey)
|
||||
}
|
||||
|
||||
return new ItemEmbed(
|
||||
this.id,
|
||||
this.left === null ? null : getItemCleanEnd(store, this.left),
|
||||
this.left,
|
||||
this.right === null ? null : getItemCleanStart(store, this.right),
|
||||
this.right,
|
||||
parent,
|
||||
this.parentSub,
|
||||
this.embed
|
||||
)
|
||||
toStruct (y, store, offset) {
|
||||
const { left, right, parent, parentSub } = computeItemParams(y, store, this.left, this.right, this.parent, this.parentSub, this.parentYKey)
|
||||
return parent === null
|
||||
? new GC(this.id, this.length)
|
||||
: new ItemEmbed(
|
||||
this.id,
|
||||
left,
|
||||
this.left,
|
||||
right,
|
||||
this.right,
|
||||
parent,
|
||||
parentSub,
|
||||
this.embed
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,12 +5,9 @@
|
||||
import {
|
||||
AbstractItem,
|
||||
AbstractItemRef,
|
||||
getItemCleanEnd,
|
||||
getItemCleanStart,
|
||||
getItemType,
|
||||
ItemDeleted,
|
||||
computeItemParams,
|
||||
GC,
|
||||
Transaction, ID, AbstractType // eslint-disable-line
|
||||
Y, StructStore, ID, AbstractType // eslint-disable-line
|
||||
} from '../internals.js'
|
||||
|
||||
import * as encoding from 'lib0/encoding.js'
|
||||
@@ -76,38 +73,25 @@ export class ItemFormatRef extends AbstractItemRef {
|
||||
this.value = JSON.parse(decoding.readVarString(decoder))
|
||||
}
|
||||
/**
|
||||
* @param {Transaction} transaction
|
||||
* @param {Y} y
|
||||
* @param {StructStore} store
|
||||
* @param {number} offset
|
||||
* @return {ItemFormat|GC}
|
||||
*/
|
||||
toStruct (transaction, offset) {
|
||||
const y = transaction.y
|
||||
const store = y.store
|
||||
|
||||
let parent
|
||||
if (this.parent !== null) {
|
||||
const parentItem = getItemType(store, this.parent)
|
||||
switch (parentItem.constructor) {
|
||||
case ItemDeleted:
|
||||
case GC:
|
||||
return new GC(this.id, 1)
|
||||
}
|
||||
parent = parentItem.type
|
||||
} else {
|
||||
// @ts-ignore
|
||||
parent = y.get(this.parentYKey)
|
||||
}
|
||||
|
||||
return new ItemFormat(
|
||||
this.id,
|
||||
this.left === null ? null : getItemCleanEnd(store, this.left),
|
||||
this.left,
|
||||
this.right === null ? null : getItemCleanStart(store, this.right),
|
||||
this.right,
|
||||
parent,
|
||||
this.parentSub,
|
||||
this.key,
|
||||
this.value
|
||||
)
|
||||
toStruct (y, store, offset) {
|
||||
const { left, right, parent, parentSub } = computeItemParams(y, store, this.left, this.right, this.parent, this.parentSub, this.parentYKey)
|
||||
return parent === null
|
||||
? new GC(this.id, this.length)
|
||||
: new ItemFormat(
|
||||
this.id,
|
||||
left,
|
||||
this.left,
|
||||
right,
|
||||
this.right,
|
||||
parent,
|
||||
parentSub,
|
||||
this.key,
|
||||
this.value
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,14 +5,11 @@
|
||||
import {
|
||||
AbstractItem,
|
||||
AbstractItemRef,
|
||||
getItemCleanEnd,
|
||||
getItemCleanStart,
|
||||
getItemType,
|
||||
computeItemParams,
|
||||
splitItem,
|
||||
changeItemRefOffset,
|
||||
GC,
|
||||
ItemDeleted,
|
||||
StructStore, Transaction, ID, AbstractType // eslint-disable-line
|
||||
StructStore, Y, ID, AbstractType // eslint-disable-line
|
||||
} from '../internals.js'
|
||||
|
||||
import * as encoding from 'lib0/encoding.js'
|
||||
@@ -122,39 +119,28 @@ export class ItemJSONRef extends AbstractItemRef {
|
||||
return this.content.length
|
||||
}
|
||||
/**
|
||||
* @param {Transaction} transaction
|
||||
* @param {Y} y
|
||||
* @param {StructStore} store
|
||||
* @param {number} offset
|
||||
* @return {ItemJSON|GC}
|
||||
*/
|
||||
toStruct (transaction, offset) {
|
||||
const y = transaction.y
|
||||
const store = y.store
|
||||
toStruct (y, store, offset) {
|
||||
if (offset > 0) {
|
||||
changeItemRefOffset(this, offset)
|
||||
this.content = this.content.slice(offset)
|
||||
}
|
||||
let parent
|
||||
if (this.parent !== null) {
|
||||
const parentItem = getItemType(store, this.parent)
|
||||
switch (parentItem.constructor) {
|
||||
case ItemDeleted:
|
||||
case GC:
|
||||
return new GC(this.id, this.content.length)
|
||||
}
|
||||
parent = parentItem.type
|
||||
} else {
|
||||
// @ts-ignore
|
||||
parent = y.get(this.parentYKey)
|
||||
}
|
||||
return new ItemJSON(
|
||||
this.id,
|
||||
this.left === null ? null : getItemCleanEnd(store, this.left),
|
||||
this.left,
|
||||
this.right === null ? null : getItemCleanStart(store, this.right),
|
||||
this.right,
|
||||
parent,
|
||||
this.parentSub,
|
||||
this.content
|
||||
)
|
||||
const { left, right, parent, parentSub } = computeItemParams(y, store, this.left, this.right, this.parent, this.parentSub, this.parentYKey)
|
||||
return parent === null
|
||||
? new GC(this.id, this.length)
|
||||
: new ItemJSON(
|
||||
this.id,
|
||||
left,
|
||||
this.left,
|
||||
right,
|
||||
this.right,
|
||||
parent,
|
||||
parentSub,
|
||||
this.content
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,14 +4,11 @@
|
||||
import {
|
||||
AbstractItem,
|
||||
AbstractItemRef,
|
||||
getItemCleanEnd,
|
||||
getItemCleanStart,
|
||||
getItemType,
|
||||
computeItemParams,
|
||||
splitItem,
|
||||
changeItemRefOffset,
|
||||
ItemDeleted,
|
||||
GC,
|
||||
StructStore, Transaction, ID, AbstractType // eslint-disable-line
|
||||
StructStore, Y, ID, AbstractType // eslint-disable-line
|
||||
} from '../internals.js'
|
||||
|
||||
import * as encoding from 'lib0/encoding.js'
|
||||
@@ -108,41 +105,29 @@ export class ItemStringRef extends AbstractItemRef {
|
||||
return this.string.length
|
||||
}
|
||||
/**
|
||||
* @param {Transaction} transaction
|
||||
* @param {Y} y
|
||||
* @param {StructStore} store
|
||||
* @param {number} offset
|
||||
* @return {ItemString|GC}
|
||||
*/
|
||||
toStruct (transaction, offset) {
|
||||
const y = transaction.y
|
||||
const store = y.store
|
||||
toStruct (y, store, offset) {
|
||||
if (offset > 0) {
|
||||
changeItemRefOffset(this, offset)
|
||||
this.string = this.string.slice(offset)
|
||||
}
|
||||
|
||||
let parent
|
||||
if (this.parent !== null) {
|
||||
const parentItem = getItemType(store, this.parent)
|
||||
switch (parentItem.constructor) {
|
||||
case ItemDeleted:
|
||||
case GC:
|
||||
return new GC(this.id, this.string.length)
|
||||
}
|
||||
parent = parentItem.type
|
||||
} else {
|
||||
// @ts-ignore
|
||||
parent = y.get(this.parentYKey)
|
||||
}
|
||||
|
||||
return new ItemString(
|
||||
this.id,
|
||||
this.left === null ? null : getItemCleanEnd(store, this.left),
|
||||
this.left,
|
||||
this.right === null ? null : getItemCleanStart(store, this.right),
|
||||
this.right,
|
||||
parent,
|
||||
this.parentSub,
|
||||
this.string
|
||||
)
|
||||
const { left, right, parent, parentSub } = computeItemParams(y, store, this.left, this.right, this.parent, this.parentSub, this.parentYKey)
|
||||
return parent === null
|
||||
? new GC(this.id, this.length)
|
||||
: new ItemString(
|
||||
this.id,
|
||||
left,
|
||||
this.left,
|
||||
right,
|
||||
this.right,
|
||||
parent,
|
||||
parentSub,
|
||||
this.string
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,7 @@
|
||||
import {
|
||||
AbstractItem,
|
||||
AbstractItemRef,
|
||||
getItemCleanEnd,
|
||||
getItemCleanStart,
|
||||
getItemType,
|
||||
computeItemParams,
|
||||
readYArray,
|
||||
readYMap,
|
||||
readYText,
|
||||
@@ -17,7 +15,7 @@ import {
|
||||
readYXmlFragment,
|
||||
readYXmlHook,
|
||||
readYXmlText,
|
||||
Y, GC, ItemDeleted, Transaction, ID, AbstractType // eslint-disable-line
|
||||
StructStore, Y, GC, ItemDeleted, Transaction, ID, AbstractType // eslint-disable-line
|
||||
} from '../internals.js'
|
||||
|
||||
import * as encoding from 'lib0/encoding.js' // eslint-disable-line
|
||||
@@ -171,38 +169,24 @@ export class ItemTypeRef extends AbstractItemRef {
|
||||
this.type = typeRefs[typeRef](decoder)
|
||||
}
|
||||
/**
|
||||
* @param {Transaction} transaction
|
||||
* @param {Y} y
|
||||
* @param {StructStore} store
|
||||
* @param {number} offset
|
||||
* @return {ItemType|GC}
|
||||
*/
|
||||
toStruct (transaction, offset) {
|
||||
const y = transaction.y
|
||||
const store = y.store
|
||||
|
||||
let parent
|
||||
if (this.parent !== null) {
|
||||
const parentItem = getItemType(store, this.parent)
|
||||
switch (parentItem.constructor) {
|
||||
case ItemDeleted:
|
||||
case GC:
|
||||
return new GC(this.id, 1)
|
||||
}
|
||||
parent = parentItem.type
|
||||
} else {
|
||||
// @ts-ignore
|
||||
parent = y.get(this.parentYKey)
|
||||
}
|
||||
|
||||
// TODO: we can probably only feed AbstractType with origins
|
||||
return new ItemType(
|
||||
this.id,
|
||||
this.left === null ? null : getItemCleanEnd(store, this.left),
|
||||
this.left,
|
||||
this.right === null ? null : getItemCleanStart(store, this.right),
|
||||
this.right,
|
||||
parent,
|
||||
this.parentSub,
|
||||
this.type
|
||||
)
|
||||
toStruct (y, store, offset) {
|
||||
const { left, right, parent, parentSub } = computeItemParams(y, store, this.left, this.right, this.parent, this.parentSub, this.parentYKey)
|
||||
return parent === null
|
||||
? new GC(this.id, this.length)
|
||||
: new ItemType(
|
||||
this.id,
|
||||
left,
|
||||
this.left,
|
||||
right,
|
||||
this.right,
|
||||
parent,
|
||||
parentSub,
|
||||
this.type
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user