Initial Common Lisp implementation of sqids - #1
Open
DavidAlphaFox wants to merge 11 commits into
Open
Conversation
Replace plain-function core with a CLOS SQIDS class whose slots are read-only via :reader (no more manual setf override). The constructor shuffles the alphabet exactly once and pre-filters the blocklist into 3 tiers (exact / ends-with / anywhere), matching the official sqids-spec. Fixes 8 algorithm bugs against sqids-spec: - B1: TO-ID now uses do/while so (encode '(0)) yields a single char. - B2: empty list returns "". - B3: DECODE of out-of-alphabet chars returns NIL instead of erroring. - B4: alphabet is shuffled once in the constructor (was: per-call). - B5: blocklist retry loop actually produces a different ID each round. - B6: tidy NIL / empty-string edge case in encode retry. - B7: blocklist matching is now the official 3-tier heuristic (was: string=). - B8: alphabet and min-length are validated at construction. Other changes: - conditions.lisp: SQIDS-ERROR base + typed sub-conditions, each with :REPORT. - constants.lisp: switch compound values to DEFPARAMETER (*name*) to avoid SBCL's 'redefining a constant' warning and CCL quirks; scalars stay DEFCONST. - blocklist.lisp: new module extracting 3-tier matching from the encoder. - codec.lisp: renamed+rewritten core.lisp; WITH-PEELED-SEPARATOR macro eliminates the duplicated separator/suffix binding. - sqids.lisp: renamed+rewritten cl-sqids.lisp with CLOS class + defgenerics. - package.lisp: exports condition readers, all conditions, introspection readers. - cl-sqids.asd: (in-package :asdf-user), add :cl-sqids/tests subsystem with test-op. Verified spec-correct on SBCL 2.6.6 and CCL 1.13: (encode '(1 2 3)) => 86Rf07, (encode '(0)) => bM, (encode '(4572721)) => JExTR (blocklist reshuffle), full min-length cascade matches the spec-pinned vectors. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Five test files plus packages.lisp/suite.lisp form a complete loadable :cl-sqids/tests system. Test vectors are ported 1:1 from sqids-python's official suite: - test-encoding.lisp: [1,2,3]=>86Rf07, [0]=>bM, [1]=>Uk, two-number tuples, empty/invalid decode. - test-minlength.lisp: 8-step + 4-step min-length cascade pinned to spec. - test-blocklist.lisp: 3-tier matching, [4572721]=>JExTR reshuffle, decoder accepts blocked IDs. - test-alphabet.lisp: hex alphabet pinned vector, validation errors (too short/duplicate/multibyte). - test-roundtrip.lisp: round-trip for 0..99, large fixnums, custom alphabet, idempotency. Run with: (asdf:test-system :cl-sqids). Result on SBCL 2.6.6 and CCL 1.13: Did 281 checks. Pass: 281 (100%). Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Adds installation, quick-start, API reference, customization, error conditions, test runner, compatibility, and project structure sections. Chinese is the primary language; an English section follows at the bottom. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Tutorial document complementing README: real-world scenarios (DB primary keys, compound routes, invite codes), customization deep-dive, error handling patterns, cross-language interop with sqids-python/js/go, performance and memory notes, best practices, and a 10-item FAQ. Chinese primary, English quick-reference at the end. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Developer-facing record of the refactor: current-state analysis, 8 algorithm bugs verified against sqids-spec, file-level task breakdown, acceptance criteria, and execution order. Chinese primary with English summary. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Previously README.md and USAGE.md each kept an English section at the bottom. That made the docs long, broke GitHub's language detection, and was awkward to maintain. Now each language has its own file, with a cross-link at the top of every document: README.md (中文) ↔ README.en.md (English) USAGE.md (中文) ↔ USAGE.en.md (English) The English versions are full mirrors of the Chinese structure (not abbreviated appendices). All four files open with a '中文 · English' line that links to the other language. The Chinese project-structure section also now lists all four documentation files. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
# Conflicts: # LICENSE
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Initial Common Lisp implementation of sqids
Summary
Initial Common Lisp implementation of sqids, ported 1:1 from the official spec.
Highlights
sqidsclass with validated constructorwith-peeled-separator) and shared helpers eliminate duplicationSpec compliance
All 281 checks pass on both supported implementations:
Spec-pinned vectors verified:
(encode '(1 2 3))→"86Rf07"(encode '(0))→"bM"(encode '(4572721))→"JExTR"(blocklist reshuffle)License
This submission is distributed under the Apache License, Version 2.0.
The parent repo
sqids/sqids-common-lispis currently MIT-licensed, so I want toflag this explicitly before merge. Apache 2.0 is BSD/MIT-compatible and is a
strict superset in terms of protections (notably the explicit patent grant and
the anti-aggression clause).
If the sqids org prefers to keep all ports uniformly MIT, I'm open to discussing
relicensing before or after merge. As-is, this submission is offered under
Apache 2.0.
Commit history
This PR was pushed with
--force-with-leasebecause the fork's initial LICENSEcommit (inherited from the parent repo) and this project's history share no
common ancestor. The 6 commits in this PR are atomic and reviewable individually:
Refactor src/ with CLOS, fix 8 spec bugs, support SBCL and CCLAdd FiveAM test suite mirroring official sqids-python vectorsRewrite README as Chinese-primary with English supplementAdd USAGE.md hands-on guide with examples and FAQAdd TASK.md refactor planning documentSplit bilingual docs into per-language files with cross-linksHappy to squash, restructure, or address any review feedback.