query method

Future<Map<String, Uint8List>> query(
  1. String collection,
  2. List<int> tagHashes, {
  3. int limit = 0,
})

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;
}