diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index f0978a30b7200b..903db80d5c0c6b 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -1793,6 +1793,7 @@ public abstract interface class com/facebook/react/common/mapbuffer/MapBuffer : public abstract fun getDouble (I)D public abstract fun getInt (I)I public abstract fun getKeyOffset (I)I + public abstract fun getLong (I)J public abstract fun getMapBuffer (I)Lcom/facebook/react/common/mapbuffer/MapBuffer; public abstract fun getMapBufferList (I)Ljava/util/List; public abstract fun getString (I)Ljava/lang/String; @@ -1806,6 +1807,7 @@ public final class com/facebook/react/common/mapbuffer/MapBuffer$DataType : java public static final field BOOL Lcom/facebook/react/common/mapbuffer/MapBuffer$DataType; public static final field DOUBLE Lcom/facebook/react/common/mapbuffer/MapBuffer$DataType; public static final field INT Lcom/facebook/react/common/mapbuffer/MapBuffer$DataType; + public static final field LONG Lcom/facebook/react/common/mapbuffer/MapBuffer$DataType; public static final field MAP Lcom/facebook/react/common/mapbuffer/MapBuffer$DataType; public static final field STRING Lcom/facebook/react/common/mapbuffer/MapBuffer$DataType; public static fun valueOf (Ljava/lang/String;)Lcom/facebook/react/common/mapbuffer/MapBuffer$DataType; @@ -1817,6 +1819,7 @@ public abstract interface class com/facebook/react/common/mapbuffer/MapBuffer$En public abstract fun getDoubleValue ()D public abstract fun getIntValue ()I public abstract fun getKey ()I + public abstract fun getLongValue ()J public abstract fun getMapBufferValue ()Lcom/facebook/react/common/mapbuffer/MapBuffer; public abstract fun getStringValue ()Ljava/lang/String; public abstract fun getType ()Lcom/facebook/react/common/mapbuffer/MapBuffer$DataType; @@ -1837,6 +1840,7 @@ public final class com/facebook/react/common/mapbuffer/ReadableMapBuffer : com/f public fun getDouble (I)D public fun getInt (I)I public fun getKeyOffset (I)I + public fun getLong (I)J public synthetic fun getMapBuffer (I)Lcom/facebook/react/common/mapbuffer/MapBuffer; public fun getMapBuffer (I)Lcom/facebook/react/common/mapbuffer/ReadableMapBuffer; public fun getMapBufferList (I)Ljava/util/List; @@ -1859,6 +1863,7 @@ public final class com/facebook/react/common/mapbuffer/WritableMapBuffer : com/f public fun getDouble (I)D public fun getInt (I)I public fun getKeyOffset (I)I + public fun getLong (I)J public fun getMapBuffer (I)Lcom/facebook/react/common/mapbuffer/MapBuffer; public fun getMapBufferList (I)Ljava/util/List; public fun getString (I)Ljava/lang/String; @@ -1866,6 +1871,7 @@ public final class com/facebook/react/common/mapbuffer/WritableMapBuffer : com/f public fun iterator ()Ljava/util/Iterator; public final fun put (ID)Lcom/facebook/react/common/mapbuffer/WritableMapBuffer; public final fun put (II)Lcom/facebook/react/common/mapbuffer/WritableMapBuffer; + public final fun put (IJ)Lcom/facebook/react/common/mapbuffer/WritableMapBuffer; public final fun put (ILcom/facebook/react/common/mapbuffer/MapBuffer;)Lcom/facebook/react/common/mapbuffer/WritableMapBuffer; public final fun put (ILjava/lang/String;)Lcom/facebook/react/common/mapbuffer/WritableMapBuffer; public final fun put (IZ)Lcom/facebook/react/common/mapbuffer/WritableMapBuffer; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/MapBuffer.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/MapBuffer.kt index 301837032fbbf0..53bb6b855434f1 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/MapBuffer.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/MapBuffer.kt @@ -44,7 +44,8 @@ public interface MapBuffer : Iterable { INT, DOUBLE, STRING, - MAP + MAP, + LONG } /** @@ -109,6 +110,16 @@ public interface MapBuffer : Iterable { */ public fun getInt(key: Int): Int + /** + * Provides parsed [Long] value if the entry for given key exists with [DataType.LONG] type + * + * @param key key to lookup [Long] value for + * @return value associated with the requested key + * @throws IllegalArgumentException if the key doesn't exist + * @throws IllegalStateException if the data type doesn't match + */ + public fun getLong(key: Int): Long + /** * Provides parsed [Double] value if the entry for given key exists with [DataType.DOUBLE] type * @@ -175,6 +186,13 @@ public interface MapBuffer : Iterable { */ public val intValue: Int + /** + * Entry value represented as [Long] + * + * @throws IllegalStateException if the data type doesn't match [DataType.LONG] + */ + public val longValue: Long + /** * Entry value represented as [Double] * diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/ReadableMapBuffer.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/ReadableMapBuffer.kt index 66add82a7e9e23..80371e93c27131 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/ReadableMapBuffer.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/ReadableMapBuffer.kt @@ -115,6 +115,10 @@ public class ReadableMapBuffer : MapBuffer { return buffer.getInt(bufferPosition) } + private fun readLongValue(bufferPosition: Int): Long { + return buffer.getLong(bufferPosition) + } + private fun readBooleanValue(bufferPosition: Int): Boolean { return readIntValue(bufferPosition) == 1 } @@ -180,6 +184,9 @@ public class ReadableMapBuffer : MapBuffer { override fun getInt(key: Int): Int = readIntValue(getTypedValueOffsetForKey(key, MapBuffer.DataType.INT)) + override fun getLong(key: Int): Long = + readLongValue(getTypedValueOffsetForKey(key, MapBuffer.DataType.LONG)) + override fun getDouble(key: Int): Double = readDoubleValue(getTypedValueOffsetForKey(key, MapBuffer.DataType.DOUBLE)) @@ -223,6 +230,7 @@ public class ReadableMapBuffer : MapBuffer { when (entry.type) { MapBuffer.DataType.BOOL -> builder.append(entry.booleanValue) MapBuffer.DataType.INT -> builder.append(entry.intValue) + MapBuffer.DataType.LONG -> builder.append(entry.longValue) MapBuffer.DataType.DOUBLE -> builder.append(entry.doubleValue) MapBuffer.DataType.STRING -> builder.append(entry.stringValue) MapBuffer.DataType.MAP -> builder.append(entry.mapBufferValue.toString()) @@ -280,6 +288,12 @@ public class ReadableMapBuffer : MapBuffer { return readIntValue(bucketOffset + VALUE_OFFSET) } + override val longValue: Long + get() { + assertType(MapBuffer.DataType.LONG) + return readLongValue(bucketOffset + VALUE_OFFSET) + } + override val booleanValue: Boolean get() { assertType(MapBuffer.DataType.BOOL) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/WritableMapBuffer.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/WritableMapBuffer.kt index fb145f4dddf697..f79e9122b53b98 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/WritableMapBuffer.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/WritableMapBuffer.kt @@ -48,6 +48,15 @@ public class WritableMapBuffer : MapBuffer { */ public fun put(key: Int, value: Int): WritableMapBuffer = putInternal(key, value) + /** + * Adds a long value for given key to the MapBuffer. + * + * @param key entry key + * @param value entry value + * @throws IllegalArgumentException if key is out of [UShort] range + */ + public fun put(key: Int, value: Long): WritableMapBuffer = putInternal(key, value) + /** * Adds a double value for given key to the MapBuffer. * @@ -107,6 +116,8 @@ public class WritableMapBuffer : MapBuffer { override fun getInt(key: Int): Int = verifyValue(key, values.get(key)) + override fun getLong(key: Int): Long = verifyValue(key, values.get(key)) + override fun getDouble(key: Int): Double = verifyValue(key, values.get(key)) override fun getString(key: Int): String = verifyValue(key, values.get(key)) @@ -128,6 +139,7 @@ public class WritableMapBuffer : MapBuffer { return when (val value = this) { is Boolean -> DataType.BOOL is Int -> DataType.INT + is Long -> DataType.LONG is Double -> DataType.DOUBLE is String -> DataType.STRING is MapBuffer -> DataType.MAP @@ -153,6 +165,9 @@ public class WritableMapBuffer : MapBuffer { override val intValue: Int get() = verifyValue(key, values.valueAt(index)) + override val longValue: Long + get() = verifyValue(key, values.valueAt(index)) + override val doubleValue: Double get() = verifyValue(key, values.valueAt(index)) diff --git a/packages/react-native/ReactCommon/react/renderer/mapbuffer/MapBuffer.cpp b/packages/react-native/ReactCommon/react/renderer/mapbuffer/MapBuffer.cpp index 8a46d17fa3b0da..5d9c0aa56ef912 100644 --- a/packages/react-native/ReactCommon/react/renderer/mapbuffer/MapBuffer.cpp +++ b/packages/react-native/ReactCommon/react/renderer/mapbuffer/MapBuffer.cpp @@ -61,6 +61,14 @@ int32_t MapBuffer::getInt(Key key) const { bytes_.data() + valueOffset(bucketIndex)); } +int64_t MapBuffer::getLong(Key key) const { + auto bucketIndex = getKeyBucket(key); + react_native_assert(bucketIndex != -1 && "Key not found in MapBuffer"); + + return *reinterpret_cast( + bytes_.data() + valueOffset(bucketIndex)); +} + bool MapBuffer::getBool(Key key) const { return getInt(key) != 0; } diff --git a/packages/react-native/ReactCommon/react/renderer/mapbuffer/MapBuffer.h b/packages/react-native/ReactCommon/react/renderer/mapbuffer/MapBuffer.h index 1efe45cf063114..968747ee64fb71 100644 --- a/packages/react-native/ReactCommon/react/renderer/mapbuffer/MapBuffer.h +++ b/packages/react-native/ReactCommon/react/renderer/mapbuffer/MapBuffer.h @@ -104,6 +104,7 @@ class MapBuffer { Double = 2, String = 3, Map = 4, + Long = 5, }; explicit MapBuffer(std::vector data); @@ -118,6 +119,8 @@ class MapBuffer { int32_t getInt(MapBuffer::Key key) const; + int64_t getLong(MapBuffer::Key key) const; + bool getBool(MapBuffer::Key key) const; double getDouble(MapBuffer::Key key) const; diff --git a/packages/react-native/ReactCommon/react/renderer/mapbuffer/MapBufferBuilder.cpp b/packages/react-native/ReactCommon/react/renderer/mapbuffer/MapBufferBuilder.cpp index 7bf76d91e6907e..c7eb0e38e9aeef 100644 --- a/packages/react-native/ReactCommon/react/renderer/mapbuffer/MapBufferBuilder.cpp +++ b/packages/react-native/ReactCommon/react/renderer/mapbuffer/MapBufferBuilder.cpp @@ -13,6 +13,7 @@ using namespace facebook::react; namespace facebook::react { constexpr uint32_t INT_SIZE = sizeof(uint32_t); +constexpr uint32_t LONG_SIZE = sizeof(uint64_t); constexpr uint32_t DOUBLE_SIZE = sizeof(double); constexpr uint32_t MAX_BUCKET_VALUE_SIZE = sizeof(uint64_t); @@ -76,6 +77,14 @@ void MapBufferBuilder::putInt(MapBuffer::Key key, int32_t value) { INT_SIZE); } +void MapBufferBuilder::putLong(MapBuffer::Key key, int64_t value) { + storeKeyValue( + key, + MapBuffer::DataType::Long, + reinterpret_cast(&value), + LONG_SIZE); +} + void MapBufferBuilder::putString(MapBuffer::Key key, const std::string& value) { auto strSize = value.size(); const char* strData = value.data(); diff --git a/packages/react-native/ReactCommon/react/renderer/mapbuffer/MapBufferBuilder.h b/packages/react-native/ReactCommon/react/renderer/mapbuffer/MapBufferBuilder.h index 60ca37d20aba74..2260e690a2d785 100644 --- a/packages/react-native/ReactCommon/react/renderer/mapbuffer/MapBufferBuilder.h +++ b/packages/react-native/ReactCommon/react/renderer/mapbuffer/MapBufferBuilder.h @@ -27,7 +27,7 @@ class MapBufferBuilder { void putInt(MapBuffer::Key key, int32_t value); - // TODO: Support 64 bit integers + void putLong(MapBuffer::Key key, int64_t value); void putBool(MapBuffer::Key key, bool value); diff --git a/packages/react-native/ReactCommon/react/renderer/mapbuffer/tests/MapBufferTest.cpp b/packages/react-native/ReactCommon/react/renderer/mapbuffer/tests/MapBufferTest.cpp index 8f3baaaf59fdcf..5be4c9e1272d25 100644 --- a/packages/react-native/ReactCommon/react/renderer/mapbuffer/tests/MapBufferTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/mapbuffer/tests/MapBufferTest.cpp @@ -5,6 +5,7 @@ * LICENSE file in the root directory of this source tree. */ +#include #include #include @@ -27,6 +28,26 @@ TEST(MapBufferTest, testSimpleIntMap) { EXPECT_EQ(map.getInt(1), 4321); } +TEST(MapBufferTest, testSimpleLongMap) { + auto builder = MapBufferBuilder(); + + int64_t minInt64 = std::numeric_limits::min(); + int64_t maxInt64 = std::numeric_limits::max(); + + builder.putLong(0, minInt64); + builder.putLong(1, maxInt64); + builder.putLong(2, 1125899906842623LL); + builder.putLong(3, -1125899906842623LL); + + auto map = builder.build(); + + EXPECT_EQ(map.count(), 4); + EXPECT_EQ(map.getLong(0), minInt64); + EXPECT_EQ(map.getLong(1), maxInt64); + EXPECT_EQ(map.getLong(2), 1125899906842623LL); + EXPECT_EQ(map.getLong(3), -1125899906842623LL); +} + TEST(MapBufferTest, testMapBufferExtension) { // 26 = 2 buckets: 2*10 + 6 sizeof(header) int initialSize = 26;