diff --git a/Cargo.lock b/Cargo.lock index 45eefc3a1551cda0884efa36f4562b9091a7db07_Q2FyZ28ubG9jaw==..6c2f8c41efbd29cdf7e60ad3370485cdac10f14e_Q2FyZ28ubG9jaw== 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -130,7 +130,7 @@ "serde", "serde_json", "smallvec", - "wy", + "wyhash", ] [[package]] @@ -180,6 +180,12 @@ ] [[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" + +[[package]] name = "redox_syscall" version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -248,6 +254,6 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "wy" -version = "1.1.2" +name = "wyhash" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -253,2 +259,5 @@ source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3dede6c845dff0b268e7b0c12bc92c97d1e9aafdce335e8e1d0eadbd52c7357" +checksum = "0fe26121db27575e4fb30ceded9806fbfe0edb489f170a17506d9ad0b1aca41c" +dependencies = [ + "rand_core", +] diff --git a/Cargo.toml b/Cargo.toml index 45eefc3a1551cda0884efa36f4562b9091a7db07_Q2FyZ28udG9tbA==..6c2f8c41efbd29cdf7e60ad3370485cdac10f14e_Q2FyZ28udG9tbA== 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,7 +60,7 @@ serde = { version = "1", default_features = false } serde_json = { path = "./json", default_features = false, features = ["std"] } smallvec = { version = "1", default_features = false, features = ["const_generics", "union", "specialization", "write"] } -wy = { version = "1" } +wyhash = { version = "0.4" } [target.'cfg(any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "i686", target_arch = "armv7"))'.dependencies] encoding_rs = { path = "./encoding_rs", default_features = false, features = ["simd-accel"] } diff --git a/src/deserialize/cache.rs b/src/deserialize/cache.rs index 45eefc3a1551cda0884efa36f4562b9091a7db07_c3JjL2Rlc2VyaWFsaXplL2NhY2hlLnJz..6c2f8c41efbd29cdf7e60ad3370485cdac10f14e_c3JjL2Rlc2VyaWFsaXplL2NhY2hlLnJz 100644 --- a/src/deserialize/cache.rs +++ b/src/deserialize/cache.rs @@ -34,6 +34,6 @@ } pub type KeyMap = - AssociativeCache<u32, CachedKey, Capacity512, HashDirectMapped, RoundRobinReplacement>; + AssociativeCache<u64, CachedKey, Capacity512, HashDirectMapped, RoundRobinReplacement>; pub static mut KEY_MAP: OnceCell<KeyMap> = OnceCell::new(); diff --git a/src/deserialize/decode.rs b/src/deserialize/decode.rs index 45eefc3a1551cda0884efa36f4562b9091a7db07_c3JjL2Rlc2VyaWFsaXplL2RlY29kZS5ycw==..6c2f8c41efbd29cdf7e60ad3370485cdac10f14e_c3JjL2Rlc2VyaWFsaXplL2RlY29kZS5ycw== 100644 --- a/src/deserialize/decode.rs +++ b/src/deserialize/decode.rs @@ -10,7 +10,7 @@ use std::borrow::Cow; use std::fmt; use std::ptr::NonNull; -use wy::hash32; +use wyhash::wyhash; pub fn deserialize( ptr: *mut pyo3::ffi::PyObject, @@ -169,7 +169,7 @@ let pyhash: pyo3::ffi::Py_hash_t; let value = map.next_value_seed(self)?; if likely!(key.len() <= 64) { - let hash = unsafe { hash32(key.as_bytes(), HASH_SEED) }; + let hash = unsafe { wyhash(key.as_bytes(), HASH_SEED) }; { let map = unsafe { KEY_MAP diff --git a/src/typeref.rs b/src/typeref.rs index 45eefc3a1551cda0884efa36f4562b9091a7db07_c3JjL3R5cGVyZWYucnM=..6c2f8c41efbd29cdf7e60ad3370485cdac10f14e_c3JjL3R5cGVyZWYucnM= 100644 --- a/src/typeref.rs +++ b/src/typeref.rs @@ -17,7 +17,7 @@ pub uint32: *mut PyTypeObject, pub uint8: *mut PyTypeObject, } -pub static mut HASH_SEED: u32 = 0; +pub static mut HASH_SEED: u64 = 0; pub static mut NONE: *mut PyObject = 0 as *mut PyObject; pub static mut TRUE: *mut PyObject = 0 as *mut PyObject; @@ -102,7 +102,7 @@ ARRAY_STRUCT_STR = pyo3::ffi::PyUnicode_InternFromString("__array_struct__\0".as_ptr() as *const c_char); VALUE_STR = pyo3::ffi::PyUnicode_InternFromString("value\0".as_ptr() as *const c_char); - HASH_SEED = ((VALUE_STR as u64).wrapping_mul(DICT_TYPE as u64)) as u32; + HASH_SEED = (VALUE_STR as u64).wrapping_mul(DICT_TYPE as u64); DEFAULT = PyUnicode_InternFromString("default\0".as_ptr() as *const c_char); OPTION = PyUnicode_InternFromString("option\0".as_ptr() as *const c_char); JsonEncodeError = pyo3::ffi::PyExc_TypeError; diff --git a/test/test_type.py b/test/test_type.py index 45eefc3a1551cda0884efa36f4562b9091a7db07_dGVzdC90ZXN0X3R5cGUucHk=..6c2f8c41efbd29cdf7e60ad3370485cdac10f14e_dGVzdC90ZXN0X3R5cGUucHk= 100644 --- a/test/test_type.py +++ b/test/test_type.py @@ -380,3 +380,17 @@ """ with self.assertRaises(orjson.JSONEncodeError): orjson.dumps(object()) + + def test_dict_similar_keys(self): + """ + loads() similar keys + + This was a regression in 3.4.2 caused by using + the implementation in wy instead of wyhash. + """ + self.assertEqual( + orjson.loads( + '{"cf_status_firefox67": "---", "cf_status_firefox57": "verified"}' + ), + {"cf_status_firefox57": "verified", "cf_status_firefox67": "---"}, + )