# std/hashes

Theme:

- Manual
- Standard library
- Index
- Compiler docs
- Fusion docs
- devel, stable

Search:
Source Edit

This module implements efficient computations of hash values for diverse Nim types. All the procs are based on these two building blocks:

- !& proc used to start or mix a hash value, and
- !$ proc used to finish the hash value.

If you want to implement hash procs for your custom types, you will end up writing the following kind of skeleton of code:

Example:

    import std/hashes
    type
      Something = object
        foo: int
        bar: string

    iterator items(x: Something): Hash =
      yield hash(x.foo)
      yield hash(x.bar)

    proc hash(x: Something): Hash =
      ## Computes a Hash from `x`.
      var h: Hash = 0
      # Iterate over parts of `x`.
      for xAtom in x:
        # Mix the atom with the partial hash.
        h = h !& xAtom
      # Finish the hash.
      result = !$h

If your custom types contain fields for which there already is a `hash` proc, you can simply hash together the hash values of the individual fields:

Example:

    import std/hashes
    type
      Something = object
        foo: int
        bar: string

    proc hash(x: Something): Hash =
      ## Computes a Hash from `x`.
      var h: Hash = 0
      h = h !& hash(x.foo)
      h = h !& hash(x.bar)
      result = !$h

Important: Use `-d:nimPreviewHashRef` to enable hashing `ref`s. It is expected that this behavior becomes the new default in upcoming versions.
Note: If the type has a `==` operator, the following must hold: If two values compare equal, their hashes must also be equal.

# See also

- md5 module for the MD5 checksum algorithm
- base64 module for a Base64 encoder and decoder
- sha1 module for the SHA-1 checksum algorithm
- tables module for hash tables

# Imports

since, jsutils, endians

# Types

    Hash = int

  A hash value. Hash tables using these values should always have a size of a power of two so they can use the `and` operator instead of `mod` for truncation of the hash value. Source Edit

