nrk (owner)

Revisions

gist: 133246 Download_button fork
public
Description:
Dead-simple bencoding using the Io language
Public Clone URL: git://gist.github.com/133246.git
bencode.io
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# See http://en.wikipedia.org/wiki/Bencode for reference
 
 
# encoding objects
 
Number asBencode := method(
    Sequence with("i", self asString, "e")
)
 
Sequence asBencode := method(
    Sequence with(self size asString, ":", self)
)
 
List asBencode := method(
    Sequence with("l", self map(value, value asBencode) join, "e")
)
 
Map asBencode := method(
    Sequence with("d", self keys sort map(key, key asBencode .. self at(key) asBencode) join, "e")
)
 
 
# decoding from string
 
Sequence fromBencode := method(
    offset := 0
 
    endOfCollection := block(
        if (self at(offset) asCharacter == "e", offset = offset + 1)
    )
 
    decodeMap := block(
        map := Map clone
        while (true,
            if (endOfCollection call, break)
            map atPut(decode call, decode call)
        )
        map
    )
 
    decodeList := block(
        collection := List clone
        while (true,
            if (endOfCollection call, break)
            collection append(decode call)
        )
        collection
    )
 
    decodeNumber := block(delimiter,
        delimiter ifNil(delimiter := "e")
        number := Sequence clone
 
        while ((digit := self at(offset) asCharacter) != delimiter,
            number appendSeq(digit)
            offset = offset + 1
        )
 
        offset = offset + 1
        number asNumber
    )
 
    decodeString := block(
        offset = offset - 1
        stringSize := decodeNumber call(":")
        self exSlice(offset, (offset = offset + stringSize))
    )
 
    decodingMap := Map with(
        "d", decodeMap,
        "l", decodeList,
        "i", decodeNumber,
        "0", decodeString,
        "1", decodeString,
        "2", decodeString,
        "3", decodeString,
        "4", decodeString,
        "5", decodeString,
        "6", decodeString,
        "7", decodeString,
        "8", decodeString
    )
 
    decode := block(
        char := self at(offset) asCharacter
        offset = offset + 1
        decodingMap at(char)? call
    )
 
    decode call
)