#lang racket/base (require racket/match racket/port racket/dict racket/format racket/string racket/sequence "int.rkt" "base.rkt") (provide (all-defined-out)) (define (length-resolvable? x) (or (not x) (exact-nonnegative-integer? x) (procedure? x) (x:int? x))) (define (resolve-length x input-port [parent #f]) (match x [#false #false] [(? exact-nonnegative-integer?) x] [(? procedure? proc) (proc parent)] [(? x:int?) #:when input-port (decode x input-port)] [_ (raise-argument-error 'resolve-length "fixed-size argument" x)])) (define (pretty-print-bytes bstr #:port [port-arg (current-output-port)] #:radix [radix 16] #:offset-min-width [offset-min-width 4] #:row-length [bytes-per-row 16] #:max-value [max-value 256]) (define port (or port-arg (open-output-bytes))) (define bs (bytes->list bstr)) (define offset-str-length (max offset-min-width (string-length (let ([lbs (length bs)]) (~r (- lbs (remainder lbs bytes-per-row))))))) (parameterize ([current-output-port port]) (display (string-join (for/list ([row-bs (in-slice bytes-per-row bs)] [ridx (in-naturals)]) (string-append (let ([idxstr (~r (* ridx bytes-per-row))]) (string-append idxstr (make-string (- offset-str-length (string-length idxstr)) #\space))) " " (string-join (let* ([max-digit-width (string-length (~r (sub1 max-value) #:base radix))] [strs (for/list ([b (in-list row-bs)]) (~r b #:base radix #:min-width max-digit-width #:pad-string "0"))]) (for/list ([2strs (in-slice 2 strs)]) (string-join 2strs "ยท"))) " ") (let ([shortfall (* (- bytes-per-row (length row-bs)) 3)]) (make-string shortfall #\space)) " " (format "~a" (bytes->string/utf-8 (apply bytes row-bs))))) "\n"))) (unless port-arg (get-output-string port)))