2011-04-28 82 views
10

我正在編寫代碼來解碼來自二進制協議的消息。每個消息類型被分配一個1字節的類型標識符,每個消息攜帶這個類型標識符。消息全部以由5個字段組成的公共頭開始。我的API很簡單:Erlang模式匹配bitstrings

decoder:decode(Bin :: binary()) -> my_message_type() | {error, binary()}` 

我的第一本能是通過寫一個解碼功能爲每個郵件類型倚重模式匹配,並以該消息類型的樂趣參數

decode(<<Hdr1:8, ?MESSAGE_TYPE_ID_X:8, Hdr3:8, Hdr4:8, Hdr5:32, 
     TypeXField1:32, TypeXFld2:32, TypeXFld3:32>>) -> 
    #message_x{hdr1=Hdr1, hdr3=Hdr3 ... fld4=TypeXFld3}; 

decode(<<Hdr1:8, ?MESSAGE_TYPE_ID_Y:8, Hdr3:8, Hdr4:8, Hdr5:32, 
     TypeYField1:32, TypeYFld2:16, TypeYFld3:4, TypeYFld4:32 
     TypeYFld5:64>>) -> 
    #message_y{hdr1=Hdr1, hdr3=Hdr3 ... fld5=TypeYFld5}. 

注完全解碼儘管消息的前5個字段在結構上是相同的,但其後的字段對於每種消息類型都不相同。

我有大約20個消息類型,因此20個函數類似於上面。我是用這種結構多次解碼完整的信息嗎?這是慣用的嗎?我只能解碼函數頭中的消息類型字段,然後解碼消息正文中的完整消息嗎?

+0

元問題:當我編輯這篇文章時,我在預覽中獲得了不錯的erlang代碼着色,但是在我發佈後,在渲染頁面中沒有。幫幫我? – mpm 2011-04-28 02:40:40

+0

在發佈erlang代碼時也注意到了這一點,可能是meta – 2011-04-28 11:08:20

+1

的問題在meta上發佈了關於語法着色的問題http://meta.stackexchange.com/questions/89117/why-do-i-get-nice-erlang -syntax-coloring-in-preiviev-but-in-the-rendered-page – 2011-04-28 14:11:54

回答

8

只是同意你的風格是非常習慣的Erlang。除非您覺得代碼更清晰,否則不要將代碼拆分爲單獨的部分。有時做這種類型的分組可能更合乎邏輯。

編譯器很聰明,編譯模式匹配的方式是它不會多次解碼消息。它將首先解碼前兩個字段(字節),然後使用第二個字段(消息類型)的值來確定如何處理消息的其餘部分。無論二進制文件的公共部分多長時間,這都可以工作。

因此,他們不需要嘗試和「幫助」編譯器通過拆分解碼成單獨的部分,它不會使它更有效。再次,只有在代碼更清晰的情況下才能做到這一點。

+0

正是我需要聽到的重新編譯優化。該代碼確實更清晰,因爲它目前是結構化的。謝謝,羅布。 – mpm 2011-04-29 00:00:50

7

你目前的做法是慣用的Erlang,所以繼續往這個方向走。不要擔心性能,Erlang編譯器在這裏做的很好。如果你的消息是完全一樣的格式,你可以爲它寫宏,但它應該生成相同的代碼。無論如何,使用宏通常會導致更差的可維護性。只是爲了好奇,當所有的字段完全相同時,爲什麼你會生成不同的記錄類型?另一種方法是將消息類型從常量轉換爲Erlang原子並將其存儲在一個記錄類型中。

+1

我其次。如果您沒有簡化帖子的結構並且記錄都具有相同的格式,請使用atom來區分記錄類型 - 一個函數和一個erlang記錄定義。 – 2011-04-28 14:24:19

+1

對不起 - 我在代碼中過分簡化了。在前5個字段之後,消息是不相似的。我已經更新了代碼示例,以表明兩個消息TypeX和TypeY具有不同數量的字段和不同的字段結構。對困惑感到抱歉。 – mpm 2011-04-28 14:58:48

+1

@mpm:那麼你的代碼就完全匹配了Elang的成語。對於閱讀代碼通常更難跟隨代碼流「匹配這個然後匹配這個然後這個」比看這裏是一種類型的消息和另一種類型的消息。長期維護更好。在項目非常早期階段之後,您將閱讀越來越多的補丁,並且初始假設可能會發生巨大變化。今天消息的常見問題不可能出現在蛾年或者年代,每一次這樣的改變都會導致更多的代碼改變來進行級聯匹配,而不是你目前的方法。 – 2011-04-28 20:29:34