query method
Query: returns IDs + data for docs matching ALL tags.
Implementation
Future<Map<String, Uint8List>> query(
String collection,
List<int> tagHashes, {
int limit = 0,
}) async {
final collBytes = utf8.encode(collection);
// [req_id:4][op:1][coll_len:2][coll][tag_count:1][tags: NĂ—8B][limit:4]
final size = 4 + 1 + 2 + collBytes.length + 1 + tagHashes.length * 8 + 4;
final frame = ByteData(size);
final view = frame.buffer.asUint8List();
var pos = 0;
pos += 4;
frame.setUint8(pos, opQuery);
pos += 1;
frame.setUint16(pos, collBytes.length, Endian.little);
pos += 2;
view.setRange(pos, pos + collBytes.length, collBytes);
pos += collBytes.length;
frame.setUint8(pos, tagHashes.length);
pos += 1;
for (final th in tagHashes) {
frame.setUint64(pos, th, Endian.little);
pos += 8;
}
frame.setUint32(pos, limit, Endian.little);
final completer = Completer<WsResult>();
_pipelineQueue.add(_PendingOp(view, completer));
_scheduleFlush();
final resp = await completer.future.timeout(
const Duration(seconds: 60),
onTimeout: () => throw TimeoutException('QUERY timeout'),
);
if (resp.isDenied)
throw WsDeniedException('QUERY: ${utf8.decode(resp.data)}');
if (resp.isError) throw WsException('QUERY: ${utf8.decode(resp.data)}');
final results = <String, Uint8List>{};
if (resp.data.length < 4) return results;
final bd = ByteData.sublistView(resp.data);
final count = bd.getUint32(0, Endian.little);
var rpos = 4;
for (var i = 0; i < count; i++) {
if (rpos + 2 > resp.data.length) break;
final klen = bd.getUint16(rpos, Endian.little);
rpos += 2;
if (rpos + klen > resp.data.length) break;
final key = utf8.decode(resp.data.sublist(rpos, rpos + klen));
rpos += klen;
if (rpos + 4 > resp.data.length) break;
final dlen = bd.getUint32(rpos, Endian.little);
rpos += 4;
if (rpos + dlen > resp.data.length) break;
results[key] = resp.data.sublist(rpos, rpos + dlen);
rpos += dlen;
}
return results;
}