Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add default key support to HiveType adapters #724

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions hive/lib/src/adapters/ignored_type_adapter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ class IgnoredTypeAdapter<T> implements TypeAdapter<T?> {
@override
final int typeId;

@override
dynamic defaultKey(obj) {
return null;
}

@override
T? read(BinaryReader reader) => null;

Expand Down
5 changes: 4 additions & 1 deletion hive/lib/src/annotations/hive_field.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,8 @@ class HiveField {
/// ```
final dynamic defaultValue;

const HiveField(this.index, {this.defaultValue});
/// Whether use this field as the default key of this type
final bool isKey;

const HiveField(this.index, {this.defaultValue, this.isKey = false});
}
18 changes: 16 additions & 2 deletions hive/lib/src/box/box_base_impl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ abstract class BoxBaseImpl<E> implements BoxBase<E> {

@override
Future<int> add(E value) async {
var key = keystore.autoIncrement();
var key = _getDefaultKey(value);
await put(key, value);
return key;
}
Expand All @@ -117,7 +117,7 @@ abstract class BoxBaseImpl<E> implements BoxBase<E> {
Future<Iterable<int>> addAll(Iterable<E> values) async {
var entries = <int, E>{};
for (var value in values) {
entries[keystore.autoIncrement()] = value;
entries[_getDefaultKey(value)] = value;
}
await putAll(entries);
return entries.keys;
Expand Down Expand Up @@ -183,6 +183,20 @@ abstract class BoxBaseImpl<E> implements BoxBase<E> {

await backend.deleteFromDisk();
}

dynamic _getDefaultKey(E value) {
var resolved = hive.findAdapterForValue(value);
if (resolved == null) {
return keystore.autoIncrement();
}
var adapter = resolved.adapter;
var key = adapter.defaultKey(value);
if (key == null) {
return keystore.autoIncrement();
} else {
return key;
}
}
}

class _NullBoxBase<E> implements BoxBase<E> {
Expand Down
5 changes: 5 additions & 0 deletions hive/lib/src/registry/type_adapter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ abstract class TypeAdapter<T> {
/// Called for type registration
int get typeId;

// Is called when the value is adding to box without a specific key.
dynamic defaultKey(T obj) {
return null;
}

/// Is called when a value has to be decoded.
T read(BinaryReader reader);

Expand Down
3 changes: 2 additions & 1 deletion hive_generator/lib/src/builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ class AdapterField {
final String name;
final DartType type;
final DartObject? defaultValue;
final bool isKey;

AdapterField(this.index, this.name, this.type, this.defaultValue);
AdapterField(this.index, this.name, this.type, this.defaultValue, this.isKey);
}

abstract class Builder {
Expand Down
4 changes: 3 additions & 1 deletion hive_generator/lib/src/helper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ import 'package:source_gen/source_gen.dart';
final _hiveFieldChecker = const TypeChecker.fromRuntime(HiveField);

class HiveFieldInfo {
HiveFieldInfo(this.index, this.defaultValue);
HiveFieldInfo(this.index, this.defaultValue, this.isKey);

final int index;
final DartObject? defaultValue;
final bool isKey;
}

HiveFieldInfo? getHiveFieldAnn(Element element) {
Expand All @@ -19,6 +20,7 @@ HiveFieldInfo? getHiveFieldAnn(Element element) {
return HiveFieldInfo(
obj.getField('index')!.toIntValue()!,
obj.getField('defaultValue'),
obj.getField('isKey')!.toBoolValue()!,
);
}

Expand Down
24 changes: 24 additions & 0 deletions hive_generator/lib/src/type_adapter_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,17 @@ class TypeAdapterGenerator extends GeneratorForAnnotation<HiveType> {
? EnumBuilder(cls, getters)
: ClassBuilder(cls, getters, setters);

var defaultKey = getDefaultKey(getters);

return '''
class $adapterName extends TypeAdapter<${cls.name}> {
@override
final int typeId = $typeId;

@override
dynamic defaultKey(${cls.name} obj) =>
${defaultKey};

@override
${cls.name} read(BinaryReader reader) {
${builder.buildRead()}
Expand Down Expand Up @@ -111,6 +117,7 @@ class TypeAdapterGenerator extends GeneratorForAnnotation<HiveType> {
field.name,
field.type,
getterAnn.defaultValue,
getterAnn.isKey,
));
}
}
Expand All @@ -126,6 +133,7 @@ class TypeAdapterGenerator extends GeneratorForAnnotation<HiveType> {
field.name,
field.type,
setterAnn.defaultValue,
false,
));
}
}
Expand All @@ -151,6 +159,22 @@ class TypeAdapterGenerator extends GeneratorForAnnotation<HiveType> {
}
}

String getDefaultKey(List<AdapterField> fields) {
String defaultKey = "null";
int keysCount = 0;
for (var field in fields) {
if (field.isKey) {
keysCount++;
defaultKey = "obj." + field.name;
}
}
check(
keysCount <= 1,
'At most one field can have isKey=true',
);
return defaultKey;
}

String getAdapterName(String typeName, ConstantReader annotation) {
var annAdapterName = annotation.read('adapterName');
if (annAdapterName.isNull) {
Expand Down