Skip to content

Commit 8e15f36

Browse files
author
Ivan Dlugos
committed
add byte-vector property support for List<Int>, Uint8List and Int8List
1 parent 5a6e09a commit 8e15f36

File tree

13 files changed

+130
-22
lines changed

13 files changed

+130
-22
lines changed

generator/integration-tests/basics/1.dart

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,12 @@ void main() {
4848
expect(property(model, 'T.tString').type, OBXPropertyType.String);
4949
expect(property(model, 'T.tDate').type, OBXPropertyType.Date);
5050
expect(property(model, 'T.tDateNano').type, OBXPropertyType.DateNano);
51-
// expect(property(model, 'T.tByteVector1').type, OBXPropertyType.ByteVector);
52-
// expect(property(model, 'T.tByteVector2').type, OBXPropertyType.ByteVector);
53-
// expect(property(model, 'T.tByteVector3').type, OBXPropertyType.ByteVector);
51+
expect(property(model, 'T.tListInt').type, OBXPropertyType.ByteVector);
52+
expect(property(model, 'T.tListInt').flags, 0);
53+
expect(property(model, 'T.tInt8List').type, OBXPropertyType.ByteVector);
54+
expect(property(model, 'T.tInt8List').flags, 0);
55+
expect(property(model, 'T.tUint8List').type, OBXPropertyType.ByteVector);
56+
expect(property(model, 'T.tUint8List').flags, OBXPropertyFlags.UNSIGNED);
5457
expect(property(model, 'T.tListString').type, OBXPropertyType.StringVector);
5558
});
5659
}

generator/integration-tests/basics/lib/lib.dart

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,17 +68,12 @@ class T {
6868
@Property(type: PropertyType.dateNano)
6969
int tDateNano;
7070

71-
// TODO
72-
// @Property(type: PropertyType.byteVector)
73-
// List<int> tByteVector1;
71+
@Property(type: PropertyType.byteVector)
72+
List<int> tListInt; // truncates int to 8-bits
7473

75-
// TODO
76-
// @Property(type: PropertyType.byteVector)
77-
// Int8List tByteVector2;
74+
Int8List tInt8List;
7875

79-
// TODO
80-
// @Property(type: PropertyType.byteVector)
81-
// Uint8List tByteVector3;
76+
Uint8List tUint8List;
8277

8378
List<String> tListString;
8479
}

