# isbn.zig A Zig library for parsing, validating, and converting International Standard Book Numbers (ISBNs) in both the 10-digit and 13-digit formats. The API documentation is generated from the doc comments in the source and published at . To read it locally instead, `zig build docs` builds it into `zig-out/docs` and `zig build docs-serve` serves it on . A server is needed rather than opening the files directly, because the viewer fetches `sources.tar` and `main.wasm` at runtime and a browser refuses those from a `file://` page. ## Features - Parse ISBNs from text, with or without `-` separators. - Validate check digits during parsing (including the `X` check digit used by ISBN-10). - Compute check digits, optionally using SIMD vector operations. - Upgrade an ISBN-10 to its equivalent ISBN-13. - Compare ISBNs across formats: an ISBN-10 is equal to its 13-digit equivalent. - Format ISBNs with proper hyphenation, using the International ISBN Agency's registration group and registrant range data. ## Requirements - Zig 0.16.0 or later ## Installation Add the dependency to your project: ```sh zig fetch --save git+https://tangled.org/jcollie.dev/isbn.zig ``` Then wire it up in your `build.zig`: ```zig const isbn = b.dependency("isbn", .{ .target = target, .optimize = optimize, }); exe.root_module.addImport("isbn", isbn.module("isbn")); ``` ## Usage ```zig const ISBN = @import("isbn").ISBN; // Parsing validates the check digit. const ten: ISBN = try .parse("0-306-40615-2"); const thirteen: ISBN = try .parse("978-0-306-40615-7"); // Upgrade an ISBN-10 to an ISBN-13. const upgraded = ten.upgrade(); // Comparison works across formats. std.debug.assert(ten.eql(&thirteen)); // Hyphenate explicitly, or format with {f}. var buf: [ISBN.max_hyphenated_len]u8 = undefined; const hyphenated = try upgraded.hyphenate(&buf); std.debug.print("{s}\n", .{hyphenated}); // 978-0-306-40615-7 std.debug.print("{f}\n", .{ten}); // 0-306-40615-2 ``` `parse` returns `error.ParseError` for malformed input and `error.InvalidCheckDigit` when the check digit doesn't match. ## Build options - `-Dsimd=[bool]` — use SIMD vector operations for computing check digits (default: `false`). It is off because it does not pay: `zig build bench` measures both implementations, and nine or twelve lanes of multiply-and-add do not earn back the cost of widening the digits and assembling the vector. - `-Ddocs-port=[u16]` — port for `zig build docs-serve` (default: `8000`). ## Standards | Standard | Title | Support in isbn.zig | | --- | --- | --- | | [ISO 2108](https://www.iso.org/standard/65483.html) | International Standard Book Number | Parsing and validating both the 10- and 13-digit forms, the two check digit algorithms, and conversion from 10 to 13 | | [ISBN range message](https://www.isbn-international.org/range_file_generation) | Registration group and registrant ranges | Hyphenation, from the International ISBN Agency's published ranges, generated into `src/ranges.zig` | | [EAN/UPC (GS1)](https://www.gs1.org/standards/barcodes/ean-upc) | Article numbering | The 978 and 979 prefixes an ISBN-13 is built on | ISO 2108 itself is not freely available. The check digit algorithms and the 978/979 prefixes are documented in the ISBN Users' Manual, which is: ## Range data Hyphenation uses the registration group and registrant ranges published by the [International ISBN Agency](https://www.isbn-international.org/), embedded at build time as `src/ranges.zig`. To update them: ```sh zig build update-ranges ``` ## Testing ```sh zig build test ``` The test suite includes unit tests and a fuzz test. `zig build check` compiles everything that `zig build test` does not run — the benchmark, the documentation server, and the range generator — so that none of them can quietly stop compiling. `zig build bench` compares the SIMD and scalar check digit implementations against each other; it calls both directly, so the `-Dsimd` setting does not affect what it measures. ## License [MIT](LICENSES/MIT.txt). This project is compliant with the [REUSE Specification](https://reuse.software/).