[Gd-chatter] r11634 - in trunk/libraries/packetizer: . packetizer-test
hannes at gwydiondylan.org
hannes at gwydiondylan.org
Fri Jan 18 03:19:33 CET 2008
Author: hannes
Date: Fri Jan 18 03:19:32 2008
New Revision: 11634
Modified:
trunk/libraries/packetizer/fields.dylan
trunk/libraries/packetizer/module.dylan
trunk/libraries/packetizer/packetizer-test/packetizer-test.dylan
trunk/libraries/packetizer/packetizer.dylan
trunk/libraries/packetizer/protocol-definer-macro.dylan
Log:
Bug: 7299
implement enum fields
Modified: trunk/libraries/packetizer/fields.dylan
==============================================================================
--- trunk/libraries/packetizer/fields.dylan (original)
+++ trunk/libraries/packetizer/fields.dylan Fri Jan 18 03:19:32 2008
@@ -103,6 +103,10 @@
define class <layering-field> (<single-field>)
end;
+define class <enum-field> (<single-field>)
+ slot mappings, required-init-keyword: mappings:;
+end;
+
define method static-field-size (field :: <single-field>) => (res :: <integer-or-unknown>)
if (field.static-length ~= $unknown-at-compile-time)
field.static-length
Modified: trunk/libraries/packetizer/module.dylan
==============================================================================
--- trunk/libraries/packetizer/module.dylan (original)
+++ trunk/libraries/packetizer/module.dylan Fri Jan 18 03:19:32 2008
@@ -139,7 +139,8 @@
export protocol-definer;
//XXX: we shouldn't need to export those
export real-class-definer, decoded-class-definer, gen-classes,
- frame-field-generator, summary-generator, unparsed-frame-field-generator;
+ frame-field-generator, summary-generator, enum-frame-field-generator,
+ unparsed-frame-field-generator;
export protocol-module-definer;
end module packetizer;
Modified: trunk/libraries/packetizer/packetizer-test/packetizer-test.dylan
==============================================================================
--- trunk/libraries/packetizer/packetizer-test/packetizer-test.dylan (original)
+++ trunk/libraries/packetizer/packetizer-test/packetizer-test.dylan Fri Jan 18 03:19:32 2008
@@ -430,10 +430,11 @@
check-equal("assembling of dynlength[1] works correct", 2, as.packet[1]);
let g = make(<dyn-length-in-container>, mylength: 3);
let as = assemble-frame(g);
+ //for now, I assume that padding does not need to work here this way
+ //somehow, we should be able to add padding-frames to dynamically
+ //length fields -- any takers on a pad api? -- Hannes, 18.1.2008
check-equal("assembly of dynlength[0] works correct", 0, as.packet[0]);
- //hah, no padding support!
check-equal("assembly of dynlength[1] works correct", 3, as.packet[1]);
- check-equal("assembly of dynlength[2] works correct", 0, as.packet[2]);
end;
define protocol dyn-length-as-client-field (container-frame)
@@ -459,28 +460,31 @@
end;
define protocol enum-field-test (container-frame)
- enum field foo :: <unsigned-byte>,
+ enum field foobar :: <unsigned-byte>,
mappings: { 1 <=> #"hello",
2 <=> #"foobar" };
end;
define test enum-assemble-test ()
- let frame = make(<enum-field-test>, foo: #"hello");
+ let frame = make(<enum-field-test>, foobar: #"hello");
+ check-equal("enum field value", #"hello", frame.foobar);
let assembled-frame = assemble-frame(frame);
check-equal("enum field value", 1, assembled-frame.packet[0]);
- assembled-frame.foo := #"foobar";
+ assembled-frame.foobar := #"foobar";
check-equal("enum field value", 2, assembled-frame.packet[0]);
- assembled-frame.foo := 23;
+ assembled-frame.foobar := 23;
check-equal("enum field value", 23, assembled-frame.packet[0]);
end;
define test enum-parse-test ()
let f = parse-frame(<enum-field-test>, #[#x01]);
- check-equal("enum field parses correct to symbol", #"hello", f.foo);
+ check-equal("enum field parses correct to symbol", #"hello", f.foobar);
let g = parse-frame(<enum-field-test>, #[#x03]);
- check-equal("enum field parses correct to integer", 3, g.foo);
- g.foo := #"foobar";
- g.foo := 23;
+ check-equal("enum field parses correct to integer", 3, g.foobar);
+ g.foobar := 23;
+ check-equal("enum field parses correct to changed integer", 23, g.foobar);
+ g.foobar := #"foobar";
+ check-equal("enum field parses correct to changed symbol", #"foobar", g.foobar);
end;
define suite packetizer-suite ()
@@ -525,7 +529,7 @@
end;
begin
- run-test-application(packetizer-suite, arguments: #("-debug"));
- run-test-application(packetizer-assemble-suite, arguments: #("-debug"));
+ run-test-application(packetizer-suite); //, arguments: #("-debug"));
+ run-test-application(packetizer-assemble-suite); //, arguments: #("-debug"));
end;
Modified: trunk/libraries/packetizer/packetizer.dylan
==============================================================================
--- trunk/libraries/packetizer/packetizer.dylan (original)
+++ trunk/libraries/packetizer/packetizer.dylan Fri Jan 18 03:19:32 2008
@@ -528,6 +528,19 @@
frame.packet.size * 8;
end;
+define method assemble-field-into(field :: <enum-field>,
+ frame :: <container-frame>,
+ packet :: <stretchy-vector-subsequence>)
+ let value = field.getter(frame);
+ if (instance?(value, <symbol>))
+ value := enum-field-symbol-to-int(field, value)
+ end;
+ let length = assemble-aux(field.type, value, packet);
+ let ff = make(<frame-field>, field: field, frame: frame, length: length);
+ frame.concrete-frame-fields[field.index] := ff;
+ length;
+end;
+
define method assemble-field-into(field :: <single-field>,
frame :: <container-frame>,
packet :: <stretchy-vector-subsequence>)
Modified: trunk/libraries/packetizer/protocol-definer-macro.dylan
==============================================================================
--- trunk/libraries/packetizer/protocol-definer-macro.dylan (original)
+++ trunk/libraries/packetizer/protocol-definer-macro.dylan Fri Jan 18 03:19:32 2008
@@ -32,6 +32,25 @@
end;
+define inline function filter-enums!(key/value-pairs :: <collection>,
+ fields :: <collection>)
+ for (ele in fields)
+ if (instance?(ele, <enum-field>))
+ let (key, pos)
+ = block(ret)
+ for (i :: <integer> from 0 below key/value-pairs.size by 2)
+ if (key/value-pairs[i] == ele.field-name)
+ ret(values(key/value-pairs[i + 1], i + 1))
+ end;
+ end;
+ end;
+
+ key/value-pairs[pos] := enum-field-symbol-to-int(ele, key);
+ end;
+ end;
+end;
+
+
define macro real-class-definer
{ real-class-definer(?attrs:*; ?:name; ?superclasses:*; ?fields-aux:*) }
=> { define abstract class ?name (?superclasses)
@@ -95,6 +114,7 @@
end;
end;
define method make (class == ?name, #rest rest, #key, #all-keys) => (res :: ?name)
+ filter-enums!(rest, "$" ## ?name ## "-fields");
let frame = apply(make, decoded-class(?name), rest);
for (field in fields(frame))
if (field.getter(frame) = #f)
@@ -153,6 +173,7 @@
{ } => { <single-field> }
{ layering } => { <layering-field> }
{ repeated } => { <repeated-field> }
+ { enum } => { <enum-field> }
args: //FIXME: better types, not <frame>!
{ } => { }
@@ -176,6 +197,13 @@
=> { static-length: ?length, ... }
{ static-end: ?end:expression, ... }
=> { static-end: ?end, ... }
+ { mappings: { ?mappings }, ... }
+ => { mappings: #( ?mappings ), ... }
+
+ mappings:
+ { } => { }
+ { ?key:expression <=> ?value:expression, ... }
+ => { ?key, ?value, ... }
end;
@@ -194,6 +222,9 @@
{ repeated field ?:name ?rest:* }
=> { slot ?name :: false-or(<collection>) = #f,
init-keyword: ?#"name" }
+ { enum field ?:name \:: ?field-type:name ?rest:* }
+ => { slot "%" ## ?name :: false-or(high-level-type(?field-type)) = #f,
+ init-keyword: ?#"name" }
{ ?attrs:* field ?:name \:: ?field-type:name ?rest:* }
=> { slot ?name :: false-or(high-level-type(?field-type)) = #f,
init-keyword: ?#"name" }
@@ -246,6 +277,55 @@
}
end;
+define inline function enum-field-symbol-to-int
+ (field :: <enum-field>, key :: <symbol>) => (res :: <integer>)
+ block(ret)
+ for (i from 1 below field.mappings.size by 2)
+ if (field.mappings[i] == key)
+ ret(field.mappings[i - 1])
+ end;
+ end;
+ error("unknown symbol for enum field");
+ end;
+end;
+
+define macro enum-frame-field-generator
+ { enum-frame-field-generator(?:name,
+ "<unparsed-" ## ?frame-type:name,
+ ?field-index:expression) }
+ => { define inline method ?name (mframe :: "<decoded-" ## ?frame-type) => (res)
+ let field = fields(mframe)[?field-index];
+ let val = "%" ## ?name (mframe);
+ block(ret)
+ for (i from 0 below field.mappings.size by 2)
+ if (field.mappings[i] == val)
+ ret(field.mappings[i + 1])
+ end;
+ end;
+ val
+ end;
+ end;
+ define inline method ?name ## "-setter"
+ (value :: <symbol>, mframe :: "<decoded-" ## ?frame-type) => (res)
+ let field = fields(mframe)[?field-index];
+ let val :: <integer> = enum-field-symbol-to-int(field, value);
+ "%" ## ?name ## "-setter"(val , mframe);
+ end;
+ define inline method ?name ## "-setter"
+ (value :: false-or(<integer>),
+ mframe :: "<decoded-" ## ?frame-type) => (res)
+ "%" ## ?name ## "-setter"(value, mframe);
+ end;
+ define inline method ?name ## "-setter"
+ (value :: <symbol>, mframe :: "<unparsed-" ## ?frame-type) => (res)
+ let field = fields(mframe)[?field-index];
+ let val :: <integer> = enum-field-symbol-to-int(field, value);
+ ?name ## "-setter" (val, mframe)
+ end;
+ }
+end;
+
+
define method parse-frame-field
(frame-field :: <frame-field>)
=> (res, length);
@@ -433,7 +513,17 @@
end;
define macro frame-field-generator
- { frame-field-generator(?type:name; ?count:expression; ?args:* field ?field-name:name ?foo:* ; ?rest:*) }
+ { frame-field-generator(?type:name; ?count:expression; enum field ?field-name:name ?foo:* ; ?rest:*) }
+ => { enum-frame-field-generator(?field-name, ?type, ?count);
+ unparsed-frame-field-generator(?field-name, ?type, ?count);
+ frame-field-generator(?type; ?count + 1; ?rest) }
+ { frame-field-generator(?type:name; ?count:expression; repeated field ?field-name:name ?foo:* ; ?rest:*) }
+ => { unparsed-frame-field-generator(?field-name, ?type, ?count);
+ frame-field-generator(?type; ?count + 1; ?rest) }
+ { frame-field-generator(?type:name; ?count:expression; layering field ?field-name:name ?foo:* ; ?rest:*) }
+ => { unparsed-frame-field-generator(?field-name, ?type, ?count);
+ frame-field-generator(?type; ?count + 1; ?rest) }
+ { frame-field-generator(?type:name; ?count:expression; field ?field-name:name ?foo:* ; ?rest:*) }
=> { unparsed-frame-field-generator(?field-name, ?type, ?count);
frame-field-generator(?type; ?count + 1; ?rest) }
{ frame-field-generator(?type:name; ?count:expression; variably-typed-field ?field-name:name ?foo:* ; ?rest:*) }
More information about the chatter
mailing list