hashcodecs 0.2.0__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hashcodecs-0.4.0/BENCHMARK.md +71 -0
- {hashcodecs-0.2.0 → hashcodecs-0.4.0}/Cargo.lock +1 -1
- {hashcodecs-0.2.0 → hashcodecs-0.4.0}/Cargo.toml +1 -1
- hashcodecs-0.4.0/PKG-INFO +190 -0
- hashcodecs-0.4.0/README.md +170 -0
- {hashcodecs-0.2.0 → hashcodecs-0.4.0}/hatch_build.py +19 -19
- {hashcodecs-0.2.0 → hashcodecs-0.4.0}/pyproject.toml +22 -1
- hashcodecs-0.4.0/python/hashcodecs/__init__.py +57 -0
- {hashcodecs-0.2.0 → hashcodecs-0.4.0}/python/hashcodecs/_hashcodecs.pyi +36 -2
- hashcodecs-0.4.0/python/hashcodecs/base64.py +89 -0
- hashcodecs-0.4.0/python/hashcodecs/base64.pyi +54 -0
- {hashcodecs-0.2.0 → hashcodecs-0.4.0}/python/hashcodecs/murmur3.py +6 -6
- {hashcodecs-0.2.0 → hashcodecs-0.4.0}/src/base64/aarch64.rs +115 -60
- hashcodecs-0.4.0/src/base64/x86.rs +822 -0
- {hashcodecs-0.2.0 → hashcodecs-0.4.0}/src/base64/x86_avx512.rs +60 -37
- hashcodecs-0.4.0/src/python/base64/encode.rs +163 -0
- hashcodecs-0.4.0/src/python/base64.rs +792 -0
- {hashcodecs-0.2.0 → hashcodecs-0.4.0}/src/python/buffer.rs +37 -12
- {hashcodecs-0.2.0 → hashcodecs-0.4.0}/src/python/murmur3.rs +28 -49
- {hashcodecs-0.2.0 → hashcodecs-0.4.0}/src/python.rs +7 -1
- hashcodecs-0.2.0/PKG-INFO +0 -179
- hashcodecs-0.2.0/README.md +0 -165
- hashcodecs-0.2.0/python/hashcodecs/__init__.py +0 -26
- hashcodecs-0.2.0/python/hashcodecs/base64.py +0 -33
- hashcodecs-0.2.0/python/hashcodecs/base64.pyi +0 -12
- hashcodecs-0.2.0/src/base64/x86.rs +0 -643
- hashcodecs-0.2.0/src/python/base64.rs +0 -217
- {hashcodecs-0.2.0 → hashcodecs-0.4.0}/.gitignore +0 -0
- {hashcodecs-0.2.0 → hashcodecs-0.4.0}/LICENSE +0 -0
- {hashcodecs-0.2.0 → hashcodecs-0.4.0}/LICENSE-MIT +0 -0
- {hashcodecs-0.2.0 → hashcodecs-0.4.0}/benches/base64.rs +0 -0
- {hashcodecs-0.2.0 → hashcodecs-0.4.0}/benches/murmur3.rs +0 -0
- {hashcodecs-0.2.0 → hashcodecs-0.4.0}/benches/support/mod.rs +0 -0
- {hashcodecs-0.2.0 → hashcodecs-0.4.0}/build.rs +0 -0
- {hashcodecs-0.2.0 → hashcodecs-0.4.0}/python/hashcodecs/py.typed +0 -0
- {hashcodecs-0.2.0 → hashcodecs-0.4.0}/src/base64/dispatch.rs +0 -0
- {hashcodecs-0.2.0 → hashcodecs-0.4.0}/src/base64.rs +0 -0
- {hashcodecs-0.2.0 → hashcodecs-0.4.0}/src/lib.rs +0 -0
- {hashcodecs-0.2.0 → hashcodecs-0.4.0}/src/murmur3/dispatch.rs +0 -0
- {hashcodecs-0.2.0 → hashcodecs-0.4.0}/src/murmur3/x86.rs +0 -0
- {hashcodecs-0.2.0 → hashcodecs-0.4.0}/src/murmur3.rs +0 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Benchmark Details
|
|
2
|
+
|
|
3
|
+
Environment: Windows 10 x64 and Intel Core Ultra 7 265K.
|
|
4
|
+
|
|
5
|
+
Conditions: clean builds, one pinned logical CPU, single-threaded execution, and 15 Python samples. Higher is better.
|
|
6
|
+
|
|
7
|
+
## Reusable Python Buffers
|
|
8
|
+
|
|
9
|
+
| Alphabet | Input | Operation | hashcodecs |
|
|
10
|
+
| --- | --- | --- | ---: |
|
|
11
|
+
| Standard | 4 KiB | encode | **15.09 GiB/s** |
|
|
12
|
+
| | 4 KiB | decode | **18.43 GiB/s** |
|
|
13
|
+
| | 1 MiB | encode | **39.66 GiB/s** |
|
|
14
|
+
| | 1 MiB | decode | **29.03 GiB/s** |
|
|
15
|
+
| | 32 MiB | encode | **10.89 GiB/s** |
|
|
16
|
+
| | 32 MiB | decode | **10.36 GiB/s** |
|
|
17
|
+
| URL-safe | 4 KiB | encode | **14.83 GiB/s** |
|
|
18
|
+
| | 4 KiB | decode | **12.26 GiB/s** |
|
|
19
|
+
| | 1 MiB | encode | **39.71 GiB/s** |
|
|
20
|
+
| | 1 MiB | decode | **20.72 GiB/s** |
|
|
21
|
+
| | 32 MiB | encode | **10.84 GiB/s** |
|
|
22
|
+
| | 32 MiB | decode | **10.44 GiB/s** |
|
|
23
|
+
|
|
24
|
+
## Python Base64 Batches
|
|
25
|
+
|
|
26
|
+
Each value is total input throughput; the parenthesized figure is items per second. Higher is better.
|
|
27
|
+
|
|
28
|
+
| Item | Batch | Operation | hashcodecs | hashcodecs loop | pybase64 loop | CPython loop |
|
|
29
|
+
| ---: | ---: | --- | ---: | ---: | ---: | ---: |
|
|
30
|
+
| 16 B | 8 | encode | **0.41 GiB/s (27.42M)** | 0.27 GiB/s (18.11M) | 0.13 GiB/s (8.45M) | 0.18 GiB/s (12.37M) |
|
|
31
|
+
| | | decode | **0.36 GiB/s (24.24M)** | 0.21 GiB/s (14.13M) | 0.08 GiB/s (5.44M) | 0.12 GiB/s (7.85M) |
|
|
32
|
+
| 16 B | 64 | encode | **0.55 GiB/s (36.69M)** | 0.31 GiB/s (20.81M) | 0.14 GiB/s (9.17M) | 0.21 GiB/s (13.81M) |
|
|
33
|
+
| | | decode | **0.49 GiB/s (32.86M)** | 0.24 GiB/s (16.13M) | 0.09 GiB/s (5.87M) | 0.13 GiB/s (8.63M) |
|
|
34
|
+
| 16 B | 1,024 | encode | **0.56 GiB/s (37.26M)** | 0.31 GiB/s (20.64M) | 0.14 GiB/s (9.07M) | 0.20 GiB/s (13.73M) |
|
|
35
|
+
| | | decode | **0.49 GiB/s (32.70M)** | 0.25 GiB/s (16.60M) | 0.09 GiB/s (5.95M) | 0.13 GiB/s (8.71M) |
|
|
36
|
+
| 256 B | 8 | encode | 1.77 GiB/s (7.43M) | 1.52 GiB/s (6.38M) | **1.93 GiB/s (8.08M)** | 0.40 GiB/s (1.67M) |
|
|
37
|
+
| | | decode | **5.03 GiB/s (21.12M)** | 3.02 GiB/s (12.66M) | 1.22 GiB/s (5.12M) | 0.76 GiB/s (3.19M) |
|
|
38
|
+
| 256 B | 64 | encode | 1.92 GiB/s (8.05M) | 1.62 GiB/s (6.82M) | **2.02 GiB/s (8.48M)** | 0.41 GiB/s (1.71M) |
|
|
39
|
+
| | | decode | **6.09 GiB/s (25.56M)** | 3.36 GiB/s (14.07M) | 1.29 GiB/s (5.40M) | 0.76 GiB/s (3.18M) |
|
|
40
|
+
| 256 B | 1,024 | encode | 1.92 GiB/s (8.05M) | 1.63 GiB/s (6.82M) | **1.99 GiB/s (8.35M)** | 0.40 GiB/s (1.69M) |
|
|
41
|
+
| | | decode | **5.87 GiB/s (24.61M)** | 3.30 GiB/s (13.83M) | 1.29 GiB/s (5.43M) | 0.76 GiB/s (3.17M) |
|
|
42
|
+
| 4 KiB | 8 | encode | **15.12 GiB/s (3.96M)** | 13.72 GiB/s (3.60M) | 12.69 GiB/s (3.33M) | 0.48 GiB/s (0.13M) |
|
|
43
|
+
| | | decode | **19.20 GiB/s (5.03M)** | 16.52 GiB/s (4.33M) | 8.29 GiB/s (2.17M) | 1.13 GiB/s (0.30M) |
|
|
44
|
+
| 4 KiB | 64 | encode | **12.59 GiB/s (3.30M)** | 11.55 GiB/s (3.03M) | 9.54 GiB/s (2.50M) | 0.48 GiB/s (0.12M) |
|
|
45
|
+
| | | decode | **18.95 GiB/s (4.97M)** | 16.12 GiB/s (4.23M) | 8.12 GiB/s (2.13M) | 1.12 GiB/s (0.29M) |
|
|
46
|
+
| 4 KiB | 1,024 | encode | 5.84 GiB/s (1.53M) | **8.81 GiB/s (2.31M)** | 7.83 GiB/s (2.05M) | 0.47 GiB/s (0.12M) |
|
|
47
|
+
| | | decode | 3.52 GiB/s (0.92M) | **3.81 GiB/s (1.00M)** | 2.99 GiB/s (0.79M) | 0.92 GiB/s (0.24M) |
|
|
48
|
+
|
|
49
|
+
## Mutable Python Inputs
|
|
50
|
+
|
|
51
|
+
### Base64
|
|
52
|
+
|
|
53
|
+
| Input | Operation | Returned `bytes` | Reusable `bytearray` |
|
|
54
|
+
| --- | --- | ---: | ---: |
|
|
55
|
+
| 4 KiB | encode | 14.12 GiB/s | **15.16 GiB/s** |
|
|
56
|
+
| | decode | 16.76 GiB/s | **18.27 GiB/s** |
|
|
57
|
+
| 1 MiB | encode | 2.88 GiB/s | **38.96 GiB/s** |
|
|
58
|
+
| | decode | 3.59 GiB/s | **28.99 GiB/s** |
|
|
59
|
+
| 32 MiB | encode | 2.92 GiB/s | **10.83 GiB/s** |
|
|
60
|
+
| | decode | 3.44 GiB/s | **10.35 GiB/s** |
|
|
61
|
+
|
|
62
|
+
### MurmurHash3
|
|
63
|
+
|
|
64
|
+
| Variant | API | 4 KiB | 1 MiB | 32 MiB |
|
|
65
|
+
| --- | --- | ---: | ---: | ---: |
|
|
66
|
+
| x86 32-bit | one-shot | **3.79 GiB/s** | **3.98 GiB/s** | **3.97 GiB/s** |
|
|
67
|
+
| | incremental | **3.58 GiB/s** | **3.96 GiB/s** | **3.92 GiB/s** |
|
|
68
|
+
| x86 128-bit | one-shot | **8.09 GiB/s** | **9.22 GiB/s** | **9.12 GiB/s** |
|
|
69
|
+
| | incremental | **7.02 GiB/s** | **9.17 GiB/s** | **9.01 GiB/s** |
|
|
70
|
+
| x64 128-bit | one-shot | **8.68 GiB/s** | **10.10 GiB/s** | **9.54 GiB/s** |
|
|
71
|
+
| | incremental | **7.70 GiB/s** | **10.01 GiB/s** | **9.41 GiB/s** |
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: hashcodecs
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: SIMD-accelerated Base64 and MurmurHash3 codecs
|
|
5
|
+
License-Expression: MIT OR Apache-2.0
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
License-File: LICENSE-MIT
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
16
|
+
Classifier: Programming Language :: Rust
|
|
17
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
# hashcodecs
|
|
22
|
+
|
|
23
|
+
[](https://github.com/kozistr/hashcodecs-rs/actions/workflows/ci.yml)
|
|
24
|
+
[](https://pypi.org/project/hashcodecs/)
|
|
25
|
+
[](https://pypi.org/project/hashcodecs/)
|
|
26
|
+
[](https://github.com/kozistr/hashcodecs-rs#license)
|
|
27
|
+
[](https://pypi.org/project/hashcodecs/)
|
|
28
|
+
|
|
29
|
+
`hashcodecs` provides runtime-dispatched SIMD Base64 codecs and fast, reference-compatible MurmurHash3 functions for Rust and Python.
|
|
30
|
+
|
|
31
|
+
## Design
|
|
32
|
+
|
|
33
|
+
- Runtime-dispatched SIMD Base64 with portable scalar fallbacks.
|
|
34
|
+
- Reference-compatible MurmurHash3 with SIMD acceleration.
|
|
35
|
+
- Rust and Python `*_into` APIs for caller-managed output buffers.
|
|
36
|
+
- A familiar Python Base64 API, including native batch encode and decode operations.
|
|
37
|
+
|
|
38
|
+
## Install
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
pip3 install hashcodecs
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Usage
|
|
45
|
+
|
|
46
|
+
### Rust
|
|
47
|
+
|
|
48
|
+
```rust
|
|
49
|
+
let encoded = hashcodecs::b64encode(b"hello");
|
|
50
|
+
assert_eq!(encoded, "aGVsbG8=");
|
|
51
|
+
|
|
52
|
+
let mut output = [0_u8; 8];
|
|
53
|
+
let written = hashcodecs::b64encode_into(b"hello", &mut output).unwrap();
|
|
54
|
+
assert_eq!(&output[..written], b"aGVsbG8=");
|
|
55
|
+
assert_eq!(hashcodecs::murmur3_x86_32(b"hello", 0), 0x248b_fa47);
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Python
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
import hashcodecs.base64 as base64
|
|
62
|
+
from hashcodecs import murmur3_32, murmur3_x64_128
|
|
63
|
+
|
|
64
|
+
assert base64.b64encode(b'hello') == b'aGVsbG8='
|
|
65
|
+
assert base64.b64decode(b'aGVsbG8=') == b'hello'
|
|
66
|
+
assert base64.b64encode_batch([b'hello', b'world']) == [b'aGVsbG8=', b'd29ybGQ=']
|
|
67
|
+
assert base64.b64decode_batch([b'aGVsbG8=', 'd29ybGQ=']) == [b'hello', b'world']
|
|
68
|
+
assert base64.b64encode(b'hello', padded=False) == b'aGVsbG8'
|
|
69
|
+
assert base64.b64decode(b'aGVsbG8', padded=False, canonical=True) == b'hello'
|
|
70
|
+
assert murmur3_32(b'hello') == 0x248BFA47
|
|
71
|
+
|
|
72
|
+
payload = b'hello'
|
|
73
|
+
encoded = bytearray(4 * ((len(payload) + 2) // 3))
|
|
74
|
+
encoded_len = base64.b64encode_into(payload, encoded)
|
|
75
|
+
decoded = bytearray(len(encoded))
|
|
76
|
+
decoded_len = base64.b64decode_into(encoded, decoded, validate=True)
|
|
77
|
+
assert encoded[:encoded_len] == b'aGVsbG8='
|
|
78
|
+
assert decoded[:decoded_len] == payload
|
|
79
|
+
|
|
80
|
+
hasher = murmur3_x64_128(seed=42)
|
|
81
|
+
hasher.update(b'hello')
|
|
82
|
+
assert hasher.hexdigest() == hasher.digest().hex()
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Build an installable wheel and source distribution with:
|
|
86
|
+
|
|
87
|
+
```sh
|
|
88
|
+
uv build
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
# Benchmark
|
|
92
|
+
|
|
93
|
+
Environment: Windows 10 x64 and Intel Core Ultra 7 265K.
|
|
94
|
+
|
|
95
|
+
Conditions: clean builds, one pinned logical CPU, single-threaded execution, 50 Rust samples, and 15 Python samples. Returned-output allocation is included except in the reusable-buffer table. Higher is better.
|
|
96
|
+
|
|
97
|
+
## Run Locally
|
|
98
|
+
|
|
99
|
+
Comparison crates are development-only dependencies and are not included in consumer builds.
|
|
100
|
+
|
|
101
|
+
```sh
|
|
102
|
+
cargo bench --bench base64
|
|
103
|
+
cargo bench --bench murmur3
|
|
104
|
+
uv sync --group benchmark --no-install-project
|
|
105
|
+
uv run --no-project --with . python benchmarks/python_base64.py
|
|
106
|
+
uv run --no-project --with . python benchmarks/python_base64.py --into
|
|
107
|
+
uv run --no-project --with . python benchmarks/python_base64.py --bytearray-input
|
|
108
|
+
uv run --no-project --with . python benchmarks/python_base64_batch.py
|
|
109
|
+
uv run --no-project --with . python benchmarks/python_murmur3.py
|
|
110
|
+
uv run --no-project --with . python benchmarks/python_murmur3.py --incremental
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Base64: Rust
|
|
114
|
+
|
|
115
|
+
| Alphabet | Input | Operation | hashcodecs | `base64` | `base64-turbo` |
|
|
116
|
+
| --- | --- | --- | ---: | ---: | ---: |
|
|
117
|
+
| Standard | 4 KiB | encode | **20.41 GiB/s** | 5.81 GiB/s | 18.29 GiB/s |
|
|
118
|
+
| | 4 KiB | decode | **27.11 GiB/s** | 4.33 GiB/s | 16.95 GiB/s |
|
|
119
|
+
| | 1 MiB | encode | **42.38 GiB/s** | 5.16 GiB/s | 19.60 GiB/s |
|
|
120
|
+
| | 1 MiB | decode | **31.07 GiB/s** | 4.10 GiB/s | 18.17 GiB/s |
|
|
121
|
+
| | 32 MiB | encode | **11.97 GiB/s** | 3.28 GiB/s | 10.94 GiB/s |
|
|
122
|
+
| | 32 MiB | decode | **11.51 GiB/s** | 3.35 GiB/s | 10.45 GiB/s |
|
|
123
|
+
| URL-safe | 4 KiB | encode | **20.46 GiB/s** | 5.81 GiB/s | 18.31 GiB/s |
|
|
124
|
+
| | 4 KiB | decode | **25.65 GiB/s** | 4.35 GiB/s | 16.96 GiB/s |
|
|
125
|
+
| | 1 MiB | encode | **42.56 GiB/s** | 5.18 GiB/s | 19.66 GiB/s |
|
|
126
|
+
| | 1 MiB | decode | **29.42 GiB/s** | 4.08 GiB/s | 18.16 GiB/s |
|
|
127
|
+
| | 32 MiB | encode | **11.86 GiB/s** | 3.29 GiB/s | 11.09 GiB/s |
|
|
128
|
+
| | 32 MiB | decode | **11.67 GiB/s** | 3.36 GiB/s | 10.62 GiB/s |
|
|
129
|
+
|
|
130
|
+
## MurmurHash3: Rust
|
|
131
|
+
|
|
132
|
+
| Variant | Input | hashcodecs | `murmur3` | `murmurs` | `fastmurmur3` | `mm3h` |
|
|
133
|
+
| --- | --- | ---: | ---: | ---: | ---: | ---: |
|
|
134
|
+
| x86 32-bit | 4 KiB | **4.30 GiB/s** | 2.60 GiB/s | 4.09 GiB/s | n/a | **4.30 GiB/s** |
|
|
135
|
+
| | 1 MiB | **4.26 GiB/s** | 2.59 GiB/s | 4.04 GiB/s | n/a | 4.25 GiB/s |
|
|
136
|
+
| | 32 MiB | **4.21 GiB/s** | 2.54 GiB/s | 3.87 GiB/s | n/a | 4.03 GiB/s |
|
|
137
|
+
| x86 128-bit | 4 KiB | **9.54 GiB/s** | 4.97 GiB/s | 8.64 GiB/s | n/a | n/a |
|
|
138
|
+
| | 1 MiB | **9.84 GiB/s** | 5.06 GiB/s | 8.77 GiB/s | n/a | n/a |
|
|
139
|
+
| | 32 MiB | **9.63 GiB/s** | 4.84 GiB/s | 6.05 GiB/s | n/a | n/a |
|
|
140
|
+
| x64 128-bit | 4 KiB | **10.76 GiB/s** | 6.83 GiB/s | 9.45 GiB/s | 10.06 GiB/s | 9.54 GiB/s |
|
|
141
|
+
| | 1 MiB | **10.84 GiB/s** | 6.89 GiB/s | 9.51 GiB/s | 10.04 GiB/s | 9.51 GiB/s |
|
|
142
|
+
| | 32 MiB | **10.12 GiB/s** | 6.11 GiB/s | 6.64 GiB/s | 7.25 GiB/s | 6.70 GiB/s |
|
|
143
|
+
|
|
144
|
+
## Base64: Python
|
|
145
|
+
|
|
146
|
+
Python decoding uses `validate=True`, and `hashcodecs` passes `bytes` directly into Rust without an input copy.
|
|
147
|
+
|
|
148
|
+
| Alphabet | Input | Operation | hashcodecs | CPython `base64` | `pybase64` |
|
|
149
|
+
| --- | --- | --- | ---: | ---: | ---: |
|
|
150
|
+
| Standard | 4 KiB | encode | 13.57 GiB/s | 0.48 GiB/s | **14.06 GiB/s** |
|
|
151
|
+
| | 4 KiB | decode | **16.70 GiB/s** | 1.13 GiB/s | 8.47 GiB/s |
|
|
152
|
+
| | 1 MiB | encode | **3.28 GiB/s** | 0.44 GiB/s | 3.02 GiB/s |
|
|
153
|
+
| | 1 MiB | decode | **4.02 GiB/s** | 0.95 GiB/s | 3.68 GiB/s |
|
|
154
|
+
| | 32 MiB | encode | **2.92 GiB/s** | 0.43 GiB/s | 2.84 GiB/s |
|
|
155
|
+
| | 32 MiB | decode | 3.40 GiB/s | 0.94 GiB/s | **3.69 GiB/s** |
|
|
156
|
+
| URL-safe | 4 KiB | encode | **12.63 GiB/s** | 0.41 GiB/s | 1.19 GiB/s |
|
|
157
|
+
| | 4 KiB | decode | **11.34 GiB/s** | 0.76 GiB/s | 1.56 GiB/s |
|
|
158
|
+
| | 1 MiB | encode | **3.24 GiB/s** | 0.36 GiB/s | 0.91 GiB/s |
|
|
159
|
+
| | 1 MiB | decode | **4.15 GiB/s** | 0.63 GiB/s | 1.45 GiB/s |
|
|
160
|
+
| | 32 MiB | encode | **3.03 GiB/s** | 0.36 GiB/s | 0.90 GiB/s |
|
|
161
|
+
| | 32 MiB | decode | **3.40 GiB/s** | 0.61 GiB/s | 1.48 GiB/s |
|
|
162
|
+
|
|
163
|
+
## MurmurHash3: Python
|
|
164
|
+
|
|
165
|
+
| Variant | API | Input | hashcodecs | `mmh3` |
|
|
166
|
+
| --- | --- | --- | ---: | ---: |
|
|
167
|
+
| x86 32-bit | one-shot | 4 KiB | **3.79 GiB/s** | 3.71 GiB/s |
|
|
168
|
+
| | | 1 MiB | **3.98 GiB/s** | 3.83 GiB/s |
|
|
169
|
+
| | | 32 MiB | **3.97 GiB/s** | 3.66 GiB/s |
|
|
170
|
+
| | incremental | 4 KiB | **3.58 GiB/s** | **3.58 GiB/s** |
|
|
171
|
+
| | | 1 MiB | **3.96 GiB/s** | 3.81 GiB/s |
|
|
172
|
+
| | | 32 MiB | **3.92 GiB/s** | 3.74 GiB/s |
|
|
173
|
+
| x86 128-bit | one-shot | 4 KiB | 8.09 GiB/s | **8.21 GiB/s** |
|
|
174
|
+
| | | 1 MiB | **9.22 GiB/s** | 8.87 GiB/s |
|
|
175
|
+
| | | 32 MiB | **9.12 GiB/s** | 6.15 GiB/s |
|
|
176
|
+
| | incremental | 4 KiB | **7.02 GiB/s** | 0.77 GiB/s |
|
|
177
|
+
| | | 1 MiB | **9.17 GiB/s** | 0.80 GiB/s |
|
|
178
|
+
| | | 32 MiB | **9.01 GiB/s** | 0.79 GiB/s |
|
|
179
|
+
| x64 128-bit | one-shot | 4 KiB | 8.68 GiB/s | **9.46 GiB/s** |
|
|
180
|
+
| | | 1 MiB | 10.10 GiB/s | **10.24 GiB/s** |
|
|
181
|
+
| | | 32 MiB | **9.54 GiB/s** | 6.61 GiB/s |
|
|
182
|
+
| | incremental | 4 KiB | 7.70 GiB/s | **7.99 GiB/s** |
|
|
183
|
+
| | | 1 MiB | **10.01 GiB/s** | 9.28 GiB/s |
|
|
184
|
+
| | | 32 MiB | **9.41 GiB/s** | 7.34 GiB/s |
|
|
185
|
+
|
|
186
|
+
Reusable-buffer and mutable-input results are available in [BENCHMARK.md](https://github.com/kozistr/hashcodecs-rs/blob/main/BENCHMARK.md).
|
|
187
|
+
|
|
188
|
+
## SIMD References
|
|
189
|
+
|
|
190
|
+
The SIMD implementation follows the approach described in [Faster Base64 Encoding and Decoding using AVX2 Instructions](https://arxiv.org/abs/1704.00605), with AVX-512 VBMI and AArch64 NEON backends selected automatically when available.
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# hashcodecs
|
|
2
|
+
|
|
3
|
+
[](https://github.com/kozistr/hashcodecs-rs/actions/workflows/ci.yml)
|
|
4
|
+
[](https://pypi.org/project/hashcodecs/)
|
|
5
|
+
[](https://pypi.org/project/hashcodecs/)
|
|
6
|
+
[](https://github.com/kozistr/hashcodecs-rs#license)
|
|
7
|
+
[](https://pypi.org/project/hashcodecs/)
|
|
8
|
+
|
|
9
|
+
`hashcodecs` provides runtime-dispatched SIMD Base64 codecs and fast, reference-compatible MurmurHash3 functions for Rust and Python.
|
|
10
|
+
|
|
11
|
+
## Design
|
|
12
|
+
|
|
13
|
+
- Runtime-dispatched SIMD Base64 with portable scalar fallbacks.
|
|
14
|
+
- Reference-compatible MurmurHash3 with SIMD acceleration.
|
|
15
|
+
- Rust and Python `*_into` APIs for caller-managed output buffers.
|
|
16
|
+
- A familiar Python Base64 API, including native batch encode and decode operations.
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
pip3 install hashcodecs
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
### Rust
|
|
27
|
+
|
|
28
|
+
```rust
|
|
29
|
+
let encoded = hashcodecs::b64encode(b"hello");
|
|
30
|
+
assert_eq!(encoded, "aGVsbG8=");
|
|
31
|
+
|
|
32
|
+
let mut output = [0_u8; 8];
|
|
33
|
+
let written = hashcodecs::b64encode_into(b"hello", &mut output).unwrap();
|
|
34
|
+
assert_eq!(&output[..written], b"aGVsbG8=");
|
|
35
|
+
assert_eq!(hashcodecs::murmur3_x86_32(b"hello", 0), 0x248b_fa47);
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Python
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
import hashcodecs.base64 as base64
|
|
42
|
+
from hashcodecs import murmur3_32, murmur3_x64_128
|
|
43
|
+
|
|
44
|
+
assert base64.b64encode(b'hello') == b'aGVsbG8='
|
|
45
|
+
assert base64.b64decode(b'aGVsbG8=') == b'hello'
|
|
46
|
+
assert base64.b64encode_batch([b'hello', b'world']) == [b'aGVsbG8=', b'd29ybGQ=']
|
|
47
|
+
assert base64.b64decode_batch([b'aGVsbG8=', 'd29ybGQ=']) == [b'hello', b'world']
|
|
48
|
+
assert base64.b64encode(b'hello', padded=False) == b'aGVsbG8'
|
|
49
|
+
assert base64.b64decode(b'aGVsbG8', padded=False, canonical=True) == b'hello'
|
|
50
|
+
assert murmur3_32(b'hello') == 0x248BFA47
|
|
51
|
+
|
|
52
|
+
payload = b'hello'
|
|
53
|
+
encoded = bytearray(4 * ((len(payload) + 2) // 3))
|
|
54
|
+
encoded_len = base64.b64encode_into(payload, encoded)
|
|
55
|
+
decoded = bytearray(len(encoded))
|
|
56
|
+
decoded_len = base64.b64decode_into(encoded, decoded, validate=True)
|
|
57
|
+
assert encoded[:encoded_len] == b'aGVsbG8='
|
|
58
|
+
assert decoded[:decoded_len] == payload
|
|
59
|
+
|
|
60
|
+
hasher = murmur3_x64_128(seed=42)
|
|
61
|
+
hasher.update(b'hello')
|
|
62
|
+
assert hasher.hexdigest() == hasher.digest().hex()
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Build an installable wheel and source distribution with:
|
|
66
|
+
|
|
67
|
+
```sh
|
|
68
|
+
uv build
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
# Benchmark
|
|
72
|
+
|
|
73
|
+
Environment: Windows 10 x64 and Intel Core Ultra 7 265K.
|
|
74
|
+
|
|
75
|
+
Conditions: clean builds, one pinned logical CPU, single-threaded execution, 50 Rust samples, and 15 Python samples. Returned-output allocation is included except in the reusable-buffer table. Higher is better.
|
|
76
|
+
|
|
77
|
+
## Run Locally
|
|
78
|
+
|
|
79
|
+
Comparison crates are development-only dependencies and are not included in consumer builds.
|
|
80
|
+
|
|
81
|
+
```sh
|
|
82
|
+
cargo bench --bench base64
|
|
83
|
+
cargo bench --bench murmur3
|
|
84
|
+
uv sync --group benchmark --no-install-project
|
|
85
|
+
uv run --no-project --with . python benchmarks/python_base64.py
|
|
86
|
+
uv run --no-project --with . python benchmarks/python_base64.py --into
|
|
87
|
+
uv run --no-project --with . python benchmarks/python_base64.py --bytearray-input
|
|
88
|
+
uv run --no-project --with . python benchmarks/python_base64_batch.py
|
|
89
|
+
uv run --no-project --with . python benchmarks/python_murmur3.py
|
|
90
|
+
uv run --no-project --with . python benchmarks/python_murmur3.py --incremental
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Base64: Rust
|
|
94
|
+
|
|
95
|
+
| Alphabet | Input | Operation | hashcodecs | `base64` | `base64-turbo` |
|
|
96
|
+
| --- | --- | --- | ---: | ---: | ---: |
|
|
97
|
+
| Standard | 4 KiB | encode | **20.41 GiB/s** | 5.81 GiB/s | 18.29 GiB/s |
|
|
98
|
+
| | 4 KiB | decode | **27.11 GiB/s** | 4.33 GiB/s | 16.95 GiB/s |
|
|
99
|
+
| | 1 MiB | encode | **42.38 GiB/s** | 5.16 GiB/s | 19.60 GiB/s |
|
|
100
|
+
| | 1 MiB | decode | **31.07 GiB/s** | 4.10 GiB/s | 18.17 GiB/s |
|
|
101
|
+
| | 32 MiB | encode | **11.97 GiB/s** | 3.28 GiB/s | 10.94 GiB/s |
|
|
102
|
+
| | 32 MiB | decode | **11.51 GiB/s** | 3.35 GiB/s | 10.45 GiB/s |
|
|
103
|
+
| URL-safe | 4 KiB | encode | **20.46 GiB/s** | 5.81 GiB/s | 18.31 GiB/s |
|
|
104
|
+
| | 4 KiB | decode | **25.65 GiB/s** | 4.35 GiB/s | 16.96 GiB/s |
|
|
105
|
+
| | 1 MiB | encode | **42.56 GiB/s** | 5.18 GiB/s | 19.66 GiB/s |
|
|
106
|
+
| | 1 MiB | decode | **29.42 GiB/s** | 4.08 GiB/s | 18.16 GiB/s |
|
|
107
|
+
| | 32 MiB | encode | **11.86 GiB/s** | 3.29 GiB/s | 11.09 GiB/s |
|
|
108
|
+
| | 32 MiB | decode | **11.67 GiB/s** | 3.36 GiB/s | 10.62 GiB/s |
|
|
109
|
+
|
|
110
|
+
## MurmurHash3: Rust
|
|
111
|
+
|
|
112
|
+
| Variant | Input | hashcodecs | `murmur3` | `murmurs` | `fastmurmur3` | `mm3h` |
|
|
113
|
+
| --- | --- | ---: | ---: | ---: | ---: | ---: |
|
|
114
|
+
| x86 32-bit | 4 KiB | **4.30 GiB/s** | 2.60 GiB/s | 4.09 GiB/s | n/a | **4.30 GiB/s** |
|
|
115
|
+
| | 1 MiB | **4.26 GiB/s** | 2.59 GiB/s | 4.04 GiB/s | n/a | 4.25 GiB/s |
|
|
116
|
+
| | 32 MiB | **4.21 GiB/s** | 2.54 GiB/s | 3.87 GiB/s | n/a | 4.03 GiB/s |
|
|
117
|
+
| x86 128-bit | 4 KiB | **9.54 GiB/s** | 4.97 GiB/s | 8.64 GiB/s | n/a | n/a |
|
|
118
|
+
| | 1 MiB | **9.84 GiB/s** | 5.06 GiB/s | 8.77 GiB/s | n/a | n/a |
|
|
119
|
+
| | 32 MiB | **9.63 GiB/s** | 4.84 GiB/s | 6.05 GiB/s | n/a | n/a |
|
|
120
|
+
| x64 128-bit | 4 KiB | **10.76 GiB/s** | 6.83 GiB/s | 9.45 GiB/s | 10.06 GiB/s | 9.54 GiB/s |
|
|
121
|
+
| | 1 MiB | **10.84 GiB/s** | 6.89 GiB/s | 9.51 GiB/s | 10.04 GiB/s | 9.51 GiB/s |
|
|
122
|
+
| | 32 MiB | **10.12 GiB/s** | 6.11 GiB/s | 6.64 GiB/s | 7.25 GiB/s | 6.70 GiB/s |
|
|
123
|
+
|
|
124
|
+
## Base64: Python
|
|
125
|
+
|
|
126
|
+
Python decoding uses `validate=True`, and `hashcodecs` passes `bytes` directly into Rust without an input copy.
|
|
127
|
+
|
|
128
|
+
| Alphabet | Input | Operation | hashcodecs | CPython `base64` | `pybase64` |
|
|
129
|
+
| --- | --- | --- | ---: | ---: | ---: |
|
|
130
|
+
| Standard | 4 KiB | encode | 13.57 GiB/s | 0.48 GiB/s | **14.06 GiB/s** |
|
|
131
|
+
| | 4 KiB | decode | **16.70 GiB/s** | 1.13 GiB/s | 8.47 GiB/s |
|
|
132
|
+
| | 1 MiB | encode | **3.28 GiB/s** | 0.44 GiB/s | 3.02 GiB/s |
|
|
133
|
+
| | 1 MiB | decode | **4.02 GiB/s** | 0.95 GiB/s | 3.68 GiB/s |
|
|
134
|
+
| | 32 MiB | encode | **2.92 GiB/s** | 0.43 GiB/s | 2.84 GiB/s |
|
|
135
|
+
| | 32 MiB | decode | 3.40 GiB/s | 0.94 GiB/s | **3.69 GiB/s** |
|
|
136
|
+
| URL-safe | 4 KiB | encode | **12.63 GiB/s** | 0.41 GiB/s | 1.19 GiB/s |
|
|
137
|
+
| | 4 KiB | decode | **11.34 GiB/s** | 0.76 GiB/s | 1.56 GiB/s |
|
|
138
|
+
| | 1 MiB | encode | **3.24 GiB/s** | 0.36 GiB/s | 0.91 GiB/s |
|
|
139
|
+
| | 1 MiB | decode | **4.15 GiB/s** | 0.63 GiB/s | 1.45 GiB/s |
|
|
140
|
+
| | 32 MiB | encode | **3.03 GiB/s** | 0.36 GiB/s | 0.90 GiB/s |
|
|
141
|
+
| | 32 MiB | decode | **3.40 GiB/s** | 0.61 GiB/s | 1.48 GiB/s |
|
|
142
|
+
|
|
143
|
+
## MurmurHash3: Python
|
|
144
|
+
|
|
145
|
+
| Variant | API | Input | hashcodecs | `mmh3` |
|
|
146
|
+
| --- | --- | --- | ---: | ---: |
|
|
147
|
+
| x86 32-bit | one-shot | 4 KiB | **3.79 GiB/s** | 3.71 GiB/s |
|
|
148
|
+
| | | 1 MiB | **3.98 GiB/s** | 3.83 GiB/s |
|
|
149
|
+
| | | 32 MiB | **3.97 GiB/s** | 3.66 GiB/s |
|
|
150
|
+
| | incremental | 4 KiB | **3.58 GiB/s** | **3.58 GiB/s** |
|
|
151
|
+
| | | 1 MiB | **3.96 GiB/s** | 3.81 GiB/s |
|
|
152
|
+
| | | 32 MiB | **3.92 GiB/s** | 3.74 GiB/s |
|
|
153
|
+
| x86 128-bit | one-shot | 4 KiB | 8.09 GiB/s | **8.21 GiB/s** |
|
|
154
|
+
| | | 1 MiB | **9.22 GiB/s** | 8.87 GiB/s |
|
|
155
|
+
| | | 32 MiB | **9.12 GiB/s** | 6.15 GiB/s |
|
|
156
|
+
| | incremental | 4 KiB | **7.02 GiB/s** | 0.77 GiB/s |
|
|
157
|
+
| | | 1 MiB | **9.17 GiB/s** | 0.80 GiB/s |
|
|
158
|
+
| | | 32 MiB | **9.01 GiB/s** | 0.79 GiB/s |
|
|
159
|
+
| x64 128-bit | one-shot | 4 KiB | 8.68 GiB/s | **9.46 GiB/s** |
|
|
160
|
+
| | | 1 MiB | 10.10 GiB/s | **10.24 GiB/s** |
|
|
161
|
+
| | | 32 MiB | **9.54 GiB/s** | 6.61 GiB/s |
|
|
162
|
+
| | incremental | 4 KiB | 7.70 GiB/s | **7.99 GiB/s** |
|
|
163
|
+
| | | 1 MiB | **10.01 GiB/s** | 9.28 GiB/s |
|
|
164
|
+
| | | 32 MiB | **9.41 GiB/s** | 7.34 GiB/s |
|
|
165
|
+
|
|
166
|
+
Reusable-buffer and mutable-input results are available in [BENCHMARK.md](https://github.com/kozistr/hashcodecs-rs/blob/main/BENCHMARK.md).
|
|
167
|
+
|
|
168
|
+
## SIMD References
|
|
169
|
+
|
|
170
|
+
The SIMD implementation follows the approach described in [Faster Base64 Encoding and Decoding using AVX2 Instructions](https://arxiv.org/abs/1704.00605), with AVX-512 VBMI and AArch64 NEON backends selected automatically when available.
|
|
@@ -15,42 +15,42 @@ class CustomBuildHook(BuildHookInterface[Any]):
|
|
|
15
15
|
"""Build the portable ABI3 extension and give the wheel its native tag."""
|
|
16
16
|
|
|
17
17
|
def initialize(self, version: str, build_data: dict[str, Any]) -> None:
|
|
18
|
-
if self.target_name !=
|
|
18
|
+
if self.target_name != 'wheel':
|
|
19
19
|
return
|
|
20
20
|
|
|
21
21
|
root = Path(self.root)
|
|
22
22
|
subprocess.run(
|
|
23
23
|
[
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
str(root /
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
24
|
+
'cargo',
|
|
25
|
+
'build',
|
|
26
|
+
'--manifest-path',
|
|
27
|
+
str(root / 'Cargo.toml'),
|
|
28
|
+
'--release',
|
|
29
|
+
'--features',
|
|
30
|
+
'extension-module',
|
|
31
31
|
],
|
|
32
32
|
check=True,
|
|
33
33
|
cwd=root,
|
|
34
34
|
)
|
|
35
35
|
|
|
36
|
-
extension = root /
|
|
37
|
-
build_data[
|
|
38
|
-
build_data[
|
|
39
|
-
build_data[
|
|
36
|
+
extension = root / 'target' / 'release' / self._library_name()
|
|
37
|
+
build_data['force_include'] = {str(extension): f'hashcodecs/_hashcodecs{self._extension_suffix()}'}
|
|
38
|
+
build_data['pure_python'] = False
|
|
39
|
+
build_data['tag'] = self._wheel_tag()
|
|
40
40
|
|
|
41
41
|
@staticmethod
|
|
42
42
|
def _library_name() -> str:
|
|
43
43
|
system = platform.system()
|
|
44
|
-
if system ==
|
|
45
|
-
return
|
|
46
|
-
if system ==
|
|
47
|
-
return
|
|
48
|
-
return
|
|
44
|
+
if system == 'Windows':
|
|
45
|
+
return 'hashcodecs.dll'
|
|
46
|
+
if system == 'Darwin':
|
|
47
|
+
return 'libhashcodecs.dylib'
|
|
48
|
+
return 'libhashcodecs.so'
|
|
49
49
|
|
|
50
50
|
@staticmethod
|
|
51
51
|
def _extension_suffix() -> str:
|
|
52
|
-
return
|
|
52
|
+
return '.pyd' if platform.system() == 'Windows' else '.so'
|
|
53
53
|
|
|
54
54
|
@staticmethod
|
|
55
55
|
def _wheel_tag() -> str:
|
|
56
|
-
return f
|
|
56
|
+
return f'cp310-abi3-{next(sys_tags()).platform}'
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "hashcodecs"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.4.0"
|
|
8
8
|
description = "SIMD-accelerated Base64 and MurmurHash3 codecs"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -12,6 +12,12 @@ license = "MIT OR Apache-2.0"
|
|
|
12
12
|
license-files = ["LICENSE", "LICENSE-MIT"]
|
|
13
13
|
classifiers = [
|
|
14
14
|
"Programming Language :: Python :: 3",
|
|
15
|
+
"Programming Language :: Python :: 3.10",
|
|
16
|
+
"Programming Language :: Python :: 3.11",
|
|
17
|
+
"Programming Language :: Python :: 3.12",
|
|
18
|
+
"Programming Language :: Python :: 3.13",
|
|
19
|
+
"Programming Language :: Python :: 3.14",
|
|
20
|
+
"Programming Language :: Python :: 3.15",
|
|
15
21
|
"Programming Language :: Rust",
|
|
16
22
|
"Operating System :: OS Independent",
|
|
17
23
|
"Topic :: Software Development :: Libraries",
|
|
@@ -33,6 +39,7 @@ packages = ["python/hashcodecs"]
|
|
|
33
39
|
|
|
34
40
|
[tool.hatch.build.targets.sdist]
|
|
35
41
|
include = [
|
|
42
|
+
"/BENCHMARK.md",
|
|
36
43
|
"/Cargo.lock",
|
|
37
44
|
"/Cargo.toml",
|
|
38
45
|
"/build.rs",
|
|
@@ -66,6 +73,7 @@ line-length = 119
|
|
|
66
73
|
target-version = "py312"
|
|
67
74
|
|
|
68
75
|
[tool.ruff.lint]
|
|
76
|
+
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
|
|
69
77
|
select = [
|
|
70
78
|
"E",
|
|
71
79
|
"F",
|
|
@@ -79,11 +87,24 @@ select = [
|
|
|
79
87
|
"PTH",
|
|
80
88
|
"PT",
|
|
81
89
|
"PYI",
|
|
90
|
+
"Q",
|
|
82
91
|
"RET",
|
|
83
92
|
"RUF",
|
|
84
93
|
"SIM",
|
|
85
94
|
]
|
|
86
95
|
|
|
96
|
+
[tool.ruff.lint.flake8-quotes]
|
|
97
|
+
docstring-quotes = "double"
|
|
98
|
+
inline-quotes = "single"
|
|
99
|
+
|
|
100
|
+
[tool.ruff.lint.isort]
|
|
101
|
+
combine-as-imports = false
|
|
102
|
+
detect-same-package = true
|
|
103
|
+
force-sort-within-sections = false
|
|
104
|
+
|
|
105
|
+
[tool.ruff.format]
|
|
106
|
+
quote-style = "single"
|
|
107
|
+
|
|
87
108
|
[tool.coverage.run]
|
|
88
109
|
branch = true
|
|
89
110
|
source = ["hashcodecs"]
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"""SIMD-accelerated Base64 and MurmurHash3 functions."""
|
|
2
|
+
|
|
3
|
+
from .base64 import (
|
|
4
|
+
b64decode,
|
|
5
|
+
b64decode_batch,
|
|
6
|
+
b64decode_into,
|
|
7
|
+
b64encode,
|
|
8
|
+
b64encode_batch,
|
|
9
|
+
b64encode_into,
|
|
10
|
+
standard_b64decode,
|
|
11
|
+
standard_b64decode_batch,
|
|
12
|
+
standard_b64decode_into,
|
|
13
|
+
standard_b64encode,
|
|
14
|
+
standard_b64encode_batch,
|
|
15
|
+
standard_b64encode_into,
|
|
16
|
+
urlsafe_b64decode,
|
|
17
|
+
urlsafe_b64decode_batch,
|
|
18
|
+
urlsafe_b64decode_into,
|
|
19
|
+
urlsafe_b64encode,
|
|
20
|
+
urlsafe_b64encode_batch,
|
|
21
|
+
urlsafe_b64encode_into,
|
|
22
|
+
)
|
|
23
|
+
from .murmur3 import (
|
|
24
|
+
murmur3_32,
|
|
25
|
+
murmur3_x64_128,
|
|
26
|
+
murmur3_x64_128_digest,
|
|
27
|
+
murmur3_x86_32,
|
|
28
|
+
murmur3_x86_128,
|
|
29
|
+
murmur3_x86_128_digest,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
__all__ = [
|
|
33
|
+
'b64decode',
|
|
34
|
+
'b64decode_batch',
|
|
35
|
+
'b64decode_into',
|
|
36
|
+
'b64encode',
|
|
37
|
+
'b64encode_batch',
|
|
38
|
+
'b64encode_into',
|
|
39
|
+
'murmur3_32',
|
|
40
|
+
'murmur3_x64_128',
|
|
41
|
+
'murmur3_x64_128_digest',
|
|
42
|
+
'murmur3_x86_32',
|
|
43
|
+
'murmur3_x86_128',
|
|
44
|
+
'murmur3_x86_128_digest',
|
|
45
|
+
'standard_b64decode',
|
|
46
|
+
'standard_b64decode_batch',
|
|
47
|
+
'standard_b64decode_into',
|
|
48
|
+
'standard_b64encode',
|
|
49
|
+
'standard_b64encode_batch',
|
|
50
|
+
'standard_b64encode_into',
|
|
51
|
+
'urlsafe_b64decode',
|
|
52
|
+
'urlsafe_b64decode_batch',
|
|
53
|
+
'urlsafe_b64decode_into',
|
|
54
|
+
'urlsafe_b64encode',
|
|
55
|
+
'urlsafe_b64encode_batch',
|
|
56
|
+
'urlsafe_b64encode_into',
|
|
57
|
+
]
|