Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/SasLuca/zig-nanoid
A tiny, secure, URL-friendly, unique string ID generator. Now available in pure Zig.
https://github.com/SasLuca/zig-nanoid
id nanoid random unique-id unique-identifier uniqueid url uuid uuid-generator zig zig-package ziglang
Last synced: 28 days ago
JSON representation
A tiny, secure, URL-friendly, unique string ID generator. Now available in pure Zig.
- Host: GitHub
- URL: https://github.com/SasLuca/zig-nanoid
- Owner: SasLuca
- License: mit
- Created: 2022-04-18T22:32:31.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2022-09-06T13:21:12.000Z (over 2 years ago)
- Last Synced: 2024-06-23T04:58:05.196Z (6 months ago)
- Topics: id, nanoid, random, unique-id, unique-identifier, uniqueid, url, uuid, uuid-generator, zig, zig-package, ziglang
- Language: Zig
- Homepage:
- Size: 53.7 KB
- Stars: 24
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
- awesome-zig - zig-nanoidποΈA tiny, secure, URL-friendly, unique string ID generator. Now available in pure Zig
README
# Nano ID in Zig
[![License](https://img.shields.io/badge/license-MIT%20License-blue.svg)](https://github.com/SasLuca/nanoid-zig/master/LICENSE)
[![cross build tests](https://github.com/SasLuca/zig-nanoid/actions/workflows/cross-build.yml/badge.svg)](https://github.com/SasLuca/zig-nanoid/actions/workflows/cross-build.yml)
![Maintenance intention for this crate](https://img.shields.io/badge/maintenance-actively--developed-brightgreen.svg)A battle-tested, tiny, secure, URL-friendly, unique string ID generator. Now available in pure Zig.
* **Freestanding.** zig-nanoid is entirely freestanding.
* **Fast.** The algorithm is very fast and relies just on basic math, speed will mostly depend on your choice of RNG.
* **Safe.** It can use any random generator you want and the library has no errors to handle.
* **Short IDs.** It uses a larger alphabet than UUID (`A-Za-z0-9_-`). So ID length was reduced from 36 to 21 symbols and it is URL friendly.
* **Battle Tested.** Original implementation has over 18 million weekly downloads on [npm](https://www.npmjs.com/package/nanoid).
* **Portable.** Nano ID was ported to [20+ programming languages](https://github.com/ai/nanoid#other-programming-languages).## Example
Basic usage with `std.crypto.random`:
```zig
const std = @import("std");
const nanoid = @import("nanoid");pub fn main() !void
{
const result = nanoid.generate(std.crypto.random);std.log.info("Nanoid: {s}", .{result});
}
```## Comparison to UUID
Nano ID is quite comparable to UUID v4 (random-based).
It has a similar number of random bits in the ID (126 in Nano ID and 122 in UUID), so it has a similar collision probability.
It also uses a bigger alphabet, so a similar number of random bits are packed in just 21 symbols instead of 36.
For there to be a one in a billion chance of duplication, 103 trillion version 4 IDs must be generated.
## How to use
### Generating an id with the default size
The simplest way to generate an id with the default alphabet and length is by using the function `generate` like so:
```zig
const result = nanoid.generate(std.crypto.random);
```If you want a custom alphabet you can use `generateWithAlphabet` and pass either a custom alphabet or one from `nanoid.alphabets`:
```zig
const result = nanoid.generateWithAlphabet(std.crypto.random, nanoid.alphabets.numbers); // This id will only contain numbers
```You can find a variety of other useful alphabets inside of `nanoid.alphabets`.
The result is an array of size `default_id_len` which happens to be 21 which is returned by value.
There are no errors to handle, assuming your rng object is valid everything will work.
The default alphabet includes the symbols "-_", numbers and English lowercase and uppercase letters.### Generating an id with a custom size
If you want a custom alphabet and length use `generateEx` or `generateExWithIterativeRng`.
The function `generateEx` takes an rng, an `alphabet`, a `result_buffer` that it will write the id to, and a `step_buffer`.
The `step_buffer` is used by the algorithm to store a random bytes so it has to do less calls to the rng and `step_buffer.len` must be at
least `computeRngStepBufferLength(computeMask(@truncate(u8, alphabet.len)), result_buffer.len, alphabet.len)`.The function `generateExWithIterativeRng` is the same as `generateEx` except it doesn't need a `step_buffer`. It will use `Random.int(u8)`
instead of `Random.bytes()` to get a random byte at a time thus avoiding the need for a rng step buffer. Normally this will be slower but
depending on your rng algorithm or other requirements it might not be, so the option is there in case you need but normally it is
recommended you use `generateEx` which requires a temporary buffer that will be filled using `Random.bytes()` in order to get the best
performance.Additionally you can precompute a sufficient length for the `step_buffer` and pre-allocate it as an optimization using
`computeSufficientRngStepBufferLengthFor` which simply asks for the largest possible id length you want to generate.If you intend to use the `default_id_len`, you can use the constant `nanoid.rng_step_buffer_len_sufficient_for_default_length_ids`.
### Regarding RNGs
You will need to provide an random number generator (rng) yourself. You can use the zig standard library ones, either `std.rand.DefaultPrng`
or if you have stricter security requirements use `std.rand.DefaultCsprng` or `std.crypto.random`.When you initialize them you need to provide a seed, providing the same one every time will result in the same ids being generated every
time you run the program, except for `std.crypto.random`.If you want a good secure seed you can generate one using `std.crypto.random.bytes`.
Here is an example of how you would initialize and seed `std.rand.DefaultCsprng` and use it:
```zig
// Generate seed
var seed: [std.rand.DefaultCsprng.secret_seed_length]u8 = undefined;
std.crypto.random.bytes(&seed);// Initialize the rng and allocator
var rng = std.rand.DefaultCsprng.init(seed);// Generate id
var id = nanoid.generate(rng.random());
```## Add zig-nanoid to your project
### Manually
To add the library as a package to your zig project:
1. Download the repo and put it in a folder (eg: `thirdparty`) in your project.
2. Import the library's `build.zig` in your build script (eg: `const nanoid = @import("thirdparty/nanoid-zig/build.zig");`)
3. Add the library as a package to your steps (eg: `exe.addPackage(nanoid.getPackage("nanoid"));`)Full example:
```zig
// build.zig
const std = @import("std");
const nanoid = @import("thirdparty/zig-nanoid/build.zig");pub fn build(b: *std.build.Builder) void
{
const target = b.standardTargetOptions(.{});
const mode = b.standardReleaseOptions();const exe = b.addExecutable("zig-nanoid-test", "src/main.zig");
exe.setTarget(target);
exe.setBuildMode(mode);
exe.addPackage(nanoid.getPackage("nanoid"));
exe.install();
}
```### Using the gyro package manager
We support the zig [gyro package manager](https://github.com/mattnite/gyro).
Here is how to use it:1. From your terminal initialize a gyro project and add the package `SasLuca/nanoid`.
```
gyro init
gyro add SasLuca/nanoid
```2. In your `build.zig` do an import like so `const pkgs = @import("deps.zig").pkgs;` and call `pkgs.addAllTo(exe);` to add all libraries to your executable (or some other target).
3. Import `const nanoid = @import("nanoid");` in your `main.zig` and use it.
4. Invoke `gyro build run` which will generate `deps.zig` and other files as well as building and running your project.
## Useful links
- Original implementation: https://github.com/ai/nanoid
- Online Tool: https://zelark.github.io/nano-id-cc/