Skip to content

Commit ee0167f

Browse files
committed
fix(dart): cache compatible type metadata safely
1 parent 403d5a5 commit ee0167f

2 files changed

Lines changed: 102 additions & 110 deletions

File tree

dart/packages/fory/lib/src/resolver/type_resolver.dart

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -865,17 +865,14 @@ final class TypeResolver {
865865
return wireTypeMetaForResolved(sharedTypes[index]);
866866
}
867867
final header = TypeHeader(buffer.readInt64());
868-
final cached =
869-
config.compatible ? null : _parsedTypeMetaCache.lookup(header);
868+
final cached = _parsedTypeMetaCache.lookup(header);
870869
if (cached != null) {
871870
header.skipRemaining(buffer);
872871
sharedTypes.add(cached);
873872
return wireTypeMetaForResolved(cached);
874873
}
875874
final resolved = _readTypeDefWithHeader(buffer, header);
876-
if (!config.compatible) {
877-
_parsedTypeMetaCache.remember(header, resolved);
878-
}
875+
_parsedTypeMetaCache.remember(header, resolved);
879876
sharedTypes.add(resolved);
880877
return wireTypeMetaForResolved(resolved);
881878
}

dart/packages/fory/lib/src/util/hash_util.dart

Lines changed: 100 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -23,145 +23,155 @@ import 'package:fory/src/meta/field_info.dart';
2323
import 'package:fory/src/meta/type_def.dart';
2424
import 'package:fory/src/meta/type_ids.dart';
2525
import 'package:fory/src/types/int64.dart';
26+
import 'package:fory/src/types/uint64.dart';
2627

2728
const int _typeDefCompressMetaFlag = 1 << 9;
2829
const int _typeDefHasFieldsMetaFlag = 1 << 8;
2930
const int _typeDefMetaSizeMask = 0xff;
3031
const int _typeDefHashShift = 14;
3132

32-
final BigInt _mask64Big = (BigInt.one << 64) - BigInt.one;
33-
final BigInt _signBit64Big = BigInt.one << 63;
34-
final BigInt _metaStringHashMaskBig =
35-
BigInt.parse('ffffffffffffff00', radix: 16);
36-
final BigInt _c1Big = BigInt.parse('87c37b91114253d5', radix: 16);
37-
final BigInt _c2Big = BigInt.parse('4cf5ad432745937f', radix: 16);
33+
final Uint64 _metaStringHashMask = Uint64.fromWords(0xffffff00, 0xffffffff);
34+
final Uint64 _c1 = Uint64.fromWords(0x114253d5, 0x87c37b91);
35+
final Uint64 _c2 = Uint64.fromWords(0x2745937f, 0x4cf5ad43);
36+
final Uint64 _fmixC1 = Uint64.fromWords(0xed558ccd, 0xff51afd7);
37+
final Uint64 _fmixC2 = Uint64.fromWords(0x1a85ec53, 0xc4ceb9fe);
3838

