lzstring-codec 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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Andrew Grinevich
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,202 @@
1
+ Metadata-Version: 2.4
2
+ Name: lzstring-codec
3
+ Version: 0.1.0
4
+ Classifier: Development Status :: 4 - Beta
5
+ Classifier: Intended Audience :: Developers
6
+ Classifier: License :: OSI Approved :: MIT License
7
+ Classifier: Programming Language :: Python :: 3.12
8
+ Classifier: Programming Language :: Python :: 3.13
9
+ Classifier: Programming Language :: Rust
10
+ Classifier: Topic :: System :: Archiving :: Compression
11
+ Classifier: Typing :: Typed
12
+ Requires-Dist: pytest>=8 ; extra == 'dev'
13
+ Requires-Dist: ruff>=0.6 ; extra == 'dev'
14
+ Provides-Extra: dev
15
+ License-File: LICENSE
16
+ License-File: THIRD_PARTY.md
17
+ Summary: lz-string for Python, held byte-for-byte to the JavaScript original
18
+ Keywords: lz-string,lzstring,lzstring-codec,compression,lzw,savegame,utf-16
19
+ Author-email: Andrew Grinevich <beulea@gmail.com>
20
+ License-Expression: MIT
21
+ Requires-Python: >=3.12
22
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
23
+ Project-URL: Homepage, https://github.com/Derfirm/lz-string
24
+ Project-URL: Issues, https://github.com/Derfirm/lz-string/issues
25
+ Project-URL: Source, https://github.com/Derfirm/lz-string
26
+ Project-URL: Specification, https://github.com/Derfirm/lz-string/blob/master/SPEC.md
27
+
28
+ # lzstring-codec
29
+
30
+ lz-string for Python, held byte-for-byte to the JavaScript original.
31
+
32
+ Installed as `lzstring-codec`, imported as `lz_string`. The obvious name is not available:
33
+ PyPI refuses it as too similar to `lzstring`, which is one of the two packages this exists
34
+ to replace.
35
+
36
+ It exists because the package that *is* on PyPI gets the format wrong in ways that quietly
37
+ corrupt real save files. It was written for [saveeditor.online](https://saveeditor.online),
38
+ which reads a few thousand lz-string saves a week and cannot afford to hand any of them back
39
+ altered.
40
+
41
+ ```python
42
+ import lz_string as lz
43
+
44
+ lz.compress_to_base64('{"gold":9000}') # 'N4Ig5g9gNgJiBcBOADKgvkA='
45
+ lz.decompress_from_base64(_) # '{"gold":9000}'
46
+ ```
47
+
48
+ ## Why
49
+
50
+ `lzstring` 1.0.4 on PyPI is a line-by-line transliteration of the JavaScript, and it
51
+ inherits neither its speed nor its correctness. Measured against 1202 vectors produced by
52
+ `lz-string` 1.5.0 on npm — the library the games themselves use:
53
+
54
+ - **294 vectors compress to different bytes**, because it walks Python code points where
55
+ the format is defined over UTF-16 code units. In practice: an emoji in a player's name is
56
+ written truncated, and the game reads back `U+F600`, a private-use box. Every save with an
57
+ astral character is corrupted on write.
58
+ - **`decompressFromUTF16` raises `TypeError` on every input.** It subtracts an integer from
59
+ a string. The function has never worked.
60
+ - Decompression rebuilds a 65-entry alphabet table *per character* and reads the bit stream
61
+ one bit at a time: **22 seconds** for a 1.8 MB save, on the request path.
62
+
63
+ This package is byte-identical to the reference on all 1202 vectors, in all four
64
+ transports, in both directions, on both backends — and 15–45× faster.
65
+
66
+ How far that was pushed, because "it round-trips" is not the same as "it is right":
67
+
68
+ | check | scale | result |
69
+ |---|---|---|
70
+ | golden corpus vs. node | 1202 vectors x 4 transports x 2 directions x 2 backends | identical |
71
+ | real production saves | 38 files up to 1.8 MB, decompress **and** recompress | identical |
72
+ | differential fuzz vs. node | 5000 generated inputs x 4 transports x 2 backends | identical |
73
+ | malformed-input fuzz | 16000 probes x 2 backends | agree with each other and with the reference; nothing raised |
74
+
75
+ The last row is the one that found bugs — two of them in this package, both invisible to
76
+ every check above it, and both now pinned by tests. SPEC.md §4 says what they were.
77
+
78
+ And it is not the only one: `py-lzstring` 0.1.1, a separate port of the same reference,
79
+ differs from it on **295 of the same 1202 vectors**, first on exactly the same astral
80
+ character. Two independent Python ports, the same mistake in both.
81
+
82
+ See [SPEC.md](SPEC.md) for the format itself and for the full divergence table.
83
+
84
+ ## Installing
85
+
86
+ The package is a compiled extension; `pip install` builds it, and a Rust toolchain is
87
+ required to do so.
88
+
89
+ ```bash
90
+ uv add git+ssh://git@github.com/Derfirm/lz-string.git # or, in a checkout:
91
+ uv sync # builds the extension in place
92
+ pip install . # pip works too; maturin does the build
93
+ ```
94
+
95
+ An import without the extension raises rather than falling back to something slower and
96
+ subtly different.
97
+
98
+ **Build it where it will run.** The binary is tied to the C library it was linked against:
99
+ one built on Debian bookworm (glibc 2.36) will not load on bullseye (2.31), which is what
100
+ `python:3.12.11-slim-bullseye` — the image this package is destined for — is built on. It
101
+ fails at import with `GLIBC_2.34 not found`, not at build time. Either build inside the
102
+ target image, or produce a manylinux wheel.
103
+
104
+ On two real saves, best of three in one run:
105
+
106
+ | | decompress | compress |
107
+ |---|---|---|
108
+ | **this package**, 259 KB → 975 K chars | **0.004 s** | **0.044 s** |
109
+ | `lzstring` 1.0.4, the same | 1.199 s | 0.312 s |
110
+ | **this package**, 1.8 MB → 13.4 M chars | **0.054 s** | **1.547 s** |
111
+ | `lzstring` 1.0.4, the same | 8.581 s | 4.766 s |
112
+
113
+ Both halves are ours, and the only Rust dependency is pyo3. The obvious alternative,
114
+ the [`lz-str`](https://crates.io/crates/lz-str) crate, was the starting point and did not
115
+ survive contact with damaged input: it answers the same thing for two failures the reference
116
+ keeps apart, skips characters the reference reads as zero bits, and refuses a payload whose
117
+ trailing padding character was trimmed. SPEC.md §7 has the measurements.
118
+
119
+ A pure-Python implementation of the whole format lives in `src/lz_string/_reference.py`.
120
+ It is the test suite's second opinion, not a fallback: nothing imports it at runtime.
121
+
122
+ ## Migrating from `lzstring`
123
+
124
+ The camelCase API is provided as-is, so the change is one import line:
125
+
126
+ ```python
127
+ -from lzstring import LZString
128
+ +from lz_string import LZString
129
+ ```
130
+
131
+ Two behaviour changes to know about, both improvements, both in SPEC.md: saves containing
132
+ astral characters stop being corrupted, and `decompressFromUTF16` starts working.
133
+
134
+ ## Tests
135
+
136
+ ```bash
137
+ uv sync --extra dev # .python-version pins 3.12, as in production
138
+ uv run pytest # every test runs against both implementations
139
+ uv sync --reinstall-package lzstring-codec # after touching the Rust: rebuild it
140
+ ./tools/check_linux.sh # built and run inside the target image (needs docker)
141
+ ./tools/check_linux.sh linux/amd64 # and on production's architecture, cross-compiled
142
+ ```
143
+
144
+ The Linux run is not ceremony. It is done in `python:3.12.11-slim-bullseye` — the exact image
145
+ this is destined for — and it has already caught two things a laptop cannot: a test that
146
+ measured the machine rather than the code, and an extension that built cleanly and then
147
+ refused to load because it wanted a newer glibc than the image has.
148
+
149
+ 251 tests: the golden corpus per category and transport, the documented behaviour on damaged
150
+ input, seeded round-trips over random code units and surrogate halves, parity between the
151
+ shipped extension and the Python reference — including a fuzz of malformed payloads, which
152
+ is what pins the three corrections the crate underneath needed — and two tests that the
153
+ extension really does let go of the interpreter while it works.
154
+
155
+ To regenerate the corpus (deterministic — a diff means the reference moved):
156
+
157
+ ```bash
158
+ npm --prefix tools install
159
+ node tools/gen_vectors.mjs
160
+ ```
161
+
162
+ `tools/bench.py` reproduces the numbers above.
163
+
164
+ ## Releasing
165
+
166
+ By tag, not by merge. Most merges here are documentation and CI, and PyPI refuses a second
167
+ upload of the same version — publishing on merge would mean either a version bump per commit
168
+ or a release job that fails as a matter of course.
169
+
170
+ ```bash
171
+ # bump `version` in pyproject.toml, note it in CHANGELOG.md, merge, then:
172
+ git tag v0.1.0 && git push origin v0.1.0
173
+ ```
174
+
175
+ The workflow builds wheels for linux and macOS on both architectures plus an sdist, checks
176
+ that the tag and the version in pyproject.toml agree, and only then uploads.
177
+ `workflow_dispatch` runs everything except the upload, which is how the pipeline is tested
178
+ without releasing anything.
179
+
180
+ The upload needs a credential, and there are two ways to give it one. Either works; the
181
+ first stores nothing.
182
+
183
+ **Trusted publishing.** On PyPI, add a pending publisher for the project name with owner
184
+ `Derfirm`, repository `lz-string`, workflow `release.yml`, environment `pypi`. Nothing to
185
+ configure here — with no `PYPI_API_TOKEN` secret set, the publish step already exchanges a
186
+ short-lived OIDC token, which is what it tries today and what fails with "Trusted publishing
187
+ exchange failure" until the publisher exists.
188
+
189
+ **A token.** Create an environment named `pypi` in the repository settings, put an API token
190
+ in it as `PYPI_API_TOKEN`, and re-run the publish job of the tagged release. Protection
191
+ rules on that environment are where you add an approval step if you want one.
192
+
193
+ ## Provenance and licence
194
+
195
+ MIT (`LICENSE`). Compression comes from the [`lz-str`](https://crates.io/crates/lz-str)
196
+ crate and the bindings from [pyo3](https://pyo3.rs), both MIT/Apache-2.0; the decoder is a
197
+ port of [pieroxy/lz-string](https://github.com/pieroxy/lz-string), MIT, which is also the
198
+ reference every claim here is measured against. See `THIRD_PARTY.md`.
199
+
200
+ No user data lives in this repository: every test input is generated, and the corpus is the
201
+ reference implementation's own output.
202
+
@@ -0,0 +1,174 @@
1
+ # lzstring-codec
2
+
3
+ lz-string for Python, held byte-for-byte to the JavaScript original.
4
+
5
+ Installed as `lzstring-codec`, imported as `lz_string`. The obvious name is not available:
6
+ PyPI refuses it as too similar to `lzstring`, which is one of the two packages this exists
7
+ to replace.
8
+
9
+ It exists because the package that *is* on PyPI gets the format wrong in ways that quietly
10
+ corrupt real save files. It was written for [saveeditor.online](https://saveeditor.online),
11
+ which reads a few thousand lz-string saves a week and cannot afford to hand any of them back
12
+ altered.
13
+
14
+ ```python
15
+ import lz_string as lz
16
+
17
+ lz.compress_to_base64('{"gold":9000}') # 'N4Ig5g9gNgJiBcBOADKgvkA='
18
+ lz.decompress_from_base64(_) # '{"gold":9000}'
19
+ ```
20
+
21
+ ## Why
22
+
23
+ `lzstring` 1.0.4 on PyPI is a line-by-line transliteration of the JavaScript, and it
24
+ inherits neither its speed nor its correctness. Measured against 1202 vectors produced by
25
+ `lz-string` 1.5.0 on npm — the library the games themselves use:
26
+
27
+ - **294 vectors compress to different bytes**, because it walks Python code points where
28
+ the format is defined over UTF-16 code units. In practice: an emoji in a player's name is
29
+ written truncated, and the game reads back `U+F600`, a private-use box. Every save with an
30
+ astral character is corrupted on write.
31
+ - **`decompressFromUTF16` raises `TypeError` on every input.** It subtracts an integer from
32
+ a string. The function has never worked.
33
+ - Decompression rebuilds a 65-entry alphabet table *per character* and reads the bit stream
34
+ one bit at a time: **22 seconds** for a 1.8 MB save, on the request path.
35
+
36
+ This package is byte-identical to the reference on all 1202 vectors, in all four
37
+ transports, in both directions, on both backends — and 15–45× faster.
38
+
39
+ How far that was pushed, because "it round-trips" is not the same as "it is right":
40
+
41
+ | check | scale | result |
42
+ |---|---|---|
43
+ | golden corpus vs. node | 1202 vectors x 4 transports x 2 directions x 2 backends | identical |
44
+ | real production saves | 38 files up to 1.8 MB, decompress **and** recompress | identical |
45
+ | differential fuzz vs. node | 5000 generated inputs x 4 transports x 2 backends | identical |
46
+ | malformed-input fuzz | 16000 probes x 2 backends | agree with each other and with the reference; nothing raised |
47
+
48
+ The last row is the one that found bugs — two of them in this package, both invisible to
49
+ every check above it, and both now pinned by tests. SPEC.md §4 says what they were.
50
+
51
+ And it is not the only one: `py-lzstring` 0.1.1, a separate port of the same reference,
52
+ differs from it on **295 of the same 1202 vectors**, first on exactly the same astral
53
+ character. Two independent Python ports, the same mistake in both.
54
+
55
+ See [SPEC.md](SPEC.md) for the format itself and for the full divergence table.
56
+
57
+ ## Installing
58
+
59
+ The package is a compiled extension; `pip install` builds it, and a Rust toolchain is
60
+ required to do so.
61
+
62
+ ```bash
63
+ uv add git+ssh://git@github.com/Derfirm/lz-string.git # or, in a checkout:
64
+ uv sync # builds the extension in place
65
+ pip install . # pip works too; maturin does the build
66
+ ```
67
+
68
+ An import without the extension raises rather than falling back to something slower and
69
+ subtly different.
70
+
71
+ **Build it where it will run.** The binary is tied to the C library it was linked against:
72
+ one built on Debian bookworm (glibc 2.36) will not load on bullseye (2.31), which is what
73
+ `python:3.12.11-slim-bullseye` — the image this package is destined for — is built on. It
74
+ fails at import with `GLIBC_2.34 not found`, not at build time. Either build inside the
75
+ target image, or produce a manylinux wheel.
76
+
77
+ On two real saves, best of three in one run:
78
+
79
+ | | decompress | compress |
80
+ |---|---|---|
81
+ | **this package**, 259 KB → 975 K chars | **0.004 s** | **0.044 s** |
82
+ | `lzstring` 1.0.4, the same | 1.199 s | 0.312 s |
83
+ | **this package**, 1.8 MB → 13.4 M chars | **0.054 s** | **1.547 s** |
84
+ | `lzstring` 1.0.4, the same | 8.581 s | 4.766 s |
85
+
86
+ Both halves are ours, and the only Rust dependency is pyo3. The obvious alternative,
87
+ the [`lz-str`](https://crates.io/crates/lz-str) crate, was the starting point and did not
88
+ survive contact with damaged input: it answers the same thing for two failures the reference
89
+ keeps apart, skips characters the reference reads as zero bits, and refuses a payload whose
90
+ trailing padding character was trimmed. SPEC.md §7 has the measurements.
91
+
92
+ A pure-Python implementation of the whole format lives in `src/lz_string/_reference.py`.
93
+ It is the test suite's second opinion, not a fallback: nothing imports it at runtime.
94
+
95
+ ## Migrating from `lzstring`
96
+
97
+ The camelCase API is provided as-is, so the change is one import line:
98
+
99
+ ```python
100
+ -from lzstring import LZString
101
+ +from lz_string import LZString
102
+ ```
103
+
104
+ Two behaviour changes to know about, both improvements, both in SPEC.md: saves containing
105
+ astral characters stop being corrupted, and `decompressFromUTF16` starts working.
106
+
107
+ ## Tests
108
+
109
+ ```bash
110
+ uv sync --extra dev # .python-version pins 3.12, as in production
111
+ uv run pytest # every test runs against both implementations
112
+ uv sync --reinstall-package lzstring-codec # after touching the Rust: rebuild it
113
+ ./tools/check_linux.sh # built and run inside the target image (needs docker)
114
+ ./tools/check_linux.sh linux/amd64 # and on production's architecture, cross-compiled
115
+ ```
116
+
117
+ The Linux run is not ceremony. It is done in `python:3.12.11-slim-bullseye` — the exact image
118
+ this is destined for — and it has already caught two things a laptop cannot: a test that
119
+ measured the machine rather than the code, and an extension that built cleanly and then
120
+ refused to load because it wanted a newer glibc than the image has.
121
+
122
+ 251 tests: the golden corpus per category and transport, the documented behaviour on damaged
123
+ input, seeded round-trips over random code units and surrogate halves, parity between the
124
+ shipped extension and the Python reference — including a fuzz of malformed payloads, which
125
+ is what pins the three corrections the crate underneath needed — and two tests that the
126
+ extension really does let go of the interpreter while it works.
127
+
128
+ To regenerate the corpus (deterministic — a diff means the reference moved):
129
+
130
+ ```bash
131
+ npm --prefix tools install
132
+ node tools/gen_vectors.mjs
133
+ ```
134
+
135
+ `tools/bench.py` reproduces the numbers above.
136
+
137
+ ## Releasing
138
+
139
+ By tag, not by merge. Most merges here are documentation and CI, and PyPI refuses a second
140
+ upload of the same version — publishing on merge would mean either a version bump per commit
141
+ or a release job that fails as a matter of course.
142
+
143
+ ```bash
144
+ # bump `version` in pyproject.toml, note it in CHANGELOG.md, merge, then:
145
+ git tag v0.1.0 && git push origin v0.1.0
146
+ ```
147
+
148
+ The workflow builds wheels for linux and macOS on both architectures plus an sdist, checks
149
+ that the tag and the version in pyproject.toml agree, and only then uploads.
150
+ `workflow_dispatch` runs everything except the upload, which is how the pipeline is tested
151
+ without releasing anything.
152
+
153
+ The upload needs a credential, and there are two ways to give it one. Either works; the
154
+ first stores nothing.
155
+
156
+ **Trusted publishing.** On PyPI, add a pending publisher for the project name with owner
157
+ `Derfirm`, repository `lz-string`, workflow `release.yml`, environment `pypi`. Nothing to
158
+ configure here — with no `PYPI_API_TOKEN` secret set, the publish step already exchanges a
159
+ short-lived OIDC token, which is what it tries today and what fails with "Trusted publishing
160
+ exchange failure" until the publisher exists.
161
+
162
+ **A token.** Create an environment named `pypi` in the repository settings, put an API token
163
+ in it as `PYPI_API_TOKEN`, and re-run the publish job of the tagged release. Protection
164
+ rules on that environment are where you add an approval step if you want one.
165
+
166
+ ## Provenance and licence
167
+
168
+ MIT (`LICENSE`). Compression comes from the [`lz-str`](https://crates.io/crates/lz-str)
169
+ crate and the bindings from [pyo3](https://pyo3.rs), both MIT/Apache-2.0; the decoder is a
170
+ port of [pieroxy/lz-string](https://github.com/pieroxy/lz-string), MIT, which is also the
171
+ reference every claim here is measured against. See `THIRD_PARTY.md`.
172
+
173
+ No user data lives in this repository: every test input is generated, and the corpus is the
174
+ reference implementation's own output.
@@ -0,0 +1,23 @@
1
+ # Third-party notices
2
+
3
+ The Python and Rust code in this repository is MIT, see `LICENSE`. The compiled extension
4
+ links one crate, and its notice is reproduced as its licence requires.
5
+
6
+ ## pyo3
7
+
8
+ <https://crates.io/crates/pyo3> — MIT OR Apache-2.0. The Python bindings.
9
+
10
+ ## lz-string (JavaScript)
11
+
12
+ <https://github.com/pieroxy/lz-string> — MIT, by Pieroxy. Not linked or redistributed: it is
13
+ the *reference*. Both halves of the codec here are ports of it, its behaviour is what this
14
+ package is measured against, and the golden vectors in `tests/data/vectors.jsonl.gz` are its
15
+ output, produced by `tools/gen_vectors.mjs`. Everything this package claims about correctness
16
+ is a claim about agreeing with it.
17
+
18
+ ## lz-str (Rust) — no longer a dependency
19
+
20
+ <https://crates.io/crates/lz-str> — MIT OR Apache-2.0. This package wrapped it until its
21
+ decompressor turned out to disagree with the reference on damaged input in three ways
22
+ (SPEC.md §7). Nothing of it ships here now; the note is kept because the analysis in SPEC.md
23
+ refers to it.
@@ -0,0 +1,55 @@
1
+ [build-system]
2
+ # 1.9 is the floor, not a guess: PEP 639 `license` / `license-files` below it are a
3
+ # parse error, and the build fails with "wanted string or table".
4
+ requires = ["maturin>=1.9,<2"]
5
+ build-backend = "maturin"
6
+
7
+ [project]
8
+ name = "lzstring-codec"
9
+ version = "0.1.0"
10
+ description = "lz-string for Python, held byte-for-byte to the JavaScript original"
11
+ readme = "README.md"
12
+ license = "MIT"
13
+ license-files = ["LICENSE", "THIRD_PARTY.md"]
14
+ requires-python = ">=3.12"
15
+ authors = [{ name = "Andrew Grinevich", email = "beulea@gmail.com" }]
16
+ keywords = ["lz-string", "lzstring", "lzstring-codec", "compression", "lzw", "savegame", "utf-16"]
17
+ dependencies = []
18
+
19
+ classifiers = [
20
+ "Development Status :: 4 - Beta",
21
+ "Intended Audience :: Developers",
22
+ "License :: OSI Approved :: MIT License",
23
+ "Programming Language :: Python :: 3.12",
24
+ "Programming Language :: Python :: 3.13",
25
+ "Programming Language :: Rust",
26
+ "Topic :: System :: Archiving :: Compression",
27
+ "Typing :: Typed",
28
+ ]
29
+
30
+ [project.urls]
31
+ Homepage = "https://github.com/Derfirm/lz-string"
32
+ Source = "https://github.com/Derfirm/lz-string"
33
+ Issues = "https://github.com/Derfirm/lz-string/issues"
34
+ Specification = "https://github.com/Derfirm/lz-string/blob/master/SPEC.md"
35
+
36
+ [project.optional-dependencies]
37
+ dev = ["pytest>=8", "ruff>=0.6"]
38
+
39
+ # A mixed layout: Python under src/, the crate under rust/. maturin builds the extension
40
+ # straight into the package, so `pip install` yields something that works rather than half
41
+ # of something that does.
42
+ [tool.maturin]
43
+ python-source = "src"
44
+ module-name = "lz_string._native"
45
+ manifest-path = "rust/Cargo.toml"
46
+ features = ["pyo3/extension-module"]
47
+
48
+ [tool.pytest.ini_options]
49
+ testpaths = ["tests"]
50
+ pythonpath = ["src", "."]
51
+ addopts = "-q"
52
+
53
+ [tool.ruff]
54
+ line-length = 110
55
+ target-version = "py312"
@@ -0,0 +1,132 @@
1
+ # This file is automatically @generated by Cargo.
2
+ # It is not intended for manual editing.
3
+ version = 4
4
+
5
+ [[package]]
6
+ name = "heck"
7
+ version = "0.5.0"
8
+ source = "registry+https://github.com/rust-lang/crates.io-index"
9
+ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
10
+
11
+ [[package]]
12
+ name = "libc"
13
+ version = "0.2.189"
14
+ source = "registry+https://github.com/rust-lang/crates.io-index"
15
+ checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
16
+
17
+ [[package]]
18
+ name = "lz-string-native"
19
+ version = "0.1.0"
20
+ dependencies = [
21
+ "pyo3",
22
+ ]
23
+
24
+ [[package]]
25
+ name = "once_cell"
26
+ version = "1.21.4"
27
+ source = "registry+https://github.com/rust-lang/crates.io-index"
28
+ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
29
+
30
+ [[package]]
31
+ name = "portable-atomic"
32
+ version = "1.15.0"
33
+ source = "registry+https://github.com/rust-lang/crates.io-index"
34
+ checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85"
35
+
36
+ [[package]]
37
+ name = "proc-macro2"
38
+ version = "1.0.107"
39
+ source = "registry+https://github.com/rust-lang/crates.io-index"
40
+ checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
41
+ dependencies = [
42
+ "unicode-ident",
43
+ ]
44
+
45
+ [[package]]
46
+ name = "pyo3"
47
+ version = "0.29.2"
48
+ source = "registry+https://github.com/rust-lang/crates.io-index"
49
+ checksum = "4688ddedf473e32662b9b067670129a8afb8c18e351482c70d62ba4a88171e8b"
50
+ dependencies = [
51
+ "libc",
52
+ "once_cell",
53
+ "portable-atomic",
54
+ "pyo3-build-config",
55
+ "pyo3-ffi",
56
+ "pyo3-macros",
57
+ ]
58
+
59
+ [[package]]
60
+ name = "pyo3-build-config"
61
+ version = "0.29.2"
62
+ source = "registry+https://github.com/rust-lang/crates.io-index"
63
+ checksum = "f41027e41b4bd03f6e60f9f417fe24a6341a6bb744edd62b6f709f2a52ea30e9"
64
+ dependencies = [
65
+ "target-lexicon",
66
+ ]
67
+
68
+ [[package]]
69
+ name = "pyo3-ffi"
70
+ version = "0.29.2"
71
+ source = "registry+https://github.com/rust-lang/crates.io-index"
72
+ checksum = "e591a95526fead067432c3b3a33fc74770b87b1e04e73671090d9c2055a2b327"
73
+ dependencies = [
74
+ "libc",
75
+ "pyo3-build-config",
76
+ ]
77
+
78
+ [[package]]
79
+ name = "pyo3-macros"
80
+ version = "0.29.2"
81
+ source = "registry+https://github.com/rust-lang/crates.io-index"
82
+ checksum = "73225868fc1cd84eef2c3c230ddb91273bf1de46aeb8a4248da76d32a0924a1c"
83
+ dependencies = [
84
+ "proc-macro2",
85
+ "pyo3-macros-backend",
86
+ "quote",
87
+ "syn",
88
+ ]
89
+
90
+ [[package]]
91
+ name = "pyo3-macros-backend"
92
+ version = "0.29.2"
93
+ source = "registry+https://github.com/rust-lang/crates.io-index"
94
+ checksum = "571575aa3749fa6216757dd47d2a3e7ef360f329a40f0666a9fbd14889024952"
95
+ dependencies = [
96
+ "heck",
97
+ "proc-macro2",
98
+ "quote",
99
+ "syn",
100
+ ]
101
+
102
+ [[package]]
103
+ name = "quote"
104
+ version = "1.0.47"
105
+ source = "registry+https://github.com/rust-lang/crates.io-index"
106
+ checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
107
+ dependencies = [
108
+ "proc-macro2",
109
+ ]
110
+
111
+ [[package]]
112
+ name = "syn"
113
+ version = "2.0.119"
114
+ source = "registry+https://github.com/rust-lang/crates.io-index"
115
+ checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
116
+ dependencies = [
117
+ "proc-macro2",
118
+ "quote",
119
+ "unicode-ident",
120
+ ]
121
+
122
+ [[package]]
123
+ name = "target-lexicon"
124
+ version = "0.13.5"
125
+ source = "registry+https://github.com/rust-lang/crates.io-index"
126
+ checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
127
+
128
+ [[package]]
129
+ name = "unicode-ident"
130
+ version = "1.0.24"
131
+ source = "registry+https://github.com/rust-lang/crates.io-index"
132
+ checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
@@ -0,0 +1,16 @@
1
+ [package]
2
+ name = "lz-string-native"
3
+ version = "0.1.0"
4
+ edition = "2021"
5
+ publish = false
6
+
7
+ [lib]
8
+ name = "_native"
9
+ crate-type = ["cdylib"]
10
+
11
+ [dependencies]
12
+ pyo3 = { version = "0.29", features = ["extension-module", "abi3-py312"] }
13
+
14
+ [profile.release]
15
+ opt-level = 3
16
+ lto = true