banglatok 0.2.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.
Files changed (58) hide show
  1. banglatok-0.2.0/CHANGELOG.md +33 -0
  2. banglatok-0.2.0/CITATION.cff +19 -0
  3. banglatok-0.2.0/CONTRIBUTING.md +34 -0
  4. banglatok-0.2.0/LICENSE +21 -0
  5. banglatok-0.2.0/MANIFEST.in +13 -0
  6. banglatok-0.2.0/MODEL_LICENSE.md +13 -0
  7. banglatok-0.2.0/PKG-INFO +204 -0
  8. banglatok-0.2.0/README.md +163 -0
  9. banglatok-0.2.0/SECURITY.md +9 -0
  10. banglatok-0.2.0/THIRD_PARTY_NOTICES.md +25 -0
  11. banglatok-0.2.0/cmd/bntok-shared/main.go +68 -0
  12. banglatok-0.2.0/docs/MODELS.md +55 -0
  13. banglatok-0.2.0/examples/quickstart.py +13 -0
  14. banglatok-0.2.0/examples/training-records.jsonl +8 -0
  15. banglatok-0.2.0/go.mod +16 -0
  16. banglatok-0.2.0/go.sum +18 -0
  17. banglatok-0.2.0/internal/native/contract_test.go +87 -0
  18. banglatok-0.2.0/internal/native/encode.go +89 -0
  19. banglatok-0.2.0/internal/native/encode_test.go +137 -0
  20. banglatok-0.2.0/internal/native/native.go +127 -0
  21. banglatok-0.2.0/internal/native/native_test.go +65 -0
  22. banglatok-0.2.0/pyproject.toml +91 -0
  23. banglatok-0.2.0/setup.cfg +4 -0
  24. banglatok-0.2.0/setup.py +56 -0
  25. banglatok-0.2.0/src/banglatok/__init__.py +33 -0
  26. banglatok-0.2.0/src/banglatok/__main__.py +61 -0
  27. banglatok-0.2.0/src/banglatok/_hf.py +119 -0
  28. banglatok-0.2.0/src/banglatok/_native.py +192 -0
  29. banglatok-0.2.0/src/banglatok/_tokenizer.py +262 -0
  30. banglatok-0.2.0/src/banglatok/data/demo-unigram.json +18 -0
  31. banglatok-0.2.0/src/banglatok/pretrained/bn-bpe-28k.json +1 -0
  32. banglatok-0.2.0/src/banglatok/pretrained/bn-bpe-58k.json +1 -0
  33. banglatok-0.2.0/src/banglatok/py.typed +0 -0
  34. banglatok-0.2.0/src/banglatok.egg-info/PKG-INFO +204 -0
  35. banglatok-0.2.0/src/banglatok.egg-info/SOURCES.txt +56 -0
  36. banglatok-0.2.0/src/banglatok.egg-info/dependency_links.txt +1 -0
  37. banglatok-0.2.0/src/banglatok.egg-info/entry_points.txt +2 -0
  38. banglatok-0.2.0/src/banglatok.egg-info/top_level.txt +1 -0
  39. banglatok-0.2.0/tests/test_distributions.py +107 -0
  40. banglatok-0.2.0/tests/test_pretrained.py +174 -0
  41. banglatok-0.2.0/tests/test_python.py +190 -0
  42. banglatok-0.2.0/third_party/licenses/GO-LICENSE +27 -0
  43. banglatok-0.2.0/third_party/licenses/X-TEXT-LICENSE +27 -0
  44. banglatok-0.2.0/third_party/licenses/X-TEXT-PATENTS +22 -0
  45. banglatok-0.2.0/tokenizer/bpe.go +290 -0
  46. banglatok-0.2.0/tokenizer/bpe_test.go +77 -0
  47. banglatok-0.2.0/tokenizer/model.go +248 -0
  48. banglatok-0.2.0/tokenizer/model_test.go +157 -0
  49. banglatok-0.2.0/tokenizer/normalize.go +157 -0
  50. banglatok-0.2.0/tokenizer/optimization_test.go +94 -0
  51. banglatok-0.2.0/tokenizer/profile_test.go +54 -0
  52. banglatok-0.2.0/tokenizer/refactor_test.go +182 -0
  53. banglatok-0.2.0/tokenizer/sample.go +25 -0
  54. banglatok-0.2.0/tokenizer/space_fusion_test.go +115 -0
  55. banglatok-0.2.0/tokenizer/train.go +110 -0
  56. banglatok-0.2.0/tokenizer/training_input.go +48 -0
  57. banglatok-0.2.0/tokenizer/unigram.go +135 -0
  58. banglatok-0.2.0/tools/check_dist.py +111 -0
