queryRange method

Future<Map<String, Uint8List>> queryRange(
  1. String collection,
  2. int fieldHash,
  3. Uint8List min,
  4. Uint8List max,
  5. List<int> andTags, {
  6. int limit = 0,
})

Range query: returns docs where field is in min, max.

Implementation

Future<Map<String, Uint8List>> queryRange(
  String collection,
  int fieldHash,
  Uint8List min,
  Uint8List max,
  List<int> andTags, {
  int limit = 0,
}) async {
  final collBytes = utf8.encode(collection);
  // [req_id:4][op:1][coll_len:2][coll][field_hash:8][min_len:2][min][max_len:2][max][and_count:1][and_tags:NĂ—8B][limit:4]
  final size =
      4 + 1 + 2 + collBytes.length +
      8 + 2 + min.length + 2 + max.length +
      1 + andTags.length * 8 + 4;
  final frame = ByteData(size);
  final view = frame.buffer.asUint8List();
  var pos = 0;
  pos += 4; // req_id
  frame.setUint8(pos, opQueryRange);
  pos += 1;
  frame.setUint16(pos, collBytes.length, Endian.little);
  pos += 2;
  view.setRange(pos, pos + collBytes.length, collBytes);
  pos += collBytes.length;
  frame.setUint64(pos, fieldHash, Endian.little);
  pos += 8;
  frame.setUint16(pos, min.length, Endian.little);
  pos += 2;
  view.setRange(pos, pos + min.length, min);
  pos += min.length;
  frame.setUint16(pos, max.length, Endian.little);
  pos += 2;
  view.setRange(pos, pos + max.length, max);
  pos += max.length;
  frame.setUint8(pos, andTags.length);
  pos += 1;
  for (final th in andTags) {
    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_RANGE timeout'),
  );
  if (resp.isDenied) throw WsDeniedException('QUERY_RANGE: ${utf8.decode(resp.data)}');
  if (resp.isError) throw WsException('QUERY_RANGE: ${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;
}