Implement LazyArray.splice(), implement unshift/shift/push/pop in terms of splice...
[logjson.git] / LazyArray.mjs
1 import assert from 'assert'
2 import LazyValue from './LazyValue.mjs'
3
4 class LazyArray extends LazyValue {
5   constructor(transaction, ptr_len, array) {
6     super(transaction, ptr_len)
7     this.array = array || []
8     this.length = this.array.length
9   }
10
11   has(key) {
12     assert(typeof key === 'number')
13     return key >= 0 && key < this.length
14   }
15
16   async get(key, default_value) {
17     assert(typeof key === 'number')
18     if (key < 0 || key >= this.length) {
19       if (default_value === undefined)
20         return undefined
21       this.set(key, this.transaction.json_to_logjson(default_value))
22     }
23
24     let value = this.array[key]
25     if (value instanceof Array) {
26       value = await this.transaction.read(value)
27       this.array[key] = value
28     }
29     return value
30   }
31
32   set(key, value) {
33     assert(typeof key === 'number')
34     assert(
35       typeof value !== 'object' ||
36       value === null ||
37       (value instanceof LazyValue && value.transaction === this.transaction)
38     )
39     this.ptr_len = null // mark dirty
40     this.array[key] = value
41     this.length = this.array.length
42   }
43
44   delete(key) {
45     if (this.has(key)) {
46       this.ptr_len = null // mark dirty
47       delete this.array[key]
48     }
49   }
50
51   splice(i, j, ...args) {
52     if (j || args.length) {
53       this.ptr_len = null // mark dirty
54       this.array.splice(i, j, ...args)
55       this.length = this.array.length
56     }
57   }
58
59   unshift(value) {
60     this.splice(0, 0, value)
61   }
62
63   unshift_json(value) {
64     this.unshift(this.transaction.json_to_logjson(value))
65   }
66
67   async shift() {
68     if (this.length === 0)
69       return undefined
70     let value = await this.get(0)
71     await this.splice(0, 1)
72     return value
73   }
74
75   async shift_json() {
76     return /*await*/ logjson.logjson_to_json(await this.shift())
77   }
78
79   push(value) {
80     this.splice(this.length, 0, value)
81   }
82
83   push_json(value) {
84     this.push(this.transaction.json_to_logjson(value))
85   }
86
87   async pop() {
88     if (this.length === 0)
89       return undefined
90     let i = this.length - 1
91     let value = await this.get(i)
92     this.splice(i, 1)
93     return value
94   }
95
96   async pop_json() {
97     return /*await*/ logjson.logjson_to_json(await this.pop())
98   }
99
100   async commit() {
101     for (let i = 0; i < this.length; ++i) {
102       let value = this.array[i]
103       if (value instanceof LazyValue) {
104         if (await value.commit())
105           this.ptr_len = null // mark dirty
106         this.array[i] = value.ptr_len
107       }
108     }
109
110     if (this.ptr_len === null) {
111       this.ptr_len = await this.transaction.database.write(this.array)
112       return true
113     }
114     return false
115   }
116 }
117
118 export default LazyArray