generator/lib/src/code_builder.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ class CodeBuilder extends Builder {
140140
propInModel.name = prop.name;
141141
propInModel.type = prop.type;
142142
propInModel.flags = prop.flags;
143+
propInModel.dartFieldType = prop.dartFieldType;
143144

144145
if (!prop.hasIndexFlag()) {
145146
propInModel.removeIndex();

generator/lib/src/code_chunks.dart

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class CodeChunks {
99
1010
// Currently loading model from "JSON" which always encodes with double quotes
1111
// ignore_for_file: prefer_single_quotes
12-
12+
${typedDataImportIfNeeded(model)}
1313
import 'package:objectbox/objectbox.dart';
1414
export 'package:objectbox/objectbox.dart'; // so that callers only have to import this file
1515
import '${imports.join("';\n import '")}';
@@ -36,13 +36,34 @@ class CodeChunks {
3636
},
3737
writer: (Map<String, dynamic> members) {
3838
final r = $name();
39-
${entity.properties.map((p) => "r.${p.name} = members['${p.name}'];").join()}
39+
${entity.properties.map(propertyBinding).join()}
4040
return r;
4141
}
4242
)
4343
""";
4444
}
4545

46+
static String typedDataImportIfNeeded(ModelInfo model) {
47+
if (model.entities
48+
.any((ModelEntity entity) => entity.properties.any(isTypedDataList))) {
49+
return "import 'dart:typed_data';\n";
50+
}
51+
return '';
52+
}
53+
54+
static bool isTypedDataList(ModelProperty property) {
55+
return (property.dartFieldType == 'Uint8List' ||
56+
property.dartFieldType == 'Int8List');
57+
}
58+
59+
static String propertyBinding(ModelProperty property) {
60+
if (isTypedDataList(property)) {
61+
return "r.${property.name} = members['${property.name}'] == null ? null : ${property.dartFieldType}.fromList(members['${property.name}']);";
62+
} else {
63+
return "r.${property.name} = members['${property.name}'];";
64+
}
65+
}
66+
4667
static String _queryConditionBuilder(ModelEntity entity) {
4768
final ret = <String>[];
4869
for (var prop in entity.properties) {
@@ -71,6 +92,9 @@ class CodeChunks {
7192
case OBXPropertyType.Relation:
7293
fieldType = 'Integer';
7394
break;
95+
case OBXPropertyType.ByteVector:
96+
fieldType = 'ByteVector';
97+
break;
7498
case OBXPropertyType.StringVector:
7599
fieldType = 'StringVector';
76100
break;

generator/lib/src/entity_resolver.dart

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ class EntityResolver extends Builder {
9595
int fieldType;
9696
var flags = 0;
9797
int propUid;
98+
String dartFieldType; // to be passed to ModelProperty.dartFieldType
9899

99100
if (_idChecker.hasAnnotationOfExact(f)) {
100101
if (hasIdProperty) {
@@ -139,8 +140,19 @@ class EntityResolver extends Builder {
139140
// ob: 8 bytes
140141
fieldType = OBXPropertyType.Double;
141142
} else if (fieldTypeDart.isDartCoreList &&
142-
listItemType(fieldTypeDart).isDartCoreString) { // List<String>
143+
listItemType(fieldTypeDart).isDartCoreString) {
144+
// List<String>
143145
fieldType = OBXPropertyType.StringVector;
146+
} else if (fieldTypeDart.element.name == 'Int8List') {
147+
fieldType = OBXPropertyType.ByteVector;
148+
dartFieldType =
149+
fieldTypeDart.element.name; // needed for code generation
150+
} else if (fieldTypeDart.element.name == 'Uint8List') {
151+
fieldType = OBXPropertyType.ByteVector;
152+
// TODO check if UNSIGNED also applies to byte-vector in the core
153+
flags |= OBXPropertyFlags.UNSIGNED;
154+
dartFieldType =
155+
fieldTypeDart.element.name; // needed for code generation
144156
} else {
145157
log.warning(
146158
" skipping property '${f.name}' in entity '${element.name}', as it has an unsupported type: '${fieldTypeDart}'");
@@ -156,6 +168,7 @@ class EntityResolver extends Builder {
156168
processAnnotationIndexUnique(f, fieldType, elementBare, prop);
157169

158170
if (propUid != null) prop.id.uid = propUid;
171+
prop.dartFieldType = dartFieldType;
159172
entity.properties.add(prop);
160173

161174
log.info(' ${prop}');

lib/src/annotations.dart

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,11 @@ enum PropertyType {
6363
/// Unix timestamp (nanoseconds since 1970), size: 8-bytes/64-bits
6464
dateNano,
6565

66-
/// dart type=Uint8List, currently not supported
67-
// byteVector,
66+
/// dart type=Uint8List - automatic, no need to specify explicitly
67+
/// dart type=Int8List - automatic, no need to specify explicitly
68+
/// dart type=List<int> - specify the type explicitly using @Property(type:)
69+
/// - values are truncated to 8-bit int (0..255)
70+
byteVector,
6871

6972
/// dart type=List<String>
7073
/// no need to specify explicitly, just use `List<String> `

lib/src/bindings/flatbuffers.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ class OBXFlatbuffersManager<T> {
5656
: builder.writeList(
5757
stringVector.map((str) => builder.writeString(str)).toList());
5858
break;
59+
case OBXPropertyType.ByteVector:
60+
final byteVector = propVals[p.name];
61+
offsets[p.id.id] =
62+
byteVector == null ? null : builder.writeListInt8(byteVector);
63+
break;
5964
}
6065
});
6166

@@ -93,6 +98,7 @@ class OBXFlatbuffersManager<T> {
9398
// offset-based fields
9499
case OBXPropertyType.String:
95100
case OBXPropertyType.StringVector:
101+
case OBXPropertyType.ByteVector:
96102
builder.addOffset(field, offsets[p.id.id] /*!*/);
97103
break;
98104
default:
@@ -144,6 +150,9 @@ class OBXFlatbuffersManager<T> {
144150
case OBXPropertyType.StringVector:
145151
propReader = const fb.ListReader<String>(fb.StringReader());
146152
break;
153+
case OBXPropertyType.ByteVector:
154+
propReader = const fb.ListReader<int>(fb.Int8Reader());
155+
break;
147156
default:
148157
throw Exception('unsupported type: ${p.type}');
149158
}

lib/src/bindings/helpers.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ int propertyTypeToOBXPropertyType(PropertyType type) {
101101
return OBXPropertyType.Date;
102102
case PropertyType.dateNano:
103103
return OBXPropertyType.DateNano;
104+
case PropertyType.byteVector:
105+
return OBXPropertyType.ByteVector;
104106
}
105107
throw Exception('Invalid PropertyType: ${type}');
106108
}

lib/src/modelinfo/modelproperty.dart

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ class ModelProperty {
1111
IdUid /*?*/ _indexId;
1212
ModelEntity /*?*/ entity;
1313

14+
/// Type used in the source dart code - used by the code generator.
15+
/// Note: must be included in to/fromMap to be handled `build_runner`.
16+
String /*?*/ dartFieldType;
17+
1418
String get name => _name;
1519

1620
set name(String /*?*/ value) {
@@ -50,7 +54,7 @@ class ModelProperty {
5054
}
5155

5256
ModelProperty(this.id, String /*?*/ name, int /*?*/ type,
53-
{int flags = 0, String /*?*/ indexId, this.entity}) {
57+
{int flags = 0, String /*?*/ indexId, this.entity, this.dartFieldType}) {
5458
this.name = name;
5559
this.type = type;
5660
this.flags = flags;
@@ -61,7 +65,8 @@ class ModelProperty {
6165
: this(IdUid.fromString(data['id']), data['name'], data['type'],
6266
flags: data['flags'] ?? 0,
6367
indexId: data['indexId'],
64-
entity: entity);
68+
entity: entity,
69+
dartFieldType: data['dartFieldType']);
6570

6671
Map<String, dynamic> toMap() {
6772
final ret = <String, dynamic>{};
@@ -70,6 +75,7 @@ class ModelProperty {
7075
ret['type'] = type;
7176
if (flags != 0) ret['flags'] = flags;
7277
if (indexId != null) ret['indexId'] = indexId /*!*/ .toString();
78+
if (dartFieldType != null) ret['dartFieldType'] = dartFieldType;
7379
return ret;
7480
}
7581

lib/src/query/query.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,16 @@ class QueryStringProperty extends QueryProperty {
129129
// Condition operator != (String p) => notEqual(p); // not overloadable
130130
}
131131

132+
class QueryByteVectorProperty extends QueryProperty {
133+
QueryByteVectorProperty(
134+
{/*required*/ int entityId,
135+
/*required*/ int propertyId,
136+
/*required*/ int obxType})
137+
: super(entityId, propertyId, obxType);
138+
139+
// TODO conditions
140+
}
141+
132142
class QueryIntegerProperty extends QueryProperty {
133143
QueryIntegerProperty(
134144
{/*required*/ int entityId,

0 commit comments

Comments
 (0)