Skip to content

Commit

Permalink
Add XXH128 supports
Browse files Browse the repository at this point in the history
  • Loading branch information
ba0f3 committed Jul 26, 2024
1 parent e582337 commit 1b6093f
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 13 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
# xxhash.nim
xxhash wrapper for Nim


## Credits
This module uses [@rockcavera](https://github.com/rockcavera)'s [nint128](https://github.com/rockcavera/nim-nint128) for XXH128 computation
80 changes: 69 additions & 11 deletions src/xxhash.nim
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import pkg/nint128

{.compile: "private/xxHash/xxhash.c".}

# One-shot functions
proc XXH32*(input: ptr UncheckedArray[byte], length: csize_t, seed: uint32): uint32 {.cdecl, importc: "XXH32".}
proc XXH64*(input: ptr UncheckedArray[byte], length: csize_t, seed: uint64): uint64 {.cdecl, importc: "XXH64".}
proc XXH32*(input: ptr UncheckedArray[byte], length: csize_t, seed: uint32): uint32 {.cdecl, importc.}
proc XXH64*(input: ptr UncheckedArray[byte], length: csize_t, seed: uint64): uint64 {.cdecl, importc.}

proc XXH32*(input: cstring, length: int, seed: uint32): uint32 {.inline.} =
XXH32(cast[ptr UncheckedArray[byte]](input), length.csize_t, seed)
Expand All @@ -16,13 +18,28 @@ proc XXH32*(input: string, seed = 0): uint32 {.inline.} =
proc XXH64*(input: string, seed = 0): uint64 {.inline.} =
XXH64(input.cstring, input.len, seed.uint64)

proc XXH3_64bits*(input: ptr UncheckedArray[byte], length: csize_t): uint64 {.cdecl, importc: "XXH3_64bits".}
proc XXH3_64bits_withSeed*(input: ptr UncheckedArray[byte], length: csize_t, seed: uint64): uint64 {.cdecl, importc: "XXH3_64bits_withSeed".}
proc XXH3_64bits*(input: ptr UncheckedArray[byte], length: csize_t): uint64 {.cdecl, importc.}
proc XXH3_64bits_withSeed*(input: ptr UncheckedArray[byte], length: csize_t, seed: uint64): uint64 {.cdecl, importc.}

template XXH3_64bits*(input: string): uint64 =
XXH3_64bits(cast[ptr UncheckedArray[byte]](input.cstring), input.len.csize_t)
template XXH3_64bits_withSeed*(input: string, seed: uint64): uint64 =
XXH3_64bits_withSeed(cast[ptr UncheckedArray[byte]](input.cstring), input.len.csize_t, seed)


proc XXH3_64bits*(input: string): uint64 =
XXH3_64bits(cast[ptr UncheckedArray[byte]](unsafeAddr input[0]), input.len.csize_t)
proc XXH3_64bits_withSeed*(input: string, seed: uint64): uint64 =
XXH3_64bits_withSeed(cast[ptr UncheckedArray[byte]](unsafeAddr input[0]), input.len.csize_t, seed)
proc XXH3_128bits*(input: ptr UncheckedArray[byte], length: csize_t): UInt128 {.cdecl, importc.}
proc XXH3_128bits_withSeed*(input: ptr UncheckedArray[byte], length: csize_t, seed: uint64): UInt128 {.cdecl, importc.}
proc XXH3_128bits_withSecret*(input: ptr UncheckedArray[byte], length: csize_t, secret: ptr UncheckedArray[byte], secretSize: csize_t): UInt128 {.cdecl, importc.}
proc XXH3_128bits_withSecretandSeed*(input: ptr UncheckedArray[byte], length: csize_t, secret: ptr UncheckedArray[byte], secretSize: csize_t, seed: uint64): UInt128 {.cdecl, importc.}

template XXH3_128bits*(input: string): UInt128 =
XXH3_128bits(cast[ptr UncheckedArray[byte]](input.cstring), input.len.csize_t)
template XXH3_128bits_withSeed*(input: string, seed: uint64): UInt128 =
XXH3_128bits_withSeed(cast[ptr UncheckedArray[byte]](input.cstring), input.len.csize_t, seed)
template XXH3_128bits_withSecret*(input: string, secret: string): UInt128 =
XXH3_128bits_withSecret(cast[ptr UncheckedArray[byte]](input.cstring), input.len.csize_t, cast[ptr UncheckedArray[byte]](secret.cstring), secret.len.csize_t)
template XXH3_128bits_withSecretandSeed*(input: string, secret: string, seed: uint64): UInt128 =
XXH3_128bits_withSecretandSeed(cast[ptr UncheckedArray[byte]](input.cstring), input.len.csize_t, cast[ptr UncheckedArray[byte]](secret.cstring), secret.len.csize_t, seed)

# Streaming api
type
Expand All @@ -35,6 +52,8 @@ type
llstate*: LLxxh64State # wrapped in a object for destructor
Xxh3_64State* = object
llstate*: LLxxh3_64State # wrapped in a object for destructor
Xxh128State* = object
llstate*: LLxxh3_64State

proc XXH32_createState*(): LLxxh32State {.cdecl, importc: "XXH32_createState".}
proc XXH32_freeState*(state: LLxxh32State) {.cdecl, importc: "XXH32_freeState".}
Expand All @@ -58,7 +77,7 @@ proc `$`*(state: Xxh32State): string =
proc reset*(state: Xxh32State, seed = 0'u32) =
state.llstate.XXH32_reset(seed)

proc `=destroy`*(state: var Xxh32State) =
proc `=destroy`*(state: Xxh32State) =
state.llstate.XXH32_freeState()


Expand All @@ -85,7 +104,7 @@ proc `$`*(state: XxH3_64State): string =
proc reset*(state: XxH3_64State, seed = 0'u64) =
state.llstate.XXH3_64_reset_withSeed(seed)

proc `=destroy`*(state: var XxH3_64State) =
proc `=destroy`*(state: XxH3_64State) =
state.llstate.XXH3_freeState()

proc XXH64_createState*(): LLxxh64State {.cdecl, importc: "XXH64_createState".}
Expand All @@ -110,20 +129,59 @@ proc `$`*(state: Xxh64State): string =
proc reset*(state: Xxh64State, seed = 0'u64) =
state.llstate.XXH64_reset(seed)

proc `=destroy`*(state: var Xxh64State) =
proc `=destroy`*(state: Xxh64State) =
state.llstate.XXH64_freeState()

proc XXH128_reset*(state: LLxxh3_64State, seed: uint64 = 0) {.cdecl, importc: "XXH3_128bits_reset".}
proc XXH128_reset_withSeed*(state: LLxxh3_64State, seed: uint64 = 0) {.cdecl, importc: "XXH128_reset_withSeed".}
proc XXH128_reset_withSecret*(state: LLxxh3_64State, secret: cstring, len: int) {.cdecl, importc: "XXH128_reset_withSecret".}
proc XXH128_update*(state: LLxxh3_64State, input: cstring, len: int) {.cdecl, importc: "XXH128_update".}
proc XXH128_digest*(state: LLxxh3_64State): UInt128 {.cdecl, importc: "XXH128_digest".}

proc newXxh128*(seed: uint64 = 0): Xxh128State =
result.llstate = XXH3_createState()
result.llstate.XXH128_reset_withSeed(seed)

proc newXxh128*(secret: string): Xxh128State =
result.llstate = XXH3_createState()
result.llstate.XXH128_reset_withSecret(secret.cstring, secret.len)

proc update*(state: Xxh128State, input: string) =
state.llstate.XXH128_update(input.cstring, input.len)

proc digest*(state: Xxh128State): UInt128 =
return state.llstate.XXH128_digest()

proc `$`*(state: Xxh128State): string =
return $state.digest

proc reset*(state: Xxh128State, seed = 0'u64) =
state.llstate.XXH128_reset_withSeed(seed)

proc resetWithSecret*(state: Xxh128State, secret: string) =
state.llstate.XXH128_reset_withSecret(secret.cstring, secret.len)

proc `=destroy`*(state: Xxh128State) =
state.llstate.XXH3_freeState()

when isMainModule:
import strutils
block:
# One Shot
assert 3794352943'u32 == XXH32("Nobody inspects the spammish repetition")
assert 0xB559B98D844E0635'u64 == XXH64("xxhash", 20141025)

block:
assert 16629034431890738719'u64 == XXH3_64bits("a")
assert 0x7051CC31E84FF73'u64 == XXH3_64bits("meow")
assert 0x4268DCFE699316D8'u64 == XXH3_64bits_withSeed("meow meow meow", 42)
assert XXH3_64bits("Abracadabra") == XXH3_64bits_withSeed("Abracadabra", 0)

block:
assert parseUInt128("225219434562328483135862406050043285023") == XXH3_128bits("a")
assert parseUInt128("225219434562328483135862406050043285023") == XXH3_128bits_withSeed("a", 0)
assert parseUInt128("337425133163118381928709500770786453280") == XXH3_128bits_withSeed("a", 1)

const msg = "foo"
const msgh32 = 0xe20f0dd9'u32
const msgh64 = 0x33bf00a859c4ba3f'u64
Expand Down
4 changes: 2 additions & 2 deletions xxhash.nimble
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
[Package]
name = "xxhash"
version = "0.10.0"
version = "0.11.0"
author = "Huy Doan"
description = "xxhash wrapper for Nim"
license = "MIT"
srcDir = "src"

[Deps]
Requires: "nim >= 1.2.6"
Requires: "nim >= 1.2.6", "nint128 >= 0.3.3"

0 comments on commit 1b6093f

Please sign in to comment.