Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions hive/lib/src/box/box.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,27 @@ abstract class Box<E> implements BoxBase<E> {
/// exist.
E? get(dynamic key, {E? defaultValue});

/// Read the given [key] and cast the value to [List<T>]
List<T>? getList<T>(dynamic key, {List<T>? defaultValue});

/// Read the given [key] and cast the value to [Set<T>]
Set<T>? getSet<T>(dynamic key, {Set<T>? defaultValue});

/// Read the given [key] and cast the value to [Map<K, V>]
Map<K, V>? getMap<K, V>(dynamic key, {Map<K, V>? defaultValue});

/// Returns the value associated with the n-th key.
E? getAt(int index);

/// Read the value at the given [index] and cast the value to [List<T>]
List<T>? getListAt<T>(int index, {List<T>? defaultValue});

/// Read the value at the given [index] and cast the value to [Set<T>]
Set<T>? getSetAt<T>(int index, {Set<T>? defaultValue});

/// Read the value at the given [index] and cast the value to [Map<K, V>]
Map<K, V>? getMapAt<K, V>(int index, {Map<K, V>? defaultValue});

/// Returns a map which contains all key - value pairs of the box.
Map<dynamic, E> toMap();
}
25 changes: 25 additions & 0 deletions hive/lib/src/box/box_impl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:hive_ce/hive.dart';
import 'package:hive_ce/src/binary/frame.dart';
import 'package:hive_ce/src/box/box_base_impl.dart';
import 'package:hive_ce/src/object/hive_object.dart';
import 'package:hive_ce/src/util/type_utils.dart';

/// Not part of public API
class BoxImpl<E> extends BoxBaseImpl<E> implements Box<E> {
Expand Down Expand Up @@ -49,13 +50,37 @@ class BoxImpl<E> extends BoxBaseImpl<E> implements Box<E> {
}
}

@override
List<T>? getList<T>(dynamic key, {List<T>? defaultValue}) =>
castList(get(key), defaultValue: defaultValue);

@override
Set<T>? getSet<T>(dynamic key, {Set<T>? defaultValue}) =>
castSet(get(key), defaultValue: defaultValue);

@override
Map<K, V>? getMap<K, V>(dynamic key, {Map<K, V>? defaultValue}) =>
castMap(get(key), defaultValue: defaultValue);

@override
E? getAt(int index) {
checkOpen();

return keystore.getAt(index)?.value as E?;
}

@override
List<T>? getListAt<T>(int index, {List<T>? defaultValue}) =>
castList(getAt(index), defaultValue: defaultValue);

@override
Set<T>? getSetAt<T>(int index, {Set<T>? defaultValue}) =>
castSet(getAt(index), defaultValue: defaultValue);

@override
Map<K, V>? getMapAt<K, V>(int index, {Map<K, V>? defaultValue}) =>
castMap(getAt(index), defaultValue: defaultValue);

