|
|
|
#lang racket/base
|
|
|
|
(require racket/class sugar/class racket/generic racket/private/generic-methods "generic.rkt")
|
|
|
|
(require sugar/debug)
|
|
|
|
(provide (all-defined-out))
|
|
|
|
|
|
|
|
(define-generics codable
|
|
|
|
(decode codable #:parent [parent] [stream])
|
|
|
|
(encode codable [val] [stream] #:parent [parent]))
|
|
|
|
|
|
|
|
|
|
|
|
(define codable<%>
|
|
|
|
(interface* ()
|
|
|
|
([(generic-property gen:codable)
|
|
|
|
(generic-method-table gen:codable
|
|
|
|
(define (decode o [stream (current-input-port)] #:parent [parent #f]) (send o decode stream parent))
|
|
|
|
(define (encode o [val #f] [stream (current-output-port)] #:parent [parent #f]) (send o encode stream val parent)))])))
|
|
|
|
|
|
|
|
|
|
|
|
(define-generics sizable
|
|
|
|
(size sizable [val] [parent]))
|
|
|
|
|
|
|
|
(define sizable<%>
|
|
|
|
(interface* ()
|
|
|
|
([(generic-property gen:sizable)
|
|
|
|
(generic-method-table gen:sizable
|
|
|
|
(define (size o [val #f] [parent #f]) (send o size val parent)))])))
|
|
|
|
|
|
|
|
|
|
|
|
(define-generics dumpable
|
|
|
|
(dump dumpable))
|
|
|
|
|
|
|
|
(define dumpable<%>
|
|
|
|
(interface* ()
|
|
|
|
([(generic-property gen:dumpable)
|
|
|
|
(generic-method-table gen:dumpable
|
|
|
|
(define (dump o) (send o dump)))])))
|
|
|
|
|
|
|
|
|
|
|
|
(define xenomorph-base%
|
|
|
|
(class* object% (codable<%> sizable<%> dumpable<%>)
|
|
|
|
(super-new)
|
|
|
|
(field [_hash (make-hash)]
|
|
|
|
[_list null])
|
|
|
|
|
|
|
|
(define/pubment (decode port [parent #f])
|
|
|
|
(when parent (unless (indexable? parent)
|
|
|
|
(raise-argument-error 'Xenomorph "indexable" parent)))
|
|
|
|
(define ip (cond
|
|
|
|
[(bytes? port) (open-input-bytes port)]
|
|
|
|
[(input-port? port) port]
|
|
|
|
[else (raise-argument-error 'Xenomorph "bytes or input port" port)]))
|
|
|
|
(post-decode (inner (void) decode ip parent)))
|
|
|
|
|
|
|
|
(define/pubment (encode port val-in [parent #f])
|
|
|
|
#;(report* port val-in parent)
|
|
|
|
(define val (pre-encode val-in))
|
|
|
|
(when parent (unless (indexable? parent)
|
|
|
|
(raise-argument-error 'Xenomorph "indexable" parent)))
|
|
|
|
(define op (cond
|
|
|
|
[(output-port? port) port]
|
|
|
|
[(not port) (open-output-bytes)]
|
|
|
|
[else (raise-argument-error 'Xenomorph "output port or #f" port)]))
|
|
|
|
(define encode-result (inner (void) encode op val parent))
|
|
|
|
(when (bytes? encode-result)
|
|
|
|
(write-bytes encode-result op))
|
|
|
|
(when (not port) (get-output-bytes op)))
|
|
|
|
|
|
|
|
(define/pubment (size [val #f] [parent #f])
|
|
|
|
(when parent (unless (indexable? parent)
|
|
|
|
(raise-argument-error 'Xenomorph "indexable" parent)))
|
|
|
|
(define result (inner (void) size val parent))
|
|
|
|
(when result (unless (and (integer? result) (not (negative? result)))
|
|
|
|
(raise-argument-error 'Xenomorph "integer" result)))
|
|
|
|
result)
|
|
|
|
|
|
|
|
(define/public (post-decode val) val)
|
|
|
|
(define/public (pre-encode val) val)
|
|
|
|
(define/public (dump) (void))))
|
|
|
|
|
|
|
|
(define-class-predicates xenomorph-base%)
|
|
|
|
|
|
|
|
(define-subclass xenomorph-base% (RestructureBase))
|
|
|
|
(define-subclass RestructureBase (Streamcoder))
|
|
|
|
|