snapfast 0.1.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.
- snapfast-0.1.0/Cargo.lock +187 -0
- snapfast-0.1.0/Cargo.toml +13 -0
- snapfast-0.1.0/PKG-INFO +27 -0
- snapfast-0.1.0/README.md +3 -0
- snapfast-0.1.0/dist/snapfast-0.1.0.tar.gz +0 -0
- snapfast-0.1.0/pyproject.toml +35 -0
- snapfast-0.1.0/python/snapfast/__init__.py +42 -0
- snapfast-0.1.0/src/lib.rs +55 -0
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# This file is automatically @generated by Cargo.
|
|
2
|
+
# It is not intended for manual editing.
|
|
3
|
+
version = 4
|
|
4
|
+
|
|
5
|
+
[[package]]
|
|
6
|
+
name = "autocfg"
|
|
7
|
+
version = "1.5.1"
|
|
8
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
9
|
+
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
|
|
10
|
+
|
|
11
|
+
[[package]]
|
|
12
|
+
name = "cfg-if"
|
|
13
|
+
version = "1.0.4"
|
|
14
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
15
|
+
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
|
16
|
+
|
|
17
|
+
[[package]]
|
|
18
|
+
name = "heck"
|
|
19
|
+
version = "0.5.0"
|
|
20
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
21
|
+
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
|
22
|
+
|
|
23
|
+
[[package]]
|
|
24
|
+
name = "indoc"
|
|
25
|
+
version = "2.0.7"
|
|
26
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
27
|
+
checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706"
|
|
28
|
+
dependencies = [
|
|
29
|
+
"rustversion",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[[package]]
|
|
33
|
+
name = "libc"
|
|
34
|
+
version = "0.2.189"
|
|
35
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
36
|
+
checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
|
|
37
|
+
|
|
38
|
+
[[package]]
|
|
39
|
+
name = "memoffset"
|
|
40
|
+
version = "0.9.1"
|
|
41
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
42
|
+
checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
|
|
43
|
+
dependencies = [
|
|
44
|
+
"autocfg",
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
[[package]]
|
|
48
|
+
name = "once_cell"
|
|
49
|
+
version = "1.21.4"
|
|
50
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
51
|
+
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
|
52
|
+
|
|
53
|
+
[[package]]
|
|
54
|
+
name = "portable-atomic"
|
|
55
|
+
version = "1.15.0"
|
|
56
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
57
|
+
checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85"
|
|
58
|
+
|
|
59
|
+
[[package]]
|
|
60
|
+
name = "proc-macro2"
|
|
61
|
+
version = "1.0.107"
|
|
62
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
63
|
+
checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
|
|
64
|
+
dependencies = [
|
|
65
|
+
"unicode-ident",
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
[[package]]
|
|
69
|
+
name = "pyo3"
|
|
70
|
+
version = "0.22.6"
|
|
71
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
72
|
+
checksum = "f402062616ab18202ae8319da13fa4279883a2b8a9d9f83f20dbade813ce1884"
|
|
73
|
+
dependencies = [
|
|
74
|
+
"cfg-if",
|
|
75
|
+
"indoc",
|
|
76
|
+
"libc",
|
|
77
|
+
"memoffset",
|
|
78
|
+
"once_cell",
|
|
79
|
+
"portable-atomic",
|
|
80
|
+
"pyo3-build-config",
|
|
81
|
+
"pyo3-ffi",
|
|
82
|
+
"pyo3-macros",
|
|
83
|
+
"unindent",
|
|
84
|
+
]
|
|
85
|
+
|
|
86
|
+
[[package]]
|
|
87
|
+
name = "pyo3-build-config"
|
|
88
|
+
version = "0.22.6"
|
|
89
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
90
|
+
checksum = "b14b5775b5ff446dd1056212d778012cbe8a0fbffd368029fd9e25b514479c38"
|
|
91
|
+
dependencies = [
|
|
92
|
+
"once_cell",
|
|
93
|
+
"target-lexicon",
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
[[package]]
|
|
97
|
+
name = "pyo3-ffi"
|
|
98
|
+
version = "0.22.6"
|
|
99
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
100
|
+
checksum = "9ab5bcf04a2cdcbb50c7d6105de943f543f9ed92af55818fd17b660390fc8636"
|
|
101
|
+
dependencies = [
|
|
102
|
+
"libc",
|
|
103
|
+
"pyo3-build-config",
|
|
104
|
+
]
|
|
105
|
+
|
|
106
|
+
[[package]]
|
|
107
|
+
name = "pyo3-macros"
|
|
108
|
+
version = "0.22.6"
|
|
109
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
110
|
+
checksum = "0fd24d897903a9e6d80b968368a34e1525aeb719d568dba8b3d4bfa5dc67d453"
|
|
111
|
+
dependencies = [
|
|
112
|
+
"proc-macro2",
|
|
113
|
+
"pyo3-macros-backend",
|
|
114
|
+
"quote",
|
|
115
|
+
"syn",
|
|
116
|
+
]
|
|
117
|
+
|
|
118
|
+
[[package]]
|
|
119
|
+
name = "pyo3-macros-backend"
|
|
120
|
+
version = "0.22.6"
|
|
121
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
122
|
+
checksum = "36c011a03ba1e50152b4b394b479826cad97e7a21eb52df179cd91ac411cbfbe"
|
|
123
|
+
dependencies = [
|
|
124
|
+
"heck",
|
|
125
|
+
"proc-macro2",
|
|
126
|
+
"pyo3-build-config",
|
|
127
|
+
"quote",
|
|
128
|
+
"syn",
|
|
129
|
+
]
|
|
130
|
+
|
|
131
|
+
[[package]]
|
|
132
|
+
name = "quote"
|
|
133
|
+
version = "1.0.47"
|
|
134
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
135
|
+
checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
|
|
136
|
+
dependencies = [
|
|
137
|
+
"proc-macro2",
|
|
138
|
+
]
|
|
139
|
+
|
|
140
|
+
[[package]]
|
|
141
|
+
name = "rustversion"
|
|
142
|
+
version = "1.0.23"
|
|
143
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
144
|
+
checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f"
|
|
145
|
+
|
|
146
|
+
[[package]]
|
|
147
|
+
name = "snap"
|
|
148
|
+
version = "1.1.2"
|
|
149
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
150
|
+
checksum = "199905e6153d6405f9728fe44daace35f8f837bbf830bb6e85fbd5828709a886"
|
|
151
|
+
|
|
152
|
+
[[package]]
|
|
153
|
+
name = "snapfast"
|
|
154
|
+
version = "0.1.0"
|
|
155
|
+
dependencies = [
|
|
156
|
+
"pyo3",
|
|
157
|
+
"snap",
|
|
158
|
+
]
|
|
159
|
+
|
|
160
|
+
[[package]]
|
|
161
|
+
name = "syn"
|
|
162
|
+
version = "2.0.119"
|
|
163
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
164
|
+
checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
|
|
165
|
+
dependencies = [
|
|
166
|
+
"proc-macro2",
|
|
167
|
+
"quote",
|
|
168
|
+
"unicode-ident",
|
|
169
|
+
]
|
|
170
|
+
|
|
171
|
+
[[package]]
|
|
172
|
+
name = "target-lexicon"
|
|
173
|
+
version = "0.12.16"
|
|
174
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
175
|
+
checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
|
|
176
|
+
|
|
177
|
+
[[package]]
|
|
178
|
+
name = "unicode-ident"
|
|
179
|
+
version = "1.0.24"
|
|
180
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
181
|
+
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
|
182
|
+
|
|
183
|
+
[[package]]
|
|
184
|
+
name = "unindent"
|
|
185
|
+
version = "0.2.4"
|
|
186
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
187
|
+
checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3"
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "snapfast"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
edition = "2021"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
|
|
7
|
+
[lib]
|
|
8
|
+
name = "snapfast"
|
|
9
|
+
crate-type = ["cdylib"]
|
|
10
|
+
|
|
11
|
+
[dependencies]
|
|
12
|
+
pyo3 = { version = "0.22", features = ["extension-module", "abi3-py312"] }
|
|
13
|
+
snap = "1.1"
|
snapfast-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: snapfast
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Classifier: Development Status :: 3 - Alpha
|
|
5
|
+
Classifier: Programming Language :: Rust
|
|
6
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
9
|
+
Classifier: Topic :: System :: Archiving :: Compression
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Requires-Dist: pytest ; extra == 'test'
|
|
12
|
+
Requires-Dist: numpy ; extra == 'test'
|
|
13
|
+
Provides-Extra: test
|
|
14
|
+
Summary: Minimal Snappy compression for Python, backed by Rust
|
|
15
|
+
Keywords: snappy,compression,rust,pyo3
|
|
16
|
+
Author-email: Isaac Onagh <adnanonagh@gmail.com>
|
|
17
|
+
License: MIT
|
|
18
|
+
Requires-Python: >=3.8
|
|
19
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
20
|
+
Project-URL: Homepage, https://github.com/unforgivenii147/snapfast
|
|
21
|
+
Project-URL: Repository, https://github.com/unforgivenii147/snapfast
|
|
22
|
+
Project-URL: Issues, https://github.com/unforgivenii147/snapfast/issues
|
|
23
|
+
|
|
24
|
+
# snapfast
|
|
25
|
+
python library to ude snappy compression
|
|
26
|
+
|
|
27
|
+
|
snapfast-0.1.0/README.md
ADDED
|
Binary file
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["maturin==1.10.2"]
|
|
3
|
+
build-backend = "maturin"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "snapfast"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Minimal Snappy compression for Python, backed by Rust"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.8"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "Isaac Onagh", email = "adnanonagh@gmail.com" }]
|
|
13
|
+
keywords = ["snappy", "compression", "rust", "pyo3"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Programming Language :: Rust",
|
|
17
|
+
"Programming Language :: Python :: Implementation :: CPython",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
20
|
+
"Topic :: System :: Archiving :: Compression",
|
|
21
|
+
"License :: OSI Approved :: MIT License",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
[project.urls]
|
|
25
|
+
Homepage = "https://github.com/unforgivenii147/snapfast"
|
|
26
|
+
Repository = "https://github.com/unforgivenii147/snapfast"
|
|
27
|
+
Issues = "https://github.com/unforgivenii147/snapfast/issues"
|
|
28
|
+
|
|
29
|
+
[project.optional-dependencies]
|
|
30
|
+
test = ["pytest", "numpy"]
|
|
31
|
+
|
|
32
|
+
[tool.maturin]
|
|
33
|
+
python-source = "python"
|
|
34
|
+
module-name = "snapfast._snapy"
|
|
35
|
+
features = ["pyo3/extension-module"]
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""snapfast: minimal Snappy compression backed by Rust."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from ._snapy import compress, decompress, decompressed_len
|
|
6
|
+
|
|
7
|
+
__all__ = ["compress", "decompress", "decompressed_len", "compress_file", "decompress_file"]
|
|
8
|
+
__version__ = "0.1.0"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def compress_file(src: str, dst: str, chunk_size: int = 1 << 20) -> None:
|
|
12
|
+
"""Read *src*, write Snappy-compressed bytes to *dst*.
|
|
13
|
+
|
|
14
|
+
Note: raw Snappy has no framing, so we concatenate per-chunk
|
|
15
|
+
compressed blocks with a length prefix so we can decompress later.
|
|
16
|
+
For a single-shot API use ``compress`` directly.
|
|
17
|
+
"""
|
|
18
|
+
import struct
|
|
19
|
+
|
|
20
|
+
with open(src, "rb") as fin, open(dst, "wb") as fout:
|
|
21
|
+
while True:
|
|
22
|
+
chunk = fin.read(chunk_size)
|
|
23
|
+
if not chunk:
|
|
24
|
+
break
|
|
25
|
+
block = compress(chunk)
|
|
26
|
+
fout.write(struct.pack("<I", len(block)))
|
|
27
|
+
fout.write(block)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def decompress_file(src: str, dst: str, chunk_size: int = 1 << 20) -> None:
|
|
31
|
+
import struct
|
|
32
|
+
|
|
33
|
+
with open(src, "rb") as fin, open(dst, "wb") as fout:
|
|
34
|
+
while True:
|
|
35
|
+
header = fin.read(4)
|
|
36
|
+
if not header:
|
|
37
|
+
break
|
|
38
|
+
(n,) = struct.unpack("<I", header)
|
|
39
|
+
block = fin.read(n)
|
|
40
|
+
if len(block) != n:
|
|
41
|
+
raise ValueError("truncated snappy block")
|
|
42
|
+
fout.write(decompress(block))
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
use pyo3::buffer::PyBuffer;
|
|
2
|
+
use pyo3::exceptions::PyValueError;
|
|
3
|
+
use pyo3::prelude::*;
|
|
4
|
+
use pyo3::types::PyBytes;
|
|
5
|
+
|
|
6
|
+
/// Helper: extract a &[u8] from anything supporting the buffer protocol.
|
|
7
|
+
fn as_slice<T, F>(data: &Bound<'_, PyAny>, f: F) -> PyResult<T>
|
|
8
|
+
where
|
|
9
|
+
F: FnOnce(&[u8]) -> PyResult<T>,
|
|
10
|
+
{
|
|
11
|
+
let buf = PyBuffer::<u8>::get_bound(data)?;
|
|
12
|
+
// Safety: we hold `buf` alive for the duration of the call, and we
|
|
13
|
+
// only read from it. We must not allow the callback to escape with
|
|
14
|
+
// the slice.
|
|
15
|
+
let slice = unsafe {
|
|
16
|
+
std::slice::from_raw_parts(buf.buf_ptr() as *const u8, buf.item_count())
|
|
17
|
+
};
|
|
18
|
+
f(slice)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
#[pyfunction]
|
|
22
|
+
fn compress<'py>(py: Python<'py>, data: &Bound<'py, PyAny>) -> PyResult<Bound<'py, PyBytes>> {
|
|
23
|
+
as_slice(data, |slice| {
|
|
24
|
+
let compressed = snap::raw::Encoder::new()
|
|
25
|
+
.compress_vec(slice)
|
|
26
|
+
.map_err(|e| PyValueError::new_err(format!("snappy compress failed: {e}")))?;
|
|
27
|
+
Ok(PyBytes::new_bound(py, &compressed))
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
#[pyfunction]
|
|
32
|
+
fn decompress<'py>(py: Python<'py>, data: &Bound<'py, PyAny>) -> PyResult<Bound<'py, PyBytes>> {
|
|
33
|
+
as_slice(data, |slice| {
|
|
34
|
+
let decompressed = snap::raw::Decoder::new()
|
|
35
|
+
.decompress_vec(slice)
|
|
36
|
+
.map_err(|e| PyValueError::new_err(format!("snappy decompress failed: {e}")))?;
|
|
37
|
+
Ok(PyBytes::new_bound(py, &decompressed))
|
|
38
|
+
})
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
#[pyfunction]
|
|
42
|
+
fn decompressed_len(data: &Bound<'_, PyAny>) -> PyResult<usize> {
|
|
43
|
+
as_slice(data, |slice| {
|
|
44
|
+
snap::raw::decompress_len(slice)
|
|
45
|
+
.map_err(|e| PyValueError::new_err(format!("bad snappy header: {e}")))
|
|
46
|
+
})
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
#[pymodule]
|
|
50
|
+
fn _snapy(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
|
51
|
+
m.add_function(wrap_pyfunction!(compress, m)?)?;
|
|
52
|
+
m.add_function(wrap_pyfunction!(decompress, m)?)?;
|
|
53
|
+
m.add_function(wrap_pyfunction!(decompressed_len, m)?)?;
|
|
54
|
+
Ok(())
|
|
55
|
+
}
|