summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--guix/utils.scm28
-rw-r--r--tests/utils.scm7
2 files changed, 35 insertions, 0 deletions
diff --git a/guix/utils.scm b/guix/utils.scm
index 65e89a0e1b..77ed9ce6ee 100644
--- a/guix/utils.scm
+++ b/guix/utils.scm
@@ -35,6 +35,7 @@
             bytevector->base16-string
             base32-string->bytevector
             nix-base32-string->bytevector
+            base16-string->bytevector
             sha256
 
             %nixpkgs-directory
@@ -327,6 +328,33 @@ starting from the right of S."
           (loop (+ 1 i)
                 (cons (vector-ref chars (bytevector-u8-ref bv i)) r))))))
 
+(define base16-string->bytevector
+  (let ((chars->value (fold (lambda (i r)
+                              (vhash-consv (string-ref (number->string i 16)
+                                                       0)
+                                           i r))
+                            vlist-null
+                            (iota 16))))
+    (lambda (s)
+      "Return the bytevector whose hexadecimal representation is string S."
+      (define bv
+        (make-bytevector (quotient (string-length s) 2) 0))
+
+      (string-fold (lambda (chr i)
+                     (let ((j (quotient i 2))
+                           (v (and=> (vhash-assv chr chars->value) cdr)))
+                       (if v
+                           (if (zero? (logand i 1))
+                               (bytevector-u8-set! bv j
+                                                   (arithmetic-shift v 4))
+                               (let ((w (bytevector-u8-ref bv j)))
+                                 (bytevector-u8-set! bv j (logior v w))))
+                           (error "invalid hexadecimal character" chr)))
+                     (+ i 1))
+                   0
+                   s)
+      bv)))
+
 
 ;;;
 ;;; Hash.
diff --git a/tests/utils.scm b/tests/utils.scm
index edea11db72..db4eb5a340 100644
--- a/tests/utils.scm
+++ b/tests/utils.scm
@@ -62,6 +62,13 @@
          ;; Examples from RFC 4648.
          (map string->utf8 '("" "f" "fo" "foo" "foob" "fooba" "foobar"))))
 
+(test-assert "bytevector->base16-string->bytevector"
+  (every (lambda (bv)
+           (equal? (base16-string->bytevector
+                    (bytevector->base16-string bv))
+                   bv))
+         (map string->utf8 '("" "f" "fo" "foo" "foob" "fooba" "foobar"))))
+
 ;; The following tests requires `nix-hash' in $PATH.
 (test-skip (if (false-if-exception (system* "nix-hash" "--version"))
                0