@@ -0,0 +1,33 @@
1
+ # Changelog
2
+
3
+ ## 0.2.0 — 2026-11-13
4
+
5
+ First public release.
6
+
7
+ ### Added
8
+
9
+ - Two pretrained models bundled in the wheel and loaded offline with `Tokenizer.from_pretrained()`. `bn-bpe-58k` (default) and `bn-bpe-28k` are space-fused BPE vocabularies, documented in `docs/MODELS.md` and licensed CC BY-SA 4.0.
10
+ - `tokenize`, `count_tokens`, `decode_batch`, `id_to_token`, `token_to_id`, `get_vocab`, the `algorithm` property, `available_models()` and the control-ID constants.
11
+ - `tokenizer(texts, add_special_tokens=..., max_length=..., padding=...)` returns encoder-ready `input_ids` and `attention_mask`. `decode(..., skip_special_tokens=True)` drops the control IDs again.
12
+ - A `banglatok` command and `python -m banglatok`.
13
+ - `benchmarks/compare_popular.py` and `benchmarks/POPULAR_COMPARISON.md` compare the models with SentencePiece/BNLP, tiktoken, BanglaBERT, MuRIL, mBERT, XLM-R and Qwen3 on unseen and in-domain text.
14
+ - `benchmarks/build_fused_model.py` reproducibly builds fused models from a base BPE model.
15
+ - `Tokenizer.save_huggingface(directory)` writes `tokenizer.json` and `tokenizer_config.json` for Hugging Face `tokenizers` and `transformers`, with the same IDs as the native tokenizer (checked on 24,799 validation, review and stress texts for both models). `tools/publish_huggingface.py` uploads both models to the Hub.
16
+ - Linux aarch64 and Windows x86_64 wheels in the release workflow.
17
+ - `benchmarks/train_sentencepiece_baselines.py` trains SentencePiece Unigram and BPE baselines with the same vocabulary sizes as the bundled models; the comparison now includes them, and a Linux x86_64 run.
18
+
19
+ ### Changed
20
+
21
+ - The project is now `banglatok` (was `bn-tokenizers-embedding`, never published to PyPI). The import is `banglatok` and the command is `banglatok`.
22
+ - Encoding is about 2× faster with identical IDs. Normalization skips work for text that is already NFC. BPE merges recompute pair ranks only around merged tokens. Single texts are encoded straight into a reusable per-thread buffer, and batch results come back in one aligned buffer. Every model and about 94,000 validation, test and stress texts produce the same IDs as before.
23
+ - Go: `Tokenizer.AppendEncode`, `Tokenizer.Vocabulary`, `Tokenizer.Algorithm` and `Tokenizer.Merges`.
24
+ - The `banglatok` command reads and writes UTF-8 regardless of the console code page.
25
+ - Research reports, experiments and scripts moved under `research/`.
26
+ - License expression: `MIT AND BSD-3-Clause AND CC-BY-SA-4.0`.
27
+
28
+ ## 0.1.0a1 — unreleased preview
29
+
30
+ - Prepared the typed Python/Go tokenizer API for a public alpha, with an offline toy vocabulary and a self-contained training example.
31
+ - Added MIT licensing, retained BSD-3-Clause native notices, installed-distribution CI, archive validation and opt-in platform-wheel/PyPI workflows.
32
+
33
+ The earlier `0.1.0` artifacts were local development builds and were never published to PyPI.
@@ -0,0 +1,19 @@
1
+ cff-version: 1.2.0
2
+ message: "If you use this software or its bundled models, please cite it as below."
3
+ title: "banglatok: fast, lossless Bangla, English and Banglish tokenizers"
4
+ type: software
5
+ authors:
6
+ - family-names: Islam
7
+ given-names: Aber
8
+ email: aber.islam.dev@gmail.com
9
+ repository-code: "https://github.com/iamaber/banglatok"
10
+ license: MIT
11
+ version: 0.2.0
12
+ date-released: 2026-11-13
13
+ keywords:
14
+ - Bengali
15
+ - Bangla
16
+ - Banglish
17
+ - tokenizer
18
+ - BPE
19
+ - code-mixing
@@ -0,0 +1,34 @@
1
+ # Contributing
2
+
3
+ Small, reproducible changes are welcome. Discuss API changes in an issue first. Keep tokenizer behavior, model formats and research claims explicit; a speed improvement must preserve IDs unless a new model version is deliberate.
4
+
5
+ ## Development
6
+
7
+ Use Python 3.10+ and Go 1.24+ with a C compiler. A supported, maintained Python version is preferable for development.
8
+
9
+ ```sh
10
+ python -m venv .venv-dev
11
+ source .venv-dev/bin/activate
12
+ python -m pip install build twine ruff
13
+ python -m pip install .
14
+ python -m unittest discover -s tests -v
15
+ go test -race ./...
16
+ go vet ./...
17
+ ruff check src tests tools examples setup.py
18
+ ```
19
+
20
+ Tests exercise the installed Go shared library. After changing Go or Python package code, reinstall with `python -m pip install --force-reinstall .` before testing. Running against an old wheel can test an obsolete native runtime.
21
+
22
+ Format changed Go files with `gofmt`. Prefer the standard library and the existing small API over new dependencies or generic abstractions. Add a focused regression test for behavior changes, and test actual native behavior rather than mocked return values.
23
+
24
+ ## Package changes
25
+
26
+ Follow [docs/RELEASING.md](docs/RELEASING.md) to build from a source archive, inspect package contents and test installed wheels. Do not add corpora, private text, credentials or research checkpoints to distributions. The only bundled models are the documented ones in `src/banglatok/pretrained/` (see [docs/MODELS.md](docs/MODELS.md)). Performance changes must keep their IDs byte-for-byte identical; `go test ./tokenizer -bench Validation` with `BNTOK_MODEL`/`BNTOK_CORPUS` measures the native path.
27
+
28
+ ## Research changes
29
+
30
+ Research environments are separate from the zero-dependency tokenizer API; see [research/experiments/retrieval/README.md](research/experiments/retrieval/README.md). Preserve frozen datasets and decisions. Report annotation origin, actual compute/data budgets, uncertainty and failed gates. Agent judgments must not be described as independent human review.
31
+
32
+ ## Pull requests
33
+
34
+ Explain the problem, resulting behavior and verification. Include OS/architecture and Python/Go versions for native changes. Use a minimal hand-written reproduction instead of uploading private data. Keep discussion respectful and specific; review the code and evidence rather than the person.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Aber Islam
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,13 @@
1
+ include go.mod go.sum
2
+ recursive-include tokenizer *.go
3
+ recursive-include internal/native *.go
4
+ include cmd/bntok-shared/main.go
5
+ recursive-include src/banglatok/pretrained *.json
6
+ recursive-include tests *.py
7
+ recursive-include examples *.py *.jsonl
8
+ include tools/check_dist.py
9
+ include CHANGELOG.md CONTRIBUTING.md SECURITY.md CITATION.cff MODEL_LICENSE.md docs/MODELS.md
10
+ prune data
11
+ prune models
12
+ prune research
13
+ prune .tools
@@ -0,0 +1,13 @@
1
+ # Bundled model files
2
+
3
+ The files in `src/banglatok/pretrained/` (`bn-bpe-58k.json` and `bn-bpe-28k.json`) are licensed under the Creative Commons Attribution-ShareAlike 4.0 International License (CC BY-SA 4.0): https://creativecommons.org/licenses/by-sa/4.0/legalcode
4
+
5
+ They contain subword vocabularies, merge rules and frequent-word lists learned from:
6
+
7
+ - Bengali Wikipedia (dump `20231101.bn`, via the `wikimedia/wikipedia` dataset). © Wikipedia contributors, CC BY-SA 3.0 / GFDL.
8
+ - Tatoeba sentences, via the ManyThings.org Anki exports. © Tatoeba contributors, CC BY 2.0.
9
+ - BanglaTLit, https://github.com/farhanishmam/BanglaTLit. MIT License.
10
+
11
+ Changes: the source text was NFC- and whitespace-normalized, filtered and split as described in `data/CORPUS.md`. The models were then learned from the training split with BPE training, space fusion and word-frequency counting. See `docs/MODELS.md`.
12
+
13
+ Everything else in this repository and in the distributions, including the tokenizer software and the hand-authored demo vocabulary, is covered by `LICENSE` (MIT) and `THIRD_PARTY_NOTICES.md`.
@@ -0,0 +1,204 @@
1
+ Metadata-Version: 2.4
2
+ Name: banglatok
3
+ Version: 0.2.0
4
+ Summary: Fast, lossless Bangla, English and Banglish subword tokenizers with bundled models and a native Go engine
5
+ Author-email: Aber Islam <aber.islam.dev@gmail.com>
6
+ License-Expression: MIT AND BSD-3-Clause AND CC-BY-SA-4.0
7
+ Project-URL: Homepage, https://github.com/iamaber/banglatok
8
+ Project-URL: Repository, https://github.com/iamaber/banglatok
9
+ Project-URL: Documentation, https://github.com/iamaber/banglatok#readme
10
+ Project-URL: Issues, https://github.com/iamaber/banglatok/issues
11
+ Project-URL: Changelog, https://github.com/iamaber/banglatok/blob/main/CHANGELOG.md
12
+ Keywords: bengali,bangla,banglish,romanized-bengali,code-mixed,tokenizer,subword,bpe,unigram,nlp,llm
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: Natural Language :: Bengali
17
+ Classifier: Natural Language :: English
18
+ Classifier: Operating System :: MacOS
19
+ Classifier: Operating System :: Microsoft :: Windows
20
+ Classifier: Operating System :: POSIX :: Linux
21
+ Classifier: Programming Language :: Python :: 3 :: Only
22
+ Classifier: Programming Language :: Python :: 3.10
23
+ Classifier: Programming Language :: Python :: 3.11
24
+ Classifier: Programming Language :: Python :: 3.12
25
+ Classifier: Programming Language :: Python :: 3.13
26
+ Classifier: Programming Language :: Python :: 3.14
27
+ Classifier: Programming Language :: Python :: 3.15
28
+ Classifier: Programming Language :: Go
29
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
30
+ Classifier: Topic :: Text Processing :: Linguistic
31
+ Classifier: Typing :: Typed
32
+ Requires-Python: >=3.10
33
+ Description-Content-Type: text/markdown
34
+ License-File: LICENSE
35
+ License-File: MODEL_LICENSE.md
36
+ License-File: THIRD_PARTY_NOTICES.md
37
+ License-File: third_party/licenses/GO-LICENSE
38
+ License-File: third_party/licenses/X-TEXT-LICENSE
39
+ License-File: third_party/licenses/X-TEXT-PATENTS
40
+ Dynamic: license-file
41
+
42
+ # banglatok
43
+
44
+ **Fast, lossless subword tokenizers for Bangla, English and Banglish (romanized Bengali), including code-mixed text.**
45
+
46
+ [![CI](https://github.com/iamaber/banglatok/actions/workflows/ci.yml/badge.svg)](https://github.com/iamaber/banglatok/actions/workflows/ci.yml)
47
+ ![Python 3.10–3.15](https://img.shields.io/badge/python-3.10%E2%80%933.15-blue)
48
+ ![Runtime dependencies: none](https://img.shields.io/badge/runtime%20deps-none-brightgreen)
49
+ [![License: MIT (code), CC BY-SA 4.0 (models)](https://img.shields.io/badge/license-MIT%20%7C%20CC%20BY--SA%204.0-lightgrey)](#license)
50
+
51
+ ```python
52
+ from banglatok import Tokenizer
53
+
54
+ tok = Tokenizer.from_pretrained() # bundled model; no download, no network
55
+ tok.tokenize("meetingটা ১০টায়, don't be late 🙂")
56
+ # ['meeting', 'টা', ' ১০', 'টায়', ',', " don't", ' be', ' late', ' 🙂']
57
+ ```
58
+
59
+ - **Short sequences.** On unseen product reviews `bn-bpe-58k` produced 22% fewer tokens than BanglaBERT and GPT-4o's `o200k_base`, 21% fewer than XLM-R/mE5/BGE-M3, 8% fewer than MuRIL, and 62% fewer than Qwen3. Most of that comes from training on Bangla and Banglish text at this vocabulary size: SentencePiece trained on the same data with the same vocabulary size comes within about 2% (see [Benchmarks](#benchmarks)).
60
+ - **Lossless.** `decode(encode(text))` gives back the normalized text exactly, for every input. There is no `[UNK]` and no lowercasing, and Bengali marks, ZWJ/ZWNJ, emoji and mixed scripts are kept.
61
+ - **Fast.** Single-threaded, on unseen text, it was 1.1–1.7× faster than SentencePiece Unigram and 2.6–4.4× faster than SentencePiece BPE at the same vocabulary size, 1.3–5.9× faster than tiktoken, and 5–12× faster than Hugging Face `tokenizers`, on both an Apple M5 and a Linux x86_64 server CPU.
62
+ - **Tiny footprint.** The engine is native Go behind `ctypes`, with zero Python runtime dependencies and typed APIs. It is thread-safe, two pretrained models ship inside the wheel, and they export to Hugging Face `tokenizers`/`transformers` with identical IDs.
63
+
64
+ The vocabularies are meant for training or adapting encoders and LLMs on Bengali text, and for counting or segmenting such text.
65
+
66
+ ## Benchmarks
67
+
68
+ Here are 10,000 naturally written e-commerce reviews from [BanglishRev](https://huggingface.co/datasets/BanglishRev/bangla-english-and-code-mixed-ecommerce-review-dataset), in Bengali, English, Banglish and mixed script. This source was never seen in training. Every tokenizer runs **single-threaded** (`RAYON_NUM_THREADS=1`, `num_threads=1`), on an Apple M5 (macOS) and on an AMD EPYC 9V74 GitHub-hosted Linux x86_64 VM, Python 3.12. Speed is MB/s for single calls / batches of 64.
69
+
70
+ | Tokenizer | Vocab | Tokens / word ↓ | Lossless round trip ↑ | Texts with UNK ↓ | MB/s, Apple M5 ↑ | MB/s, Linux x86_64 ↑ |
71
+ |---|---:|---:|---:|---:|---:|---:|
72
+ | **bn-bpe-58k (this package)** | 57,925 | **1.379** | **100%** | **0** | 58.5 / 71.6 | 24.4 / 29.7 |
73
+ | **bn-bpe-28k (this package)** | 27,760 | 1.587 | **100%** | **0** | **61.6 / 72.9** | **26.1 / 33.6** |
74
+ | SentencePiece Unigram, same data and size as 58k | 57,925 | 1.410 | 100% | 0 | 42.4 / 41.7 | 20.5 / 20.9 |
75
+ | SentencePiece BPE, same data and size as 58k | 57,925 | 1.407 | 100% | 0 | 17.7 / 17.4 | 9.5 / 9.8 |
76
+ | SentencePiece Unigram, same data and size as 28k | 27,760 | 1.572 | 100% | 0 | 46.4 / 43.2 | 22.8 / 23.4 |
77
+ | SentencePiece BPE, same data and size as 28k | 27,760 | 1.578 | 100% | 0 | 16.6 / 16.4 | 9.8 / 9.8 |
78
+ | BNLP `bn_spm` (SentencePiece) | 50,000 | 1.825 | 80.1% | 1,932 | 40.1 / 39.2 | 19.3 / 19.8 |
79
+ | tiktoken `o200k_base` (GPT-4o) | 200,019 | 1.780 | 100% | 0 | 37.3 / 12.1 | 19.4 / 5.4 |
80
+ | BanglaBERT (csebuetnlp) | 32,000 | 1.771 | 51.1% | 1,110 | 9.1 / 9.2 | 4.8 / 4.6 |
81
+ | MuRIL (Google) | 197,258 | 1.498 | 47.9% | 1,617 | 8.8 / 8.9 | 4.6 / 4.4 |
82
+ | XLM-R / multilingual-E5 / BGE-M3 | 250,002 | 1.740 | 98.2% | 109 | 6.5 / 6.4 | 3.7 / 3.5 |
83
+ | mBERT cased | 119,547 | 2.122 | 48.0% | 1,706 | 8.1 / 8.1 | 4.2 / 4.1 |
84
+ | Qwen3 | 151,669 | 3.588 | 100% | 0 | 6.0 / 6.0 | 3.3 / 3.1 |
85
+
86
+ What this shows:
87
+
88
+ - **Against SentencePiece with the same data and vocabulary size, compression is a tie.** `bn-bpe-58k` is about 2% shorter than both SentencePiece models; `bn-bpe-28k` is about 1% longer. On the in-domain validation split, SentencePiece at the 28k size is 3–4.5% shorter. The gap to BanglaBERT, XLM-R and tiktoken comes from the training data and the vocabulary size, not from a better algorithm.
89
+ - **The speed lead is real but depends on the CPU.** Against SentencePiece Unigram it is 1.3–1.7× on the M5 and 1.1–1.4× on the Linux VM. Hugging Face `tokenizers` was limited to one thread like everything else; its batch API can use all cores, which this table does not measure.
90
+ - BanglaBERT is about 3% shorter on Bengali-only text but lossy. Among lossless tokenizers, `bn-bpe-58k` is the most compact on Bengali, Latin and mixed script.
91
+
92
+ [Full report](benchmarks/POPULAR_COMPARISON.md): per-script breakdown, the in-domain validation split, more tokenizers, method, limitations, and the commands to reproduce it. Shorter sequences cut compute and context use, but they do not by themselves make a downstream model more accurate.
93
+
94
+ ## Install
95
+
96
+ ```sh
97
+ pip install banglatok
98
+ ```
99
+
100
+ Prebuilt wheels target Linux (x86_64, aarch64), macOS (x86_64, arm64) and Windows (x86_64) for CPython 3.10–3.15, and need no compiler. On other platforms pip builds from source, which needs Go 1.24+ and a C compiler:
101
+
102
+ ```sh
103
+ pip install git+https://github.com/iamaber/banglatok
104
+ ```
105
+
106
+ ## Usage
107
+
108
+ ```python
109
+ from banglatok import Tokenizer
110
+
111
+ with Tokenizer.from_pretrained("bn-bpe-58k") as tok:
112
+ ids = tok.encode("আমি বাংলায় গান গাই। ami banglay gaan gai")
113
+ tok.decode(ids) # 'আমি বাংলায় গান গাই। ami banglay gaan gai'
114
+ tok.encode_batch(["আমি ভালো আছি", "kemon acho?"]) # one native call
115
+ tok.count_tokens("অনেক লম্বা লেখা…") # fast length, no list built
116
+
117
+ # Encoder-ready inputs: <s> … </s>, truncation and padding with <pad>.
118
+ batch = tok(["আমি ভালো আছি", "hi"], max_length=128, padding=True)
119
+ batch["input_ids"], batch["attention_mask"]
120
+ ```
121
+
122
+ Load a tokenizer once and reuse it. Calls from many threads at once are safe, because the native call releases the GIL. In worker processes, create a fresh tokenizer inside each worker.
123
+
124
+ ### Hugging Face
125
+
126
+ ```python
127
+ tok.save_huggingface("bn-bpe-58k-hf") # tokenizer.json + tokenizer_config.json
128
+
129
+ from transformers import AutoTokenizer
130
+ hf = AutoTokenizer.from_pretrained("bn-bpe-58k-hf") # same IDs as tok.encode / tok(...)
131
+ ```
132
+
133
+ The exported models are also on the Hub as [`iamaber/banglatok-bn-bpe-58k`](https://huggingface.co/iamaber/banglatok-bn-bpe-58k) and [`iamaber/banglatok-bn-bpe-28k`](https://huggingface.co/iamaber/banglatok-bn-bpe-28k). Only BPE models can be exported. With the `tokenizers` library alone, set `encode_special_tokens = True` so that literal `<s>` in text stays text; `transformers` does this from the saved configuration.
134
+
135
+ ### Command line
136
+
137
+ ```sh
138
+ $ banglatok "আমি বাংলা বলি"
139
+ আমি | বাংলা | বলি
140
+ $ echo "ami bangla boli" | banglatok --ids
141
+ 4405 33616 34749
142
+ $ banglatok --json "ami valo"
143
+ {"ids": [4405, 32047], "tokens": ["ami", " valo"]}
144
+ $ banglatok --count --model bn-bpe-28k < lines.txt # one count per line
145
+ ```
146
+
147
+ ### API
148
+
149
+ | Member | Description |
150
+ |---|---|
151
+ | `Tokenizer.from_pretrained(name="bn-bpe-58k")` | Load a bundled model, offline |
152
+ | `Tokenizer(path)` | Load your own JSON model, e.g. one trained with `bntok train` |
153
+ | `encode(text)` / `encode_batch(texts)` | Token IDs, without control tokens |
154
+ | `decode(ids, skip_special_tokens=False)` / `decode_batch(batch)` | Normalized text |
155
+ | `tokenize(text)` | Token strings: fused IDs start with `" "`, fallback bytes look like `"<0xF0>"` |
156
+ | `count_tokens(text)` | `len(encode(text))`, without building the list |
157
+ | `save_huggingface(directory)` | Write a Hugging Face `tokenizer.json` with identical IDs (BPE models) |
158
+ | `tok(texts, add_special_tokens=True, max_length=None, padding=False)` | `{"input_ids", "attention_mask"}` |
159
+ | `id_to_token`, `token_to_id`, `get_vocab()`, `vocab_size`, `algorithm` | Vocabulary access |
160
+ | `normalize(text)` | The shared normalization: NFC plus whitespace collapse and trim |
161
+ | `available_models()`, `PAD_ID=0`, `UNK_ID=1`, `BOS_ID=2`, `EOS_ID=3` | Constants |
162
+
163
+ ## Models
164
+
165
+ | Name | Vocab | Best for |
166
+ |---|---:|---|
167
+ | `bn-bpe-58k` (default) | 57,925 | Shortest sequences |
168
+ | `bn-bpe-28k` | 27,760 | Smaller embedding tables, same speed |
169
+
170
+ Both are BPE vocabularies with *space fusion*: a space and the token after it can share a single ID. That removes most standalone space tokens without overloading a literal marker such as `▁`. They were learned from 563k records of Bengali Wikipedia, Tatoeba and BanglaTLit. [docs/MODELS.md](docs/MODELS.md) covers the build commands, checksums, behavior and limitations. They are not SentencePiece or Hugging Face vocabularies, so pairing one with a pretrained encoder means adapting that encoder's embeddings.
171
+
172
+ ## Train your own
173
+
174
+ The Go CLI trains Unigram or BPE models on your JSONL corpus, and `Tokenizer(path)` loads the result:
175
+
176
+ ```sh
177
+ go run ./cmd/bntok train -algorithm bpe -vocab 384 \
178
+ -input examples/training-records.jsonl -out models/toy-bpe.json
179
+ go run ./cmd/bntok encode -model models/toy-bpe.json -text 'আমি বাংলা বলি। ami bangla boli'
180
+ python benchmarks/build_fused_model.py --base models/my-bpe.json --budget 64000 \
181
+ --output models/my-fused.json # optional: add space fusion
182
+ ```
183
+
184
+ See [docs/TRAINING_AND_RESEARCH.md](docs/TRAINING_AND_RESEARCH.md) for the corpus format, the full research pipeline and the model contract.
185
+
186
+ ## Research
187
+
188
+ This repository also holds the research behind the models, under [research/](research/). [data/CORPUS.md](data/CORPUS.md) documents the corpus construction, provenance and leakage controls. [research/reports/RESULTS.md](research/reports/RESULTS.md) has the intrinsic evaluation. The retrieval experiments are in [research/experiments/retrieval/](research/experiments/retrieval/README.md), and [research/reports/ROUND2_ORIGINAL_COMPARISON.md](research/reports/ROUND2_ORIGINAL_COMPARISON.md) has the encoder-adaptation results. In those experiments, swapping a custom vocabulary into multilingual-E5 did not beat the unchanged model. Treat these vocabularies as a strong starting point for training, not as a drop-in accuracy gain for existing encoders.
189
+
190
+ ## Contributing
191
+
192
+ [CONTRIBUTING.md](CONTRIBUTING.md) explains how to work on the project, [SECURITY.md](SECURITY.md) how to report vulnerabilities, and [docs/RELEASING.md](docs/RELEASING.md) how releases are made. Platform reports, regression cases and independent benchmark runs are especially welcome.
193
+
194
+ ## Citation
195
+
196
+ If you use this library or its models, please cite it with the metadata in [CITATION.cff](CITATION.cff).
197
+
198
+ ## License
199
+
200
+ - Code, documentation and the demo vocabulary: [MIT](LICENSE).
201
+ - Bundled model files (`bn-bpe-58k`, `bn-bpe-28k`): [CC BY-SA 4.0](MODEL_LICENSE.md), because they are learned from Wikipedia and Tatoeba text.
202
+ - Native wheels include BSD-3-Clause Go components ([notices](THIRD_PARTY_NOTICES.md)).
203
+
204
+ The SPDX expression is `MIT AND BSD-3-Clause AND CC-BY-SA-4.0`. Research corpora keep their own terms and are not distributed.
@@ -0,0 +1,163 @@
1
+ # banglatok
2
+
3
+ **Fast, lossless subword tokenizers for Bangla, English and Banglish (romanized Bengali), including code-mixed text.**
4
+
5
+ [![CI](https://github.com/iamaber/banglatok/actions/workflows/ci.yml/badge.svg)](https://github.com/iamaber/banglatok/actions/workflows/ci.yml)
6
+ ![Python 3.10–3.15](https://img.shields.io/badge/python-3.10%E2%80%933.15-blue)
7
+ ![Runtime dependencies: none](https://img.shields.io/badge/runtime%20deps-none-brightgreen)
8
+ [![License: MIT (code), CC BY-SA 4.0 (models)](https://img.shields.io/badge/license-MIT%20%7C%20CC%20BY--SA%204.0-lightgrey)](#license)
9
+
10
+ ```python
11
+ from banglatok import Tokenizer
12
+
13
+ tok = Tokenizer.from_pretrained() # bundled model; no download, no network
14
+ tok.tokenize("meetingটা ১০টায়, don't be late 🙂")
15
+ # ['meeting', 'টা', ' ১০', 'টায়', ',', " don't", ' be', ' late', ' 🙂']
16
+ ```
17
+
18
+ - **Short sequences.** On unseen product reviews `bn-bpe-58k` produced 22% fewer tokens than BanglaBERT and GPT-4o's `o200k_base`, 21% fewer than XLM-R/mE5/BGE-M3, 8% fewer than MuRIL, and 62% fewer than Qwen3. Most of that comes from training on Bangla and Banglish text at this vocabulary size: SentencePiece trained on the same data with the same vocabulary size comes within about 2% (see [Benchmarks](#benchmarks)).
19
+ - **Lossless.** `decode(encode(text))` gives back the normalized text exactly, for every input. There is no `[UNK]` and no lowercasing, and Bengali marks, ZWJ/ZWNJ, emoji and mixed scripts are kept.
20
+ - **Fast.** Single-threaded, on unseen text, it was 1.1–1.7× faster than SentencePiece Unigram and 2.6–4.4× faster than SentencePiece BPE at the same vocabulary size, 1.3–5.9× faster than tiktoken, and 5–12× faster than Hugging Face `tokenizers`, on both an Apple M5 and a Linux x86_64 server CPU.
21
+ - **Tiny footprint.** The engine is native Go behind `ctypes`, with zero Python runtime dependencies and typed APIs. It is thread-safe, two pretrained models ship inside the wheel, and they export to Hugging Face `tokenizers`/`transformers` with identical IDs.
22
+
23
+ The vocabularies are meant for training or adapting encoders and LLMs on Bengali text, and for counting or segmenting such text.
24
+
25
+ ## Benchmarks
26
+
27
+ Here are 10,000 naturally written e-commerce reviews from [BanglishRev](https://huggingface.co/datasets/BanglishRev/bangla-english-and-code-mixed-ecommerce-review-dataset), in Bengali, English, Banglish and mixed script. This source was never seen in training. Every tokenizer runs **single-threaded** (`RAYON_NUM_THREADS=1`, `num_threads=1`), on an Apple M5 (macOS) and on an AMD EPYC 9V74 GitHub-hosted Linux x86_64 VM, Python 3.12. Speed is MB/s for single calls / batches of 64.
28
+
29
+ | Tokenizer | Vocab | Tokens / word ↓ | Lossless round trip ↑ | Texts with UNK ↓ | MB/s, Apple M5 ↑ | MB/s, Linux x86_64 ↑ |
30
+ |---|---:|---:|---:|---:|---:|---:|
31
+ | **bn-bpe-58k (this package)** | 57,925 | **1.379** | **100%** | **0** | 58.5 / 71.6 | 24.4 / 29.7 |
32
+ | **bn-bpe-28k (this package)** | 27,760 | 1.587 | **100%** | **0** | **61.6 / 72.9** | **26.1 / 33.6** |
33
+ | SentencePiece Unigram, same data and size as 58k | 57,925 | 1.410 | 100% | 0 | 42.4 / 41.7 | 20.5 / 20.9 |
34
+ | SentencePiece BPE, same data and size as 58k | 57,925 | 1.407 | 100% | 0 | 17.7 / 17.4 | 9.5 / 9.8 |
35
+ | SentencePiece Unigram, same data and size as 28k | 27,760 | 1.572 | 100% | 0 | 46.4 / 43.2 | 22.8 / 23.4 |
36
+ | SentencePiece BPE, same data and size as 28k | 27,760 | 1.578 | 100% | 0 | 16.6 / 16.4 | 9.8 / 9.8 |
37
+ | BNLP `bn_spm` (SentencePiece) | 50,000 | 1.825 | 80.1% | 1,932 | 40.1 / 39.2 | 19.3 / 19.8 |
38
+ | tiktoken `o200k_base` (GPT-4o) | 200,019 | 1.780 | 100% | 0 | 37.3 / 12.1 | 19.4 / 5.4 |
39
+ | BanglaBERT (csebuetnlp) | 32,000 | 1.771 | 51.1% | 1,110 | 9.1 / 9.2 | 4.8 / 4.6 |
40
+ | MuRIL (Google) | 197,258 | 1.498 | 47.9% | 1,617 | 8.8 / 8.9 | 4.6 / 4.4 |
41
+ | XLM-R / multilingual-E5 / BGE-M3 | 250,002 | 1.740 | 98.2% | 109 | 6.5 / 6.4 | 3.7 / 3.5 |
42
+ | mBERT cased | 119,547 | 2.122 | 48.0% | 1,706 | 8.1 / 8.1 | 4.2 / 4.1 |
43
+ | Qwen3 | 151,669 | 3.588 | 100% | 0 | 6.0 / 6.0 | 3.3 / 3.1 |
44
+
45
+ What this shows:
46
+
47
+ - **Against SentencePiece with the same data and vocabulary size, compression is a tie.** `bn-bpe-58k` is about 2% shorter than both SentencePiece models; `bn-bpe-28k` is about 1% longer. On the in-domain validation split, SentencePiece at the 28k size is 3–4.5% shorter. The gap to BanglaBERT, XLM-R and tiktoken comes from the training data and the vocabulary size, not from a better algorithm.
48
+ - **The speed lead is real but depends on the CPU.** Against SentencePiece Unigram it is 1.3–1.7× on the M5 and 1.1–1.4× on the Linux VM. Hugging Face `tokenizers` was limited to one thread like everything else; its batch API can use all cores, which this table does not measure.
49
+ - BanglaBERT is about 3% shorter on Bengali-only text but lossy. Among lossless tokenizers, `bn-bpe-58k` is the most compact on Bengali, Latin and mixed script.
50
+
51
+ [Full report](benchmarks/POPULAR_COMPARISON.md): per-script breakdown, the in-domain validation split, more tokenizers, method, limitations, and the commands to reproduce it. Shorter sequences cut compute and context use, but they do not by themselves make a downstream model more accurate.
52
+
53
+ ## Install
54
+
55
+ ```sh
56
+ pip install banglatok
57
+ ```
58
+
59
+ Prebuilt wheels target Linux (x86_64, aarch64), macOS (x86_64, arm64) and Windows (x86_64) for CPython 3.10–3.15, and need no compiler. On other platforms pip builds from source, which needs Go 1.24+ and a C compiler:
60
+
61
+ ```sh
62
+ pip install git+https://github.com/iamaber/banglatok
63
+ ```
64
+
65
+ ## Usage
66
+
67
+ ```python
68
+ from banglatok import Tokenizer
69
+
70
+ with Tokenizer.from_pretrained("bn-bpe-58k") as tok:
71
+ ids = tok.encode("আমি বাংলায় গান গাই। ami banglay gaan gai")
72
+ tok.decode(ids) # 'আমি বাংলায় গান গাই। ami banglay gaan gai'
73
+ tok.encode_batch(["আমি ভালো আছি", "kemon acho?"]) # one native call
74
+ tok.count_tokens("অনেক লম্বা লেখা…") # fast length, no list built
75
+
76
+ # Encoder-ready inputs: <s> … </s>, truncation and padding with <pad>.
77
+ batch = tok(["আমি ভালো আছি", "hi"], max_length=128, padding=True)
78
+ batch["input_ids"], batch["attention_mask"]
79
+ ```
80
+
81
+ Load a tokenizer once and reuse it. Calls from many threads at once are safe, because the native call releases the GIL. In worker processes, create a fresh tokenizer inside each worker.
82
+
83
+ ### Hugging Face
84
+
85
+ ```python
86
+ tok.save_huggingface("bn-bpe-58k-hf") # tokenizer.json + tokenizer_config.json
87
+
88
+ from transformers import AutoTokenizer
89
+ hf = AutoTokenizer.from_pretrained("bn-bpe-58k-hf") # same IDs as tok.encode / tok(...)
90
+ ```
91
+
92
+ The exported models are also on the Hub as [`iamaber/banglatok-bn-bpe-58k`](https://huggingface.co/iamaber/banglatok-bn-bpe-58k) and [`iamaber/banglatok-bn-bpe-28k`](https://huggingface.co/iamaber/banglatok-bn-bpe-28k). Only BPE models can be exported. With the `tokenizers` library alone, set `encode_special_tokens = True` so that literal `<s>` in text stays text; `transformers` does this from the saved configuration.
93
+
94
+ ### Command line
95
+
96
+ ```sh
97
+ $ banglatok "আমি বাংলা বলি"
98
+ আমি | বাংলা | বলি
99
+ $ echo "ami bangla boli" | banglatok --ids
100
+ 4405 33616 34749
101
+ $ banglatok --json "ami valo"
102
+ {"ids": [4405, 32047], "tokens": ["ami", " valo"]}
103
+ $ banglatok --count --model bn-bpe-28k < lines.txt # one count per line
104
+ ```
105
+
106
+ ### API
107
+
108
+ | Member | Description |
109
+ |---|---|
110
+ | `Tokenizer.from_pretrained(name="bn-bpe-58k")` | Load a bundled model, offline |
111
+ | `Tokenizer(path)` | Load your own JSON model, e.g. one trained with `bntok train` |
112
+ | `encode(text)` / `encode_batch(texts)` | Token IDs, without control tokens |
113
+ | `decode(ids, skip_special_tokens=False)` / `decode_batch(batch)` | Normalized text |
114
+ | `tokenize(text)` | Token strings: fused IDs start with `" "`, fallback bytes look like `"<0xF0>"` |
115
+ | `count_tokens(text)` | `len(encode(text))`, without building the list |
116
+ | `save_huggingface(directory)` | Write a Hugging Face `tokenizer.json` with identical IDs (BPE models) |
117
+ | `tok(texts, add_special_tokens=True, max_length=None, padding=False)` | `{"input_ids", "attention_mask"}` |
118
+ | `id_to_token`, `token_to_id`, `get_vocab()`, `vocab_size`, `algorithm` | Vocabulary access |
119
+ | `normalize(text)` | The shared normalization: NFC plus whitespace collapse and trim |
120
+ | `available_models()`, `PAD_ID=0`, `UNK_ID=1`, `BOS_ID=2`, `EOS_ID=3` | Constants |
121
+
122
+ ## Models
123
+
124
+ | Name | Vocab | Best for |
125
+ |---|---:|---|
126
+ | `bn-bpe-58k` (default) | 57,925 | Shortest sequences |
127
+ | `bn-bpe-28k` | 27,760 | Smaller embedding tables, same speed |
128
+
129
+ Both are BPE vocabularies with *space fusion*: a space and the token after it can share a single ID. That removes most standalone space tokens without overloading a literal marker such as `▁`. They were learned from 563k records of Bengali Wikipedia, Tatoeba and BanglaTLit. [docs/MODELS.md](docs/MODELS.md) covers the build commands, checksums, behavior and limitations. They are not SentencePiece or Hugging Face vocabularies, so pairing one with a pretrained encoder means adapting that encoder's embeddings.
130
+
131
+ ## Train your own
132
+
133
+ The Go CLI trains Unigram or BPE models on your JSONL corpus, and `Tokenizer(path)` loads the result:
134
+
135
+ ```sh
136
+ go run ./cmd/bntok train -algorithm bpe -vocab 384 \
137
+ -input examples/training-records.jsonl -out models/toy-bpe.json
138
+ go run ./cmd/bntok encode -model models/toy-bpe.json -text 'আমি বাংলা বলি। ami bangla boli'
139
+ python benchmarks/build_fused_model.py --base models/my-bpe.json --budget 64000 \
140
+ --output models/my-fused.json # optional: add space fusion
141
+ ```
142
+
143
+ See [docs/TRAINING_AND_RESEARCH.md](docs/TRAINING_AND_RESEARCH.md) for the corpus format, the full research pipeline and the model contract.
144
+
145
+ ## Research
146
+
147
+ This repository also holds the research behind the models, under [research/](research/). [data/CORPUS.md](data/CORPUS.md) documents the corpus construction, provenance and leakage controls. [research/reports/RESULTS.md](research/reports/RESULTS.md) has the intrinsic evaluation. The retrieval experiments are in [research/experiments/retrieval/](research/experiments/retrieval/README.md), and [research/reports/ROUND2_ORIGINAL_COMPARISON.md](research/reports/ROUND2_ORIGINAL_COMPARISON.md) has the encoder-adaptation results. In those experiments, swapping a custom vocabulary into multilingual-E5 did not beat the unchanged model. Treat these vocabularies as a strong starting point for training, not as a drop-in accuracy gain for existing encoders.
148
+
149
+ ## Contributing
150
+
151
+ [CONTRIBUTING.md](CONTRIBUTING.md) explains how to work on the project, [SECURITY.md](SECURITY.md) how to report vulnerabilities, and [docs/RELEASING.md](docs/RELEASING.md) how releases are made. Platform reports, regression cases and independent benchmark runs are especially welcome.
152
+
153
+ ## Citation
154
+
155
+ If you use this library or its models, please cite it with the metadata in [CITATION.cff](CITATION.cff).
156
+
157
+ ## License
158
+
159
+ - Code, documentation and the demo vocabulary: [MIT](LICENSE).
160
+ - Bundled model files (`bn-bpe-58k`, `bn-bpe-28k`): [CC BY-SA 4.0](MODEL_LICENSE.md), because they are learned from Wikipedia and Tatoeba text.
161
+ - Native wheels include BSD-3-Clause Go components ([notices](THIRD_PARTY_NOTICES.md)).
162
+
163
+ The SPDX expression is `MIT AND BSD-3-Clause AND CC-BY-SA-4.0`. Research corpora keep their own terms and are not distributed.
@@ -0,0 +1,9 @@
1
+ # Security reporting
2
+
3
+ Report vulnerabilities privately to **aber.islam.dev@gmail.com**, or use the repository's private vulnerability reporting feature if enabled. Include the affected version, OS/architecture, a minimal reproduction and expected impact. Do not post credentials, private corpus text or exploit details in a public issue before coordination.
4
+
5
+ This project is in beta. Security fixes target current development and the latest published release; there is no supported older-release series yet. Prefer maintained Python and Go versions for deployment and source builds.
6
+
7
+ The native library runs inside the Python process. Report native crashes, memory-safety problems, unsafe archive/build behavior and unexpected network activity. Model loading uses JSON; the package does not automatically fetch models or execute model-supplied Python code.
8
+
9
+ Contributors should keep build/publish jobs separate, retain least-privilege workflow permissions and preserve third-party notices. Only the protected publishing job receives an OIDC token permission; ordinary pushes and pull requests do not publish packages.
@@ -0,0 +1,25 @@
1
+ # Third-party notices and scope
2
+
3
+ Original software, documentation and the hand-authored demo vocabulary are
4
+ MIT-licensed; see LICENSE. Native wheels also contain Go runtime/standard-library
5
+ code and golang.org/x/text v0.28.0, each under BSD-3-Clause. Their notices are
6
+ included in third_party/licenses and in the distribution's license directory.
7
+ The bundled pretrained vocabularies in src/banglatok/pretrained
8
+ are learned from Wikipedia, Tatoeba and BanglaTLit text and are distributed under
9
+ CC BY-SA 4.0 with attribution; see MODEL_LICENSE.md. The distribution's SPDX
10
+ expression is MIT AND BSD-3-Clause AND CC-BY-SA-4.0 to reflect all three.
11
+
12
+ - Go: https://go.dev/ — third_party/licenses/GO-LICENSE
13
+ - golang.org/x/text: https://pkg.go.dev/golang.org/x/text —
14
+ third_party/licenses/X-TEXT-LICENSE and X-TEXT-PATENTS
15
+
16
+ The Go corpus-preparation CLI additionally depends on modules listed in go.mod
17
+ and go.sum. Those modules are fetched separately when building the CLI; the
18
+ Python wheel's native bridge imports only the tokenizer and its Unicode dependency.
19
+ Dependencies retain their own licenses.
20
+
21
+ The software license does not grant rights to third-party corpus text, source
22
+ snapshots or external pretrained models. data/CORPUS.md and the research reports
23
+ record source-specific terms and limitations. Raw corpora and research checkpoints
24
+ are excluded from Python distributions. Do not treat their presence in a local
25
+ research checkout as permission to redistribute them.
@@ -0,0 +1,68 @@
1
+ // Package main exposes the Go tokenizer through owned C buffers.
2
+ package main
3
+
4
+ /*
5
+ #include <stdint.h>
6
+ #include <stdlib.h>
7
+ */
8
+ import "C"
9
+
10
+ import (
11
+ "math"
12
+ "unsafe"
13
+
14
+ "github.com/iamaber/banglatok/internal/native"
15
+ )
16
+
17
+ var registry native.Registry
18
+
19
+ // Status codes returned by bntok_encode_into in place of an ID count.
20
+ const (
21
+ encodeClosed = -1
22
+ encodeInvalid = -2
23
+ )
24
+
25
+ // bntok_encode_into encodes one UTF-8 text into a caller-owned uint32 buffer.
26
+ // It returns the ID count; a count above capacity means retry with that size.
27
+ // Input and output memory are only used during the call.
28
+ //
29
+ //export bntok_encode_into
30
+ func bntok_encode_into(handle C.ulonglong, data *C.char, length C.size_t, out *C.uint32_t, capacity C.size_t) C.longlong {
31
+ if uint64(length) > math.MaxInt32 || uint64(capacity) > math.MaxInt32 || (data == nil && length != 0) || (out == nil && capacity != 0) {
32
+ return encodeInvalid
33
+ }
34
+ text := unsafe.String((*byte)(unsafe.Pointer(data)), int(length))
35
+ ids := unsafe.Slice((*uint32)(unsafe.Pointer(out)), int(capacity))
36
+ n, err := registry.EncodeInto(uint64(handle), text, ids)
37
+ if err != nil {
38
+ return encodeClosed
39
+ }
40
+ return C.longlong(n)
41
+ }
42
+
43
+ //export bntok_encode
44
+ func bntok_encode(handle C.ulonglong, data *C.char, length C.size_t, outputLength *C.size_t) *C.char {
45
+ if outputLength == nil {
46
+ return nil
47
+ }
48
+ var response []byte
49
+ if uint64(length) > math.MaxInt32 || (data == nil && length != 0) {
50
+ response = native.EncodeError("invalid encode input size")
51
+ } else {
52
+ response = registry.EncodeBinary(uint64(handle), unsafe.Slice((*byte)(unsafe.Pointer(data)), int(length)))
53
+ }
54
+ *outputLength = C.size_t(len(response))
55
+ return (*C.char)(C.CBytes(response))
56
+ }
57
+
58
+ //export bntok_call
59
+ func bntok_call(request *C.char) *C.char {
60
+ return C.CString(string(registry.Call([]byte(C.GoString(request)))))
61
+ }
62
+
63
+ //export bntok_free
64
+ func bntok_free(response *C.char) {
65
+ C.free(unsafe.Pointer(response))
66
+ }
67
+
68
+ func main() {}