diff options
| author | Ludovic Courtès <ludo@gnu.org> | 2012-06-09 15:25:51 +0200 |
|---|---|---|
| committer | Ludovic Courtès <ludo@gnu.org> | 2012-06-09 15:25:51 +0200 |
| commit | c8369caccef256f9e7bfa02ac2cc7fcbd72db04f (patch) | |
| tree | e1b4c2db6c4d64824847d83d4c5bee7e00bb1334 | |
| parent | 4255d4e3c5c17b3f170f287388710ca1dc5cb711 (diff) | |
Add `base32-string->bytevector' and `nix-base32-string->bytevector'.
* guix/utils.scm (bytevector-quintet-set!,
bytevector-quintet-set-right!, base32-string-unfold,
base32-string-unfold-right, make-base32-string->bytevector,
base32-string->bytevector, nix-base32-string->bytevector): New
procedures.
* tests/utils.scm ("base32-string->bytevector",
"nix-base32-string->bytevector"): New tests.
| -rw-r--r-- | guix/utils.scm | 130 | ||||
| -rw-r--r-- | tests/utils.scm | 16 |
2 files changed, 146 insertions, 0 deletions
diff --git a/guix/utils.scm b/guix/utils.scm index 2ffecbfab9a..65e89a0e1b0 100644 --- a/guix/utils.scm +++ b/guix/utils.scm | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #:use-module (srfi srfi-39) | 22 | #:use-module (srfi srfi-39) |
| 23 | #:use-module (srfi srfi-60) | 23 | #:use-module (srfi srfi-60) |
| 24 | #:use-module (rnrs bytevectors) | 24 | #:use-module (rnrs bytevectors) |
| 25 | #:use-module (ice-9 vlist) | ||
| 25 | #:use-module (ice-9 format) | 26 | #:use-module (ice-9 format) |
| 26 | #:autoload (ice-9 popen) (open-pipe*) | 27 | #:autoload (ice-9 popen) (open-pipe*) |
| 27 | #:autoload (ice-9 rdelim) (read-line) | 28 | #:autoload (ice-9 rdelim) (read-line) |
| @@ -32,6 +33,8 @@ | |||
| 32 | bytevector->base32-string | 33 | bytevector->base32-string |
| 33 | bytevector->nix-base32-string | 34 | bytevector->nix-base32-string |
| 34 | bytevector->base16-string | 35 | bytevector->base16-string |
| 36 | base32-string->bytevector | ||
| 37 | nix-base32-string->bytevector | ||
| 35 | sha256 | 38 | sha256 |
| 36 | 39 | ||
| 37 | %nixpkgs-directory | 40 | %nixpkgs-directory |
| @@ -169,6 +172,133 @@ the previous application or INIT." | |||
| 169 | (make-bytevector->base32-string bytevector-quintet-fold-right | 172 | (make-bytevector->base32-string bytevector-quintet-fold-right |
| 170 | %nix-base32-chars)) | 173 | %nix-base32-chars)) |
| 171 | 174 | ||
| 175 | |||
| 176 | (define bytevector-quintet-set! | ||
| 177 | (let* ((setq! (lambda (bv offset start stop value) | ||
| 178 | (let ((v (bytevector-u8-ref bv offset)) | ||
| 179 | (w (arithmetic-shift value start)) | ||
| 180 | (m (bitwise-xor (1- (expt 2 stop)) | ||
| 181 | (1- (expt 2 start))))) | ||
| 182 | (bytevector-u8-set! bv offset | ||
| 183 | (bitwise-merge m w v))))) | ||
| 184 | (set0! (lambda (bv offset value) | ||
| 185 | (setq! bv offset 3 8 value))) | ||
| 186 | (set1! (lambda (bv offset value) | ||
| 187 | (setq! bv offset 0 3 (bit-field value 2 5)) | ||
| 188 | (or (= (+ 1 offset) (bytevector-length bv)) | ||
| 189 | (setq! bv (+ 1 offset) 6 8 (bit-field value 0 2))))) | ||
| 190 | (set2! (lambda (bv offset value) | ||
| 191 | (setq! bv offset 1 6 value))) | ||
| 192 | (set3! (lambda (bv offset value) | ||
| 193 | (setq! bv offset 0 1 (bit-field value 4 5)) | ||
| 194 | (or (= (+ 1 offset) (bytevector-length bv)) | ||
| 195 | (setq! bv (+ 1 offset) 4 8 (bit-field value 0 4))))) | ||
| 196 | (set4! (lambda (bv offset value) | ||
| 197 | (setq! bv offset 0 4 (bit-field value 1 5)) | ||
| 198 | (or (= (+ 1 offset) (bytevector-length bv)) | ||
| 199 | (setq! bv (+ 1 offset) 7 8 (bit-field value 0 1))))) | ||
| 200 | (set5! (lambda (bv offset value) | ||
| 201 | (setq! bv offset 2 7 value))) | ||
| 202 | (set6! (lambda (bv offset value) | ||
| 203 | (setq! bv offset 0 2 (bit-field value 3 5)) | ||
| 204 | (or (= (+ 1 offset) (bytevector-length bv)) | ||
| 205 | (setq! bv (+ 1 offset) 5 8 (bit-field value 0 3))))) | ||
| 206 | (set7! (lambda (bv offset value) | ||
| 207 | (setq! bv offset 0 5 value))) | ||
| 208 | (sets (vector set0! set1! set2! set3! set4! set5! set6! set7!))) | ||
| 209 | (lambda (bv index value) | ||
| 210 | "Set the INDEXth quintet of BV to VALUE." | ||
| 211 | (let ((p (vector-ref sets (modulo index 8)))) | ||
| 212 | (p bv (quotient (* index 5) 8) (logand value #x1f)))))) | ||
| 213 | |||
| 214 | (define bytevector-quintet-set-right! | ||
| 215 | (let* ((setq! (lambda (bv offset start stop value) | ||
| 216 | (let ((v (bytevector-u8-ref bv offset)) | ||
| 217 | (w (arithmetic-shift value start)) | ||
| 218 | (m (bitwise-xor (1- (expt 2 stop)) | ||
| 219 | (1- (expt 2 start))))) | ||
| 220 | (bytevector-u8-set! bv offset | ||
| 221 | (bitwise-merge m w v))))) | ||
| 222 | (set0! (lambda (bv offset value) | ||
| 223 | (setq! bv offset 0 5 value))) | ||
| 224 | (set1! (lambda (bv offset value) | ||
| 225 | (setq! bv offset 5 8 (bit-field value 0 3)) | ||
| 226 | (or (= (+ 1 offset) (bytevector-length bv)) | ||
| 227 | (setq! bv (+ 1 offset) 0 2 (bit-field value 3 5))))) | ||
| 228 | (set2! (lambda (bv offset value) | ||
| 229 | (setq! bv offset 2 7 value))) | ||
| 230 | (set3! (lambda (bv offset value) | ||
| 231 | (setq! bv offset 7 8 (bit-field value 0 1)) | ||
| 232 | (or (= (+ 1 offset) (bytevector-length bv)) | ||
| 233 | (setq! bv (+ 1 offset) 0 4 (bit-field value 1 5))))) | ||
| 234 | (set4! (lambda (bv offset value) | ||
| 235 | (setq! bv offset 4 8 (bit-field value 0 4)) | ||
| 236 | (or (= (+ 1 offset) (bytevector-length bv)) | ||
| 237 | (setq! bv (+ 1 offset) 0 1 (bit-field value 4 5))))) | ||
| 238 | (set5! (lambda (bv offset value) | ||
| 239 | (setq! bv offset 1 6 value))) | ||
| 240 | (set6! (lambda (bv offset value) | ||
| 241 | (setq! bv offset 6 8 (bit-field value 0 2)) | ||
| 242 | (or (= (+ 1 offset) (bytevector-length bv)) | ||
| 243 | (setq! bv (+ 1 offset) 0 3 (bit-field value 2 5))))) | ||
| 244 | (set7! (lambda (bv offset value) | ||
| 245 | (setq! bv offset 3 8 value))) | ||
| 246 | (sets (vector set0! set1! set2! set3! set4! set5! set6! set7!))) | ||
| 247 | (lambda (bv index value) | ||
| 248 | "Set the INDEXth quintet of BV to VALUE, assuming quintets start from | ||
| 249 | the least-significant bits." | ||
| 250 | (let ((p (vector-ref sets (modulo index 8)))) | ||
| 251 | (p bv (quotient (* index 5) 8) (logand value #x1f)))))) | ||
| 252 | |||
| 253 | (define (base32-string-unfold f s) | ||
| 254 | "Given procedure F which, when applied to a character, returns the | ||
| 255 | corresponding quintet, return the bytevector corresponding to string S." | ||
| 256 | (define len (string-length s)) | ||
| 257 | |||
| 258 | (let ((bv (make-bytevector (quotient (* len 5) 8)))) | ||
| 259 | (string-fold (lambda (chr index) | ||
| 260 | (bytevector-quintet-set! bv index (f chr)) | ||
| 261 | (+ 1 index)) | ||
| 262 | 0 | ||
| 263 | s) | ||
| 264 | bv)) | ||
| 265 | |||
| 266 | (define (base32-string-unfold-right f s) | ||
| 267 | "Given procedure F which, when applied to a character, returns the | ||
| 268 | corresponding quintet, return the bytevector corresponding to string S, | ||
| 269 | starting from the right of S." | ||
| 270 | (define len (string-length s)) | ||
| 271 | |||
| 272 | (let ((bv (make-bytevector (quotient (* len 5) 8)))) | ||
| 273 | (string-fold-right (lambda (chr index) | ||
| 274 | (bytevector-quintet-set-right! bv index (f chr)) | ||
| 275 | (+ 1 index)) | ||
| 276 | 0 | ||
| 277 | s) | ||
| 278 | bv)) | ||
| 279 | |||
| 280 | (define (make-base32-string->bytevector base32-string-unfold base32-chars) | ||
| 281 | (let ((char->value (let loop ((i 0) | ||
| 282 | (v vlist-null)) | ||
| 283 | (if (= i (vector-length base32-chars)) | ||
| 284 | v | ||
| 285 | (loop (+ 1 i) | ||
| 286 | (vhash-consv (vector-ref base32-chars i) | ||
| 287 | i v)))))) | ||
| 288 | (lambda (s) | ||
| 289 | "Return the binary representation of base32 string S as a bytevector." | ||
| 290 | (base32-string-unfold (lambda (chr) | ||
| 291 | (or (and=> (vhash-assv chr char->value) cdr) | ||
| 292 | (error "invalid base32 character" chr))) | ||
| 293 | s)))) | ||
| 294 | |||
| 295 | (define base32-string->bytevector | ||
| 296 | (make-base32-string->bytevector base32-string-unfold %rfc4648-base32-chars)) | ||
| 297 | |||
| 298 | (define nix-base32-string->bytevector | ||
| 299 | (make-base32-string->bytevector base32-string-unfold-right %nix-base32-chars)) | ||
| 300 | |||
| 301 | |||
| 172 | 302 | ||
| 173 | ;;; | 303 | ;;; |
| 174 | ;;; Base 16. | 304 | ;;; Base 16. |
diff --git a/tests/utils.scm b/tests/utils.scm index eade84b5d49..edea11db720 100644 --- a/tests/utils.scm +++ b/tests/utils.scm | |||
| @@ -46,6 +46,22 @@ | |||
| 46 | "mzxw6ytb" | 46 | "mzxw6ytb" |
| 47 | "mzxw6ytboi"))) | 47 | "mzxw6ytboi"))) |
| 48 | 48 | ||
| 49 | (test-assert "base32-string->bytevector" | ||
| 50 | (every (lambda (bv) | ||
| 51 | (equal? (base32-string->bytevector | ||
| 52 | (bytevector->base32-string bv)) | ||
| 53 | bv)) | ||
| 54 | ;; Examples from RFC 4648. | ||
| 55 | (map string->utf8 '("" "f" "fo" "foo" "foob" "fooba" "foobar")))) | ||
| 56 | |||
| 57 | (test-assert "nix-base32-string->bytevector" | ||
| 58 | (every (lambda (bv) | ||
| 59 | (equal? (nix-base32-string->bytevector | ||
| 60 | (bytevector->nix-base32-string bv)) | ||
| 61 | bv)) | ||
| 62 | ;; Examples from RFC 4648. | ||
| 63 | (map string->utf8 '("" "f" "fo" "foo" "foob" "fooba" "foobar")))) | ||
| 64 | |||
| 49 | ;; The following tests requires `nix-hash' in $PATH. | 65 | ;; The following tests requires `nix-hash' in $PATH. |
| 50 | (test-skip (if (false-if-exception (system* "nix-hash" "--version")) | 66 | (test-skip (if (false-if-exception (system* "nix-hash" "--version")) |
| 51 | 0 | 67 | 0 |
