Skip to content

Commit e12eea8

Browse files
Flex map: support restoring Long maps as always Long.
1 parent 388a56e commit e12eea8

File tree

8 files changed

+72
-9
lines changed

8 files changed

+72
-9
lines changed

objectbox-java/src/main/java/io/objectbox/converter/FlexMapConverter.java

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -132,16 +132,16 @@ public Map<Object, Object> convertToEntityProperty(byte[] databaseValue) {
132132
abstract Object convertToKey(String keyValue);
133133

134134
/**
135-
* Returns the width in bytes stored in the private parentWidth field of FlexBuffers.Reference.
135+
* Returns true if the width in bytes stored in the private parentWidth field of FlexBuffers.Reference is 8.
136136
* Note: FlexBuffers stores all items in a map/vector using the size of the widest item. However,
137137
* an item's size is only as wide as needed, e.g. a 64-bit integer (Java Long, 8 bytes) will be
138138
* reduced to 1 byte if it does not exceed its value range.
139139
*/
140-
private int getParentWidthInBytesOf(FlexBuffers.Reference reference) {
140+
protected boolean shouldRestoreAsLong(FlexBuffers.Reference reference) {
141141
try {
142142
Field parentWidthF = reference.getClass().getDeclaredField("parentWidth");
143143
parentWidthF.setAccessible(true);
144-
return (int) parentWidthF.get(reference);
144+
return (int) parentWidthF.get(reference) == 8;
145145
} catch (Exception e) {
146146
// If thrown, it is likely the FlexBuffers API has changed and the above should be updated.
147147
throw new RuntimeException("FlexMapConverter could not determine FlexBuffers integer bit width.", e);
@@ -167,8 +167,7 @@ private Map<Object, Object> buildMap(FlexBuffers.Map map) {
167167
} else if (value.isBoolean()) {
168168
resultMap.put(key, value.asBoolean());
169169
} else if (value.isInt()) {
170-
int parentWidthInBytes = getParentWidthInBytesOf(value);
171-
if (parentWidthInBytes == 8) {
170+
if (shouldRestoreAsLong(value)) {
172171
resultMap.put(key, value.asLong());
173172
} else {
174173
resultMap.put(key, value.asInt());
@@ -192,7 +191,7 @@ private List<Object> buildList(FlexBuffers.Vector vector) {
192191
List<Object> list = new ArrayList<>(itemCount);
193192

194193
// FlexBuffers uses the byte width of the biggest item to size all items, so only need to check the first.
195-
Integer parentWidthInBytes = null;
194+
Boolean shouldRestoreAsLong = null;
196195

197196
for (int i = 0; i < itemCount; i++) {
198197
FlexBuffers.Reference item = vector.get(i);
@@ -205,10 +204,10 @@ private List<Object> buildList(FlexBuffers.Vector vector) {
205204
} else if (item.isBoolean()) {
206205
list.add(item.asBoolean());
207206
} else if (item.isInt()) {
208-
if (parentWidthInBytes == null) {
209-
parentWidthInBytes = getParentWidthInBytesOf(item);
207+
if (shouldRestoreAsLong == null) {
208+
shouldRestoreAsLong = shouldRestoreAsLong(item);
210209
}
211-
if (parentWidthInBytes == 8) {
210+
if (shouldRestoreAsLong) {
212211
list.add(item.asLong());
213212
} else {
214213
list.add(item.asInt());

objectbox-java/src/main/java/io/objectbox/converter/IntegerFlexMapConverter.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package io.objectbox.converter;
22

3+
/**
4+
* Used to automatically convert {@code Map<Integer, V>}.
5+
*/
36
public class IntegerFlexMapConverter extends FlexMapConverter {
47
@Override
58
Integer convertToKey(String keyValue) {
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package io.objectbox.converter;
2+
3+
import io.objectbox.flatbuffers.FlexBuffers;
4+
5+
/**
6+
* Used to automatically convert {@code Map<Integer, Long>}.
7+
*/
8+
public class IntegerLongMapConverter extends IntegerFlexMapConverter {
9+
@Override
10+
protected boolean shouldRestoreAsLong(FlexBuffers.Reference reference) {
11+
return true; // Restore all integers as java.lang.Long.
12+
}
13+
}

objectbox-java/src/main/java/io/objectbox/converter/LongFlexMapConverter.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package io.objectbox.converter;
22

3+
/**
4+
* Used to automatically convert {@code Map<Long, V>}.
5+
*/
36
public class LongFlexMapConverter extends FlexMapConverter {
47
@Override
58
Object convertToKey(String keyValue) {
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package io.objectbox.converter;
2+
3+
import io.objectbox.flatbuffers.FlexBuffers;
4+
5+
/**
6+
* Used to automatically convert {@code Map<Long, Long>}.
7+
*/
8+
public class LongLongMapConverter extends LongFlexMapConverter {
9+
@Override
10+
protected boolean shouldRestoreAsLong(FlexBuffers.Reference reference) {
11+
return true; // Restore all integers as java.lang.Long.
12+
}
13+
}

objectbox-java/src/main/java/io/objectbox/converter/StringFlexMapConverter.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package io.objectbox.converter;
22

3+
/**
4+
* Used to automatically convert {@code Map<String, V>}.
5+
*/
36
public class StringFlexMapConverter extends FlexMapConverter {
47
@Override
58
Object convertToKey(String keyValue) {
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package io.objectbox.converter;
2+
3+
import io.objectbox.flatbuffers.FlexBuffers;
4+
5+
/**
6+
* Used to automatically convert {@code Map<String, Long>}.
7+
*/
8+
public class StringLongMapConverter extends StringFlexMapConverter {
9+
@Override
10+
protected boolean shouldRestoreAsLong(FlexBuffers.Reference reference) {
11+
return true; // Restore all integers as java.lang.Long.
12+
}
13+
}

tests/objectbox-java-test/src/test/java/io/objectbox/converter/FlexMapConverterTest.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,22 @@ public void keysString_valsIntegersBiggest32Bit_works() {
7171
}
7272
}
7373

74+
/**
75+
* Using Long value converter, even if no item is wider than 32 bits, all integers are restored as Long.
76+
*/
77+
@Test
78+
public void keysString_valsLongBiggest32Bit_works() {
79+
FlexMapConverter converter = new StringLongMapConverter();
80+
Map<String, Long> expected = new HashMap<>();
81+
82+
expected.put("long-8bit-neg", -1L);
83+
expected.put("long-8bit", 2L);
84+
expected.put("long-32bit-neg", (long) Integer.MIN_VALUE);
85+
expected.put("long-32bit", (long) Integer.MAX_VALUE);
86+
87+
convertAndBackThenAssert(expected, converter);
88+
}
89+
7490
/**
7591
* If at least one item is 64 bit wide, all integers are restored as Long.
7692
*/

0 commit comments

Comments
 (0)