-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathsegment.dart
278 lines (219 loc) · 10.3 KB
/
segment.dart
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
import 'dart:typed_data';
import 'package:capnp/capnp.dart';
import 'package:capnp/rpc/capnp_rpc.dart';
import 'constants.dart';
import 'message.dart';
import 'objects/list.dart';
import 'objects/struct.dart';
import 'pointer.dart';
class Segment {
Segment(this.message, this.data) : assert(data.lengthInBytes % CapnpConstants.bytesPerWord == 0);
CapnpMessage message;
ByteData data;
int get lengthInBytes => data.lengthInBytes;
SegmentView fullView() => SegmentView._(this, 0, lengthInBytes ~/ 8);
SegmentView view(int offsetInWords, int lengthInWords) => SegmentView._(this, offsetInWords, lengthInWords);
}
class SegmentView {
SegmentView._(this.segment, this.offsetInWords, this.lengthInWords)
: assert(offsetInWords >= 0),
assert(lengthInWords >= 0),
assert((offsetInWords + lengthInWords) * CapnpConstants.bytesPerWord <= segment.lengthInBytes),
data = segment.data.buffer.asByteData(
segment.data.offsetInBytes + offsetInWords * CapnpConstants.bytesPerWord,
lengthInWords * CapnpConstants.bytesPerWord,
);
final Segment segment;
final ByteData data;
final int offsetInWords;
int get offsetInBytes => offsetInWords * CapnpConstants.bytesPerWord;
int get totalOffsetInBytes => segment.data.offsetInBytes + offsetInBytes;
final int lengthInWords;
int get lengthInBytes => lengthInWords * CapnpConstants.bytesPerWord;
SegmentView subview(int offsetInWords, int lengthInWords) {
assert(offsetInWords >= 0);
assert(lengthInWords >= 0);
assert(offsetInWords + lengthInWords <= this.lengthInWords);
return SegmentView._(
segment,
this.offsetInWords + offsetInWords,
lengthInWords,
);
}
SegmentView viewRelativeToEnd(int offsetInWords, int lengthInWords) {
assert(offsetInWords >= 0);
assert(lengthInWords >= 0);
return SegmentView._(
segment,
this.offsetInWords + offsetInWords + this.lengthInWords,
lengthInWords,
);
}
// Primitives:
NullableVoid getVoid(int offsetInBytes) => NullableVoid();
void setVoid(int offsetInBytes, NullableVoid value) {}
bool getBool(int offsetInBits, {bool defaultValue = false}) {
final byte = data.getUint8(offsetInBits ~/ CapnpConstants.bitsPerByte);
final bitIndex = offsetInBits % CapnpConstants.bitsPerByte;
final bit = (byte >> bitIndex) & 1;
return bit == 1;
}
void setBool(int offsetInBits, bool value, {bool defaultValue = false}) {
value ^= defaultValue;
int valueAsInt = value ? 1 : 0;
int byteOffset = offsetInBits ~/ CapnpConstants.bitsPerByte;
int byte = data.getUint8(byteOffset);
final bitIndex = offsetInBits % CapnpConstants.bitsPerByte;
byte |= (valueAsInt << bitIndex);
data.setUint8(byteOffset, byte);
}
int getUInt8(int offsetInBytes, {int defaultValue = 0}) => data.getUint8(offsetInBytes) ^ defaultValue;
int getUInt16(int offsetInBytes, {int defaultValue = 0}) =>
data.getUint16(offsetInBytes, Endian.little) ^ defaultValue;
int getUInt32(int offsetInBytes, {int defaultValue = 0}) =>
data.getUint32(offsetInBytes, Endian.little) ^ defaultValue;
int getUInt64(int offsetInBytes, {int defaultValue = 0}) =>
data.getUint64(offsetInBytes, Endian.little) ^ defaultValue;
int getInt8(int offsetInBytes, {int defaultValue = 0}) => data.getInt8(offsetInBytes) ^ defaultValue;
int getInt16(int offsetInBytes, {int defaultValue = 0}) => data.getInt16(offsetInBytes, Endian.little) ^ defaultValue;
int getInt32(int offsetInBytes, {int defaultValue = 0}) => data.getInt32(offsetInBytes, Endian.little) ^ defaultValue;
int getInt64(int offsetInBytes, {int defaultValue = 0}) => data.getInt64(offsetInBytes, Endian.little) ^ defaultValue;
double getFloat32(int offsetInBytes, {int? defaultValue}) => data.getFloat32(offsetInBytes, Endian.little);
double getFloat64(int offsetInBytes, {int? defaultValue}) => data.getFloat64(offsetInBytes, Endian.little);
void setInt8(int offsetInBytes, int value, {int defaultValue = 0}) =>
data.setInt8(offsetInBytes, value ^ defaultValue);
void setInt16(int offsetInBytes, int value, {int defaultValue = 0}) =>
data.setInt16(offsetInBytes, value ^ defaultValue, Endian.little);
void setInt32(int offsetInBytes, int value, {int defaultValue = 0}) =>
data.setInt32(offsetInBytes, value ^ defaultValue, Endian.little);
void setInt64(int offsetInBytes, int value, {int defaultValue = 0}) =>
data.setInt64(offsetInBytes, value ^ defaultValue, Endian.little);
void setUInt8(int offsetInBytes, int value, {int defaultValue = 0}) =>
data.setUint8(offsetInBytes, value ^ defaultValue);
void setUInt16(int offsetInBytes, int value, {int defaultValue = 0}) =>
data.setUint16(offsetInBytes, value ^ defaultValue, Endian.little);
void setUInt32(int offsetInBytes, int value, {int defaultValue = 0}) =>
data.setUint32(offsetInBytes, value ^ defaultValue, Endian.little);
void setUInt64(int offsetInBytes, int value, {int defaultValue = 0}) =>
data.setUint64(offsetInBytes, value ^ defaultValue, Endian.little);
void setFloat32(int offsetInBytes, double value, {int defaultValue = 0}) =>
data.setFloat32(offsetInBytes, value, Endian.little);
void setFloat64(int offsetInBytes, double value, {int defaultValue = 0}) =>
data.setFloat64(offsetInBytes, value, Endian.little);
String getText(int offsetInWords) {
var view = subview(offsetInWords, 1);
final pointer = ListPointer.resolvedFromView(view);
return Text(pointer).value;
}
void setText(int offsetIntoView, String text) {
segment.message.newTextSegment(this, offsetIntoView, text);
}
UnmodifiableUint8ListView getData(int offsetInWords) {
final pointer = ListPointer.resolvedFromView(subview(offsetInWords, 1));
return CapnpUInt8List(pointer).value;
}
void setData(int offsetInWords, ByteBuffer data) {
throw UnimplementedError;
}
// Nested structs:
T getStruct<T>(int offsetInWords, StructFactory<T> factory) {
final pointer = StructPointer.resolvedFromView(subview(offsetInWords, 1));
return factory(pointer.structView, pointer.dataSectionLengthInWords);
}
T newStruct<T>(int offsetInWords, StructBuilderFactory<T> factory) {
return segment.message.newStructSegment(this, offsetInWords, factory);
}
void setStruct<T>(int offsetInWords, T reader) {
throw UnimplementedError;
}
// Enums:
T getEnum<T>(int offsetInBytes, List<T> values) {
return values[getUInt16(offsetInBytes)];
}
// Lists of primitives:
UnmodifiableBoolListView getBoolList(int offsetInWords) {
final pointer = ListPointer.resolvedFromView(subview(offsetInWords, 1));
return CapnpBoolList(pointer).value;
}
UnmodifiableUint8ListView getUInt8List(int offsetInWords) {
final pointer = ListPointer.resolvedFromView(subview(offsetInWords, 1));
return CapnpUInt8List(pointer).value;
}
UnmodifiableUint16ListView getUInt16List(int offsetInWords) {
final pointer = ListPointer.resolvedFromView(subview(offsetInWords, 1));
return CapnpUInt16List(pointer).value;
}
UnmodifiableUint32ListView getUInt32List(int offsetInWords) {
final pointer = ListPointer.resolvedFromView(subview(offsetInWords, 1));
return CapnpUInt32List(pointer).value;
}
UnmodifiableUint64ListView getUInt64List(int offsetInWords) {
final pointer = ListPointer.resolvedFromView(subview(offsetInWords, 1));
return CapnpUInt64List(pointer).value;
}
UnmodifiableInt8ListView getInt8List(int offsetInWords) {
final pointer = ListPointer.resolvedFromView(subview(offsetInWords, 1));
return CapnpInt8List(pointer).value;
}
UnmodifiableInt16ListView getInt16List(int offsetInWords) {
final pointer = ListPointer.resolvedFromView(subview(offsetInWords, 1));
return CapnpInt16List(pointer).value;
}
UnmodifiableInt32ListView getInt32List(int offsetInWords) {
final pointer = ListPointer.resolvedFromView(subview(offsetInWords, 1));
return CapnpInt32List(pointer).value;
}
UnmodifiableInt64ListView getInt64List(int offsetInWords) {
final pointer = ListPointer.resolvedFromView(subview(offsetInWords, 1));
return CapnpInt64List(pointer).value;
}
UnmodifiableFloat32ListView getFloat32List(int offsetInWords) {
final pointer = ListPointer.resolvedFromView(subview(offsetInWords, 1));
return CapnpFloat32List(pointer).value;
}
// Complex types:
UnmodifiableCompositeListView<T> getCompositeList<T>(
int offsetInWords,
StructFactory<T> factory,
) {
final pointer = CompositeListPointer.resolvedFromView(
subview(offsetInWords, 1),
factory,
);
return UnmodifiableCompositeListView(CompositeList.fromPointer(pointer));
}
CompositeList<T> newCompositeList<T>(int offsetIntoView, int numElements, StructBuilderFactory<T> factory) {
var built = factory();
ByteData data = ByteData(16 + built.layout.bytes() * numElements);
Segment segment = Segment(this.segment.message, data);
ListPointer.save(segment.fullView(), 0, 0, 7, built.layout.words() * numElements);
StructPointer.save(
segment.fullView(), 1, numElements, built.layout.dataSectionLengthInWords, built.layout.numPointers);
CompositeListPointer<T> ptr = CompositeListPointer.resolvedFromView(
segment.view(0, 2 + numElements * built.layout.words()),
(segmentView, dataSectionLengthInWords) => built.builder(segmentView));
CompositeList<T> list = CompositeList.fromPointer(ptr);
int newSegmentId = segment.message.addSegment(segment);
InterSegmentPointer.save(this, offsetIntoView, InterSegmentPointerType.Simple, 0, newSegmentId);
return list;
}
CapabilityPointer getCapabilityPointer(int offsetInWords) {
return CapabilityPointer.fromView(subview(offsetInWords, 1));
}
CapabilityList newCapabilityList(int offsetInWords, int len) {
throw UnimplementedError;
}
T getClient<T>(int offsetInWords, ClientFactory<T> factory) {
var ptr = CapabilityPointer.fromView(subview(offsetInWords, 1));
return factory(segment.message.network!.resolveCapability(ptr, segment.message.capTable!)!);
}
CapabilityList getCapabilityList(int offsetInWords) {
throw UnimplementedError;
}
Pointer getAnyPointer(int offsetInWords) {
return Pointer.resolveAnyPointer(subview(offsetInWords, 1));
}
AnyPointerBuilder setAnyPointer(int offsetInWords) {
return AnyPointerBuilder(subview(offsetInWords, 1));
}
}