mirror of
https://gitlab.com/veilid/veilid.git
synced 2024-10-01 01:26:08 -04:00
add union/intersection for ValueSubkeyRange lists, and some tests
This commit is contained in:
parent
d244c1f6a5
commit
995a794ea3
@ -15,6 +15,10 @@ class ValueSubkeyRange with _$ValueSubkeyRange {
|
||||
|
||||
factory ValueSubkeyRange.single(int val) =>
|
||||
ValueSubkeyRange(low: val, high: val);
|
||||
factory ValueSubkeyRange.make(int low, int high) =>
|
||||
ValueSubkeyRange(low: low, high: high);
|
||||
factory ValueSubkeyRange.fromIntPair((int, int) pair) =>
|
||||
ValueSubkeyRange(low: pair.$1, high: pair.$2);
|
||||
|
||||
factory ValueSubkeyRange.fromJson(dynamic json) =>
|
||||
_$ValueSubkeyRangeFromJson(json as Map<String, dynamic>);
|
||||
@ -49,9 +53,20 @@ extension ValueSubkeyRangeExt on ValueSubkeyRange {
|
||||
return ValueSubkeyRange(
|
||||
low: max(low, other.low), high: min(high, other.high));
|
||||
}
|
||||
|
||||
ValueSubkeyRange? union(ValueSubkeyRange other) {
|
||||
if (high < (other.low - 1) || low > (other.high + 1)) {
|
||||
return null;
|
||||
}
|
||||
return ValueSubkeyRange(
|
||||
low: min(low, other.low), high: max(high, other.high));
|
||||
}
|
||||
}
|
||||
|
||||
extension ListValueSubkeyRangeExt on List<ValueSubkeyRange> {
|
||||
static List<ValueSubkeyRange> fromIntPairs(List<(int, int)> x) =>
|
||||
x.map(ValueSubkeyRange.fromIntPair).toList();
|
||||
|
||||
void validate() {
|
||||
int? lastHigh;
|
||||
for (final r in this) {
|
||||
@ -107,4 +122,32 @@ extension ListValueSubkeyRangeExt on List<ValueSubkeyRange> {
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
List<ValueSubkeyRange> unionSubkeys(List<ValueSubkeyRange> other) {
|
||||
final out = <ValueSubkeyRange>[];
|
||||
ValueSubkeyRange? current;
|
||||
for (var i = 0, j = 0; i < length || j < other.length;) {
|
||||
if (i == length) {
|
||||
current = other[j];
|
||||
j++;
|
||||
} else if (j == other.length) {
|
||||
current = this[i];
|
||||
i++;
|
||||
} else if (this[i].low < other[j].low) {
|
||||
current = this[i];
|
||||
i++;
|
||||
} else {
|
||||
current = other[j];
|
||||
j++;
|
||||
}
|
||||
|
||||
if (out.isNotEmpty && out.last.high >= (current.low - 1)) {
|
||||
out[out.length - 1] = ValueSubkeyRange(
|
||||
low: out.last.low, high: max(out.last.high, current.high));
|
||||
} else {
|
||||
out.add(current);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
69
veilid-flutter/test/test_value_subkey_range.dart
Normal file
69
veilid-flutter/test/test_value_subkey_range.dart
Normal file
@ -0,0 +1,69 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:veilid/value_subkey_range.dart';
|
||||
|
||||
void expectCommute<T>(T? Function(T, T) func, T a, T b, T? c) {
|
||||
expect(func(a, b), c);
|
||||
expect(func(b, a), c);
|
||||
}
|
||||
|
||||
ValueSubkeyRange? vsrUnion(ValueSubkeyRange a, ValueSubkeyRange b) =>
|
||||
a.union(b);
|
||||
|
||||
ValueSubkeyRange? vsrIntersect(ValueSubkeyRange a, ValueSubkeyRange b) =>
|
||||
a.intersect(b);
|
||||
|
||||
List<ValueSubkeyRange> lvsrUnion(
|
||||
List<ValueSubkeyRange> a, List<ValueSubkeyRange> b) =>
|
||||
a.unionSubkeys(b);
|
||||
|
||||
List<ValueSubkeyRange> lvsrIntersect(
|
||||
List<ValueSubkeyRange> a, List<ValueSubkeyRange> b) =>
|
||||
a.intersectSubkeys(b);
|
||||
|
||||
Future<void> testValueSubkeyRange() async {
|
||||
final a = ValueSubkeyRange.single(1);
|
||||
const b = ValueSubkeyRange(low: 2, high: 3);
|
||||
const c = ValueSubkeyRange(low: 3, high: 4);
|
||||
|
||||
expectCommute(vsrUnion, a, a, a);
|
||||
expectCommute(vsrUnion, a, b, const ValueSubkeyRange(low: 1, high: 3));
|
||||
expectCommute<ValueSubkeyRange>(vsrUnion, a, c, null);
|
||||
expectCommute(vsrUnion, b, c, const ValueSubkeyRange(low: 2, high: 4));
|
||||
|
||||
const d = ValueSubkeyRange(low: 0, high: 3);
|
||||
|
||||
expectCommute<ValueSubkeyRange>(vsrIntersect, a, b, null);
|
||||
expectCommute(vsrIntersect, c, d, ValueSubkeyRange.single(3));
|
||||
expectCommute(vsrIntersect, d, d, d);
|
||||
}
|
||||
|
||||
Future<void> testValueSubkeyRangeList() async {
|
||||
final a = [ValueSubkeyRange.single(1)];
|
||||
final b = [ValueSubkeyRange.fromIntPair((2, 3))];
|
||||
final c = [ValueSubkeyRange.make(3, 4)];
|
||||
|
||||
expectCommute(lvsrUnion, a, a, a);
|
||||
expectCommute(lvsrUnion, a, b, [const ValueSubkeyRange(low: 1, high: 3)]);
|
||||
expectCommute<List<ValueSubkeyRange>>(
|
||||
lvsrUnion, a, c, ListValueSubkeyRangeExt.fromIntPairs([(1, 1), (3, 4)]));
|
||||
expectCommute(lvsrUnion, b, c, [const ValueSubkeyRange(low: 2, high: 4)]);
|
||||
|
||||
const d = [ValueSubkeyRange(low: 0, high: 3)];
|
||||
|
||||
expectCommute(lvsrIntersect, a, b, <ValueSubkeyRange>[]);
|
||||
expectCommute(lvsrIntersect, c, d, [ValueSubkeyRange.single(3)]);
|
||||
expectCommute(lvsrIntersect, d, d, d);
|
||||
|
||||
final e = ListValueSubkeyRangeExt.fromIntPairs([(1, 5), (10, 14), (16, 18)]);
|
||||
final f = ListValueSubkeyRangeExt.fromIntPairs([(2, 6), (8, 10), (12, 20)]);
|
||||
final g = ListValueSubkeyRangeExt.fromIntPairs([(1, 6), (8, 20)]);
|
||||
|
||||
expectCommute(lvsrUnion, e, f, g);
|
||||
|
||||
final h = ListValueSubkeyRangeExt.fromIntPairs(
|
||||
[(2, 5), (10, 10), (12, 14), (16, 18)]);
|
||||
expectCommute(lvsrIntersect, e, f, h);
|
||||
|
||||
expectCommute<List<ValueSubkeyRange>>(lvsrUnion, [], [], []);
|
||||
expectCommute<List<ValueSubkeyRange>>(lvsrIntersect, [], [], []);
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'test_encoding.dart';
|
||||
import 'test_value_subkey_range.dart';
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
@ -11,4 +12,7 @@ void main() {
|
||||
test('testEncodingKnownVectors', testEncodingKnownVectors);
|
||||
test('testEncodeDecodeGarbage', testEncodeDecodeGarbage);
|
||||
test('testEncodeDecodeGarbagePad', testEncodeDecodeGarbagePad);
|
||||
|
||||
test('testVSR', testValueSubkeyRange);
|
||||
test('test List<ValueSubkeyRange>', testValueSubkeyRangeList);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user