Skip to content

Instantly share code, notes, and snippets.

@yllan
Last active December 23, 2019 10:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yllan/6560703536303d9a501246423e7c8d4b to your computer and use it in GitHub Desktop.
Save yllan/6560703536303d9a501246423e7c8d4b to your computer and use it in GitHub Desktop.
My Hack for declarative resumable parsing

前提: Syntax很簡單,不用look ahead,而且都會知道要讀多少byte(沒有那種「讀到0x00為止」)

我的作法看起來長這樣:

const msgParser = expect([10, 10, 20], (datetime, messageType, messageID) => {
    switch (messageType) {
        case "HI":
            expect([10, 10], (senderID, senderName) => {
                // connect
            })
            break
        case "Message":
            expect([4], (messageLength) => {
                expect([messageLength], (message) => {
                    // 
                })
            })
            break
        case "File":
            expect([10, 4], (fileName, fileLength) => {
                expect([fileLength], (fileBytes) => {
                    // save the file
                })
            })
            break
        case "Sticker":
            // ...
            break
    }
})

這個 expect 會接收一個 length array 和 callback function。 expect([10, 20], (a, b) => {}) 代表說讀 30 bytes, 前 10 byte 當成第一個參數,後 20 bytes 當成第二個參數傳給 callback。

這個 expect 做的事是:

  1. 把總共要讀多少 byte 算出來,存在一個 global variable (or instance variable) 叫 expectLength
  2. 把一個 lambda 存在 parsingFunction。這個 lambda 負責把 buffer 切下 expectLength,按照長度丟給 callback。

其實可以想像 expect 成「install要用哪個parser」。

實際上程式要動起來,必須寫另外一個 feed(),負責看之前剩下的buffer和餵進來的data有沒有到expectLength, 有的話呼叫 parsingFunction,切 buffer 之類的 housekeeping。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment