Files
triplex/README.md
2026-03-02 04:05:11 +01:00

140 lines
3.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
Copyright (c) 2026 Micha Hoiting
# triplex
[![Gitea CI](https://git.hoiting.org/micha/triplex/actions/workflows/ci.yml/badge.svg)](https://git.hoiting.org/micha/triplex/actions)
<!-- TODO: [![GitHub CI](https://github.com/micha/triplex/actions/workflows/ci.yml/badge.svg)](https://github.com/micha/triplex/actions/workflows/ci.yml) -->
`triplex` is a deterministic, reversible serial number engine for
high-integrity identifiers. It maps a compact 32-bit integer space to a
human-readable serial format:
```text
LLL-NNN-LLC
```
Where:
- `L` = data letter (`A` `Z` excluding `F`, `I`, `O`, `Q`, `U`)
- `N` = number (`100``999`)
- `C` = checksum letter (`A` `Z`)
For instance
```text
ABC-123-DEO
```
## What it provides
- 5 data letters
- 3 numeric digits (`100``999`)
- 1 checksum letter
- Optional forbidden-triplet letter combination filtering on the first three letters
- Reversible integer encoding/decoding
- Deterministic checksum generation
Total index capacity: **3,675,690,900** (`21^5 * 900`)
## Features
- Reversible mapping: `Decode(code) ↔ Encode(index)`
- Deterministic checksum: `C = 'A' + (index % 26)`
- Compact index space: fits in `uint`
- Human-readable serial format
- Useful for manufacturing, logistics, SaaS identifiers, and audit-safe systems
## Example
```go
package main
import (
"fmt"
"git.hoiting.org/micha/triplex/serial"
)
func main() {
idx := uint(123456)
code, err := serial.Encode(idx)
if err != nil {
panic(err)
}
idx2, err := serial.Decode(code)
if err != nil {
panic(err)
}
fmt.Println(code)
fmt.Println(idx == idx2) // true
}
```
## Notes
- The current serial format is `LLL-NNN-LLC`.
- Forbidden-triplet logic is centralized in `serial.IsForbiddenTriplet` and can be tailored to project rules.
## API
- `serial.Decode(code string) (uint, error)`
- Parses and validates `LLL-NNN-LLC`, checks checksum, and returns the deterministic index.
- `serial.Encode(idx uint) (string, error)`
- Converts a valid index back to `LLL-NNN-LLC`.
- `serial.CompleteCode(codeWithoutChecksum string) (string, uint, error)`
- Takes `LLL-NNN-L` and returns the completed `LLL-NNN-LLC` plus index.
- `serial.RandomCode(isInUse ...func(uint) bool) (string, uint, error)`
- Generates a random valid `LLL-NNN-LLC` code and its corresponding index.
- If provided, the callback is used to skip indices already in use by the client.
- `serial.RandomCodeWithOptions(options serial.RandomCodeOptions) (string, uint, error)`
- Configurable variant with `MaxAttempts`, `IsInUse`, and custom `RandomIndex` source.
Example with options:
```go
// See the runnable command at ./cmd/triplex-example/main.go
```
## Commands
Runnable example command:
```bash
go run ./cmd/triplex-example
```
Using Makefile:
```bash
make run-example
make build-example
make test
```
Exported errors:
- `serial.ErrInvalidFormat`
- `serial.ErrInvalidFormatNoChecksum`
- `serial.ErrInvalidLetter`
- `serial.ErrForbiddenLetterTriplet`
- `serial.ErrInvalidNumber`
- `serial.ErrNumberOutOfRange`
- `serial.ErrInvalidChecksum`
- `serial.ErrIndexOutOfRange`
- `serial.ErrRandomSourceFailed`
- `serial.ErrNoAvailableIndex`
## Testing
Run all tests:
```bash
go test ./...
```
## License
This project is licensed under the MIT License. See [LICENSE](LICENSE).