hashCall computes the composite bucket key for an async call. Only string, int, double, uint, and bool argument values contribute to the hash. More complex types rely on a richer notion of equivalence (e.g. unordered maps, proto equality, custom types) that a byte-level hash cannot capture safely,
(id int64, overload string, args []ref.Val)
| 150 | // that a byte-level hash cannot capture safely, so they are intentionally excluded from the key |
| 151 | // and are instead disambiguated within the bucket by asyncCallState.matches. |
| 152 | func hashCall(id int64, overload string, args []ref.Val) uint64 { |
| 153 | h := fnv.New64a() |
| 154 | var idBuf [8]byte |
| 155 | binary.LittleEndian.PutUint64(idBuf[:], uint64(id)) |
| 156 | h.Write(idBuf[:]) |
| 157 | h.Write([]byte(overload)) |
| 158 | h.Write(hashZeroMarker) |
| 159 | for _, arg := range args { |
| 160 | switch v := arg.(type) { |
| 161 | case types.String: |
| 162 | h.Write(hashStringMarker) |
| 163 | h.Write([]byte(string(v))) |
| 164 | case types.Bool: |
| 165 | if bool(v) { |
| 166 | h.Write(hashBoolTrueMarker) |
| 167 | } else { |
| 168 | h.Write(hashBoolFalseMarker) |
| 169 | } |
| 170 | case types.Int: |
| 171 | h.Write(hashNumberMarker) |
| 172 | var buf [8]byte |
| 173 | binary.LittleEndian.PutUint64(buf[:], math.Float64bits(float64(v))) |
| 174 | h.Write(buf[:]) |
| 175 | case types.Uint: |
| 176 | h.Write(hashNumberMarker) |
| 177 | var buf [8]byte |
| 178 | binary.LittleEndian.PutUint64(buf[:], math.Float64bits(float64(v))) |
| 179 | h.Write(buf[:]) |
| 180 | case types.Double: |
| 181 | h.Write(hashNumberMarker) |
| 182 | if math.IsNaN(float64(v)) { |
| 183 | h.Write([]byte("NaN")) |
| 184 | h.Write(hashZeroMarker) |
| 185 | continue |
| 186 | } |
| 187 | // Normalize -0.0 to 0.0. Go will treat -0.0 as 0.0 at compile time, |
| 188 | // but the function math.Copysign(0.0, -1.0) can be used to test the -0.0 case. |
| 189 | if v == types.Double(0.0) && math.Signbit(float64(v)) { |
| 190 | v = types.Double(0.0) |
| 191 | } |
| 192 | var buf [8]byte |
| 193 | binary.LittleEndian.PutUint64(buf[:], math.Float64bits(float64(v))) |
| 194 | h.Write(buf[:]) |
| 195 | default: |
| 196 | // Value intentionally omitted; bucket membership falls back to matches. |
| 197 | h.Write(hashDefaultMarker) |
| 198 | } |
| 199 | // Separator to avoid cross-argument collisions, e.g. ("a", "bc") vs ("ab", "c"). |
| 200 | h.Write(hashZeroMarker) |
| 201 | } |
| 202 | return h.Sum64() |
| 203 | } |
| 204 | |
| 205 | // findInBucket returns the call state in the bucket matching the same node id and call identity, |
| 206 | // or nil if no match is present. |