Coverage for /home/jenkins/workspace/NDS/Zserio/NDS_ZSERIO-linux-build/compiler/extensions/python/runtime/src/zserio/hashcode.py: 100%

90 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-12-13 15:12 +0000

1""" 

2The module provides utility methods for hash code calculation. 

3""" 

4 

5import typing 

6 

7from zserio.float import float_to_uint32, float_to_uint64 

8 

9HASH_SEED = 23 

10HASH_PRIME_NUMBER = 37 

11 

12def calc_hashcode_bool(seed_value: int, value: bool) -> int: 

13 """ 

14 Calculates hash code for a boolean value. 

15 

16 :param seed_value: Seed value (current hash code). 

17 :param value: Value to use. 

18 :returns: Calculated hash code. 

19 """ 

20 

21 return calc_hashcode_int32(seed_value, 1 if value else 0) 

22 

23def calc_hashcode_int32(seed_value: int, value: int) -> int: 

24 """ 

25 Calculates hash code for a 32-bit integral value. 

26 

27 :param seed_value: Seed value (current hash code). 

28 :param value: Value to use. 

29 :returns: Calculated hash code. 

30 """ 

31 

32 if value is None: 

33 return calc_hashcode_int32(seed_value, 0) 

34 

35 return (HASH_PRIME_NUMBER * seed_value + value) & 0xFFFFFFFF 

36 

37def calc_hashcode_int64(seed_value: int, value: int) -> int: 

38 """ 

39 Calculates hash code for a 64-bit integral value. 

40 

41 :param seed_value: Seed value (current hash code). 

42 :param value: Value to use. 

43 :returns: Calculated hash code. 

44 """ 

45 

46 if value is None: 

47 return calc_hashcode_int32(seed_value, 0) 

48 

49 int_value_for_hash = (value & 0xFFFFFFFF) ^ ((value & 0xFFFFFFFFFFFFFFFF) >> 32) 

50 return (HASH_PRIME_NUMBER * seed_value + int_value_for_hash) & 0xFFFFFFFF 

51 

52def calc_hashcode_float32(seed_value: int, value: float) -> int: 

53 """ 

54 Calculates hash code for a 32-bit float value. 

55 

56 :param seed_value: Seed value (current hash code). 

57 :param value: Value to use. 

58 :returns: Calculated hash code. 

59 """ 

60 

61 if value is None: 

62 return calc_hashcode_int32(seed_value, 0) 

63 

64 int_value = float_to_uint32(value) 

65 return calc_hashcode_int32(seed_value, int_value) 

66 

67def calc_hashcode_float64(seed_value: int, value: float) -> int: 

68 """ 

69 Calculates hash code for a 64-bit float value. 

70 

71 :param seed_value: Seed value (current hash code). 

72 :param value: Value to use. 

73 :returns: Calculated hash code. 

74 """ 

75 

76 if value is None: 

77 return calc_hashcode_int32(seed_value, 0) 

78 

79 int_value = float_to_uint64(value) 

80 return calc_hashcode_int64(seed_value, int_value) 

81 

82def calc_hashcode_bytes(seed_value: int, value: bytearray) -> int: 

83 """ 

84 Calculates hash code for a bytes value. 

85 

86 :param seed_value: Seed value (current hash code). 

87 :param value: Value to use. 

88 :returns: Calculated hash code. 

89 """ 

90 

91 if value is None: 

92 return calc_hashcode_int32(seed_value, 0) 

93 

94 result = seed_value 

95 for element in value: 

96 result = calc_hashcode_int32(result, element) 

97 

98 return result 

99 

100def calc_hashcode_string(seed_value: int, value: str) -> int: 

101 """ 

102 Calculates hash code for a string value. 

103 

104 :param seed_value: Seed value (current hash code). 

105 :param value: Value to use. 

106 :returns: Calculated hash code. 

107 """ 

108 

109 if value is None: 

110 return calc_hashcode_int32(seed_value, 0) 

111 

112 result = seed_value 

113 for element in value: 

114 result = calc_hashcode_int32(result, ord(element)) 

115 

116 return result 

117 

118def calc_hashcode_object(seed_value: int, value: typing.Any) -> int: 

