blob: c77f8b45f34d87eb0aa7b3177556f03c4f9ce106 [file] [log] [blame]
22301102bc6da0a2025-06-02 17:47:29 +08001package com.pt.utils;
2
3import java.io.ByteArrayInputStream;
4import java.io.IOException;
5import java.io.InputStream;
6import java.util.*;
7
8public class BdecodeUtils {
9 public static Object decode(byte[] data) throws IOException {
10 try (ByteArrayInputStream in = new ByteArrayInputStream(data)) {
11 return decodeNext(in);
12 }
13 }
14
15 private static Object decodeNext(InputStream in) throws IOException {
16 int prefix = in.read();
17 if (prefix == -1) {
18 throw new IOException("Unexpected end of stream");
19 }
20
21 if (prefix >= '0' && prefix <= '9') {
22 // 字符串,回退一个字节给parseString处理
23 in.reset();
24 return parseString(in, prefix);
25 } else if (prefix == 'i') {
26 return parseInteger(in);
27 } else if (prefix == 'l') {
28 return parseList(in);
29 } else if (prefix == 'd') {
30 return parseDict(in);
31 } else {
32 throw new IOException("Invalid bencode prefix: " + (char) prefix);
33 }
34 }
35
36 private static String parseString(InputStream in, int firstDigit) throws IOException {
37 // 读长度前缀
38 StringBuilder lenStr = new StringBuilder();
39 lenStr.append((char) firstDigit);
40 int b;
41 while ((b = in.read()) != -1 && b != ':') {
42 lenStr.append((char) b);
43 }
44 int length = Integer.parseInt(lenStr.toString());
45
46 // 读内容
47 byte[] buf = new byte[length];
48 int read = in.read(buf);
49 if (read < length) throw new IOException("Unexpected end of stream reading string");
50 return new String(buf);
51 }
52
53 private static long parseInteger(InputStream in) throws IOException {
54 StringBuilder intStr = new StringBuilder();
55 int b;
56 while ((b = in.read()) != -1 && b != 'e') {
57 intStr.append((char) b);
58 }
59 return Long.parseLong(intStr.toString());
60 }
61
62 private static List<Object> parseList(InputStream in) throws IOException {
63 List<Object> list = new ArrayList<>();
64 int b;
65 while ((b = in.read()) != 'e') {
66 in.reset();
67 list.add(decodeNext(in));
68 }
69 return list;
70 }
71
72 private static Map<String, Object> parseDict(InputStream in) throws IOException {
73 Map<String, Object> map = new LinkedHashMap<>();
74 int b;
75 while ((b = in.read()) != 'e') {
76 in.reset();
77 String key = (String) decodeNext(in);
78 Object value = decodeNext(in);
79 map.put(key, value);
80 }
81 return map;
82 }
83}
84