Skip to content

Commit eea337e

Browse files
committed
nullsafety hints and minor refactorings
1 parent 7c77ca6 commit eea337e

23 files changed

+97
-145
lines changed

objectbox/lib/src/bindings/bindings.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ void initializeDartAPI() {
5858
if (_dartAPIinitialized == null) {
5959
final errCode = C.dartc_init_api(NativeApi.initializeApiDLData);
6060
_dartAPIinitialized = (OBX_SUCCESS == errCode);
61-
if (!_dartAPIinitialized) {
61+
if (!_dartAPIinitialized /*!*/) {
6262
_dartAPIinitException = latestNativeError(
6363
codeIfMissing: errCode,
6464
dartMsg: "Dart/Flutter SDK you're using is not compatible with "

objectbox/lib/src/bindings/flatbuffers.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ class BuilderWithCBuffer {
4545
typedef _dart_memset = void Function(Pointer<Uint8>, int, int);
4646
typedef _c_memset = Void Function(Pointer<Uint8>, Int32, IntPtr);
4747

48-
_dart_memset fbMemset;
48+
_dart_memset /*?*/ fbMemset;
4949

5050
class Allocator extends fb.Allocator {
5151
// We may, in practice, have only two active allocations: one used and one
@@ -76,7 +76,7 @@ class Allocator extends fb.Allocator {
7676
final index = _flipIndex();
7777
_allocs[index] = f.allocate<Uint8>(count: size);
7878
_data[index] = ByteData.view(_allocs[index].asTypedList(size).buffer);
79-
return _data[index];
79+
return _data[index] /*!*/;
8080
}
8181

8282
@override
@@ -119,7 +119,7 @@ class Allocator extends fb.Allocator {
119119
assert(_data[_index] == data);
120120
assert(_allocs[_index].address != 0);
121121

122-
fbMemset(_allocs[_index], 0, data.lengthInBytes);
122+
fbMemset /*!*/ (_allocs[_index], 0, data.lengthInBytes);
123123
}
124124

125125
void freeAll() {

objectbox/lib/src/bindings/helpers.dart

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ bool checkObxSuccess(int code) {
2424
}
2525

2626
Pointer<T> checkObxPtr<T extends NativeType>(Pointer<T> /*?*/ ptr,
27-
[String dartMsg]) {
27+
[String /*?*/ dartMsg]) {
2828
if (ptr == null || ptr.address == 0) {
2929
throw latestNativeError(dartMsg: dartMsg);
3030
}
@@ -156,3 +156,16 @@ class CursorHelper<T> {
156156
return _entity.objectFromFB(_store, readData);
157157
}
158158
}
159+
160+
T withNativeBytes<T>(
161+
Uint8List data, T Function(Pointer<Void> ptr, int size) fn) {
162+
final size = data.length;
163+
assert(size == data.lengthInBytes);
164+
final ptr = allocate<Uint8>(count: size);
165+
try {
166+
ptr.asTypedList(size).setAll(0, data); // copies `data` to `ptr`
167+
return fn(ptr.cast<Void>(), size);
168+
} finally {
169+
free(ptr);
170+
}
171+
}

objectbox/lib/src/bindings/structs.dart

Lines changed: 0 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import 'dart:ffi';
2-
import 'dart:typed_data' show Uint8List;
32

43
import 'package:ffi/ffi.dart' show allocate, free, Utf8;
54

6-
import '../common.dart';
75
import 'bindings.dart';
86

97
// ignore_for_file: public_member_api_docs
@@ -31,56 +29,6 @@ R executeWithIdArray<R>(List<int> items, R Function(Pointer<OBX_id_array>) fn) {
3129
}
3230
}
3331

34-
class OBX_bytes_wrapper {
35-
final Pointer<OBX_bytes> _cBytes;
36-
37-
int get size => _cBytes == nullptr ? 0 : _cBytes.ref.size;
38-
39-
Uint8List get data => safeDataAccess(_cBytes);
40-
41-
/// Get access to the data (no-copy)
42-
static Uint8List safeDataAccess(Pointer<OBX_bytes> /*?*/ cBytes) =>
43-
cBytes == null || cBytes.address == 0 || cBytes.ref.size == 0
44-
? throw ObjectBoxException(
45-
dartMsg: "can't access data of empty OBX_bytes")
46-
: cBytes.ref.data.cast<Uint8>().asTypedList(cBytes.ref.size);
47-
48-
bool get isEmpty => size == 0;
49-
50-
Pointer<Void> get ptr => _cBytes.ref.data;
51-
52-
/// Returns a pointer to OBX_bytes with copy of the passed data.
53-
/// Warning: this creates two unmanaged pointers which must be freed manually:
54-
/// [freeManaged()].
55-
/// ObjectBox requires object data to be aligned to the length of 4.
56-
OBX_bytes_wrapper.managedCopyOf(Uint8List data, {/*required*/ bool align})
57-
: _cBytes = allocate<OBX_bytes>() {
58-
final bytes = _cBytes.ref;
59-
60-
bytes.size = align ? ((data.length + 3.0) ~/ 4.0) * 4 : data.length;
61-
62-
// NOTE: currently there's no way to get access to the underlying memory of
63-
// Uint8List to avoid a copy.
64-
// See https://github.com/dart-lang/ffi/issues/27
65-
// if (data.length == bytes.length) {
66-
// bytes._dataPtr = data.some-way-to-get-the-underlying-memory-pointer
67-
// return ptr;
68-
// }
69-
70-
// create a copy of the data
71-
bytes.data = allocate<Uint8>(count: bytes.size).cast<Void>();
72-
for (var i = 0; i < data.length; ++i) {
73-
bytes.data.cast<Uint8>()[i] = data[i];
74-
}
75-
}
76-
77-
/// Free a dart-created OBX_bytes pointer.
78-
void freeManaged() {
79-
free(_cBytes.ref.data);
80-
free(_cBytes);
81-
}
82-
}
83-
8432
class OBX_string_array_wrapper {
8533
final Pointer<OBX_string_array> _cPtr;
8634

objectbox/lib/src/box.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ class Box<T> {
104104
final newId = C.box_put_object4(
105105
_cBox, _builder.bufPtr, _builder.fbb.size, _getOBXPutMode(mode));
106106
id = _handlePutObjectResult(object, id, newId);
107-
if (_hasToManyRelations) _putToManyRelFields(object, mode, tx);
107+
if (_hasToManyRelations) _putToManyRelFields(object, mode, tx /*!*/);
108108
_builder.resetIfLarge();
109109
return id;
110110
}
@@ -170,7 +170,8 @@ class Box<T> {
170170
///
171171
/// Pass growableResult: true for the resulting list to be growable.
172172
List<T /*?*/ > getMany(List<int> ids, {bool growableResult = false}) {
173-
final result = List<T>.filled(ids.length, null, growable: growableResult);
173+
final result =
174+
List<T /*?*/ >.filled(ids.length, null, growable: growableResult);
174175
if (ids.isEmpty) return result;
175176
final tx = Transaction(_store, TxMode.read);
176177
try {

objectbox/lib/src/common.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ class ObjectBoxException implements Exception {
6161
if (nativeCode != 0 || nativeMsg != null) result += ': ';
6262
}
6363
if (nativeCode != 0) result += '$nativeCode ';
64-
if (nativeMsg != null) result += nativeMsg;
64+
if (nativeMsg != null) result += nativeMsg /*!*/;
6565
return result.trimRight();
6666
}
6767
}

objectbox/lib/src/modelinfo/modelbacklink.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ class ModelBacklink {
1111
ModelBacklink(this.name, this.srcEntity, this.srcField);
1212

1313
ModelBacklink.fromMap(Map<String, dynamic> data)
14-
: this(data['name'] as String, data['srcEntity'] as String,
15-
data['srcField'] as String);
14+
: this(data['name'] as String /*!*/, data['srcEntity'] as String /*!*/,
15+
data['srcField'] as String /*!*/);
1616

1717
Map<String, String> toMap() =>
1818
{'name': name, 'srcEntity': srcEntity, 'srcField': srcField};

objectbox/lib/src/modelinfo/modelentity.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ class ModelEntity {
6666
id = IdUid.fromString(data['id'] as String),
6767
lastPropertyId = IdUid.fromString(data['lastPropertyId'] as String) {
6868
name = data['name'] as String;
69-
flags = data['flags'] as int ?? 0;
69+
flags = data['flags'] as int /*?*/ ?? 0;
7070

7171
if (data['properties'] == null) throw Exception('properties is null');
7272
for (final p in data['properties']) {
@@ -169,7 +169,7 @@ class ModelEntity {
169169
ModelProperty /*?*/ findSameProperty(ModelProperty other) {
170170
ModelProperty /*?*/ ret;
171171
if (other.id.uid != 0) ret = _findPropertyByUid(other.id.uid);
172-
return ret ??= findPropertyByName(other.name);
172+
return ret ?? findPropertyByName(other.name);
173173
}
174174

175175
ModelProperty createProperty(String name, [int uid = 0]) {
@@ -197,7 +197,7 @@ class ModelEntity {
197197
model.retiredPropertyUids.add(prop.id.uid);
198198

199199
if (prop.indexId != null) {
200-
model.retiredIndexUids.add(prop.indexId.uid);
200+
model.retiredIndexUids.add(prop.indexId /*!*/ .uid);
201201
}
202202
}
203203

@@ -221,7 +221,7 @@ class ModelEntity {
221221
ModelRelation /*?*/ findSameRelation(ModelRelation other) {
222222
ModelRelation /*?*/ ret;
223223
if (other.id.uid != 0) ret = _findRelationByUid(other.id.uid);
224-
return ret ??= _findRelationByName(other.name);
224+
return ret ?? _findRelationByName(other.name);
225225
}
226226

227227
ModelRelation createRelation(String name, [int uid = 0]) {

objectbox/lib/src/modelinfo/modelinfo.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,7 @@ class ModelInfo {
177177
ModelEntity /*?*/ findSameEntity(ModelEntity other) {
178178
ModelEntity /*?*/ ret;
179179
if (other.id.uid != 0) ret = findEntityByUid(other.id.uid);
180-
ret ??= findEntityByName(other.name);
181-
return ret;
180+
return ret ?? findEntityByName(other.name);
182181
}
183182

184183
ModelEntity createEntity(String name, [int uid = 0]) {

objectbox/lib/src/observable.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import 'store.dart';
1212
/// Simple wrapper used below in ObservableStore to reduce code duplication.
1313
/// Contains shared code for single-entity observer and the generic/global one.
1414
class _Observer<StreamValueType> {
15-
StreamController<StreamValueType> /*?*/ controller;
15+
/*late final*/ StreamController<StreamValueType> controller;
1616
Pointer<OBX_observer> /*?*/ _cObserver;
1717
ReceivePort /*?*/ receivePort;
1818

@@ -23,7 +23,7 @@ class _Observer<StreamValueType> {
2323
_debugLog('started');
2424
}
2525

26-
Stream<StreamValueType> get stream => controller /*!*/ .stream;
26+
Stream<StreamValueType> get stream => controller.stream;
2727

2828
_Observer() {
2929
initializeDartAPI();

objectbox/lib/src/query/builder.dart

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class _QueryBuilder<T> {
3737
final Store _store;
3838
final EntityDefinition<T> _entity;
3939
final Condition /*?*/ _queryCondition;
40-
Pointer<OBX_query_builder> /*?*/ _cBuilder;
40+
final Pointer<OBX_query_builder> _cBuilder;
4141
final _innerQBs = <_QueryBuilder>[];
4242

4343
_QueryBuilder(
@@ -50,12 +50,12 @@ class _QueryBuilder<T> {
5050
_entity = InternalStoreAccess.entityDef<T>(srcQB._store) {
5151
checkObxPtr(_cBuilder, 'failed to create QueryBuilder');
5252
_applyCondition();
53+
srcQB._innerQBs.add(this);
5354
}
5455

5556
void _close() {
5657
_innerQBs.forEach((iqb) => iqb._close());
5758
checkObx(C.qb_close(_cBuilder));
58-
_cBuilder = null;
5959
}
6060

6161
void _throwExceptionIfNecessary() {
@@ -84,35 +84,31 @@ class _QueryBuilder<T> {
8484
QueryRelationProperty<_, TargetEntityT> rel,
8585
[Condition /*?*/ qc]) {
8686
_throwIfOtherEntity(rel._entityId);
87-
_innerQBs.add(_QueryBuilder<TargetEntityT>._link(
88-
this, qc, C.qb_link_property(_cBuilder, rel._propertyId)));
89-
return _innerQBs.last as _QueryBuilder<TargetEntityT>;
87+
return _QueryBuilder<TargetEntityT>._link(
88+
this, qc, C.qb_link_property(_cBuilder, rel._propertyId));
9089
}
9190

9291
_QueryBuilder<SourceEntityT> backlink<SourceEntityT, _>(
9392
QueryRelationProperty<SourceEntityT, _> rel,
9493
[Condition /*?*/ qc]) {
9594
_throwIfOtherEntity(rel._targetEntityId);
96-
_innerQBs.add(_QueryBuilder<SourceEntityT>._link(this, qc,
97-
C.qb_backlink_property(_cBuilder, rel._entityId, rel._propertyId)));
98-
return _innerQBs.last as _QueryBuilder<SourceEntityT>;
95+
return _QueryBuilder<SourceEntityT>._link(this, qc,
96+
C.qb_backlink_property(_cBuilder, rel._entityId, rel._propertyId));
9997
}
10098

10199
_QueryBuilder<TargetEntityT> linkMany<_, TargetEntityT>(
102100
QueryRelationMany<_, TargetEntityT> rel,
103101
[Condition /*?*/ qc]) {
104102
_throwIfOtherEntity(rel._entityId);
105-
_innerQBs.add(_QueryBuilder<TargetEntityT>._link(
106-
this, qc, C.qb_link_standalone(_cBuilder, rel._relationId)));
107-
return _innerQBs.last as _QueryBuilder<TargetEntityT>;
103+
return _QueryBuilder<TargetEntityT>._link(
104+
this, qc, C.qb_link_standalone(_cBuilder, rel._relationId));
108105
}
109106

110107
_QueryBuilder<SourceEntityT> backlinkMany<SourceEntityT, _>(
111108
QueryRelationMany<SourceEntityT, _> rel,
112109
[Condition /*?*/ qc]) {
113110
_throwIfOtherEntity(rel._targetEntityId);
114-
_innerQBs.add(_QueryBuilder<SourceEntityT>._link(
115-
this, qc, C.qb_backlink_standalone(_cBuilder, rel._relationId)));
116-
return _innerQBs.last as _QueryBuilder<SourceEntityT>;
111+
return _QueryBuilder<SourceEntityT>._link(
112+
this, qc, C.qb_backlink_standalone(_cBuilder, rel._relationId));
117113
}
118114
}

objectbox/lib/src/query/query.dart

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import '../store.dart';
1515
import '../transaction.dart';
1616

1717
part 'builder.dart';
18+
1819
part 'property.dart';
1920

2021
// ignore_for_file: public_member_api_docs
@@ -432,7 +433,7 @@ class _IntegerCondition extends _PropertyCondition<int> {
432433
: super(op, prop, value, value2);
433434

434435
int _op1(_QueryBuilder builder,
435-
int Function(Pointer<OBX_query_builder>, int, int /*?*/) func) =>
436+
int Function(Pointer<OBX_query_builder>, int, int) func) =>
436437
func(builder._cBuilder, _property._propertyId, _value);
437438

438439
@override
@@ -452,7 +453,7 @@ class _IntegerCondition extends _PropertyCondition<int> {
452453
return _op1(builder, C.qb_less_or_equal_int);
453454
case _ConditionOp.between:
454455
return C.qb_between_2ints(
455-
builder._cBuilder, _property._propertyId, _value, _value2);
456+
builder._cBuilder, _property._propertyId, _value, _value2 /*!*/);
456457
default:
457458
throw Exception('Unsupported operation ${_op.toString()}');
458459
}
@@ -541,7 +542,7 @@ class _DoubleCondition extends _PropertyCondition<double> {
541542
builder._cBuilder, _property._propertyId, _value);
542543
case _ConditionOp.between:
543544
return C.qb_between_2doubles(
544-
builder._cBuilder, _property._propertyId, _value, _value2);
545+
builder._cBuilder, _property._propertyId, _value, _value2 /*!*/);
545546
default:
546547
throw Exception('Unsupported operation ${_op.toString()}');
547548
}
@@ -552,16 +553,14 @@ class _ByteVectorCondition extends _PropertyCondition<Uint8List> {
552553
_ByteVectorCondition(_ConditionOp op, QueryProperty prop, Uint8List value)
553554
: super(op, prop, value);
554555

555-
int _op1(_QueryBuilder builder,
556-
int Function(Pointer<OBX_query_builder>, int, Pointer<Void>, int) func) {
557-
final cBytes = OBX_bytes_wrapper.managedCopyOf(_value, align: false);
558-
try {
559-
return func(
560-
builder._cBuilder, _property._propertyId, cBytes.ptr, cBytes.size);
561-
} finally {
562-
cBytes.freeManaged();
563-
}
564-
}
556+
int _op1(
557+
_QueryBuilder builder,
558+
int Function(Pointer<OBX_query_builder>, int, Pointer<Void>, int)
559+
func) =>
560+
withNativeBytes(
561+
_value,
562+
(Pointer<Void> ptr, int size) =>
563+
func(builder._cBuilder, _property._propertyId, ptr, size));
565564

566565
@override
567566
int _apply(_QueryBuilder builder, {/*required*/ bool isRoot}) {

objectbox/lib/src/relations/info.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,6 @@ class RelInfo<SourceEntityT> {
5151
RelType get type => _type;
5252

5353
/// Source field associated with this toOne relation backlink.
54-
ToOne toOneSourceField(SourceEntityT object) => _getToOneSourceField(object);
54+
ToOne toOneSourceField(SourceEntityT object) =>
55+
_getToOneSourceField /*!*/ (object);
5556
}

objectbox/lib/src/relations/to_many.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class ToMany<EntityT> extends Object with ListMixin<EntityT> {
5959
/*late final*/
6060
EntityDefinition<EntityT> _entity;
6161

62-
RelInfo _rel;
62+
RelInfo /*?*/ _rel;
6363

6464
List<EntityT> /*?*/ __items;
6565
final _counts = <EntityT, int>{};
@@ -152,7 +152,7 @@ class ToMany<EntityT> extends Object with ListMixin<EntityT> {
152152
/// If this collection contains new objects (with zero IDs), applyToDb()
153153
/// will put them on-the-fly. For this to work the source object (the object
154154
/// owing this ToMany) must be already stored because its ID is required.
155-
void applyToDb({PutMode mode = PutMode.put, Transaction tx}) {
155+
void applyToDb({PutMode mode = PutMode.put, Transaction /*?*/ tx}) {
156156
if (!_hasPendingDbChanges) return;
157157
_verifyAttached();
158158

@@ -250,7 +250,7 @@ class ToMany<EntityT> extends Object with ListMixin<EntityT> {
250250
__items.addAll(_addedBeforeLoad);
251251
_addedBeforeLoad.clear();
252252
}
253-
return __items;
253+
return __items /*!*/;
254254
}
255255

256256
void _verifyAttached() {

0 commit comments

Comments
 (0)