39-
(int, int) murmurHash3X64_128(List<int> bytes, {int seed = 47}) {
40-
var h1 = seed & 0x00000000ffffffff;
41-
var h2 = seed & 0x00000000ffffffff;
39+
(Int64, Int64) murmurHash3X64_128(List<int> bytes, {int seed = 47}) {
40+
final hash = _murmurHash3X64_128Bits(bytes, seed: seed);
41+
return (_int64FromUint64(hash.$1), _int64FromUint64(hash.$2));
42+
}
43+
44+
(Uint64, Uint64) _murmurHash3X64_128Bits(List<int> bytes, {int seed = 47}) {
45+
var h1 = Uint64(seed & 0x00000000ffffffff);
46+
var h2 = Uint64(seed & 0x00000000ffffffff);
4247

4348
final blockCount = bytes.length ~/ 16;
4449
for (var index = 0; index < blockCount; index += 1) {
4550
var k1 = _readLongLittleEndian(bytes, index * 16);
4651
var k2 = _readLongLittleEndian(bytes, index * 16 + 8);
4752

48-
k1 = _mul64(k1, _c1Big);
53+
k1 = k1 * _c1;
4954
k1 = _rotateLeft64(k1, 31);
50-
k1 = _mul64(k1, _c2Big);
51-
h1 = _toSigned64(h1 ^ k1);
55+
k1 = k1 * _c2;
56+
h1 = h1 ^ k1;
5257

5358
h1 = _rotateLeft64(h1, 27);
54-
h1 = _add64(h1, h2);
55-
h1 = _add64(_mul64(h1, BigInt.from(5)), 0x52dce729);
59+
h1 = h1 + h2;
60+
h1 = (h1 * 5) + 0x52dce729;
5661

57-
k2 = _mul64(k2, _c2Big);
62+
k2 = k2 * _c2;
5863
k2 = _rotateLeft64(k2, 33);
59-
k2 = _mul64(k2, _c1Big);
60-
h2 = _toSigned64(h2 ^ k2);
64+
k2 = k2 * _c1;
65+
h2 = h2 ^ k2;
6166

6267
h2 = _rotateLeft64(h2, 31);
63-
h2 = _add64(h2, h1);
64-
h2 = _add64(_mul64(h2, BigInt.from(5)), 0x38495ab5);
68+
h2 = h2 + h1;
69+
h2 = (h2 * 5) + 0x38495ab5;
6570
}
6671

67-
var k1 = 0;
68-
var k2 = 0;
72+
var k1 = Uint64(0);
73+
var k2 = Uint64(0);
6974
final tailOffset = blockCount * 16;
7075
final tailLength = bytes.length & 15;
7176
if (tailLength >= 15) {
72-
k2 ^= (bytes[tailOffset + 14] & 0xff) << 48;
77+
k2 = k2 ^ (Uint64(bytes[tailOffset + 14] & 0xff) << 48);
7378
}
7479
if (tailLength >= 14) {
75-
k2 ^= (bytes[tailOffset + 13] & 0xff) << 40;
80+
k2 = k2 ^ (Uint64(bytes[tailOffset + 13] & 0xff) << 40);
7681
}
7782
if (tailLength >= 13) {
78-
k2 ^= (bytes[tailOffset + 12] & 0xff) << 32;
83+
k2 = k2 ^ (Uint64(bytes[tailOffset + 12] & 0xff) << 32);
7984
}
8085
if (tailLength >= 12) {
81-
k2 ^= (bytes[tailOffset + 11] & 0xff) << 24;
86+
k2 = k2 ^ (Uint64(bytes[tailOffset + 11] & 0xff) << 24);
8287
}
8388
if (tailLength >= 11) {
84-
k2 ^= (bytes[tailOffset + 10] & 0xff) << 16;
89+
k2 = k2 ^ (Uint64(bytes[tailOffset + 10] & 0xff) << 16);
8590
}
8691
if (tailLength >= 10) {
87-
k2 ^= (bytes[tailOffset + 9] & 0xff) << 8;
92+
k2 = k2 ^ (Uint64(bytes[tailOffset + 9] & 0xff) << 8);
8893
}
8994
if (tailLength >= 9) {
90-
k2 ^= bytes[tailOffset + 8] & 0xff;
91-
k2 = _mul64(k2, _c2Big);
95+
k2 = k2 ^ (bytes[tailOffset + 8] & 0xff);
96+
k2 = k2 * _c2;
9297
k2 = _rotateLeft64(k2, 33);
93-
k2 = _mul64(k2, _c1Big);
94-
h2 = _toSigned64(h2 ^ k2);
98+
k2 = k2 * _c1;
99+
h2 = h2 ^ k2;
95100
}
96101
if (tailLength >= 8) {
97-
k1 ^= _signedByte(bytes[tailOffset + 7]) << 56;
102+
k1 = k1 ^ (Uint64(bytes[tailOffset + 7] & 0xff) << 56);
98103
}
99104
if (tailLength >= 7) {
100-
k1 ^= (bytes[tailOffset + 6] & 0xff) << 48;
105+
k1 = k1 ^ (Uint64(bytes[tailOffset + 6] & 0xff) << 48);
101106
}
102107
if (tailLength >= 6) {
103-
k1 ^= (bytes[tailOffset + 5] & 0xff) << 40;
108+
k1 = k1 ^ (Uint64(bytes[tailOffset + 5] & 0xff) << 40);
104109
}
105110
if (tailLength >= 5) {
106-
k1 ^= (bytes[tailOffset + 4] & 0xff) << 32;
111+
k1 = k1 ^ (Uint64(bytes[tailOffset + 4] & 0xff) << 32);
107112
}
108113
if (tailLength >= 4) {
109-
k1 ^= (bytes[tailOffset + 3] & 0xff) << 24;
114+
k1 = k1 ^ (Uint64(bytes[tailOffset + 3] & 0xff) << 24);
110115
}
111116
if (tailLength >= 3) {
112-
k1 ^= (bytes[tailOffset + 2] & 0xff) << 16;
117+
k1 = k1 ^ (Uint64(bytes[tailOffset + 2] & 0xff) << 16);
113118
}
114119
if (tailLength >= 2) {
115-
k1 ^= (bytes[tailOffset + 1] & 0xff) << 8;
120+
k1 = k1 ^ (Uint64(bytes[tailOffset + 1] & 0xff) << 8);
116121
}
117122
if (tailLength >= 1) {
118-
k1 ^= bytes[tailOffset] & 0xff;
119-
k1 = _mul64(k1, _c1Big);
123+
k1 = k1 ^ (bytes[tailOffset] & 0xff);
124+
k1 = k1 * _c1;
120125
k1 = _rotateLeft64(k1, 31);
121-
k1 = _mul64(k1, _c2Big);
122-
h1 = _toSigned64(h1 ^ k1);
126+
k1 = k1 * _c2;
127+
h1 = h1 ^ k1;
123128
}
124129

125-
h1 = _toSigned64(h1 ^ bytes.length);
126-
h2 = _toSigned64(h2 ^ bytes.length);
130+
h1 = h1 ^ bytes.length;
131+
h2 = h2 ^ bytes.length;
127132

128-
h1 = _add64(h1, h2);
129-
h2 = _add64(h2, h1);
133+
h1 = h1 + h2;
134+
h2 = h2 + h1;
130135

131136
h1 = _fmix64(h1);
132137
h2 = _fmix64(h2);
133138

134-
h1 = _add64(h1, h2);
135-
h2 = _add64(h2, h1);
139+
h1 = h1 + h2;
140+
h2 = h2 + h1;
136141

137142
return (h1, h2);
138143
}
139144

140145
Int64 metaStringHash(List<int> bytes, {int encoding = 0}) {
141-
var hash = _absSigned64(murmurHash3X64_128(bytes).$1);
142-
if (hash == 0) {
143-
hash += 0x100;
146+
var hash =
147+
_absSigned64Bits(_int64FromUint64(_murmurHash3X64_128Bits(bytes).$1));
148+
if (hash.isZero) {
149+
hash = hash + 0x100;
144150
}
145-
hash = (BigInt.from(hash) & _metaStringHashMaskBig).toInt();
146-
return Int64(hash | (encoding & 0xff));
151+
hash = (hash & _metaStringHashMask) | (encoding & 0xff);
152+
return _int64FromUint64(hash);
147153
}
148154

149155
Int64 typeDefHeader(
150156
List<int> bytes, {
151157
required bool hasFieldsMeta,
152158
bool compressed = false,
153159
}) {
154-
final hash = _toSigned64(murmurHash3X64_128(bytes).$1 << _typeDefHashShift);
155-
var header = _absSigned64(hash);
160+
final hash = _int64FromUint64(
161+
_murmurHash3X64_128Bits(bytes).$1 << _typeDefHashShift,
162+
);
163+
var header = _absSigned64Bits(hash);
156164
if (compressed) {
157-
header |= _typeDefCompressMetaFlag;
165+
header = header | _typeDefCompressMetaFlag;
158166
}
159167
if (hasFieldsMeta) {
160-
header |= _typeDefHasFieldsMetaFlag;
168+
header = header | _typeDefHasFieldsMetaFlag;
161169
}
162-
header |=
163-
bytes.length > _typeDefMetaSizeMask ? _typeDefMetaSizeMask : bytes.length;
164-
return Int64(_toSigned64(header));
170+
header = header |
171+
(bytes.length > _typeDefMetaSizeMask
172+
? _typeDefMetaSizeMask
173+
: bytes.length);
174+
return _int64FromUint64(header);
165175
}
166176

167177
int schemaHash(TypeDef typeDef) {
@@ -180,8 +190,7 @@ int schemaHash(TypeDef typeDef) {
180190
.map((buffer) => buffer.toString())
181191
.toList(growable: false)
182192
..sort();
183-
final hash = murmurHash3X64_128(utf8.encode(parts.join())).$1;
184-
return hash & 0xffffffff;
193+
return _murmurHash3X64_128Bits(utf8.encode(parts.join())).$1.low32;
185194
}
186195

187196
int _fingerprintTypeId(FieldInfo field) {
@@ -207,56 +216,42 @@ int _fingerprintTypeId(FieldInfo field) {
207216
}
208217
}
209218

210-
int _toSigned64Big(BigInt value) {
211-
final normalized = _u64Big(value);
212-
if ((normalized & _signBit64Big) != BigInt.zero) {
213-
return (normalized - (BigInt.one << 64)).toInt();
214-
}
215-
return normalized.toInt();
216-
}
217-
218-
int _readLongLittleEndian(List<int> bytes, int offset) {
219-
final value = (_signedByte(bytes[offset + 7]) << 56) |
220-
((bytes[offset + 6] & 0xff) << 48) |
221-
((bytes[offset + 5] & 0xff) << 40) |
222-
((bytes[offset + 4] & 0xff) << 32) |
223-
((bytes[offset + 3] & 0xff) << 24) |
224-
((bytes[offset + 2] & 0xff) << 16) |
225-
((bytes[offset + 1] & 0xff) << 8) |
226-
(bytes[offset] & 0xff);
227-
return _toSigned64(value);
219+
Uint64 _readLongLittleEndian(List<int> bytes, int offset) {
220+
final low = (bytes[offset] & 0xff) +
221+
((bytes[offset + 1] & 0xff) << 8) +
222+
((bytes[offset + 2] & 0xff) << 16) +
223+
((bytes[offset + 3] & 0xff) * 0x1000000);
224+
final high = (bytes[offset + 4] & 0xff) +
225+
((bytes[offset + 5] & 0xff) << 8) +
226+
((bytes[offset + 6] & 0xff) << 16) +
227+
((bytes[offset + 7] & 0xff) * 0x1000000);
228+
return Uint64.fromWords(low, high);
228229
}
229230

230-
int _signedByte(int value) => value >= 0x80 ? value - 0x100 : value;
231-
232-
int _rotateLeft64(int value, int shift) {
233-
final normalized = _u64Big(BigInt.from(value));
234-
return _toSigned64Big((normalized << shift) | (normalized >> (64 - shift)));
231+
Uint64 _rotateLeft64(Uint64 value, int shift) {
232+
return (value << shift) | (value >> (64 - shift));
235233
}
236234

237-
int _unsignedRightShift64(int value, int shift) =>
238-
(_u64Big(BigInt.from(value)) >> shift).toInt();
239-
240-
int _mul64(int value, BigInt factor) =>
241-
_toSigned64Big(BigInt.from(value) * factor);
242-
243-
int _add64(int left, int right) =>
244-
_toSigned64Big(BigInt.from(left) + BigInt.from(right));
245-
246-
int _fmix64(int value) {
235+
Uint64 _fmix64(Uint64 value) {
247236
var mixed = value;
248-
mixed = _toSigned64(mixed ^ _unsignedRightShift64(mixed, 33));
249-
mixed = _mul64(mixed, BigInt.parse('ff51afd7ed558ccd', radix: 16));
250-
mixed = _toSigned64(mixed ^ _unsignedRightShift64(mixed, 33));
251-
mixed = _mul64(mixed, BigInt.parse('c4ceb9fe1a85ec53', radix: 16));
252-
mixed = _toSigned64(mixed ^ _unsignedRightShift64(mixed, 33));
237+
mixed = mixed ^ (mixed >> 33);
238+
mixed = mixed * _fmixC1;
239+
mixed = mixed ^ (mixed >> 33);
240+
mixed = mixed * _fmixC2;
241+
mixed = mixed ^ (mixed >> 33);
253242
return mixed;
254243
}
255244

256-
BigInt _u64Big(BigInt value) => value & _mask64Big;
257-
258-
int _toSigned64(int value) {
259-
return _toSigned64Big(BigInt.from(value));
245+
Uint64 _absSigned64Bits(Int64 value) {
246+
if (!value.isNegative) {
247+
return _uint64FromInt64(value);
248+
}
249+
final negated = -value;
250+
return Uint64.fromWords(negated.low32, negated.high32Unsigned);
260251
}
261252

262-
int _absSigned64(int value) => value < 0 ? -value : value;
253+
Int64 _int64FromUint64(Uint64 value) =>
254+
Int64.fromWords(value.low32, value.high32Unsigned);
255+
256+
Uint64 _uint64FromInt64(Int64 value) =>
257+
Uint64.fromWords(value.low32, value.high32Unsigned);

0 commit comments

Comments
 (0)