-
-
Notifications
You must be signed in to change notification settings - Fork 11
/
StrNode.ts
126 lines (108 loc) · 3.06 KB
/
StrNode.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import {ITimestampStruct, tick} from '../../../json-crdt-patch/clock';
import {AbstractRga, Chunk} from '../rga/AbstractRga';
import {next} from 'sonic-forest/lib/util';
import type {JsonNode} from '..';
/**
* @ignore
* @category CRDT Node
*/
export class StrChunk implements Chunk<string> {
public readonly id: ITimestampStruct;
public span: number;
public del: boolean;
public data: string;
public len: number;
public p: StrChunk | undefined;
public l: StrChunk | undefined;
public r: StrChunk | undefined;
public p2: StrChunk | undefined;
public l2: StrChunk | undefined;
public r2: StrChunk | undefined;
public s: StrChunk | undefined;
constructor(id: ITimestampStruct, span: number, str: string) {
this.id = id;
this.span = span;
this.len = str ? span : 0;
this.del = !str;
this.p = undefined;
this.l = undefined;
this.r = undefined;
this.p2 = undefined;
this.l2 = undefined;
this.r2 = undefined;
this.s = undefined;
this.data = str;
}
public merge(str: string) {
this.data += str;
this.span = this.data.length;
}
public split(ticks: number): StrChunk {
if (!this.del) {
const chunk = new StrChunk(tick(this.id, ticks), this.span - ticks, this.data.slice(ticks));
this.data = this.data.slice(0, ticks);
this.span = ticks;
return chunk;
}
const chunk = new StrChunk(tick(this.id, ticks), this.span - ticks, '');
this.span = ticks;
return chunk;
}
public delete(): void {
this.del = true;
this.data = '';
}
public clone(): StrChunk {
const chunk = new StrChunk(this.id, this.span, this.data);
return chunk;
}
public view(): string {
return this.data;
}
}
/**
* Represents the `str` type in JSON CRDT. The `str` type is a RGA (Replicated
* Growable Array) of UTF-16 code units.
*
* @category CRDT Node
*/
export class StrNode<T extends string = string> extends AbstractRga<string> implements JsonNode<string> {
// ----------------------------------------------------------------- JsonNode
/** @ignore */
public children() {}
/** @ignore */
public child() {
return undefined;
}
/** @ignore */
public container(): JsonNode | undefined {
return undefined;
}
/** @ignore */
private _view: string = '';
public view(): T {
if (this._view) return this._view as T;
let str = '';
for (let chunk = this.first(); chunk; chunk = next(chunk))
// TODO: Check if this optimization improves performance: if (!chunk.del) str += chunk.data;
str += chunk.data;
return (this._view = str) as T;
}
/** @ignore */
public api: undefined | unknown = undefined;
public name(): string {
return 'str';
}
// -------------------------------------------------------------- AbstractRga
/** @ignore */
public createChunk(id: ITimestampStruct, str: string | undefined): StrChunk {
return new StrChunk(id, str ? str.length : 0, str || '');
}
/** @ignore */
protected onChange(): void {
this._view = '';
}
protected toStringName(): string {
return this.name();
}
}