a codec for CTCS Balise Telegram.
一個報文中存可能存在多個用戶信息包,而若能成功的爲所有用戶信息包分片,則解碼之最小單位是用戶信息包.
而分片的核心在於找到每個 Packet 的起點,這裏從用戶信息包的定義中,我們可以發現一個有用的變量:L_PACKET 。這個變量標記了該信息包的位置, 通常來說該變量是處於某個 Packet 的 (10, 23] 位.
因爲長報文也不過千位, 實在沒有並行化之必要. 所以解碼器採用線性解碼. 即從前往後以此解碼多個用戶信息包
因此我們需要一個數組, 以保存每個 Packet 之類型與長度. 該數組的目的同時還有充當緩存之用, 即避免重複解析 NID_PACKET 和 L_PACKET 兩個變量.
let l = [(21, 50), (7, 50), (141, 50), (21, 60)];
我們還需要一個指針 start_ptr = 0,其值爲數組 l 的前
流程: 讀入用戶信息包區的前 8 位從而獲得第一個 Packet 的類型. 通過 macro 預設好的長度確定其 L_PACKET 的值,即長度, 同時也等於下一個 Packet 的起點. 記入數組 l. 讀入下一個 Packet 的 NID 再找到 L_PACKET 以確定下一個 Packet 的長度記入 l... 如此循環
校驗:因爲沒有校驗碼, 我們只得通過信息結束 11111111 來判斷是否有信息錯誤. 而且我們需要一個快速的方法來校驗其合法性. 而且校驗應該在解碼之前,但要想辦法不做重複的工作.
如果一個報文是合法的, 那麼在其最後一個數據包結束之後就應該是幀結束標記. 當我們爲所有 Packet 分片之後, 從 l 之和處起連續 8 bits 就應該是 11111111. 當然我們不需要計算這個加法. 前文提到的 start_ptr 就是累加器.
這個校驗應該在正式解碼之前完成. 如果校驗失敗,那麼說明輸入非法. 直接 panic!
關於宏: 本案中宏的作用十分巨大. 爲每一個 Packet 的變量增加 meta 信息, 同時使用 Derive 宏實現上述算法.
對於如何解析變量含義的問題. 需要從 i18n 中讀入
在 CTCS 中, Packet 44 中寄生着 CTCS 用戶信息包. 因此 Packet 44 不能用宏來實現. 需要手動實現以正確解析其中的 CTCS 包.
src: encoder & decoder 的接口 ctcsbt-cli: clap 封裝 ctcsbt-macro: 過程宏, ctcsbt-packets: 用戶信息包定義