119 """ 

120 Calculates hash code for an object value. 

121 

122 This is used for all objects (in zserio runtime or generated) which override the default __hash__ method. 

123 

124 :param seed_value: Seed value (current hash code). 

125 :param value: Value to use. 

126 :returns: Calculated hash code. 

127 """ 

128 

129 # using __hash__ to prevent 32-bit Python hash() truncation 

130 # pylint: disable=unnecessary-dunder-call 

131 return calc_hashcode_int32(seed_value, value.__hash__() if value else 0) 

132 

133def calc_hashcode_bool_array(seed_value: int, value: typing.List[bool]) -> int: 

134 """ 

135 Calculates hash code for a boolean array value. 

136 

137 :param seed_value: Seed value (current hash code). 

138 :param value: Value to use. 

139 :returns: Calculated hash code. 

140 """ 

141 

142 if value is None: 

143 return calc_hashcode_int32(seed_value, 0) 

144 

145 result = seed_value 

146 for element in value: 

147 result = calc_hashcode_bool(result, element) 

148 return result 

149 

150def calc_hashcode_int_array(seed_value: int, value: typing.List[int]) -> int: 

151 """ 

152 Calculates hash code for an integral array value. 

153 

154 :param seed_value: Seed value (current hash code). 

155 :param value: Value to use. 

156 :returns: Calculated hash code. 

157 """ 

158 

159 if value is None: 

160 return calc_hashcode_int32(seed_value, 0) 

161 

162 result = seed_value 

163 for element in value: 

164 result = calc_hashcode_int32(result, element) 

165 return result 

166 

167def calc_hashcode_float32_array(seed_value: int, value: typing.List[int]) -> int: 

168 """ 

169 Calculates hash code for a 32-bit float array value. 

170 

171 :param seed_value: Seed value (current hash code). 

172 :param value: Value to use. 

173 :returns: Calculated hash code. 

174 """ 

175 

176 if value is None: 

177 return calc_hashcode_int32(seed_value, 0) 

178 

179 result = seed_value 

180 for element in value: 

181 result = calc_hashcode_float32(result, element) 

182 return result 

183 

184def calc_hashcode_float64_array(seed_value: int, value: typing.List[int]) -> int: 

185 """ 

186 Calculates hash code for a 64-bit float array value. 

187 

188 :param seed_value: Seed value (current hash code). 

189 :param value: Value to use. 

190 :returns: Calculated hash code. 

191 """ 

192 

193 if value is None: 

194 return calc_hashcode_int32(seed_value, 0) 

195 

196 result = seed_value 

197 for element in value: 

198 result = calc_hashcode_float64(result, element) 

199 return result 

200 

201def calc_hashcode_bytes_array(seed_value: int, value: typing.List[bytearray]) -> int: 

202 """ 

203 Calculates hash code for a bytes array value. 

204 

205 :param seed_value: Seed value (current hash code). 

206 :param value: Value to use. 

207 :returns: Calculated hash code. 

208 """ 

209 

210 if value is None: 

211 return calc_hashcode_int32(seed_value, 0) 

212 

213 result = seed_value 

214 for element in value: 

215 result = calc_hashcode_bytes(result, element) 

216 return result 

217 

218def calc_hashcode_string_array(seed_value: int, value: typing.List[str]) -> int: 

219 """ 

220 Calculates hash code for a string array value. 

221 

222 :param seed_value: Seed value (current hash code). 

223 :param value: Value to use. 

224 :returns: Calculated hash code. 

225 """ 

226 

227 if value is None: 

228 return calc_hashcode_int32(seed_value, 0) 

229 

230 result = seed_value 

231 for element in value: 

232 result = calc_hashcode_string(result, element) 

233 return result 

234 

235def calc_hashcode_object_array(seed_value: int, value: typing.List[typing.Any]) -> int: 

236 """ 

237 Calculates hash code for an object array value. 

238 

239 This is used for arrays of all objects (in zserio runtime or generated) which override the default 

240 __hash__ method. 

241 

242 :param seed_value: Seed value (current hash code). 

243 :param value: Value to use. 

244 :returns: Calculated hash code. 

245 """ 

246 

247 if value is None: 

248 return calc_hashcode_int32(seed_value, 0) 

249 

250 result = seed_value 

251 for element in value: 

252 result = calc_hashcode_object(result, element) 

253 return result