@override
Future<void> putAll(Map<dynamic, E> kvPairs) {
final frames = <Frame>[];
Expand Down
18 changes: 18 additions & 0 deletions hive/lib/src/box/lazy_box.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,24 @@ abstract class LazyBox<E> extends BoxBase<E> {
/// exist.
Future<E?> get(dynamic key, {E? defaultValue});

/// Read the given [key] and cast the value to [List<T>]
Future<List<T>?> getList<T>(dynamic key, {List<T>? defaultValue});

/// Read the given [key] and cast the value to [Set<T>]
Future<Set<T>?> getSet<T>(dynamic key, {Set<T>? defaultValue});

/// Read the given [key] and cast the value to [Map<K, V>]
Future<Map<K, V>?> getMap<K, V>(dynamic key, {Map<K, V>? defaultValue});

/// Returns the value associated with the n-th key.
Future<E?> getAt(int index);

/// Read the value at the given [index] and cast the value to [List<T>]
Future<List<T>?> getListAt<T>(int index, {List<T>? defaultValue});

/// Read the value at the given [index] and cast the value to [Set<T>]
Future<Set<T>?> getSetAt<T>(int index, {Set<T>? defaultValue});

/// Read the value at the given [index] and cast the value to [Map<K, V>]
Future<Map<K, V>?> getMapAt<K, V>(int index, {Map<K, V>? defaultValue});
}
31 changes: 31 additions & 0 deletions hive/lib/src/box/lazy_box_impl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:hive_ce/hive.dart';
import 'package:hive_ce/src/binary/frame.dart';
import 'package:hive_ce/src/box/box_base_impl.dart';
import 'package:hive_ce/src/object/hive_object.dart';
import 'package:hive_ce/src/util/type_utils.dart';

/// Not part of public API
class LazyBoxImpl<E> extends BoxBaseImpl<E> implements LazyBox<E> {
Expand Down Expand Up @@ -38,11 +39,41 @@ class LazyBoxImpl<E> extends BoxBaseImpl<E> implements LazyBox<E> {
}
}

@override
Future<List<T>?> getList<T>(dynamic key, {List<T>? defaultValue}) async =>
castList(await get(key), defaultValue: defaultValue);

@override
Future<Set<T>?> getSet<T>(dynamic key, {Set<T>? defaultValue}) async =>
castSet(await get(key), defaultValue: defaultValue);

@override
Future<Map<K, V>?> getMap<K, V>(
dynamic key, {
Map<K, V>? defaultValue,
}) async =>
castMap(await get(key), defaultValue: defaultValue);

@override
Future<E?> getAt(int index) {
return get(keystore.keyAt(index));
}

@override
Future<List<T>?> getListAt<T>(int index, {List<T>? defaultValue}) async =>
castList(await getAt(index), defaultValue: defaultValue);

@override
Future<Set<T>?> getSetAt<T>(int index, {Set<T>? defaultValue}) async =>
castSet(await getAt(index), defaultValue: defaultValue);

@override
Future<Map<K, V>?> getMapAt<K, V>(
int index, {
Map<K, V>? defaultValue,
}) async =>
castMap(await getAt(index), defaultValue: defaultValue);

@override
Future<void> putAll(Map<dynamic, dynamic> kvPairs) async {
checkOpen();
Expand Down
18 changes: 18 additions & 0 deletions hive/lib/src/isolate/isolated_box.dart
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,26 @@ abstract class IsolatedBoxBase<E> {
/// Get a value from the box
Future<E?> get(dynamic key, {E? defaultValue});

/// Get a value from the box and cast the value to [List<T>]
Future<List<T>?> getList<T>(dynamic key, {List<T>? defaultValue});

/// Get a value from the box and cast the value to [Set<T>]
Future<Set<T>?> getSet<T>(dynamic key, {Set<T>? defaultValue});

/// Get a value from the box and cast the value to [Map<K, V>]
Future<Map<K, V>?> getMap<K, V>(dynamic key, {Map<K, V>? defaultValue});

/// Get a value at the given index
Future<E?> getAt(int index);

/// Get a value at the given index and cast the value to [List<T>]
Future<List<T>?> getListAt<T>(int index, {List<T>? defaultValue});

/// Get a value at the given index and cast the value to [Set<T>]
Future<Set<T>?> getSetAt<T>(int index, {Set<T>? defaultValue});

/// Get a value at the given index and cast the value to [Map<K, V>]
Future<Map<K, V>?> getMapAt<K, V>(int index, {Map<K, V>? defaultValue});
}

/// Isolated version of [Box]
Expand Down
31 changes: 31 additions & 0 deletions hive/lib/src/isolate/isolated_box_impl/isolated_box_impl_vm.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:hive_ce/hive.dart';
import 'package:hive_ce/src/binary/binary_reader_impl.dart';
import 'package:hive_ce/src/binary/binary_writer_impl.dart';
import 'package:hive_ce/src/isolate/isolated_hive_impl/impl/isolated_hive_impl_vm.dart';
import 'package:hive_ce/src/util/type_utils.dart';
import 'package:isolate_channel/isolate_channel.dart';

/// Isolated implementation of [BoxBase]
Expand Down Expand Up @@ -154,13 +155,43 @@ abstract class IsolatedBoxBaseImpl<E> implements IsolatedBoxBase<E> {
return _readValue(result);
}

@override
Future<List<T>?> getList<T>(dynamic key, {List<T>? defaultValue}) async =>
castList(await get(key), defaultValue: defaultValue);

@override
Future<Set<T>?> getSet<T>(dynamic key, {Set<T>? defaultValue}) async =>
castSet(await get(key), defaultValue: defaultValue);

@override
Future<Map<K, V>?> getMap<K, V>(
dynamic key, {
Map<K, V>? defaultValue,
}) async =>
castMap(await get(key), defaultValue: defaultValue);

@override
Future<E?> getAt(int index) async {
final bytes =
await _channel.invokeMethod('getAt', {'name': name, 'index': index});
return _readValue(bytes);
}

@override
Future<List<T>?> getListAt<T>(int index, {List<T>? defaultValue}) async =>
castList(await getAt(index), defaultValue: defaultValue);

@override
Future<Set<T>?> getSetAt<T>(int index, {Set<T>? defaultValue}) async =>
castSet(await getAt(index), defaultValue: defaultValue);

@override
Future<Map<K, V>?> getMapAt<K, V>(
int index, {
Map<K, V>? defaultValue,
}) async =>
castMap(await getAt(index), defaultValue: defaultValue);

Uint8List _writeValue(E value) {
final writer = BinaryWriterImpl(_hive);
if (_cipher != null) {
Expand Down
31 changes: 31 additions & 0 deletions hive/lib/src/isolate/isolated_box_impl/isolated_box_impl_web.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:async';

import 'package:hive_ce/hive.dart';
import 'package:hive_ce/src/util/type_utils.dart';
import 'package:meta/meta.dart';

/// Web implementation of [IsolatedBoxBase]
Expand Down Expand Up @@ -93,6 +94,21 @@ abstract class IsolatedBoxBaseImpl<E> implements IsolatedBoxBase<E> {
}
}

@override
Future<List<T>?> getList<T>(dynamic key, {List<T>? defaultValue}) async =>
castList(await get(key), defaultValue: defaultValue);

@override
Future<Set<T>?> getSet<T>(dynamic key, {Set<T>? defaultValue}) async =>
castSet(await get(key), defaultValue: defaultValue);

@override
Future<Map<K, V>?> getMap<K, V>(
dynamic key, {
Map<K, V>? defaultValue,
}) async =>
castMap(await get(key), defaultValue: defaultValue);

@override
Future<E?> getAt(int index) async {
if (lazy) {
Expand All @@ -102,6 +118,21 @@ abstract class IsolatedBoxBaseImpl<E> implements IsolatedBoxBase<E> {
}
}

@override
Future<List<T>?> getListAt<T>(int index, {List<T>? defaultValue}) async =>
castList(await getAt(index), defaultValue: defaultValue);

@override
Future<Set<T>?> getSetAt<T>(int index, {Set<T>? defaultValue}) async =>
castSet(await getAt(index), defaultValue: defaultValue);

@override
Future<Map<K, V>?> getMapAt<K, V>(
int index, {
Map<K, V>? defaultValue,
}) async =>
castMap(await getAt(index), defaultValue: defaultValue);

@override
bool operator ==(Object other) {
return other is IsolatedBoxBaseImpl && other._box == _box;
Expand Down
32 changes: 30 additions & 2 deletions hive/lib/src/util/type_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,40 @@ void typedMapOrIterableCheck<E>() {
final type = E.toString();
if (type.startsWith('Map<') && type != 'Map<dynamic, dynamic>') {
throw AssertionError(
'Cannot open a box of type $type. It is not possible to read typed Maps. Use Map.cast<RK, RV>() after reading.',
'Cannot open a box of type $type. Instead open a `Box<Map>` and call `getMap<K, V>()`.',
);
} else if ({'Iterable<', 'List<', 'Set<'}.any(type.startsWith) &&
!_allowedIterableTypes.any(type.endsWith)) {
final iterableType = type.substring(0, type.indexOf('<'));
throw AssertionError(
'Cannot open a box of type $type. It is not possible to read Iterables of custom types. Use Iterable.cast<R>() after reading.',
'Cannot open a box of type $type. Instead open a `Box<$iterableType>` and call `get$iterableType<T>()`.',
);
}
}

/// Common logic for casting a typed list
List<T>? castList<T>(Object? value, {List<T>? defaultValue}) {
if (value != null) {
return (value as List).cast<T>();
} else {
return defaultValue;
}
}

/// Common logic for casting a typed set
Set<T>? castSet<T>(Object? value, {Set<T>? defaultValue}) {
if (value != null) {
return (value as Set).cast<T>();
} else {
return defaultValue;
}
}

/// Common logic for casting a typed map
Map<K, V>? castMap<K, V>(Object? value, {Map<K, V>? defaultValue}) {
if (value != null) {
return (value as Map).cast<K, V>();
} else {
return defaultValue;
}
}
56 changes: 56 additions & 0 deletions hive/test/tests/box/box_impl_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,62 @@ void main() {
expect(box.getAt(1), 'A');
});

group('Iterable and Map casting', () {
test('.getList()', () {
final keystore = Keystore.debug(frames: [
Frame(0, [1, 2, 3]),
]);
final box = _getBox(keystore: keystore);

expect(box.getList<num>(0), [1, 2, 3]);
});

test('.getSet()', () {
final keystore = Keystore.debug(frames: [
Frame(0, {1, 2, 3}),
]);
final box = _getBox(keystore: keystore);

expect(box.getSet<num>(0), {1, 2, 3});
});

test('.getMap()', () {
final keystore = Keystore.debug(frames: [
Frame(0, {'a': 1, 'b': 2, 'c': 3}),
]);
final box = _getBox(keystore: keystore);

expect(box.getMap<String, num>(0), {'a': 1, 'b': 2, 'c': 3});
});

test('.getListAt()', () {
final keystore = Keystore.debug(frames: [
Frame(0, [1, 2, 3]),
]);
final box = _getBox(keystore: keystore);

expect(box.getListAt<num>(0), [1, 2, 3]);
});

test('.getSetAt()', () {
final keystore = Keystore.debug(frames: [
Frame(0, {1, 2, 3}),
]);
final box = _getBox(keystore: keystore);

expect(box.getSetAt<num>(0), {1, 2, 3});
});

test('.getMapAt()', () {
final keystore = Keystore.debug(frames: [
Frame(0, {'a': 1, 'b': 2, 'c': 3}),
]);
final box = _getBox(keystore: keystore);

expect(box.getMapAt<String, num>(0), {'a': 1, 'b': 2, 'c': 3});
});
});

group('.putAll()', () {
test('values', () async {
final frames = <Frame>[
Expand Down
Loading
Loading