You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
typesetting/pitfall/restructure/number.rkt

64 lines
2.3 KiB
Racket

#lang restructure/racket
(require "decodestream.rkt")
;; approximates https://github.com/mbutterick/restructure/blob/master/src/Number.coffee
(define (ends-with-8? type)
(define str (symbol->string type))
(equal? (substring str (sub1 (string-length str))) "8"))
(define (unsigned-type? type)
(equal? "U" (substring (symbol->string type) 0 1)))
(test-module
(check-true (unsigned-type? 'UInt16))
(check-false (unsigned-type? 'Int16)))
8 years ago
(define-subclass RestructureBase% (NumberT type [endian (if (system-big-endian?) 'BE 'LE)])
8 years ago
(getter-field [fn (string->symbol (format "~a~a" type (if (ends-with-8? type) "" endian)))])
8 years ago
8 years ago
(unless (hash-has-key? type-sizes fn)
(raise-argument-error 'NumberT "valid type and endian" (format "~v ~v" type endian)))
8 years ago
(getter-field [size (hash-ref type-sizes fn)])
8 years ago
(define/override (decode stream)
8 years ago
(unless (input-port? stream)
(raise-argument-error 'decode "input port" stream))
(define bstr (read-bytes-exact size stream))
(if (= 1 size)
(bytes-ref bstr 0)
(integer-bytes->integer bstr (unsigned-type? type) (eq? endian 'BE))))
8 years ago
(define/override (encode stream val)
8 years ago
(unless (output-port? stream)
(raise-argument-error 'encode "output port" stream))
8 years ago
(if (= 1 size)
(bytes val)
(integer->integer-bytes val size (unsigned-type? type) (eq? endian 'BE)))))
(test-module
(let ([o (make-object NumberT 'UInt16 'LE)]
8 years ago
[ip (open-input-bytes (bytes 1 2 3 4))]
[op (open-output-bytes)])
(check-equal? (send o decode ip) 513) ;; 1000 0000 0100 0000
8 years ago
(check-equal? (send o decode ip) 1027) ;; 1100 0000 0010 0000
(check-equal? (send o encode op 513) (bytes 1 2))
(check-equal? (send o encode op 1027) (bytes 3 4)))
(let ([o (make-object NumberT 'UInt16 'BE)]
8 years ago
[ip (open-input-bytes (bytes 1 2 3 4))]
[op (open-output-bytes)])
(check-equal? (send o decode ip) 258) ;; 0100 0000 1000 0000
8 years ago
(check-equal? (send o decode ip) 772) ;; 0010 0000 1100 0000
(check-equal? (send o encode op 258) (bytes 1 2))
(check-equal? (send o encode op 772) (bytes 3 4))))
(test-module
(check-equal? (send (make-object NumberT 'UInt8) size) 1)
(check-equal? (send (make-object NumberT 'UInt32) size) 4)
(check-equal? (send (make-object NumberT 'Double) size) 8))