From a49b615b9ac7ddadf50603d6e63724fc5277f0cb Mon Sep 17 00:00:00 2001 From: Asumu Takikawa Date: Sat, 2 Mar 2013 12:53:35 -0500 Subject: [PATCH] Shorten IPv6 addresses for display original commit: cf4c71a51f8ef8a2535eaa79a3e825edaa610b09 --- collects/net/dns.rkt | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/collects/net/dns.rkt b/collects/net/dns.rkt index 1bbf775ab0..6e7525a1e8 100644 --- a/collects/net/dns.rkt +++ b/collects/net/dns.rkt @@ -5,6 +5,7 @@ (require racket/bool racket/contract racket/format + racket/list racket/match racket/string racket/system @@ -356,13 +357,36 @@ ;; Convert a list of bytes representing an IPv6 address to a string (define (ipv6->string lob) - (define two-octet-strings + (define two-octets (for/list ([oct-pair (in-slice 2 (in-list lob))]) (define oct1 (car oct-pair)) (define oct2 (cadr oct-pair)) - (~r (+ (arithmetic-shift oct1 8) oct2) - #:base 16))) - (string-join two-octet-strings ":")) + (+ (arithmetic-shift oct1 8) oct2))) + (define compressed (compress two-octets)) + (define compressed-strs + (for/list ([elem compressed]) + (if (eq? elem '::) + "" ; string-join will turn this into :: + (~r elem #:base 16)))) + (string-join compressed-strs ":")) + +;; (Listof Number) -> (Listof (U Number '::)) +;; Compress an IPv6 address to its shortest representation +(define (compress lon) + (let loop ([acc '()] [lon lon]) + (cond [(empty? lon) (reverse acc)] + [else + (define zeroes (for/list ([n lon] #:break (not (zero? n))) n)) + (define num-zs (length zeroes)) + (if (<= num-zs 1) + (loop (cons (car lon) acc) (cdr lon)) + (append (reverse acc) '(::) (drop lon num-zs)))]))) + +(module+ test + (check-equal? (compress '(0 0 0 5 5)) '(:: 5 5)) + (check-equal? (compress '(0 5 5)) '(0 5 5)) + (check-equal? (compress '(0 0 5 0 0 5)) '(:: 5 0 0 5)) + (check-equal? (compress '(0 5 0 0 0 5)) '(0 5 :: 5))) ;; (NameServer -> (Values Any LB Boolean)) NameServer -> Any ;; Run the given query function, trying until an answer is found