# Procs

    proc `!$`(h: Hash): Hash {.inline, ...raises: [], tags: [], forbids: [].}

  Finishes the computation of the hash value.

  This is only needed if you need to implement a `hash` proc for a new datatype.

  Source Edit

    proc `!&`(h: Hash; val: int): Hash {.inline, ...raises: [], tags: [], forbids: [].}

  Mixes a hash value `h` with `val` to produce a new hash value.

  This is only needed if you need to implement a `hash` proc for a new datatype.

  Source Edit

    proc hash(sBuf: string; sPos, ePos: int): Hash {....raises: [], tags: [],
        forbids: [].}

  Efficient hashing of a string buffer, from starting position `sPos` to ending position `ePos` (included).

  `hash(myStr, 0, myStr.high)` is equivalent to `hash(myStr)`.

  Example:

      var a = "abracadabra"
      doAssert hash(a, 0, 3) == hash(a, 7, 10)

  Source Edit

    proc hash(x: cstring): Hash {....raises: [], tags: [], forbids: [].}

  Efficient hashing of null-terminated strings.

  Example:

      doAssert hash(cstring"abracadabra") == hash("abracadabra")
      doAssert hash(cstring"AbracadabrA") == hash("AbracadabrA")
      doAssert hash(cstring"abracadabra") != hash(cstring"AbracadabrA")

  Source Edit

    proc hash(x: float): Hash {.inline, ...raises: [], tags: [], forbids: [].}

  Efficient hashing of floats. Source Edit

    proc hash(x: pointer): Hash {.inline, ...raises: [], tags: [], forbids: [].}

  Efficient `hash` overload. Source Edit

    proc hash(x: string): Hash {....raises: [], tags: [], forbids: [].}

  Efficient hashing of strings.

  See also:

  - hashIgnoreStyle
  - hashIgnoreCase

  Example:

      doAssert hash("abracadabra") != hash("AbracadabrA")

  Source Edit

    proc hash[A](aBuf: openArray[A]; sPos, ePos: int): Hash

  Efficient hashing of portions of arrays and sequences, from starting position `sPos` to ending position `ePos` (included). There must be a `hash` proc defined for the element type `A`.

  `hash(myBuf, 0, myBuf.high)` is equivalent to `hash(myBuf)`.

  Example:

      let a = [1, 2, 5, 1, 2, 6]
      doAssert hash(a, 0, 1) == hash(a, 3, 4)

  Source Edit

    proc hash[A](x: openArray[A]): Hash

  Source Edit

    proc hash[A](x: set[A]): Hash

  Source Edit

    proc hash[T: Ordinal | enum](x: T): Hash {.inline.}

  Efficient hashing of integers. Source Edit

    proc hash[T: tuple | object | proc | iterator {.closure.}](x: T): Hash

  Efficient `hash` overload.

  Example:

      # for `tuple|object`, `hash` must be defined for each component of `x`.
      type Obj = object
        x: int
        y: string
      type Obj2[T] = object
        x: int
        y: string
      assert hash(Obj(x: 520, y: "Nim")) != hash(Obj(x: 520, y: "Nim2"))
      # you can define custom hashes for objects (even if they're generic):
      proc hash(a: Obj2): Hash = hash((a.x))
      assert hash(Obj2[float](x: 520, y: "Nim")) == hash(Obj2[float](x: 520, y: "Nim2"))

  Example:

      # proc
      proc fn1() = discard
      const fn1b = fn1
      assert hash(fn1b) == hash(fn1)

      # closure
      proc outer =
        var a = 0
        proc fn2() = a.inc
        assert fn2 is "closure"
        let fn2b = fn2
        assert hash(fn2b) == hash(fn2)
        assert hash(fn2) != hash(fn1)
      outer()

  Source Edit

    proc hash[T](x: ptr [T]): Hash {.inline.}

  Efficient `hash` overload.

  Example:

      var a: array[10, uint8]
      assert a[0].addr.hash != a[1].addr.hash
      assert cast[pointer](a[0].addr).hash == a[0].addr.hash

  Source Edit

    proc hash[T](x: ref [T]): Hash {.inline.}

  Efficient `hash` overload.
  Important: Use `-d:nimPreviewHashRef` to enable hashing `ref`s. It is expected that this behavior becomes the new default in upcoming versions.

  Example: cmd: -d:nimPreviewHashRef

      type A = ref object
        x: int
      let a = A(x: 3)
      let ha = a.hash
      assert ha != A(x: 3).hash # A(x: 3) is a different ref object from `a`.
      a.x = 4
      assert ha == a.hash # the hash only depends on the address

  Example: cmd: -d:nimPreviewHashRef

      # you can overload `hash` if you want to customize semantics
      type A[T] = ref object
        x, y: T
      proc hash(a: A): Hash = hash(a.x)
      assert A[int](x: 3, y: 4).hash == A[int](x: 3, y: 5).hash

  Source Edit

    proc hashData(data: pointer; size: int): Hash {....raises: [], tags: [],
        forbids: [].}

  Hashes an array of bytes of size `size`. Source Edit

    proc hashIdentity[T: Ordinal | enum](x: T): Hash {.inline.}

  The identity hash, i.e. `hashIdentity(x) = x`. Source Edit

    proc hashIgnoreCase(sBuf: string; sPos, ePos: int): Hash {....raises: [], tags: [],
        forbids: [].}

  Efficient hashing of a string buffer, from starting position `sPos` to ending position `ePos` (included); case is ignored.

  Note: This uses a different hashing algorithm than `hash(string)`.

  `hashIgnoreCase(myBuf, 0, myBuf.high)` is equivalent to `hashIgnoreCase(myBuf)`.

  Example:

      var a = "ABracadabRA"
      doAssert hashIgnoreCase(a, 0, 3) == hashIgnoreCase(a, 7, 10)

  Source Edit

    proc hashIgnoreCase(x: string): Hash {....raises: [], tags: [], forbids: [].}

  Efficient hashing of strings; case is ignored.

  Note: This uses a different hashing algorithm than `hash(string)`.

  See also:

  - hashIgnoreStyle

  Example:

      doAssert hashIgnoreCase("ABRAcaDABRA") == hashIgnoreCase("abRACAdabra")
      doAssert hashIgnoreCase("abcdefghi") != hash("abcdefghi")

  Source Edit

    proc hashIgnoreStyle(sBuf: string; sPos, ePos: int): Hash {....raises: [],
        tags: [], forbids: [].}

  Efficient hashing of a string buffer, from starting position `sPos` to ending position `ePos` (included); style is ignored.

  Note: This uses a different hashing algorithm than `hash(string)`.

  `hashIgnoreStyle(myBuf, 0, myBuf.high)` is equivalent to `hashIgnoreStyle(myBuf)`.

  Example:

      var a = "ABracada_b_r_a"
      doAssert hashIgnoreStyle(a, 0, 3) == hashIgnoreStyle(a, 7, a.high)

  Source Edit

    proc hashIgnoreStyle(x: string): Hash {....raises: [], tags: [], forbids: [].}

  Efficient hashing of strings; style is ignored.

  Note: This uses a different hashing algorithm than `hash(string)`.

  See also:

  - hashIgnoreCase

  Example:

      doAssert hashIgnoreStyle("aBr_aCa_dAB_ra") == hashIgnoreStyle("abracadabra")
      doAssert hashIgnoreStyle("abcdefghi") != hash("abcdefghi")

  Source Edit

    proc hashWangYi1(x: int64 | uint64 | Hash): Hash {.inline.}

  Wang Yi's hash_v1 for 64-bit ints (see https://github.com/rurban/smhasher for more details). This passed all scrambling tests in Spring 2019 and is simple.

  Note: It's ok to define `proc(x: int16): Hash = hashWangYi1(Hash(x))`.

  Source Edit