(module ethernet-address mzscheme
(require (lib "etc.ss")
(lib "string.ss" "srfi" "13")
(lib "string.ss"))
(define-struct ethernet-address (fields) #f)
(define (list->ethernet-address ls)
(unless (= (length ls) 6)
(error 'list->ethernet-address "must be exactly 6 bytes"))
(make-ethernet-address
(vector->immutable-vector (list->vector ls))))
(define bytes->ethernet-address
(opt-lambda (bytes [start 0] [end (bytes-length bytes)])
(unless (= (- end start) 6)
(error 'bytes->ethernet-address "must be exactly 6 bytes"))
(make-ethernet-address
(vector->immutable-vector (list->vector (bytes->list (subbytes bytes start end)))))))
(define (%02X x)
(string-upcase (string-pad (format "~x" x) 2 #\0)))
(define ethernet-address->string
(opt-lambda (address [sep #\:])
(let ([fields (vector->list (ethernet-address-fields address))])
(string-join (map %02X fields)
(format "~a" sep)))))
(define (ethernet-address->bytes address)
(list->bytes (vector->list (ethernet-address-fields address))))
(define string->ethernet-address
(opt-lambda (str [sep #\:])
(let ([pieces (regexp-split (regexp-quote (format "~a" sep)) str)])
(unless (= (length pieces) 6)
(error 'string->ethernet-address "invalid format"))
(let ([ns (map (lambda (s)
(string->number s 16))
pieces)])
(unless (andmap (lambda (x)
(<= #x00 x #xFF))
ns)
(error 'string->ethernet-address "address field out of range"))
(make-ethernet-address (list->vector ns))))))
(provide ethernet-address?
list->ethernet-address
bytes->ethernet-address
string->ethernet-address
ethernet-address->bytes
ethernet-address->string))