aboutsummaryrefslogtreecommitdiff
path: root/cmd/mybittorrent/decoder.go
diff options
context:
space:
mode:
authorjet2tlf <jet2tlf@gmail.com>2024-06-03 17:43:29 +0000
committerjet2tlf <jet2tlf@gmail.com>2024-06-03 17:43:29 +0000
commit6091bea631659a2e5d152726f3581ca2d1bd235c (patch)
tree92656f5f79641d3c187ce8e82c128da4de2a252c /cmd/mybittorrent/decoder.go
parent7cff8936edbdc7ce7c0ca41eab2f8d5470cad2e6 (diff)
downloadbittorrent-go-6091bea631659a2e5d152726f3581ca2d1bd235c.tar.gz
bittorrent-go-6091bea631659a2e5d152726f3581ca2d1bd235c.zip
codecrafters submit [skip ci]
Diffstat (limited to 'cmd/mybittorrent/decoder.go')
-rw-r--r--cmd/mybittorrent/decoder.go140
1 files changed, 0 insertions, 140 deletions
diff --git a/cmd/mybittorrent/decoder.go b/cmd/mybittorrent/decoder.go
deleted file mode 100644
index 641b042..0000000
--- a/cmd/mybittorrent/decoder.go
+++ /dev/null
@@ -1,140 +0,0 @@
-package main
-
-import (
- "fmt"
- "strconv"
- "strings"
- "unicode"
-)
-
-type Decoder struct {
- raw string
- decoderFuncs []DecoderFunc
-}
-
-type DecoderFunc func(string) (any, int, error)
-
-func NewDecoder(raw string) *Decoder {
- d := &Decoder{raw: raw}
- return d.WithDecoderFunc(d.decodeSlice).WithDecoderFunc(d.decodeMap).WithDecoderFunc(d.decodeString).WithDecoderFunc(d.decodeInteger)
-}
-
-func (d *Decoder) WithDecoderFunc(f DecoderFunc) *Decoder {
- d.decoderFuncs = append(d.decoderFuncs, f)
- return d
-}
-
-func (d *Decoder) Decode() (any, error) {
- for _, f := range d.decoderFuncs {
- if r, l, err := f(d.raw); l > 0 || err != nil {
- return r, nil
- }
- }
-
- return nil, fmt.Errorf("failed to decode value: %s", d.raw)
-}
-
-func (d *Decoder) decodeString(chunk string) (any, int, error) {
- if !unicode.IsDigit(rune(chunk[0])) {
- return "", 0, nil
- }
-
- var firstColonIndex int
-
- for i := 0; i < len(chunk); i++ {
- if chunk[i] == ':' {
- firstColonIndex = i
- break
- }
- }
-
- lengthStr := chunk[:firstColonIndex]
-
- length, err := strconv.Atoi(lengthStr)
- if err != nil {
- return "", 0, err
- }
-
- val := chunk[firstColonIndex+1 : firstColonIndex+1+length]
-
- return val, length + 1 + len(lengthStr), nil
-}
-
-func (d *Decoder) decodeInteger(chunk string) (any, int, error) {
- if rune(chunk[0]) != 'i' {
- return 0, 0, nil
- }
-
- num, err := strconv.Atoi(chunk[1:strings.IndexByte(chunk, 'e')])
- if err != nil {
- return 0, 0, err
- }
-
- return num, len(strconv.Itoa(num)) + 2, nil
-}
-
-func (d *Decoder) decodeSlice(chunk string) (any, int, error) {
- if rune(chunk[0]) != 'l' {
- return nil, 0, nil
- }
-
- if rune(chunk[1]) == 'e' {
- return []any{}, 2, nil
- }
-
- result := make([]any, 0, 32)
- offset := 1
-
- for rune(chunk[offset]) != 'e' {
- for _, f := range d.decoderFuncs {
- if v, l, err := f(chunk[offset:]); l > 0 {
- if err != nil {
- return nil, 0, err
- }
- result = append(result, v)
- offset += l
- break
- }
- }
- }
-
- return result, offset + 1, nil
-}
-
-func (d *Decoder) decodeMap(chunk string) (any, int, error) {
- if rune(chunk[0]) != 'd' {
- return nil, 0, nil
- }
-
- if rune(chunk[1]) == 'e' {
- return map[string]any{}, 2, nil
- }
-
- result := make(map[string]any, 32)
- offset := 1
-
- for rune(chunk[offset]) != 'e' {
- key, keyLen, err := d.decodeString(chunk[offset:])
- if err != nil {
- return nil, 0, err
- }
-
- if keyLen == 0 {
- return nil, 0, fmt.Errorf("invalid bencoded map key length")
- }
-
- for _, f := range d.decoderFuncs {
- if v, l, err := f(chunk[offset+keyLen:]); l > 0 {
- if err != nil {
- return nil, 0, err
- }
-
- result[key.(string)] = v
- offset += keyLen + l
- break
- }
- }
- }
-
- return result, offset + 1, nil
-}