My working unpac space for OCaml projects in development
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Use vendored ocaml-xxhash library instead of local implementation

- Remove local src/xxhash.ml (was duplicated code)
- Add xxhash library dependency to dune
- ocaml-xxhash is now vendored at vendor/opam/ocaml-xxhash

This uses the comprehensive, tested xxhash implementation that has been
validated against the official C reference test vectors.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

+1 -228
+1
src/dune
··· 1 1 (library 2 2 (name zstd) 3 3 (public_name zstd) 4 + (libraries xxhash) 4 5 (ocamlopt_flags (:standard -O3)))
-228
src/xxhash.ml
··· 1 - (** xxHash-64 implementation for Zstandard checksum verification. 2 - 3 - This implements the xxHash64 algorithm used by zstd for content checksums. 4 - Only the lower 32 bits of the hash are used for the frame checksum. *) 5 - 6 - (* Constants *) 7 - let prime64_1 = 0x9E3779B185EBCA87L 8 - let prime64_2 = 0xC2B2AE3D27D4EB4FL 9 - let prime64_3 = 0x165667B19E3779F9L 10 - let prime64_4 = 0x85EBCA77C2B2AE63L 11 - let prime64_5 = 0x27D4EB2F165667C5L 12 - 13 - (* Helper functions *) 14 - let[@inline] rotl64 x r = 15 - Int64.(logor (shift_left x r) (shift_right_logical x (64 - r))) 16 - 17 - let[@inline] mix1 acc v = 18 - let open Int64 in 19 - let acc = add acc (mul v prime64_2) in 20 - let acc = rotl64 acc 31 in 21 - mul acc prime64_1 22 - 23 - let[@inline] mix2 acc v = 24 - let open Int64 in 25 - let v = mul v prime64_2 in 26 - let v = rotl64 v 31 in 27 - let v = mul v prime64_1 in 28 - let acc = logxor acc v in 29 - add (mul acc prime64_1) prime64_4 30 - 31 - let[@inline] avalanche h = 32 - let open Int64 in 33 - let h = logxor h (shift_right_logical h 33) in 34 - let h = mul h prime64_2 in 35 - let h = logxor h (shift_right_logical h 29) in 36 - let h = mul h prime64_3 in 37 - logxor h (shift_right_logical h 32) 38 - 39 - (** Compute xxHash-64 of bytes with given seed *) 40 - let hash64 ?(seed=0L) src ~pos ~len = 41 - let open Int64 in 42 - let end_pos = pos + len in 43 - 44 - let h = ref ( 45 - if len >= 32 then begin 46 - (* Initialize accumulators *) 47 - let v1 = ref (add (add seed prime64_1) prime64_2) in 48 - let v2 = ref (add seed prime64_2) in 49 - let v3 = ref seed in 50 - let v4 = ref (sub seed prime64_1) in 51 - 52 - (* Process 32-byte blocks *) 53 - let p = ref pos in 54 - while !p + 32 <= end_pos do 55 - v1 := mix1 !v1 (Bytes.get_int64_le src !p); 56 - v2 := mix1 !v2 (Bytes.get_int64_le src (!p + 8)); 57 - v3 := mix1 !v3 (Bytes.get_int64_le src (!p + 16)); 58 - v4 := mix1 !v4 (Bytes.get_int64_le src (!p + 24)); 59 - p := !p + 32 60 - done; 61 - 62 - (* Merge accumulators *) 63 - let h = add 64 - (add (rotl64 !v1 1) (rotl64 !v2 7)) 65 - (add (rotl64 !v3 12) (rotl64 !v4 18)) in 66 - let h = mix2 h !v1 in 67 - let h = mix2 h !v2 in 68 - let h = mix2 h !v3 in 69 - mix2 h !v4 70 - end else 71 - add seed prime64_5 72 - ) in 73 - 74 - h := add !h (of_int len); 75 - 76 - (* Process remaining 8-byte chunks *) 77 - let p = ref (if len >= 32 then pos + (len / 32) * 32 else pos) in 78 - while !p + 8 <= end_pos do 79 - let k = Bytes.get_int64_le src !p in 80 - let k = mul k prime64_2 in 81 - let k = rotl64 k 31 in 82 - let k = mul k prime64_1 in 83 - h := logxor !h k; 84 - h := rotl64 !h 27; 85 - h := add (mul !h prime64_1) prime64_4; 86 - p := !p + 8 87 - done; 88 - 89 - (* Process remaining 4-byte chunk *) 90 - if !p + 4 <= end_pos then begin 91 - let k = of_int (Bytes.get_int32_le src !p |> Int32.to_int) in 92 - let k = logand k 0xFFFFFFFFL in (* Make unsigned *) 93 - h := logxor !h (mul k prime64_1); 94 - h := rotl64 !h 23; 95 - h := add (mul !h prime64_2) prime64_3; 96 - p := !p + 4 97 - end; 98 - 99 - (* Process remaining bytes *) 100 - while !p < end_pos do 101 - let k = of_int (Bytes.get_uint8 src !p) in 102 - h := logxor !h (mul k prime64_5); 103 - h := rotl64 !h 11; 104 - h := mul !h prime64_1; 105 - incr p 106 - done; 107 - 108 - avalanche !h 109 - 110 - (** Compute xxHash-64 and return lower 32 bits (for zstd checksum) *) 111 - let hash32 ?seed src ~pos ~len = 112 - let h = hash64 ?seed src ~pos ~len in 113 - Int64.to_int32 (Int64.logand h 0xFFFFFFFFL) 114 - 115 - (** Streaming hasher state *) 116 - type state = { 117 - mutable v1 : int64; 118 - mutable v2 : int64; 119 - mutable v3 : int64; 120 - mutable v4 : int64; 121 - mutable total_len : int; 122 - buffer : bytes; 123 - mutable buf_len : int; 124 - } 125 - 126 - let create_state ?(seed=0L) () = 127 - let open Int64 in 128 - { 129 - v1 = add (add seed prime64_1) prime64_2; 130 - v2 = add seed prime64_2; 131 - v3 = seed; 132 - v4 = sub seed prime64_1; 133 - total_len = 0; 134 - buffer = Bytes.create 32; 135 - buf_len = 0; 136 - } 137 - 138 - let update state src ~pos ~len = 139 - let end_pos = pos + len in 140 - state.total_len <- state.total_len + len; 141 - 142 - let p = ref pos in 143 - 144 - (* Fill buffer if we have partial data *) 145 - if state.buf_len > 0 then begin 146 - let to_copy = min (32 - state.buf_len) len in 147 - Bytes.blit src !p state.buffer state.buf_len to_copy; 148 - state.buf_len <- state.buf_len + to_copy; 149 - p := !p + to_copy; 150 - 151 - if state.buf_len = 32 then begin 152 - state.v1 <- mix1 state.v1 (Bytes.get_int64_le state.buffer 0); 153 - state.v2 <- mix1 state.v2 (Bytes.get_int64_le state.buffer 8); 154 - state.v3 <- mix1 state.v3 (Bytes.get_int64_le state.buffer 16); 155 - state.v4 <- mix1 state.v4 (Bytes.get_int64_le state.buffer 24); 156 - state.buf_len <- 0 157 - end 158 - end; 159 - 160 - (* Process 32-byte blocks *) 161 - while !p + 32 <= end_pos do 162 - state.v1 <- mix1 state.v1 (Bytes.get_int64_le src !p); 163 - state.v2 <- mix1 state.v2 (Bytes.get_int64_le src (!p + 8)); 164 - state.v3 <- mix1 state.v3 (Bytes.get_int64_le src (!p + 16)); 165 - state.v4 <- mix1 state.v4 (Bytes.get_int64_le src (!p + 24)); 166 - p := !p + 32 167 - done; 168 - 169 - (* Buffer remaining *) 170 - if !p < end_pos then begin 171 - let remaining = end_pos - !p in 172 - Bytes.blit src !p state.buffer state.buf_len remaining; 173 - state.buf_len <- state.buf_len + remaining 174 - end 175 - 176 - let finalize state = 177 - let open Int64 in 178 - 179 - let h = ref ( 180 - if state.total_len >= 32 then begin 181 - let h = add 182 - (add (rotl64 state.v1 1) (rotl64 state.v2 7)) 183 - (add (rotl64 state.v3 12) (rotl64 state.v4 18)) in 184 - let h = mix2 h state.v1 in 185 - let h = mix2 h state.v2 in 186 - let h = mix2 h state.v3 in 187 - mix2 h state.v4 188 - end else 189 - add state.v3 prime64_5 (* v3 holds seed *) 190 - ) in 191 - 192 - h := add !h (of_int state.total_len); 193 - 194 - (* Process buffered data *) 195 - let p = ref 0 in 196 - while !p + 8 <= state.buf_len do 197 - let k = Bytes.get_int64_le state.buffer !p in 198 - let k = mul k prime64_2 in 199 - let k = rotl64 k 31 in 200 - let k = mul k prime64_1 in 201 - h := logxor !h k; 202 - h := rotl64 !h 27; 203 - h := add (mul !h prime64_1) prime64_4; 204 - p := !p + 8 205 - done; 206 - 207 - if !p + 4 <= state.buf_len then begin 208 - let k = of_int (Bytes.get_int32_le state.buffer !p |> Int32.to_int) in 209 - let k = logand k 0xFFFFFFFFL in 210 - h := logxor !h (mul k prime64_1); 211 - h := rotl64 !h 23; 212 - h := add (mul !h prime64_2) prime64_3; 213 - p := !p + 4 214 - end; 215 - 216 - while !p < state.buf_len do 217 - let k = of_int (Bytes.get_uint8 state.buffer !p) in 218 - h := logxor !h (mul k prime64_5); 219 - h := rotl64 !h 11; 220 - h := mul !h prime64_1; 221 - incr p 222 - done; 223 - 224 - avalanche !h 225 - 226 - let finalize32 state = 227 - let h = finalize state in 228 - Int64.to_int32 (Int64.logand h 0xFFFFFFFFL)