Implement experimental new encoder 🚀

This commit is contained in:
Kevin Jahns
2020-07-12 18:25:45 +02:00
parent e31e968f0d
commit 6c2cf0f769
36 changed files with 1224 additions and 336 deletions

View File

@@ -1,9 +1,8 @@
import {
StructStore, ID, Transaction // eslint-disable-line
AbstractUpdateEncoder, ID, Transaction // eslint-disable-line
} from '../internals.js'
import * as encoding from 'lib0/encoding.js' // eslint-disable-line
import * as error from 'lib0/error.js'
export class AbstractStruct {
@@ -35,7 +34,7 @@ export class AbstractStruct {
}
/**
* @param {encoding.Encoder} encoder The encoder to write data to.
* @param {AbstractUpdateEncoder} encoder The encoder to write data to.
* @param {number} offset
* @param {number} encodingRef
*/

View File

@@ -1,10 +1,7 @@
import {
Transaction, Item, StructStore // eslint-disable-line
AbstractUpdateDecoder, AbstractUpdateEncoder, Transaction, Item, StructStore // eslint-disable-line
} from '../internals.js'
import * as encoding from 'lib0/encoding.js'
import * as decoding from 'lib0/decoding.js'
export class ContentAny {
/**
* @param {Array<any>} arr
@@ -77,15 +74,15 @@ export class ContentAny {
*/
gc (store) {}
/**
* @param {encoding.Encoder} encoder
* @param {AbstractUpdateEncoder} encoder
* @param {number} offset
*/
write (encoder, offset) {
const len = this.arr.length
encoding.writeVarUint(encoder, len - offset)
encoder.writeLen(len - offset)
for (let i = offset; i < len; i++) {
const c = this.arr[i]
encoding.writeAny(encoder, c)
encoder.writeAny(c)
}
}
@@ -98,14 +95,14 @@ export class ContentAny {
}
/**
* @param {decoding.Decoder} decoder
* @param {AbstractUpdateDecoder} decoder
* @return {ContentAny}
*/
export const readContentAny = decoder => {
const len = decoding.readVarUint(decoder)
const len = decoder.readLen()
const cs = []
for (let i = 0; i < len; i++) {
cs.push(decoding.readAny(decoder))
cs.push(decoder.readAny())
}
return new ContentAny(cs)
}

View File

@@ -1,10 +1,7 @@
import {
StructStore, Item, Transaction // eslint-disable-line
AbstractUpdateDecoder, AbstractUpdateEncoder, StructStore, Item, Transaction // eslint-disable-line
} from '../internals.js'
import * as encoding from 'lib0/encoding.js'
import * as decoding from 'lib0/decoding.js'
import * as buffer from 'lib0/buffer.js'
import * as error from 'lib0/error.js'
export class ContentBinary {
@@ -73,11 +70,11 @@ export class ContentBinary {
*/
gc (store) {}
/**
* @param {encoding.Encoder} encoder
* @param {AbstractUpdateEncoder} encoder
* @param {number} offset
*/
write (encoder, offset) {
encoding.writeVarUint8Array(encoder, this.content)
encoder.writeBuf(this.content)
}
/**
@@ -89,7 +86,7 @@ export class ContentBinary {
}
/**
* @param {decoding.Decoder} decoder
* @param {AbstractUpdateDecoder} decoder
* @return {ContentBinary}
*/
export const readContentBinary = decoder => new ContentBinary(buffer.copyUint8Array(decoding.readVarUint8Array(decoder)))
export const readContentBinary = decoder => new ContentBinary(decoder.readBuf())

View File

@@ -1,12 +1,9 @@
import {
addToDeleteSet,
StructStore, Item, Transaction // eslint-disable-line
AbstractUpdateDecoder, AbstractUpdateEncoder, StructStore, Item, Transaction // eslint-disable-line
} from '../internals.js'
import * as encoding from 'lib0/encoding.js'
import * as decoding from 'lib0/decoding.js'
export class ContentDeleted {
/**
* @param {number} len
@@ -67,7 +64,7 @@ export class ContentDeleted {
* @param {Item} item
*/
integrate (transaction, item) {
addToDeleteSet(transaction.deleteSet, item.id, this.len)
addToDeleteSet(transaction.deleteSet, item.id.client, item.id.clock, this.len)
item.markDeleted()
}
@@ -80,11 +77,11 @@ export class ContentDeleted {
*/
gc (store) {}
/**
* @param {encoding.Encoder} encoder
* @param {AbstractUpdateEncoder} encoder
* @param {number} offset
*/
write (encoder, offset) {
encoding.writeVarUint(encoder, this.len - offset)
encoder.writeLen(this.len - offset)
}
/**
@@ -98,7 +95,7 @@ export class ContentDeleted {
/**
* @private
*
* @param {decoding.Decoder} decoder
* @param {AbstractUpdateDecoder} decoder
* @return {ContentDeleted}
*/
export const readContentDeleted = decoder => new ContentDeleted(decoding.readVarUint(decoder))
export const readContentDeleted = decoder => new ContentDeleted(decoder.readLen())

View File

@@ -1,10 +1,8 @@
import {
StructStore, Item, Transaction // eslint-disable-line
AbstractUpdateDecoder, AbstractUpdateEncoder, StructStore, Item, Transaction // eslint-disable-line
} from '../internals.js'
import * as encoding from 'lib0/encoding.js'
import * as decoding from 'lib0/decoding.js'
import * as error from 'lib0/error.js'
/**
@@ -76,11 +74,11 @@ export class ContentEmbed {
*/
gc (store) {}
/**
* @param {encoding.Encoder} encoder
* @param {AbstractUpdateEncoder} encoder
* @param {number} offset
*/
write (encoder, offset) {
encoding.writeVarString(encoder, JSON.stringify(this.embed))
encoder.writeJSON(this.embed)
}
/**
@@ -94,7 +92,7 @@ export class ContentEmbed {
/**
* @private
*
* @param {decoding.Decoder} decoder
* @param {AbstractUpdateDecoder} decoder
* @return {ContentEmbed}
*/
export const readContentEmbed = decoder => new ContentEmbed(JSON.parse(decoding.readVarString(decoder)))
export const readContentEmbed = decoder => new ContentEmbed(decoder.readJSON())

View File

@@ -1,10 +1,8 @@
import {
Item, StructStore, Transaction // eslint-disable-line
AbstractUpdateDecoder, AbstractUpdateEncoder, Item, StructStore, Transaction // eslint-disable-line
} from '../internals.js'
import * as encoding from 'lib0/encoding.js'
import * as decoding from 'lib0/decoding.js'
import * as error from 'lib0/error.js'
/**
@@ -78,12 +76,12 @@ export class ContentFormat {
*/
gc (store) {}
/**
* @param {encoding.Encoder} encoder
* @param {AbstractUpdateEncoder} encoder
* @param {number} offset
*/
write (encoder, offset) {
encoding.writeVarString(encoder, this.key)
encoding.writeVarString(encoder, JSON.stringify(this.value))
encoder.writeKey(this.key)
encoder.writeJSON(this.value)
}
/**
@@ -95,7 +93,7 @@ export class ContentFormat {
}
/**
* @param {decoding.Decoder} decoder
* @param {AbstractUpdateDecoder} decoder
* @return {ContentFormat}
*/
export const readContentFormat = decoder => new ContentFormat(decoding.readVarString(decoder), JSON.parse(decoding.readVarString(decoder)))
export const readContentFormat = decoder => new ContentFormat(decoder.readString(), decoder.readJSON())

View File

@@ -1,10 +1,7 @@
import {
Transaction, Item, StructStore // eslint-disable-line
AbstractUpdateDecoder, AbstractUpdateEncoder, Transaction, Item, StructStore // eslint-disable-line
} from '../internals.js'
import * as encoding from 'lib0/encoding.js'
import * as decoding from 'lib0/decoding.js'
/**
* @private
*/
@@ -80,15 +77,15 @@ export class ContentJSON {
*/
gc (store) {}
/**
* @param {encoding.Encoder} encoder
* @param {AbstractUpdateEncoder} encoder
* @param {number} offset
*/
write (encoder, offset) {
const len = this.arr.length
encoding.writeVarUint(encoder, len - offset)
encoder.writeLen(len - offset)
for (let i = offset; i < len; i++) {
const c = this.arr[i]
encoding.writeVarString(encoder, c === undefined ? 'undefined' : JSON.stringify(c))
encoder.writeString(c === undefined ? 'undefined' : JSON.stringify(c))
}
}
@@ -103,14 +100,14 @@ export class ContentJSON {
/**
* @private
*
* @param {decoding.Decoder} decoder
* @param {AbstractUpdateDecoder} decoder
* @return {ContentJSON}
*/
export const readContentJSON = decoder => {
const len = decoding.readVarUint(decoder)
const len = decoder.readLen()
const cs = []
for (let i = 0; i < len; i++) {
const c = decoding.readVarString(decoder)
const c = decoder.readString()
if (c === 'undefined') {
cs.push(undefined)
} else {

View File

@@ -1,10 +1,7 @@
import {
Transaction, Item, StructStore // eslint-disable-line
AbstractUpdateDecoder, AbstractUpdateEncoder, Transaction, Item, StructStore // eslint-disable-line
} from '../internals.js'
import * as encoding from 'lib0/encoding.js'
import * as decoding from 'lib0/decoding.js'
/**
* @private
*/
@@ -80,11 +77,11 @@ export class ContentString {
*/
gc (store) {}
/**
* @param {encoding.Encoder} encoder
* @param {AbstractUpdateEncoder} encoder
* @param {number} offset
*/
write (encoder, offset) {
encoding.writeVarString(encoder, offset === 0 ? this.str : this.str.slice(offset))
encoder.writeString(offset === 0 ? this.str : this.str.slice(offset))
}
/**
@@ -98,7 +95,7 @@ export class ContentString {
/**
* @private
*
* @param {decoding.Decoder} decoder
* @param {AbstractUpdateDecoder} decoder
* @return {ContentString}
*/
export const readContentString = decoder => new ContentString(decoding.readVarString(decoder))
export const readContentString = decoder => new ContentString(decoder.readString())

View File

@@ -7,15 +7,13 @@ import {
readYXmlFragment,
readYXmlHook,
readYXmlText,
ID, StructStore, Transaction, Item, YEvent, AbstractType // eslint-disable-line
AbstractUpdateDecoder, AbstractUpdateEncoder, StructStore, Transaction, Item, YEvent, AbstractType // eslint-disable-line
} from '../internals.js'
import * as encoding from 'lib0/encoding.js' // eslint-disable-line
import * as decoding from 'lib0/decoding.js'
import * as error from 'lib0/error.js'
/**
* @type {Array<function(decoding.Decoder):AbstractType<any>>}
* @type {Array<function(AbstractUpdateDecoder):AbstractType<any>>}
* @private
*/
export const typeRefs = [
@@ -150,7 +148,7 @@ export class ContentType {
}
/**
* @param {encoding.Encoder} encoder
* @param {AbstractUpdateEncoder} encoder
* @param {number} offset
*/
write (encoder, offset) {
@@ -168,7 +166,7 @@ export class ContentType {
/**
* @private
*
* @param {decoding.Decoder} decoder
* @param {AbstractUpdateDecoder} decoder
* @return {ContentType}
*/
export const readContentType = decoder => new ContentType(typeRefs[decoding.readVarUint(decoder)](decoder))
export const readContentType = decoder => new ContentType(typeRefs[decoder.readTypeRef()](decoder))

View File

@@ -2,11 +2,9 @@
import {
AbstractStruct,
addStruct,
StructStore, Transaction, ID // eslint-disable-line
AbstractUpdateEncoder, StructStore, Transaction, ID // eslint-disable-line
} from '../internals.js'
import * as encoding from 'lib0/encoding.js'
export const structGCRefNumber = 0
/**
@@ -41,12 +39,12 @@ export class GC extends AbstractStruct {
}
/**
* @param {encoding.Encoder} encoder
* @param {AbstractUpdateEncoder} encoder
* @param {number} offset
*/
write (encoder, offset) {
encoding.writeUint8(encoder, structGCRefNumber)
encoding.writeVarUint(encoder, this.length - offset)
encoder.writeInfo(structGCRefNumber)
encoder.writeLen(this.length - offset)
}
/**

View File

@@ -1,7 +1,5 @@
import {
readID,
writeID,
GC,
getState,
AbstractStruct,
@@ -23,12 +21,10 @@ import {
readContentFormat,
readContentType,
addChangedTypeToTransaction,
Doc, ContentType, ContentDeleted, StructStore, ID, AbstractType, Transaction // eslint-disable-line
AbstractUpdateDecoder, AbstractUpdateEncoder, ContentType, ContentDeleted, StructStore, ID, AbstractType, Transaction // eslint-disable-line
} from '../internals.js'
import * as error from 'lib0/error.js'
import * as encoding from 'lib0/encoding.js'
import * as decoding from 'lib0/decoding.js'
import * as maplib from 'lib0/map.js'
import * as set from 'lib0/set.js'
import * as binary from 'lib0/binary.js'
@@ -574,7 +570,7 @@ export class Item extends AbstractStruct {
parent._length -= this.length
}
this.markDeleted()
addToDeleteSet(transaction.deleteSet, this.id, this.length)
addToDeleteSet(transaction.deleteSet, this.id.client, this.id.clock, this.length)
maplib.setIfUndefined(transaction.changed, parent, set.create).add(this.parentSub)
this.content.delete(transaction)
}
@@ -602,7 +598,7 @@ export class Item extends AbstractStruct {
*
* This is called when this Item is sent to a remote peer.
*
* @param {encoding.Encoder} encoder The encoder to write data to.
* @param {AbstractUpdateEncoder} encoder The encoder to write data to.
* @param {number} offset
*/
write (encoder, offset) {
@@ -613,12 +609,12 @@ export class Item extends AbstractStruct {
(origin === null ? 0 : binary.BIT8) | // origin is defined
(rightOrigin === null ? 0 : binary.BIT7) | // right origin is defined
(parentSub === null ? 0 : binary.BIT6) // parentSub is non-null
encoding.writeUint8(encoder, info)
encoder.writeInfo(info)
if (origin !== null) {
writeID(encoder, origin)
encoder.writeLeftID(origin)
}
if (rightOrigin !== null) {
writeID(encoder, rightOrigin)
encoder.writeRightID(rightOrigin)
}
if (origin === null && rightOrigin === null) {
const parent = /** @type {AbstractType<any>} */ (this.parent)
@@ -627,14 +623,14 @@ export class Item extends AbstractStruct {
// parent type on y._map
// find the correct key
const ykey = findRootTypeKey(parent)
encoding.writeVarUint(encoder, 1) // write parentYKey
encoding.writeVarString(encoder, ykey)
encoder.writeParentInfo(true) // write parentYKey
encoder.writeString(ykey)
} else {
encoding.writeVarUint(encoder, 0) // write parent id
writeID(encoder, parentItem.id)
encoder.writeParentInfo(false) // write parent id
encoder.writeLeftID(parentItem.id)
}
if (parentSub !== null) {
encoding.writeVarString(encoder, parentSub)
encoder.writeString(parentSub)
}
}
this.content.write(encoder, offset)
@@ -642,15 +638,15 @@ export class Item extends AbstractStruct {
}
/**
* @param {decoding.Decoder} decoder
* @param {AbstractUpdateDecoder} decoder
* @param {number} info
*/
const readItemContent = (decoder, info) => contentRefs[info & binary.BITS5](decoder)
export const readItemContent = (decoder, info) => contentRefs[info & binary.BITS5](decoder)
/**
* A lookup map for reading Item content.
*
* @type {Array<function(decoding.Decoder):AbstractContent>}
* @type {Array<function(AbstractUpdateDecoder):AbstractContent>}
*/
export const contentRefs = [
() => { throw error.unexpectedCase() }, // GC is not ItemContent
@@ -741,7 +737,7 @@ export class AbstractContent {
}
/**
* @param {encoding.Encoder} encoder
* @param {AbstractUpdateEncoder} encoder
* @param {number} offset
*/
write (encoder, offset) {
@@ -755,38 +751,3 @@ export class AbstractContent {
throw error.methodUnimplemented()
}
}
/**
* @param {decoding.Decoder} decoder
* @param {ID} id
* @param {number} info
* @param {Doc} doc
*/
export const readItem = (decoder, id, info, doc) => {
/**
* The item that was originally to the left of this item.
* @type {ID | null}
*/
const origin = (info & binary.BIT8) === binary.BIT8 ? readID(decoder) : null
/**
* The item that was originally to the right of this item.
* @type {ID | null}
*/
const rightOrigin = (info & binary.BIT7) === binary.BIT7 ? readID(decoder) : null
const canCopyParentInfo = (info & (binary.BIT7 | binary.BIT8)) === 0
const hasParentYKey = canCopyParentInfo ? decoding.readVarUint(decoder) === 1 : false
/**
* If parent = null and neither left nor right are defined, then we know that `parent` is child of `y`
* and we read the next string as parentYKey.
* It indicates how we store/retrieve parent from `y.share`
* @type {string|null}
*/
const parentYKey = canCopyParentInfo && hasParentYKey ? decoding.readVarString(decoder) : null
return new Item(
id, null, origin, null, rightOrigin,
canCopyParentInfo && !hasParentYKey ? readID(decoder) : (parentYKey ? doc.get(parentYKey) : null), // parent
canCopyParentInfo && (info & binary.BIT6) === binary.BIT6 ? decoding.readVarString(decoder) : null, // parentSub
/** @type {AbstractContent} */ (readItemContent(decoder, info)) // item content
)
}