(module util mzscheme
(require (only (lib "vector-lib.ss" "srfi" "43") vector-index)
(only (lib "etc.ss") identity))
(provide hex unhex shrink-bytes)
(define hexes (list->vector (bytes->list #"0123456789abcdef")))
(define hexes2 (list->vector (bytes->list #"0123456789ABCDEF")))
(define << arithmetic-shift)
(define (>> n k) (arithmetic-shift n (- k)))
(define && bitwise-and)
(define :: bitwise-ior)
(define (hex bs)
(let* ((len (bytes-length bs))
(obs (make-bytes (* 2 len))))
(do ((i 0 (add1 i))
(j 0 (+ 2 j)))
((= i len) obs)
(let ((b (bytes-ref bs i)))
(bytes-set! obs j (vector-ref hexes (>> b 4)))
(bytes-set! obs (add1 j) (vector-ref hexes (&& b #x0f)))))))
(define (hex->byte c)
(cond
((vector-index (lambda (x) (eq? x c)) hexes) => identity)
((vector-index (lambda (x) (eq? x c)) hexes2) => identity)
(else (error 'unhex "bad character"))))
(define (unhex bs)
(let ((len (bytes-length bs)))
(unless (even? len)
(error 'unhex "odd length byte-string"))
(if (> len 0)
(let ((obs (make-bytes (/ len 2))))
(do ((i 0 (+ 2 i))
(j 0 (add1 j)))
((= i len) obs)
(bytes-set! obs j (:: (<< (hex->byte (bytes-ref bs i)) 4)
(hex->byte (bytes-ref bs (add1 i)))))))
bs)))
(define (shrink-bytes bs len)
(if (< len (bytes-length bs))
(let ((nbs (make-bytes len)))
(bytes-copy! nbs 0 bs 0 len)
nbs)
bs))
)