@@ -28,7 +28,7 @@ module Data.HashMap.Internal.Debug
28
28
import Data.Bits (complement , countTrailingZeros , popCount , shiftL ,
29
29
unsafeShiftL , (.&.) , (.|.) )
30
30
import Data.Hashable (Hashable )
31
- import Data.HashMap.Internal (Bitmap , Hash , HashMap (.. ), Leaf (.. ),
31
+ import Data.HashMap.Internal (Bitmap , Hash , HashMap (.. ), Leaf (.. ), Tree ( .. ),
32
32
bitsPerSubkey , fullBitmap , hash ,
33
33
isLeafOrCollision , maxChildren , sparseIndex )
34
34
import Data.Semigroup (Sum (.. ))
@@ -65,6 +65,7 @@ data Error k
65
65
| INV8_bad_Full_size ! Int
66
66
| INV9_Collision_size ! Int
67
67
| INV10_Collision_duplicate_key k ! Hash
68
+ | INV11_Negative_HM_Size ! Int
68
69
deriving (Eq , Show )
69
70
70
71
-- TODO: Name this 'Index'?!
@@ -95,55 +96,60 @@ hashMatchesSubHashPath (SubHashPath ph l) h = maskToLength h l == ph
95
96
maskToLength h' l' = h' .&. complement (complement 0 `shiftL` l')
96
97
97
98
valid :: Hashable k => HashMap k v -> Validity k
98
- valid Empty = Valid
99
- valid t = validInternal initialSubHashPath t
99
+ valid (HashMap sz hm) = if sz >= 0
100
+ then valid' hm
101
+ else Invalid (INV11_Negative_HM_Size $ A. unSize sz) initialSubHashPath
100
102
where
101
- validInternal p Empty = Invalid INV1_internal_Empty p
102
- validInternal p (Leaf h l) = validHash p h <> validLeaf p h l
103
- validInternal p (Collision h ary) = validHash p h <> validCollision p h ary
104
- validInternal p (BitmapIndexed b ary) = validBitmapIndexed p b ary
105
- validInternal p (Full ary) = validFull p ary
103
+ valid' :: Hashable k => Tree k v -> Validity k
104
+ valid' Empty = Valid
105
+ valid' t = validInternal initialSubHashPath t
106
+ where
107
+ validInternal p Empty = Invalid INV1_internal_Empty p
108
+ validInternal p (Leaf h l) = validHash p h <> validLeaf p h l
109
+ validInternal p (Collision h ary) = validHash p h <> validCollision p h ary
110
+ validInternal p (BitmapIndexed b ary) = validBitmapIndexed p b ary
111
+ validInternal p (Full ary) = validFull p ary
106
112
107
- validHash p h | hashMatchesSubHashPath p h = Valid
108
- | otherwise = Invalid (INV6_misplaced_hash h) p
113
+ validHash p h | hashMatchesSubHashPath p h = Valid
114
+ | otherwise = Invalid (INV6_misplaced_hash h) p
109
115
110
- validLeaf p h (L k _) | hash k == h = Valid
111
- | otherwise = Invalid (INV7_key_hash_mismatch k h) p
116
+ validLeaf p h (L k _) | hash k == h = Valid
117
+ | otherwise = Invalid (INV7_key_hash_mismatch k h) p
112
118
113
- validCollision p h ary = validCollisionSize <> A. foldMap (validLeaf p h) ary <> distinctKeys
114
- where
115
- n = A. length ary
116
- validCollisionSize | n < 2 = Invalid (INV9_Collision_size n) p
117
- | otherwise = Valid
118
- distinctKeys = A. foldMap (\ (L k _) -> appearsOnce k) ary
119
- appearsOnce k | A. foldMap (\ (L k' _) -> if k' == k then Sum @ Int 1 else Sum 0 ) ary == 1 = Valid
120
- | otherwise = Invalid (INV10_Collision_duplicate_key k h) p
121
-
122
- validBitmapIndexed p b ary = validBitmap <> validArraySize <> validSubTrees p b ary
123
- where
124
- validBitmap | b .&. complement fullBitmap == 0 = Valid
125
- | otherwise = Invalid (INV2_Bitmap_unexpected_1_bits b) p
126
- n = A. length ary
127
- validArraySize | n < 1 || n >= maxChildren = Invalid (INV3_bad_BitmapIndexed_size n) p
128
- | popCount b == n = Valid
129
- | otherwise = Invalid (INV4_bitmap_array_size_mismatch b n) p
130
-
131
- validSubTrees p b ary
132
- | A. length ary == 1
133
- , isLeafOrCollision (A. index ary 0 )
134
- = Invalid INV5_BitmapIndexed_invalid_single_subtree p
135
- | otherwise = go b
136
- where
137
- go 0 = Valid
138
- go b' = validInternal (addSubHash p (fromIntegral c)) (A. index ary i) <> go b''
119
+ validCollision p h ary = validCollisionSize <> A. foldMap (validLeaf p h) ary <> distinctKeys
139
120
where
140
- c = countTrailingZeros b'
141
- m = 1 `unsafeShiftL` c
142
- i = sparseIndex b m
143
- b'' = b' .&. complement m
144
-
145
- validFull p ary = validArraySize <> validSubTrees p fullBitmap ary
146
- where
147
- n = A. length ary
148
- validArraySize | n == maxChildren = Valid
149
- | otherwise = Invalid (INV8_bad_Full_size n) p
121
+ n = A. length ary
122
+ validCollisionSize | n < 2 = Invalid (INV9_Collision_size n) p
123
+ | otherwise = Valid
124
+ distinctKeys = A. foldMap (\ (L k _) -> appearsOnce k) ary
125
+ appearsOnce k | A. foldMap (\ (L k' _) -> if k' == k then Sum @ Int 1 else Sum 0 ) ary == 1 = Valid
126
+ | otherwise = Invalid (INV10_Collision_duplicate_key k h) p
127
+
128
+ validBitmapIndexed p b ary = validBitmap <> validArraySize <> validSubTrees p b ary
129
+ where
130
+ validBitmap | b .&. complement fullBitmap == 0 = Valid
131
+ | otherwise = Invalid (INV2_Bitmap_unexpected_1_bits b) p
132
+ n = A. length ary
133
+ validArraySize | n < 1 || n >= maxChildren = Invalid (INV3_bad_BitmapIndexed_size n) p
134
+ | popCount b == n = Valid
135
+ | otherwise = Invalid (INV4_bitmap_array_size_mismatch b n) p
136
+
137
+ validSubTrees p b ary
138
+ | A. length ary == 1
139
+ , isLeafOrCollision (A. index ary 0 )
140
+ = Invalid INV5_BitmapIndexed_invalid_single_subtree p
141
+ | otherwise = go b
142
+ where
143
+ go 0 = Valid
144
+ go b' = validInternal (addSubHash p (fromIntegral c)) (A. index ary i) <> go b''
145
+ where
146
+ c = countTrailingZeros b'
147
+ m = 1 `unsafeShiftL` c
148
+ i = sparseIndex b m
149
+ b'' = b' .&. complement m
150
+
151
+ validFull p ary = validArraySize <> validSubTrees p fullBitmap ary
152
+ where
153
+ n = A. length ary
154
+ validArraySize | n == maxChildren = Valid
155
+ | otherwise = Invalid (INV8_bad_Full_size n) p
0 commit comments