我正在寫一個相當簡單的二進制協議的Ragel機器,我在這裏展示的是甚至更簡化的版本,沒有任何錯誤恢復,只是爲了演示問題,試圖解決。Ragel:避免「when」子句功能的多餘調用
所以,這裏要解析的消息是這樣的:
<1 byte: length> <$length bytes: user data> <1 byte: checksum>
整機看起來如下:
%%{
machine my_machine;
write data;
alphtype unsigned char;
}%%
%%{
action message_reset {
/* TODO */
data_received = 0;
}
action got_len {
len = fc;
}
action got_data_byte {
/* TODO */
}
action message_received {
/* TODO */
}
action is_waiting_for_data {
(data_received++ < len);
}
action is_checksum_correct {
1/*TODO*/
}
len = (any);
fmt_separate_len = (0x80 any);
data = (any);
checksum = (any);
message =
(
# first byte: length of the data
(len @got_len)
# user data
(data when is_waiting_for_data @got_data_byte)*
# place higher priority on the previous machine (i.e. data)
<:
# last byte: checksum
(checksum when is_checksum_correct @message_received)
) >to(message_reset)
;
main := (msg_start: message)*;
# Initialize and execute.
write init;
write exec;
}%%
正如你看到的,首先我們收到代表長度1個字節;那麼我們將收到data
字節,直到我們收到所需的字節數(檢查由is_waiting_for_data
完成),當我們收到下一個(額外)字節時,我們檢查它是否是正確的校驗和(由is_checksum_correct
)。如果是,機器將等待下一條消息;否則,該特定的機器停止(我在這裏沒有包含任何錯誤恢復,以簡化圖)。
它的示意圖如下所示:
$ ragel -Vp ./msg.rl | dot -Tpng -o msg.png
正如你看到的,在狀態1,當我們接收用戶數據,條件如下:
0..255(is_waiting_for_data, !is_checksum_correct),
0..255(is_waiting_for_data, is_checksum_correct)
因此,在每個數據字節中,它冗餘地調用is_checksum_correct
,儘管結果根本不重要。
條件應儘可能簡單:0..255(is_waiting_for_data)
如何實現這一目標?