summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2012-06-09 15:25:51 +0200
committerLudovic Courtès <ludo@gnu.org>2012-06-09 15:25:51 +0200
commitc8369caccef256f9e7bfa02ac2cc7fcbd72db04f (patch)
treee1b4c2db6c4d64824847d83d4c5bee7e00bb1334
parent4255d4e3c5c17b3f170f287388710ca1dc5cb711 (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.scm130
-rw-r--r--tests/utils.scm16
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
249the 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
255corresponding 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
268corresponding quintet, return the bytevector corresponding to string S,
269starting 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