#lang racket/base (require "bitstring.rkt") (require "bitmatch.rkt") (require "bitstitch.rkt") (require rackunit) (define (experiment-one v) (bit-string-case v ([(= 0 :: bytes 2)] 'yeah) ([(f :: bits 10) (:: binary)] (when (and (< f 123) (>= f 100))) 'between-100-and-123) ([(f :: bits 10) (:: bits 6)] f) ([(f :: bits 10) (:: bits 6) (rest :: binary)] (list f rest)))) (check-equal? (experiment-one (bytes 0 0)) 'yeah) (check-equal? (experiment-one (bytes 252 0)) 1008) (check-equal? (experiment-one (bytes 25 64)) 'between-100-and-123) (check-equal? (experiment-one (bytes 252 0 123)) (list 1008 (sub-bit-string (bytes 252 0 123) 16 24))) (check-equal? (bit-string-pack (cadr (experiment-one (bytes 252 0 123)))) (bytes 123)) (check-equal? (bit-string-pack (bit-string (1008 :: bits 10) (0 :: bits 6))) (bytes 252 0)) (define (pascal->string/utf-8 bs) (bit-string-case bs ([len (body :: binary bytes len)] (bytes->string/utf-8 (bit-string-pack body))))) (define (string->pascal/utf-8 str) (let ((bs (string->bytes/utf-8 str))) (bit-string (bytes-length bs) (bs :: binary)))) (check-equal? (pascal->string/utf-8 #"\010abcdefgh") "abcdefgh") (check-equal? (bit-string-pack (string->pascal/utf-8 "abcdefgh")) #"\010abcdefgh") (check-equal? (bit-string (49152 :: big-endian)) (bytes 0)) (check-equal? (bit-string (49152 :: little-endian)) (bytes 0)) (check-equal? (bit-string (49152 :: bits 16 big-endian)) (bytes 192 0)) (check-equal? (bit-string (49152 :: bits 16 little-endian)) (bytes 0 192)) (check-equal? (bit-string (inexact->exact 1.0)) (bytes 1)) (check-equal? (bit-string [1.0 :: float]) (bytes 63 240 0 0 0 0 0 0)) (check-equal? (bit-string [1.0 :: float bits 32]) (bytes 63 128 0 0)) (check-equal? (bit-string [1.0 :: float little-endian]) (bytes 0 0 0 0 0 0 240 63)) (define (p:pascal-string/utf-8 is-matching) (if is-matching (lambda (input ks kf) (bit-string-case input ([len (body :: binary bytes len) (rest :: binary)] (ks (bytes->string/utf-8 (bit-string->bytes body)) rest)) (else (kf)))) (lambda (str) (let* ((bs (string->bytes/utf-8 str)) (len (bytes-length bs))) (when (> len 255) (error 'p:pascal-string "String of length ~v too long; max is 255 encoded bytes" len)) (bit-string len (bs :: binary bytes len)))))) (define (p:d bs) (bit-string-case bs ([ (s :: (p:pascal-string/utf-8)) (rest :: binary) ] (list s (bit-string-pack rest))) (else #f))) (define (p:e str) (bit-string-pack (bit-string (str :: (p:pascal-string/utf-8))))) (check-equal? (p:d #"\010abcdefghijkl") (list "abcdefgh" #"ijkl")) (check-equal? (p:d #"\010abcdefgh") (list "abcdefgh" #"")) (check-equal? (p:d #"\010abcd") #f) (check-equal? (p:d #"\000") (list "" #"")) (check-equal? (p:e "abcdefgh") #"\010abcdefgh") (check-equal? (p:e "") #"\000") (check-equal? (p:e (make-string 255 #\a)) (bytes-append (bytes 255) (make-bytes 255 (char->integer #\a)))) (check-exn #rx"too long" (lambda () (p:e (make-string 256 #\a)))) (define-syntax m:test (syntax-rules () ((_ #t substval) (lambda (input ks kf) (ks substval input))) ((_ #f substval) (lambda (dontcare) (bytes substval))))) (check-equal? (bit-string-case #"" ([ (v :: (m:test 123)) ] v)) 123) (check-equal? (bit-string (234 :: (m:test 123))) (bytes 123)) (define-syntax utf-8 (syntax-rules () [(_ #t) (lambda (input ks kf) (ks (bytes->string/utf-8 (bit-string->bytes input)) (bytes)))] [(_ #t length-in-bytes) (lambda (input ks kf) (bit-string-case input ([ (body :: binary bytes length-in-bytes) (rest :: binary) ] (ks (bytes->string/utf-8 (bit-string->bytes body)) rest)) (else (kf))))] [(_ #f) (lambda (str) (string->bytes/utf-8 str))] [(_ #f (length-format-options ...)) (lambda (str) (let* ((bs (string->bytes/utf-8 str)) (len (bytes-length bs))) (bit-string (len :: length-format-options ...) (bs :: binary))))])) (check-equal? (bit-string-case (bytes #xc3 #xa5 #xc3 #xa4 #xc3 #xb6) ([ (s :: (utf-8)) ] s)) (list->string (map integer->char (list 229 228 246)))) (check-equal? (bit-string-case (bytes #xc3 #xa5 #xc3 #xa4 #xc3 #xb6) ([ (s :: (utf-8 4)) (rest :: binary) ] (list s (bit-string->bytes rest)))) (list (list->string (map integer->char (list 229 228))) (bytes #xc3 #xb6))) (check-equal? (bit-string->bytes (bit-string ((list->string (map integer->char (list 229 228 246))) :: (utf-8)))) (bytes #xc3 #xa5 #xc3 #xa4 #xc3 #xb6)) (check-equal? (bit-string->bytes (bit-string ((list->string (map integer->char (list 229 228 246))) :: (utf-8 (integer bytes 4))))) (bytes #x00 #x00 #x00 #x06 #xc3 #xa5 #xc3 #xa4 #xc3 #xb6))