Last night I had an idea about a possable pack API. Most likely when Pugs gets signifigently powerfull I will attempt to implement it. However I would like everyones input, below is a draft of its POD.
=head1 NAME Pack - (un)pack structures as defined by a Template =head1 SYNOPSIS my Pack $template = Pack::compile {uint8 rat32}; my $string = pack($template, 244, 3.14); my @unpack = unpack($template, $string); =head1 ABSTRACT This perl library defines a declarative minilanuage that allows the conversion of Perl6 variables into (and from) a string of bytes. =head1 DESCRIPTION =head2 MACROS and SUBS macro Pack::compile ($template) is parsed (/\{ <Pack.template> \}/) {...} This macro is used to compile a template at compile time. This may throw a execution at compile time if there is an error in the template. sub Pack::eval (Str $template) returns Pack {...} And this sub will compile a template at runtime. This may return undef and set $! if there is an error in the template. sub Pack::pack (Pack $template,[EMAIL PROTECTED]) returns Str of byte {...} This function takes a [EMAIL PROTECTED] of ordinary Perl values and converts them into a string of bytes according to the $template. If you procide more arguments then $template requires, the extra arguments are ignored. sub Pack::pack (Str $template,[EMAIL PROTECTED]) returns Str of byte {...} A convenience function, $template is compiled into a Pack object and then run on @list; sub Pack::unpack (Pack $template,Str of byte $expr) returns List {...} sub Pack::unpack (Str $template,Str of byte $expr) returns List {...} These functions do the reverse of Pack::pack =head2 THE PACK TEMPLATE DESCRIPTION LANGUAGE (PTDL) =head3 SYNTAX The template description language describes the structure of the string as a sequence of declarations. Each declaration consists of a type, an optional argument and zero or more adjectives. Also each declaration may be bound to a variable. grammar { rule template :w { [<binding>? <declaration>]* }; rule binding :w { [<Perl6.variable> | <Perl6.literal>] <":=:"> } rule declaration :w { [\: <adjective>]* <Perl6.name> [\( <argument> \)]? } rule adjective :w { <Perl6.name> [\( <argument> \)]? } rule argument :w { <Perl6.variable> | <Perl6.closure> | <Perl6.literal> } } For example the following are valid templates $^0 :=: byte @^_ :=: str(8) @^_ :=: str($^0) $^1 :=: rat32 =head3 SEMANTICS When packing if a declaration is bound to a scalar variable then the contents of that variable are packed into the return value of pack according to the nature of that declaration. Simmerly when unpacking each declaration will set the value of the scalar it is bound to based on its nature and the value of $expr. $^number has a special meaning in PTDL $^i is the ith (zero indexed) item of @list when packing and the ith (zero indexed) item of the return array when unpacking. If a declaration is bound to an array, when packing items will be shifted out of the array and then packed according to the declaration. Simmerly when unpacking the array will have the declaration's return values pushed into it. @^_ has a special meaning in PTDL. It is an alias to @list when packing and an alias to the return array when unpacking. By default a declaration is bound to @^_ . If a declaration is bound to a literal then when packing the value of that literal is packed, when unpacking the unpacked value is discarded. The following declarations are built in. int1 int2 int4 int8 int16 int32 (aka int on 32-bit machines) int64 (aka int on 64-bit machines) uint1 (aka bit) (like vec) uint2 uint4 uint8 (aka byte) uint16 uint32 uint64 rat32 rat64 (aka rat on most architectures) rat128 str A string of bytes utf8 A number encoded using the utf8 mapping (doesn't check for bad unicode) UTF-8 A codepoint endcoded using UTF-8 noop Does nothing (though its adjectives may have side effects) hex A hexadecimal string uuencode A uuencoded string base64 A base64 encoded string base32 A base32 encoded string base16 A base16 encoded string ber A ber compressed integer The following adjectives are built in. :bigend Endcode this using bigendian order :litend Endcode this using littleendian order :pad($n) Pad to $n bytes :padchar($char) Pad using $char :term($char) String is $char terminated :mvabs Move to absolute position filling with padchar if defined. :mvrel Move to relative position filling with padchar if defined. For convenience the following declarations are defined. a($n) => :pad($n) :padchar("\x00") byte A($n) => :pad($n) :padchar(" ") byte b($n) => :bigend bit($n) B($n) => :litend bit($n) c => int8 C => uint8 d => rat64 f => rat32 h => :bigend hex H => :litend hex i => int I => uint l => int32 L => uint32 n => :bigend int16 N => :bigend int32 q => int64 Q => uint64 s => int16 S => uint16 u => uuencode U => UTF-8 v => :litend int16 V => :litend int32 w => ber x => :pad(1) :padchar("\x00") noop X => :mvrel(-1) noop Z($n) => :term("\x00") :pad($n) :padchar("\x00") byte @($n) => :mvabs($n) :padchar("\x00") noop For convenience the following adjectives are defined :network => :bigend :vax => :litend =cut -- Please excuse my spelling as I suffer from agraphia. See http://dformosa.zeta.org.au/~dformosa/Spelling.html to find out more. Free the Memes.