main
Matthew Butterick 5 years ago
parent ee21fdd131
commit db778a162a

@ -1,5 +1,10 @@
#lang racket/base
(require racket/class racket/match "base.rkt" racket/list)
(require racket/class
racket/match
"base.rkt"
"int.rkt"
racket/contract
racket/list)
(provide (all-defined-out))
#|
@ -12,14 +17,17 @@ https://github.com/mbutterick/restructure/blob/master/src/Enum.coffee
(super-new)
(init-field [(@type type)] [(@values values)])
(unless (xenomorphic-type? @type)
(raise-argument-error 'x:enum "xenomorphic type" @type))
(unless (x:int? @type)
(raise-argument-error 'x:enum "xenomorphic integer type" @type))
(unless (list? @values)
(raise-argument-error 'x:enum "list of values" @values))
(define/augment (x:decode port parent)
(define index (send @type x:decode port parent))
(or (list-ref @values index) index))
(if (< index (length @values))
(or (list-ref @values index) index)
index))
(define/augment (x:encode val port [parent #f])
(match (index-of @values val)
@ -29,12 +37,25 @@ https://github.com/mbutterick/restructure/blob/master/src/Enum.coffee
(define/augment (x:size [val #f] [parent #f])
(send @type x:size val parent))))
(define (x:enum [type-arg #f] [values-arg #f]
#:type [type-kwarg #f]
#:values [values-kwarg #f]
#:pre-encode [pre-proc #f]
#:post-decode [post-proc #f]
#:base-class [base-class x:enum%])
(define (x:enum? x) (is-a? x x:enum%))
(define/contract (x:enum [type-arg #f]
[values-arg #f]
#:type [type-kwarg #f]
#:values [values-kwarg #f]
#:pre-encode [pre-proc #f]
#:post-decode [post-proc #f]
#:base-class [base-class x:enum%])
(()
((or/c x:int? #false)
(listof any/c)
#:type (or/c x:int? #false)
#:values (listof any/c)
#:pre-encode (or/c (any/c . -> . any/c) #false)
#:post-decode (or/c (any/c . -> . any/c) #false)
#:base-class (λ (c) (subclass? c x:enum%)))
. ->* .
x:enum?)
(define type (or type-arg type-kwarg))
(define values (or values-arg values-kwarg))
(new (generate-subclass base-class pre-proc post-proc) [type type] [values values]))

@ -1155,6 +1155,68 @@ Generate an instance of @racket[x:bitfield%] (or a subclass of @racket[x:bitfiel
@defmodule[xenomorph/enum]
An @deftech{enumeration} is a mapping of values to sequential integers.
@defclass[x:enum% x:base% ()]{
Base class for list formats. Use @racket[x:enum] to conveniently instantiate new list formats.
@defconstructor[
([type x:int?]
[values (listof any/c)])]{
Create class instance that represents an enumeration format of type @racket[type], sequentially mapped to @racket[values].
}
@defmethod[
#:mode extend
(x:decode
[input-port input-port?]
[parent (or/c xenomorphic? #false)])
any/c]{
Returns either the value associated with a certain integer, or if the value is @racket[#false] or doesn't exist, then the integer itself.
}
@defmethod[
#:mode extend
(x:encode
[val any/c]
[input-port input-port?]
[parent (or/c xenomorphic? #false)])
bytes?]{
Take value listed in the @racket[_values] field and encode it as a @tech{byte string}.
}
}
@defproc[
(x:enum?
[x any/c])
boolean?]{
Whether @racket[x] is an object of type @racket[x:enum%].
}
@defproc[
(x:enum
[type-arg (or/c x:int? #false) #false]
[values-arg (listof any/c) #false]
[#:type type-kw (or/c x:int? #false) uint8]
[#:values values-kw (listof any/c) null]
[#:pre-encode pre-encode-proc (or/c (any/c . -> . any/c) #false) #false]
[#:post-decode post-decode-proc (or/c (any/c . -> . any/c) #false) #false]
[#:base-class base-class (λ (c) (subclass? c x:enum%)) x:enum%]
)
x:enum?]{
Generate an instance of @racket[x:enum%] (or a subclass of @racket[x:enum%]) with certain optional attributes.
@racket[type-arg] or @racket[type-kw] (whichever is provided, though @racket[type-arg] takes precedence) determines the integer type for the enumeration. Default is @racket[uint8].
@racket[values-arg] or @racket[values-kw] (whichever is provided, though @racket[values-arg] takes precedence) determines the mapping of values to integers, where each value corresponds to its index in the list. @racket[#false] indicates skipped values. Default is @racket[null].
@racket[pre-encode-proc] and @racket[post-decode-proc] control the pre-encoding and post-decoding procedures, respectively. Each takes as input the value to be processed and returns a new value.
@racket[base-class] controls the class used for instantiation of the new object.
}
@subsection{Optional}

@ -11,7 +11,7 @@ https://github.com/mbutterick/restructure/blob/master/test/Enum.coffee
|#
(define e (x:enum #:type uint8
#:values '("foo" "bar" "baz")))
#:values '("foo" "bar" "baz" #f)))
(test-case
"enum: should error with invalid type"
@ -27,10 +27,12 @@ https://github.com/mbutterick/restructure/blob/master/test/Enum.coffee
(test-case
"enum: decode should decode"
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 0))])
(parameterize ([current-input-port (open-input-bytes (bytes 1 2 0 3 4))])
(check-equal? (decode e) "bar")
(check-equal? (decode e) "baz")
(check-equal? (decode e) "foo")))
(check-equal? (decode e) "foo")
(check-equal? (decode e) 3)
(check-equal? (decode e) 4)))
(test-case
"enum: decode should decode with post-decode"

Loading…
Cancel
Save