Upload images to your PDS and get instant CDN URLs via images.blue
1package util
2
3import (
4 "fmt"
5 "github.com/ipfs/go-cid"
6 "math/big"
7 "strings"
8)
9
10const base62Alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
11
12// ConvertCIDBase32ToBase62 converts an IPFS CID from base32 to base62
13func ConvertCIDBase32ToBase62(cidBase32 string) (string, error) {
14 c, err := cid.Decode(cidBase32)
15 if err != nil {
16 return "", err
17 }
18 return encodeBase62(c.Bytes()), nil
19}
20
21// ConvertCIDBase62ToBase32 converts an IPFS CID from base62 to base32
22func ConvertCIDBase62ToBase32(cidBase62 string) (string, error) {
23 decodedBytes, err := decodeBase62(cidBase62)
24 if err != nil {
25 return "", fmt.Errorf("failed to decode base62: %w", err)
26 }
27 c, err := cid.Cast(decodedBytes)
28 if err != nil {
29 return "", err
30 }
31
32 return c.String(), nil
33}
34
35func encodeBase62(data []byte) string {
36 if len(data) == 0 {
37 return ""
38 }
39
40 num := new(big.Int).SetBytes(data)
41 if num.Cmp(big.NewInt(0)) == 0 {
42 return "0"
43 }
44
45 var result []byte
46 base := big.NewInt(62)
47 zero := big.NewInt(0)
48
49 for num.Cmp(zero) > 0 {
50 remainder := new(big.Int)
51 num.DivMod(num, base, remainder)
52 result = append(result, base62Alphabet[remainder.Int64()])
53 }
54
55 // Reverse the result
56 for i, j := 0, len(result)-1; i < j; i, j = i+1, j-1 {
57 result[i], result[j] = result[j], result[i]
58 }
59
60 return string(result)
61}
62
63func decodeBase62(encoded string) ([]byte, error) {
64 if encoded == "" {
65 return []byte{}, nil
66 }
67
68 num := big.NewInt(0)
69 base := big.NewInt(62)
70
71 for _, char := range encoded {
72 index := strings.IndexRune(base62Alphabet, char)
73 if index == -1 {
74 return nil, fmt.Errorf("invalid character in base62 string: %c", char)
75 }
76
77 num.Mul(num, base)
78 num.Add(num, big.NewInt(int64(index)))
79 }
80
81 return num.Bytes(), nil
82}
83
84func IsBase32(str string) bool {
85 if str == "" {
86 return false
87 }
88 // Base32 uses A-Z, 2-7 (case insensitive)
89 for _, char := range strings.ToUpper(str) {
90 if !((char >= 'A' && char <= 'Z') || (char >= '2' && char <= '7') || char == '=') {
91 return false
92 }
93 }
94 return len(str) > 0
95}