Various improvements and changed encoding/decoding format to LLL-NNN-LLC with reduced character set.
All checks were successful
CI / test (push) Successful in 16s

This commit is contained in:
2026-03-02 04:05:11 +01:00
parent ed5a23bce1
commit 3fc26e0743
6 changed files with 456 additions and 186 deletions

View File

@@ -10,36 +10,36 @@ high-integrity identifiers. It maps a compact 32-bit integer space to a
human-readable serial format:
```text
LLL-NNN-LC
LLL-NNN-LLC
```
Where:
- `L` = data letter (`A``Z`)
- `L` = data letter (`A` `Z` excluding `F`, `I`, `O`, `Q`, `U`)
- `N` = number (`100``999`)
- `C` = checksum letter (`A``Z`)
- `C` = checksum letter (`A` `Z`)
For instance
```text
ABC-123-DT
ABC-123-DEO
```
## What it provides
- 4 data letters
- 5 data letters
- 3 numeric digits (`100``999`)
- 1 checksum letter
- Optional forbidden-triplet filtering on the first three letters
- Optional forbidden-triplet letter combination filtering on the first three letters
- Reversible integer encoding/decoding
- Deterministic checksum generation
Total index capacity: **386,942,400** (`26^4 * 900`)
Total index capacity: **3,675,690,900** (`21^5 * 900`)
## Features
- Reversible mapping: `Encode(code) ↔ Decode(index)`
- Reversible mapping: `Decode(code) ↔ Encode(index)`
- Deterministic checksum: `C = 'A' + (index % 26)`
- Compact index space: fits in `uint32`
- Compact index space: fits in `uint`
- Human-readable serial format
- Useful for manufacturing, logistics, SaaS identifiers, and audit-safe systems
@@ -55,14 +55,14 @@ import (
)
func main() {
idx := uint32(123456)
idx := uint(123456)
code, err := serial.Decode(idx)
code, err := serial.Encode(idx)
if err != nil {
panic(err)
}
idx2, err := serial.Encode(code)
idx2, err := serial.Decode(code)
if err != nil {
panic(err)
}
@@ -74,21 +74,21 @@ func main() {
## Notes
- The current serial format is `LLL-NNN-LC`.
- 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.Encode(code string) (uint32, error)`
- Parses and validates `LLL-NNN-LC`, checks checksum, and returns the deterministic index.
- `serial.Decode(idx uint32) (string, error)`
- Converts a valid index back to `LLL-NNN-LC`.
- `serial.CompleteCode(codeWithoutChecksum string) (string, uint32, error)`
- Takes `LLL-NNN-L` and returns the completed `LLL-NNN-LC` plus index.
- `serial.RandomCode(isInUse ...func(uint32) bool) (string, uint32, error)`
- Generates a random valid `LLL-NNN-LC` code and its corresponding index.
- `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, uint32, error)`
- `serial.RandomCodeWithOptions(options serial.RandomCodeOptions) (string, uint, error)`
- Configurable variant with `MaxAttempts`, `IsInUse`, and custom `RandomIndex` source.
Example with options:
@@ -117,7 +117,7 @@ Exported errors:
- `serial.ErrInvalidFormat`
- `serial.ErrInvalidFormatNoChecksum`
- `serial.ErrInvalidLetters`
- `serial.ErrInvalidLetter`
- `serial.ErrForbiddenLetterTriplet`
- `serial.ErrInvalidNumber`
- `serial.ErrNumberOutOfRange`