├── LICENSE ├── README.md ├── README_CN.md ├── base100 ├── base100.go └── base100_test.go ├── base36 ├── base36.go └── base36_test.go ├── base45 ├── base45.go └── base45_test.go ├── base58 ├── base58.go ├── base58_test.go └── base58check.go ├── base62 ├── base62.go └── base62_test.go ├── base91 ├── base91.go └── base91_test.go ├── base92 ├── base92.go └── base92_test.go ├── baseenc ├── baseenc.go └── baseenc_test.go ├── basex ├── basex.go └── basex_test.go ├── bcd ├── bcd.go ├── bcd8421 │ ├── bcd.go │ ├── bcd8421.go │ ├── bcd8421_test.go │ └── bcd_test.go └── bcd_test.go ├── chaocipher ├── chaocipher.go └── chaocipher_test.go ├── encoding ├── asn1.go ├── asn1_test.go ├── base100.go ├── base100_test.go ├── base32.go ├── base32_test.go ├── base36.go ├── base36_test.go ├── base45.go ├── base45_test.go ├── base58.go ├── base58_test.go ├── base62.go ├── base62_test.go ├── base64.go ├── base64_test.go ├── base85.go ├── base85_test.go ├── base91.go ├── base91_test.go ├── base92.go ├── base92_test.go ├── basex.go ├── basex_test.go ├── binary.go ├── binary_test.go ├── convert.go ├── csv.go ├── csv_test.go ├── data_set.go ├── encoding.go ├── encoding_from.go ├── encoding_test.go ├── encoding_to.go ├── encoding_use.go ├── encoding_use_test.go ├── gob.go ├── gob_test.go ├── hex.go ├── hex_test.go ├── json.go ├── json_test.go ├── morse.go ├── morse_test.go ├── puny.go ├── puny_test.go ├── quotedprintable.go ├── quotedprintable_test.go ├── safe_url.go ├── safe_url_test.go ├── serialize.go ├── serialize_test.go ├── xml.go └── xml_test.go ├── example.md ├── go.mod ├── go.sum ├── leb128 ├── leb128.go └── leb128_test.go ├── logo.png ├── morse ├── morse.go └── morse_test.go ├── puny ├── puny.go ├── puny_test.go └── utils.go └── quotedprintable ├── quotedprintable.go ├── quotedprintable_test.go └── utils.go /README.md: -------------------------------------------------------------------------------- 1 | ## go-encoding 2 | 3 |

4 | Go Reference 5 | 6 | 7 |

8 | 9 | [中文](README_CN.md) | English 10 | 11 | 12 | ### Desc 13 | 14 | * data encoding/decoding pkg 15 | * encodings has some (Hex/Base32/Base36/Base45/Base58/Base62/Base64/Base85/Base91/Base92/Base100/MorseITU/JSON) 16 | 17 | 18 | ### Download 19 | 20 | ~~~go 21 | go get -u github.com/deatil/go-encoding 22 | ~~~ 23 | 24 | 25 | ### Get Starting 26 | 27 | ~~~go 28 | package main 29 | 30 | import ( 31 | "fmt" 32 | "github.com/deatil/go-encoding/encoding" 33 | ) 34 | 35 | func main() { 36 | oldData := "useData" 37 | 38 | // Base64 Encode 39 | base64Data := encoding. 40 | FromString(oldData). 41 | Base64Encode(). 42 | ToString() 43 | fmt.Println("Base64 Encoded:", base64Data) 44 | 45 | // Base64 Decode 46 | base64DecodeData := encoding. 47 | FromString(base64Data). 48 | Base64Decode(). 49 | ToString() 50 | fmt.Println("Base64 Decoded:", base64DecodeData) 51 | } 52 | ~~~ 53 | 54 | 55 | ### Use encoding 56 | 57 | ~~~go 58 | base64Data := encoding. 59 | FromString(oldData). // input data 60 | Base64Encode(). // encoding/decoding type 61 | ToString() // output data 62 | ~~~ 63 | 64 | 65 | ### Input and Output 66 | 67 | * Input: 68 | `FromBytes(data []byte)`, `FromString(data string)`, `FromReader(reader io.Reader)` 69 | * Output: 70 | `String() string`, `ToBytes() []byte`, `ToString() string`, `ToReader() io.Reader` 71 | 72 | 73 | ### Encoding Types 74 | 75 | * Decode: 76 | `Base32Encode()`, `Base32RawEncode()`, `Base32HexEncode()`,`Base32RawHexEncode()`, `Base32EncodeWithEncoder(encoder string)`, `Base32RawEncodeWithEncoder(encoder string)`, 77 | `Base45Encode()`, 78 | `Base58Encode()`, 79 | `Base62Encode()`, 80 | `Base64Encode()`, `Base64URLEncode()`, `Base64RawEncode()`, `Base64RawURLEncode()`, `Base64SegmentEncode()`, `Base64EncodeWithEncoder(encoder string)`, 81 | `Base85Encode()`, 82 | `Base91Encode()`, 83 | `Base100Encode()`, 84 | `Basex2Encode()`, `Basex16Encode()`, `Basex62Encode()`, `BasexEncodeWithEncoder(encoder string)`, 85 | `HexEncode()`, 86 | `MorseITUEncode()`, 87 | `SafeURLEncode()`, 88 | `SerializeEncode()`, 89 | `JSONEncode(data any)`, `JSONIteratorEncode(data any)`, `JSONIteratorIndentEncode(v any, prefix, indent string)`, 90 | `GobEncode(data any)` 91 | 92 | * Encode: 93 | `Base32Decode()`, `Base32RawDecode()`, `Base32HexDecode()`,`Base32RawHexDecode()`, `Base32DecodeWithEncoder(encoder string)`, `Base32RawDecodeWithEncoder(encoder string)`, 94 | `Base45Decode()`, 95 | `Base58Decode()`, 96 | `Base62Decode()`, 97 | `Base64Decode()`, `Base64URLDecode()`, `Base64RawDecode()`, `Base64RawURLDecode()`, `Base64SegmentDecode(paddingAllowed ...bool)`, `Base64DecodeWithEncoder(encoder string)`, 98 | `Base85Encode()`, 99 | `Base91Decode()`, 100 | `Base100Decode()`, 101 | `Basex2Decode()`, `Basex16Decode()`, `Basex62Decode()`, `BasexDecodeWithEncoder(encoder string)`, 102 | `HexDecode()`, 103 | `MorseITUDecode()`, 104 | `SafeURLDecode()`, 105 | `SerializeDecode()`, 106 | `JSONDecode(dst any)`, `JSONIteratorDecode(dst any)`, 107 | `GobDecode(dst any)` 108 | 109 | 110 | ### LICENSE 111 | 112 | * The library LICENSE is `Apache2`, using the library need keep the LICENSE. 113 | 114 | 115 | ### Copyright 116 | 117 | * Copyright deatil(https://github.com/deatil). 118 | -------------------------------------------------------------------------------- /README_CN.md: -------------------------------------------------------------------------------- 1 | ## go-encoding 2 | 3 |

4 | Go Reference 5 | 6 | 7 |

8 | 9 | 中文 | [English](README.md) 10 | 11 | ### 项目介绍 12 | 13 | * 常用的编码解码算法 14 | * 算法包括: (Hex/Base32/Base36/Base45/Base58/Base62/Base64/Base85/Base91/Base92/Base100/MorseITU/JSON) 15 | 16 | 17 | ### 下载安装 18 | 19 | ~~~go 20 | go get -u github.com/deatil/go-encoding 21 | ~~~ 22 | 23 | 24 | ### 开始使用 25 | 26 | ~~~go 27 | package main 28 | 29 | import ( 30 | "fmt" 31 | "github.com/deatil/go-encoding/encoding" 32 | ) 33 | 34 | func main() { 35 | oldData := "useData" 36 | 37 | // Base64 编码 38 | base64Data := encoding. 39 | FromString(oldData). 40 | Base64Encode(). 41 | ToString() 42 | fmt.Println("Base64 编码为:", base64Data) 43 | 44 | // Base64 解码 45 | base64DecodeData := encoding. 46 | FromString(base64Data). 47 | Base64Decode(). 48 | ToString() 49 | fmt.Println("Base64 解码为:", base64DecodeData) 50 | } 51 | ~~~ 52 | 53 | 54 | ### 格式说明 55 | 56 | ~~~go 57 | base64Data := encoding. 58 | FromString(oldData). // 输入数据 59 | Base64Encode(). // 编码方式/解码方式 60 | ToString() // 输出数据 61 | ~~~ 62 | 63 | 64 | ### 输入输出数据 65 | 66 | * 输入数据: 67 | `FromBytes(data []byte)`, `FromString(data string)`, `FromReader(reader io.Reader)` 68 | * 输出数据: 69 | `String() string`, `ToBytes() []byte`, `ToString() string`, `ToReader() io.Reader` 70 | 71 | 72 | ### 常用解码编码 73 | 74 | * 编码方式: 75 | `Base32Encode()`, `Base32RawEncode()`, `Base32HexEncode()`,`Base32RawHexEncode()`, `Base32EncodeWithEncoder(encoder string)`, `Base32RawEncodeWithEncoder(encoder string)`, 76 | `Base45Encode()`, 77 | `Base58Encode()`, 78 | `Base62Encode()`, 79 | `Base64Encode()`, `Base64URLEncode()`, `Base64RawEncode()`, `Base64RawURLEncode()`, `Base64SegmentEncode()`, `Base64EncodeWithEncoder(encoder string)`, 80 | `Base85Encode()`, 81 | `Base91Encode()`, 82 | `Base100Encode()`, 83 | `Basex2Encode()`, `Basex16Encode()`, `Basex62Encode()`, `BasexEncodeWithEncoder(encoder string)`, 84 | `HexEncode()`, 85 | `MorseITUEncode()`, 86 | `SafeURLEncode()`, 87 | `SerializeEncode()`, 88 | `JSONEncode(data any)`, `JSONIteratorEncode(data any)`, `JSONIteratorIndentEncode(v any, prefix, indent string)`, 89 | `GobEncode(data any)` 90 | 91 | * 解码方式: 92 | `Base32Decode()`, `Base32RawDecode()`, `Base32HexDecode()`,`Base32RawHexDecode()`, `Base32DecodeWithEncoder(encoder string)`, `Base32RawDecodeWithEncoder(encoder string)`, 93 | `Base45Decode()`, 94 | `Base58Decode()`, 95 | `Base62Decode()`, 96 | `Base64Decode()`, `Base64URLDecode()`, `Base64RawDecode()`, `Base64RawURLDecode()`, `Base64SegmentDecode(paddingAllowed ...bool)`, `Base64DecodeWithEncoder(encoder string)`, 97 | `Base85Encode()`, 98 | `Base91Decode()`, 99 | `Base100Decode()`, 100 | `Basex2Decode()`, `Basex16Decode()`, `Basex62Decode()`, `BasexDecodeWithEncoder(encoder string)`, 101 | `HexDecode()`, 102 | `MorseITUDecode()`, 103 | `SafeURLDecode()`, 104 | `SerializeDecode()`, 105 | `JSONDecode(dst any)`, `JSONIteratorDecode(dst any)`, 106 | `GobDecode(dst any)` 107 | 108 | 109 | ### 开源协议 110 | 111 | * 本软件包遵循 `Apache2` 开源协议发布,在保留本软件包版权的情况下提供个人及商业免费使用。 112 | 113 | 114 | ### 版权 115 | 116 | * 本软件包所属版权归 deatil(https://github.com/deatil) 所有。 117 | -------------------------------------------------------------------------------- /base100/base100.go: -------------------------------------------------------------------------------- 1 | package base100 2 | 3 | const ( 4 | first = 0xf0 5 | second = 0x9f 6 | 7 | shift = 55 8 | divisor = 64 9 | 10 | third = 0x8f 11 | forth = 0x80 12 | ) 13 | 14 | // InvalidInputError is returned when Decode fails 15 | type InvalidInputError struct { 16 | message string 17 | } 18 | 19 | func (e InvalidInputError) Error() string { 20 | return e.message 21 | } 22 | 23 | // ErrInvalidLength is returned when length of string being decoded is 24 | // not divisible by four 25 | var ErrInvalidLength = InvalidInputError{"go-encoding/base100: len(data) should be divisible by 4"} 26 | 27 | // ErrInvalidData is returned if data is not a valid base100 string 28 | var ErrInvalidData = InvalidInputError{"go-encoding/base100: data is invalid"} 29 | 30 | // Encode tranforms bytes into base100 utf-8 encoded string 31 | func Encode(data []byte) string { 32 | result := make([]byte, len(data)*4) 33 | for i, b := range data { 34 | result[i*4+0] = first 35 | result[i*4+1] = second 36 | result[i*4+2] = byte((uint16(b)+shift)/divisor + third) 37 | result[i*4+3] = (b+shift)%divisor + forth 38 | } 39 | 40 | return string(result) 41 | } 42 | 43 | // Decode transforms base100 utf-8 encoded string into bytes 44 | func Decode(data string) ([]byte, error) { 45 | if len(data)%4 != 0 { 46 | return nil, ErrInvalidLength 47 | } 48 | 49 | result := make([]byte, len(data)/4) 50 | for i := 0; i != len(data); i += 4 { 51 | if data[i+0] != first || data[i+1] != second { 52 | return nil, ErrInvalidData 53 | } 54 | 55 | result[i/4] = (data[i+2]-third)*divisor + 56 | data[i+3] - forth - shift 57 | } 58 | 59 | return result, nil 60 | } 61 | -------------------------------------------------------------------------------- /base100/base100_test.go: -------------------------------------------------------------------------------- 1 | package base100 2 | 3 | import "testing" 4 | 5 | func TestInvalidInput(t *testing.T) { 6 | if _, err := Decode("aaaa"); err != ErrInvalidData { 7 | t.Errorf("Expected ErrInvalidData but got %v", err) 8 | } 9 | 10 | if _, err := Decode("aaa"); err != ErrInvalidLength { 11 | t.Errorf("Expected ErrInvalidLength but got %v", err) 12 | } 13 | } 14 | 15 | func TestCoverError(t *testing.T) { 16 | const message = "are you happy now, code coverage?" 17 | err := InvalidInputError{message} 18 | if err.Error() != message { 19 | t.Errorf("(InvalidInputError).Error(): Expected %v, got %v", message, err.Error()) 20 | } 21 | } 22 | 23 | var tests = []struct { 24 | name string 25 | text string 26 | emoji string 27 | }{ 28 | { 29 | "ASCII", 30 | "hello", 31 | "👟👜👣👣👦", 32 | }, 33 | { 34 | "Cyrillic", 35 | "РАШ Бэ", 36 | "📇💗📇💇📇💟🐗📇💈📈💄", 37 | }, 38 | { 39 | "HelloUnicode", 40 | "Hello, 世界", 41 | "🐿👜👣👣👦🐣🐗📛💯💍📞💌💃", 42 | }, 43 | } 44 | 45 | func TestDecode(t *testing.T) { 46 | for _, test := range tests { 47 | res, err := Decode(test.emoji) 48 | if err != nil { 49 | t.Errorf("%v: Unexpected error: %v", test.name, err) 50 | } 51 | 52 | if string(res) != test.text { 53 | t.Errorf("%v: Expected to get '%v', got '%v'", test.name, test.text, string(res)) 54 | } 55 | } 56 | } 57 | 58 | func TestEncode(t *testing.T) { 59 | for _, test := range tests { 60 | res := Encode([]byte(test.text)) 61 | 62 | if res != test.emoji { 63 | t.Errorf("%v: Expected to get '%v', got '%v'", test.name, test.emoji, res) 64 | } 65 | } 66 | } 67 | 68 | func TestFlow(t *testing.T) { 69 | text := []byte("the quick brown fox 😂😂👌👌👌 over the lazy dog привет") 70 | 71 | res, err := Decode(Encode(text)) 72 | 73 | if err != nil { 74 | t.Errorf("Unexpected error: %v", err) 75 | } 76 | 77 | if string(res) != string(text) { 78 | t.Errorf("Expected to get '%v', got '%v'", string(text), string(res)) 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /base36/base36.go: -------------------------------------------------------------------------------- 1 | package base36 2 | 3 | import ( 4 | "github.com/deatil/go-encoding/baseenc" 5 | ) 6 | 7 | // encodeStd is the standard base36 encoding alphabet 8 | const encodeStd = "0123456789abcdefghijklmnopqrstuvwxyz" 9 | 10 | // StdEncoding is the default encoding enc. 11 | var StdEncoding = NewEncoding(encodeStd) 12 | 13 | /* 14 | * Encodings 15 | */ 16 | 17 | // NewEncoding returns a new Encoding defined by the given alphabet, which must 18 | // be a 36-byte string that does not contain CR or LF ('\r', '\n'). 19 | func NewEncoding(encoder string) *baseenc.Encoding { 20 | return baseenc.NewEncoding("base36", 36, encoder) 21 | } 22 | -------------------------------------------------------------------------------- /base36/base36_test.go: -------------------------------------------------------------------------------- 1 | package base36 2 | 3 | import ( 4 | "bytes" 5 | "reflect" 6 | "testing" 7 | ) 8 | 9 | var cases = []struct { 10 | name string 11 | bin []byte 12 | }{ 13 | {"nil", nil}, 14 | {"empty", []byte{}}, 15 | {"zero", []byte{0}}, 16 | {"one", []byte{1}}, 17 | {"two", []byte{2}}, 18 | {"ten", []byte{10}}, 19 | {"2zeros", []byte{0, 0}}, 20 | {"2ones", []byte{1, 1}}, 21 | {"64zeros", []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 22 | {"65zeros", []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 23 | {"ascii", []byte("c'est une longue chanson")}, 24 | {"utf8", []byte("Garçon, un café très fort !")}, 25 | } 26 | 27 | func Test_Encode(t *testing.T) { 28 | for _, c := range cases { 29 | t.Run(c.name, func(t *testing.T) { 30 | str := StdEncoding.EncodeToString(c.bin) 31 | 32 | ni := len(c.bin) 33 | if ni > 70 { 34 | ni = 70 // print max the first 70 bytes 35 | } 36 | na := len(str) 37 | if na > 70 { 38 | na = 70 // print max the first 70 characters 39 | } 40 | t.Logf("bin len=%d [:%d]=%v", len(c.bin), ni, c.bin[:ni]) 41 | t.Logf("str len=%d [:%d]=%q", len(str), na, str[:na]) 42 | 43 | got, err := StdEncoding.DecodeString(str) 44 | if err != nil { 45 | t.Errorf("Decode() error = %v", err) 46 | return 47 | } 48 | 49 | ng := len(got) 50 | if ng > 70 { 51 | ng = 70 // print max the first 70 bytes 52 | } 53 | t.Logf("got len=%d [:%d]=%v", len(got), ng, got[:ng]) 54 | 55 | if (len(got) == 0) && (len(c.bin) == 0) { 56 | return 57 | } 58 | 59 | if !reflect.DeepEqual(got, c.bin) { 60 | t.Errorf("Decode() = %v, want %v", got, c.bin) 61 | } 62 | }) 63 | } 64 | } 65 | 66 | func Test_Encode2(t *testing.T) { 67 | for _, s := range SamplesStd { 68 | encoded := string(StdEncoding.Encode(s.sourceBytes)) 69 | if len(encoded) == len(s.target) && encoded == s.target { 70 | t.Logf("source: %-15s\ttarget: %s", s.source, s.target) 71 | } else { 72 | t.Errorf("source: %-15s\texpected target: %s(%d)\tactual target: %s(%d)", s.source, s.target, len(s.target), encoded, len(encoded)) 73 | } 74 | } 75 | } 76 | 77 | func Test_Decode2(t *testing.T) { 78 | for _, s := range SamplesStd { 79 | decoded, err := StdEncoding.Decode(s.targetBytes) 80 | if err != nil { 81 | t.Error(err) 82 | continue 83 | } 84 | 85 | if bytes.Equal(decoded, s.sourceBytes) { 86 | t.Logf("target: %-15s\tsource: %s", s.target, s.source) 87 | } else { 88 | str := string(decoded) 89 | t.Errorf("target: %-15s\texpected source: %s(%d)\tactual source: %s(%d)", s.target, s.source, len(s.source), str, len(str)) 90 | } 91 | } 92 | } 93 | 94 | func Test_EncodeToString(t *testing.T) { 95 | for _, s := range SamplesStd { 96 | encoded := StdEncoding.EncodeToString([]byte(s.source)) 97 | if len(encoded) == len(s.target) && encoded == s.target { 98 | t.Logf("source: %-15s\ttarget: %s", s.source, s.target) 99 | } else { 100 | t.Errorf("source: %-15s\texpected target: %s(%d)\tactual target: %s(%d)", s.source, s.target, len(s.target), encoded, len(encoded)) 101 | } 102 | } 103 | } 104 | 105 | func Test_DecodeString(t *testing.T) { 106 | for _, s := range SamplesStd { 107 | decoded, err := StdEncoding.DecodeString(s.target) 108 | if err != nil { 109 | t.Error(err) 110 | continue 111 | } 112 | 113 | if bytes.Equal(decoded, s.sourceBytes) { 114 | t.Logf("target: %-15s\tsource: %s", s.target, s.source) 115 | } else { 116 | str := string(decoded) 117 | t.Errorf("target: %-15s\texpected source: %s(%d)\tactual source: %s(%d)", s.target, s.source, len(s.source), str, len(str)) 118 | } 119 | } 120 | } 121 | 122 | func Test_EncodeWithCustomAlphabet(t *testing.T) { 123 | for _, s := range SamplesWithAlphabet { 124 | encoded := NewEncoding(s.alphabet).EncodeToString(s.sourceBytes) 125 | if encoded == s.target { 126 | t.Logf("source: %-15s\ttarget: %s", s.source, s.target) 127 | } else { 128 | str := string(encoded) 129 | t.Errorf("source: %-15s\texpected target: %s(%d)\tactual target: %s(%d)", s.source, s.target, len(s.target), str, len(str)) 130 | } 131 | } 132 | } 133 | 134 | func Test_DecodeWithCustomAlphabet(t *testing.T) { 135 | for _, s := range SamplesWithAlphabet { 136 | decoded, err := NewEncoding(s.alphabet).DecodeString(s.target) 137 | if err != nil { 138 | t.Error(err) 139 | continue 140 | } 141 | if bytes.Equal(decoded, s.sourceBytes) { 142 | t.Logf("target: %-15s\tsource: %s", s.target, s.source) 143 | } else { 144 | str := string(decoded) 145 | t.Errorf("target: %-15s\texpected source: %s(%d)\tactual source: %s(%d)", s.target, s.source, len(s.source), str, len(str)) 146 | } 147 | } 148 | } 149 | 150 | func Test_DecodeError(t *testing.T) { 151 | for _, s := range SamplesErr { 152 | decoded, err := StdEncoding.DecodeString(s.target) 153 | if err != nil { 154 | t.Logf("%s: \"%c\"", err.Error(), err) 155 | continue 156 | } 157 | 158 | str := string(decoded) 159 | t.Errorf("An error should have occurred, instead of returning \"%s\"", str) 160 | } 161 | } 162 | 163 | func NewSample(source, target string) *Sample { 164 | return &Sample{source: source, target: target, sourceBytes: []byte(source), targetBytes: []byte(target)} 165 | } 166 | 167 | func NewSampleWithAlphabet(source, target, alphabet string) *Sample { 168 | return &Sample{source: source, target: target, sourceBytes: []byte(source), targetBytes: []byte(target), alphabet: alphabet} 169 | } 170 | 171 | type Sample struct { 172 | source string 173 | target string 174 | sourceBytes []byte 175 | targetBytes []byte 176 | alphabet string 177 | } 178 | 179 | var SamplesStd = []*Sample{ 180 | NewSample("", ""), 181 | NewSample("f", "2u"), 182 | NewSample("fo", "k8f"), 183 | NewSample("foo", "3zvxr"), 184 | NewSample("foob", "sf742q"), 185 | NewSample("fooba", "5m42kzfl"), 186 | NewSample("foobar", "13x8yd7ywi"), 187 | 188 | NewSample("su", "mt1"), 189 | NewSample("sur", "4i6ia"), 190 | NewSample("sure", "w1aa1x"), 191 | NewSample("sure.", "6bt53hny"), 192 | NewSample("asure.", "11zbcm20j2"), 193 | NewSample("easure.", "7sz7l367x2m"), 194 | NewSample("leasure.", "1ncbu0pxvv6em"), 195 | 196 | NewSample("=", "1p"), 197 | NewSample(">", "1q"), 198 | NewSample("?", "1r"), 199 | NewSample("11", "9pt"), 200 | NewSample("111", "1x3jl"), 201 | NewSample("1111", "dnd7ap"), 202 | NewSample("11111", "2p25vw35"), 203 | NewSample("111111", "j67dus6cx"), 204 | 205 | NewSample("Hello, World!", "fg3h7vqw7een6jwwnzmp"), 206 | NewSample("你好,世界!", "j0sguou3jtppn6fagdqrb3kre1z5"), 207 | NewSample("こんにちは", "1w6pjye0qjvyw4xul6ds5jfz"), 208 | NewSample("안녕하십니까", "jo9sbh1ov904nwwy5gosugf1cmfg"), 209 | 210 | NewSample(string([]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255}), "0rwg9z1idsugqv3"), 211 | } 212 | 213 | var SamplesWithAlphabet = []*Sample{ 214 | NewSampleWithAlphabet("", "", "0123456789ghijklmnopqrstuvwxyzabcdef"), 215 | NewSampleWithAlphabet("f", "2a", "0123456789ghijklmnopqrstuvwxyzabcdef"), 216 | NewSampleWithAlphabet("fo", "q8l", "0123456789ghijklmnopqrstuvwxyzabcdef"), 217 | NewSampleWithAlphabet("foo", "3fbdx", "0123456789ghijklmnopqrstuvwxyzabcdef"), 218 | NewSampleWithAlphabet("foob", "yl742w", "0123456789ghijklmnopqrstuvwxyzabcdef"), 219 | NewSampleWithAlphabet("fooba", "5s42qflr", "0123456789ghijklmnopqrstuvwxyzabcdef"), 220 | NewSampleWithAlphabet("foobar", "13d8ej7eco", "0123456789ghijklmnopqrstuvwxyzabcdef"), 221 | 222 | NewSampleWithAlphabet("su", "sz1", "0123456789ghijklmnopqrstuvwxyzabcdef"), 223 | NewSampleWithAlphabet("sur", "4o6og", "0123456789ghijklmnopqrstuvwxyzabcdef"), 224 | NewSampleWithAlphabet("sure", "c1gg1d", "0123456789ghijklmnopqrstuvwxyzabcdef"), 225 | NewSampleWithAlphabet("sure.", "6hz53nte", "0123456789ghijklmnopqrstuvwxyzabcdef"), 226 | NewSampleWithAlphabet("asure.", "11fhis20p2", "0123456789ghijklmnopqrstuvwxyzabcdef"), 227 | NewSampleWithAlphabet("easure.", "7yf7r367d2s", "0123456789ghijklmnopqrstuvwxyzabcdef"), 228 | NewSampleWithAlphabet("leasure.", "1tiha0vdbb6ks", "0123456789ghijklmnopqrstuvwxyzabcdef"), 229 | 230 | NewSampleWithAlphabet("=", "1v", "0123456789ghijklmnopqrstuvwxyzabcdef"), 231 | NewSampleWithAlphabet(">", "1w", "0123456789ghijklmnopqrstuvwxyzabcdef"), 232 | NewSampleWithAlphabet("?", "1x", "0123456789ghijklmnopqrstuvwxyzabcdef"), 233 | NewSampleWithAlphabet("11", "9vz", "0123456789ghijklmnopqrstuvwxyzabcdef"), 234 | NewSampleWithAlphabet("111", "1d3pr", "0123456789ghijklmnopqrstuvwxyzabcdef"), 235 | NewSampleWithAlphabet("1111", "jtj7gv", "0123456789ghijklmnopqrstuvwxyzabcdef"), 236 | NewSampleWithAlphabet("11111", "2v25bc35", "0123456789ghijklmnopqrstuvwxyzabcdef"), 237 | NewSampleWithAlphabet("111111", "p67jay6id", "0123456789ghijklmnopqrstuvwxyzabcdef"), 238 | 239 | NewSampleWithAlphabet("Hello, World!", "lm3n7bwc7kkt6pcctfsv", "0123456789ghijklmnopqrstuvwxyzabcdef"), 240 | NewSampleWithAlphabet("你好,世界!", "p0ymaua3pzvvt6lgmjwxh3qxk1f5", "0123456789ghijklmnopqrstuvwxyzabcdef"), 241 | NewSampleWithAlphabet("こんにちは", "1c6vpek0wpbec4dar6jy5plf", "0123456789ghijklmnopqrstuvwxyzabcdef"), 242 | NewSampleWithAlphabet("안녕하십니까", "pu9yhn1ub904tcce5muyaml1islm", "0123456789ghijklmnopqrstuvwxyzabcdef"), 243 | } 244 | 245 | var SamplesErr = []*Sample{ 246 | NewSample("", "Hello, World!"), 247 | NewSample("", "哈哈"), 248 | NewSample("", "はは"), 249 | } 250 | -------------------------------------------------------------------------------- /base45/base45_test.go: -------------------------------------------------------------------------------- 1 | package base45 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | type testPair struct { 8 | decoded string 9 | encoded string 10 | } 11 | 12 | type malformedTestPair struct { 13 | encoded string 14 | error error 15 | } 16 | 17 | var pairs = []testPair{ 18 | { 19 | decoded: "AB", 20 | encoded: "BB8", 21 | }, 22 | { 23 | decoded: "Hello!!", 24 | encoded: "%69 VD92EX0", 25 | }, 26 | { 27 | decoded: "base-45", 28 | encoded: "UJCLQE7W581", 29 | }, 30 | { 31 | decoded: "ietf!", 32 | encoded: "QED8WEX0", 33 | }, 34 | { 35 | decoded: "Lorem ipsum dolor sit amet", 36 | encoded: "$T9ZKE ZD$ED$QE ZDGVC*VDBJEPQESUEBEC7$C", 37 | }, 38 | } 39 | 40 | var malformedPairs = []malformedTestPair{ 41 | { 42 | encoded: "A", 43 | error: InvalidLengthError{length: 1, mod: 1}, 44 | }, 45 | { 46 | encoded: "FAILEd", 47 | error: InvalidCharacterError{char: 'd', position: 5}, 48 | }, 49 | { 50 | encoded: "GGW", 51 | error: IllegalBase45ByteError{position: 0}, 52 | }, 53 | { 54 | encoded: ":::", 55 | error: IllegalBase45ByteError{position: 0}, 56 | }, 57 | { 58 | encoded: "ABC:::", 59 | error: IllegalBase45ByteError{position: 1}, 60 | }, 61 | } 62 | 63 | func testEqual(t *testing.T, msg string, args ...any) bool { 64 | t.Helper() 65 | if args[len(args)-2] != args[len(args)-1] { 66 | t.Errorf(msg, args...) 67 | return false 68 | } 69 | return true 70 | } 71 | 72 | func TestEncode(t *testing.T) { 73 | for _, p := range pairs { 74 | got := StdEncoding.EncodeToString([]byte(p.decoded)) 75 | testEqual(t, "Encode(%q) = %q, want %q", p.decoded, got, p.encoded) 76 | } 77 | } 78 | 79 | func TestDecode(t *testing.T) { 80 | for _, p := range pairs { 81 | got, err := StdEncoding.DecodeString(p.encoded) 82 | if err != nil { 83 | t.Failed() 84 | } 85 | 86 | testEqual(t, "Decode(%q) = %q, want %q", p.encoded, string(got), p.decoded) 87 | } 88 | } 89 | 90 | func TestDecodeMalformed(t *testing.T) { 91 | for _, p := range malformedPairs { 92 | _, err := StdEncoding.DecodeString(p.encoded) 93 | if err == nil { 94 | t.Failed() 95 | } 96 | switch err := err.(type) { 97 | case InvalidLengthError: 98 | testEqual(t, "Error(%s) = %s, want %s", p.error, err, p.error) 99 | case InvalidCharacterError: 100 | testEqual(t, "Error(%s) = %s, want %s", p.error, err, p.error) 101 | case IllegalBase45ByteError: 102 | testEqual(t, "Error(%s) = %s, want %s", p.error, err, p.error) 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /base58/base58.go: -------------------------------------------------------------------------------- 1 | package base58 2 | 3 | import ( 4 | "unsafe" 5 | "reflect" 6 | "strconv" 7 | "math/big" 8 | ) 9 | 10 | var bigRadix = [...]*big.Int{ 11 | big.NewInt(0), 12 | big.NewInt(58), 13 | big.NewInt(58 * 58), 14 | big.NewInt(58 * 58 * 58), 15 | big.NewInt(58 * 58 * 58 * 58), 16 | big.NewInt(58 * 58 * 58 * 58 * 58), 17 | big.NewInt(58 * 58 * 58 * 58 * 58 * 58), 18 | big.NewInt(58 * 58 * 58 * 58 * 58 * 58 * 58), 19 | big.NewInt(58 * 58 * 58 * 58 * 58 * 58 * 58 * 58), 20 | big.NewInt(58 * 58 * 58 * 58 * 58 * 58 * 58 * 58 * 58), 21 | bigRadix10, 22 | } 23 | 24 | var bigRadix10 = big.NewInt(58 * 58 * 58 * 58 * 58 * 58 * 58 * 58 * 58 * 58) // 58^10 25 | 26 | const ( 27 | alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" 28 | 29 | alphabetIdx0 = '1' 30 | ) 31 | 32 | type CorruptInputError int64 33 | 34 | func (e CorruptInputError) Error() string { 35 | return "go-encoding/base58: illegal base58 data at input byte " + strconv.FormatInt(int64(e), 10) 36 | } 37 | 38 | var StdEncoding = NewEncoding(alphabet) 39 | 40 | /* 41 | * Encodings 42 | */ 43 | 44 | // An Encoding is a base 58 encoding/decoding scheme defined by a 58-character alphabet. 45 | type Encoding struct { 46 | encode [58]byte 47 | decodeMap [256]byte 48 | } 49 | 50 | // NewEncoding returns a new Encoding defined by the given alphabet, which must 51 | // be a 58-byte string that does not contain CR or LF ('\r', '\n'). 52 | func NewEncoding(encoder string) *Encoding { 53 | if len(encoder) != 58 { 54 | panic("go-encoding/base58: encoding alphabet is not 58 bytes long") 55 | } 56 | 57 | for i := 0; i < len(encoder); i++ { 58 | if encoder[i] == '\n' || encoder[i] == '\r' { 59 | panic("go-encoding/base58: encoding alphabet contains newline character") 60 | } 61 | } 62 | 63 | e := new(Encoding) 64 | copy(e.encode[:], encoder) 65 | 66 | for i := 0; i < len(e.decodeMap); i++ { 67 | // 0xff indicates that this entry in the decode map is not in the encoding alphabet. 68 | e.decodeMap[i] = 0xff 69 | } 70 | 71 | for i := 0; i < len(encoder); i++ { 72 | e.decodeMap[encoder[i]] = byte(i) 73 | } 74 | 75 | return e 76 | } 77 | 78 | /* 79 | * Encoder 80 | */ 81 | 82 | // Encode encodes src using the encoding enc. 83 | func (enc *Encoding) Encode(b []byte) []byte { 84 | x := new(big.Int) 85 | x.SetBytes(b) 86 | 87 | maxlen := int(float64(len(b))*1.365658237309761) + 1 88 | answer := make([]byte, 0, maxlen) 89 | mod := new(big.Int) 90 | 91 | for x.Sign() > 0 { 92 | x.DivMod(x, bigRadix10, mod) 93 | if x.Sign() == 0 { 94 | m := mod.Int64() 95 | for m > 0 { 96 | answer = append(answer, enc.encode[m%58]) 97 | m /= 58 98 | } 99 | } else { 100 | m := mod.Int64() 101 | for i := 0; i < 10; i++ { 102 | answer = append(answer, enc.encode[m%58]) 103 | m /= 58 104 | } 105 | } 106 | } 107 | 108 | for _, i := range b { 109 | if i != 0 { 110 | break 111 | } 112 | 113 | answer = append(answer, alphabetIdx0) 114 | } 115 | 116 | alen := len(answer) 117 | for i := 0; i < alen/2; i++ { 118 | answer[i], answer[alen-1-i] = answer[alen-1-i], answer[i] 119 | } 120 | 121 | return answer 122 | } 123 | 124 | // EncodeToString returns the base58 encoding of src. 125 | func (enc *Encoding) EncodeToString(src []byte) string { 126 | answer := enc.Encode(src) 127 | 128 | return string(answer) 129 | } 130 | 131 | /* 132 | * Decoder 133 | */ 134 | 135 | // Decode decodes src using the encoding enc. It writes at most DecodedLen(len(src)) 136 | // bytes to dst and returns the number of bytes written. If src contains invalid base58 137 | // data, it will return the number of bytes successfully written and CorruptInputError. 138 | func (enc *Encoding) Decode(src []byte) ([]byte, error) { 139 | answer := big.NewInt(0) 140 | scratch := new(big.Int) 141 | 142 | b := string(src) 143 | 144 | for t := b; len(t) > 0; { 145 | n := len(t) 146 | if n > 10 { 147 | n = 10 148 | } 149 | 150 | total := uint64(0) 151 | for _, v := range t[:n] { 152 | if v > 255 { 153 | return []byte(""), CorruptInputError(v) 154 | } 155 | 156 | tmp := enc.decodeMap[v] 157 | if tmp == 255 { 158 | return []byte(""), CorruptInputError(v) 159 | } 160 | 161 | total = total*58 + uint64(tmp) 162 | } 163 | 164 | answer.Mul(answer, bigRadix[n]) 165 | scratch.SetUint64(total) 166 | answer.Add(answer, scratch) 167 | 168 | t = t[n:] 169 | } 170 | 171 | tmpval := answer.Bytes() 172 | 173 | var numZeros int 174 | for numZeros = 0; numZeros < len(b); numZeros++ { 175 | if b[numZeros] != alphabetIdx0 { 176 | break 177 | } 178 | } 179 | 180 | flen := numZeros + len(tmpval) 181 | val := make([]byte, flen) 182 | copy(val[numZeros:], tmpval) 183 | 184 | return val, nil 185 | } 186 | 187 | // DecodeString returns the bytes represented by the base58 string s. 188 | func (enc *Encoding) DecodeString(s string) ([]byte, error) { 189 | sh := (*reflect.StringHeader)(unsafe.Pointer(&s)) 190 | bh := reflect.SliceHeader{Data: sh.Data, Len: sh.Len, Cap: sh.Len} 191 | return enc.Decode(*(*[]byte)(unsafe.Pointer(&bh))) 192 | } 193 | 194 | -------------------------------------------------------------------------------- /base58/base58_test.go: -------------------------------------------------------------------------------- 1 | package base58 2 | 3 | import ( 4 | "bytes" 5 | "testing" 6 | ) 7 | 8 | func Test_Encode(t *testing.T) { 9 | for _, s := range SamplesStd { 10 | encoded := StdEncoding.Encode([]byte(s.source)) 11 | if bytes.Equal(encoded, s.targetBytes) { 12 | t.Logf("source: %-15s\ttarget: %s", s.source, s.target) 13 | } else { 14 | str := string(encoded) 15 | t.Errorf("source: %-15s\texpected target: %s(%d)\tactual target: %s(%d)", s.source, s.target, len(s.target), str, len(str)) 16 | } 17 | } 18 | } 19 | 20 | func Test_EncodeToString(t *testing.T) { 21 | for _, s := range SamplesStd { 22 | encoded := StdEncoding.EncodeToString([]byte(s.source)) 23 | if len(encoded) == len(s.target) && encoded == s.target { 24 | t.Logf("source: %-15s\ttarget: %s", s.source, s.target) 25 | } else { 26 | t.Errorf("source: %-15s\texpected target: %s(%d)\tactual target: %s(%d)", s.source, s.target, len(s.target), encoded, len(encoded)) 27 | } 28 | } 29 | } 30 | 31 | func Test_Decode(t *testing.T) { 32 | for _, s := range SamplesStd { 33 | decoded, err := StdEncoding.Decode(s.targetBytes) 34 | if err != nil { 35 | t.Error(err) 36 | continue 37 | } 38 | if bytes.Equal(decoded, s.sourceBytes) { 39 | t.Logf("target: %-15s\tsource: %s", s.target, s.source) 40 | } else { 41 | str := string(decoded) 42 | t.Errorf("target: %-15s\texpected source: %s(%d)\tactual source: %s(%d)", s.target, s.source, len(s.source), str, len(str)) 43 | } 44 | } 45 | } 46 | 47 | func Test_DecodeString(t *testing.T) { 48 | for _, s := range SamplesStd { 49 | decoded, err := StdEncoding.DecodeString(s.target) 50 | if err != nil { 51 | t.Error(err) 52 | continue 53 | } 54 | if bytes.Equal(decoded, s.sourceBytes) { 55 | t.Logf("target: %-15s\tsource: %s", s.target, s.source) 56 | } else { 57 | str := string(decoded) 58 | t.Errorf("target: %-15s\texpected source: %s(%d)\tactual source: %s(%d)", s.target, s.source, len(s.source), str, len(str)) 59 | } 60 | } 61 | } 62 | 63 | func Test_EncodeWithCustomAlphabet(t *testing.T) { 64 | for _, s := range SamplesWithAlphabet { 65 | encoded := NewEncoding(s.alphabet).Encode([]byte(s.source)) 66 | if bytes.Equal(encoded, s.targetBytes) { 67 | t.Logf("source: %-15s\ttarget: %s", s.source, s.target) 68 | } else { 69 | str := string(encoded) 70 | t.Errorf("source: %-15s\texpected target: %s(%d)\tactual target: %s(%d)", s.source, s.target, len(s.target), str, len(str)) 71 | } 72 | } 73 | } 74 | 75 | func Test_DecodeWithCustomAlphabet(t *testing.T) { 76 | for _, s := range SamplesWithAlphabet { 77 | decoded, err := NewEncoding(s.alphabet).Decode(s.targetBytes) 78 | if err != nil { 79 | t.Error(err) 80 | continue 81 | } 82 | if bytes.Equal(decoded, s.sourceBytes) { 83 | t.Logf("target: %-15s\tsource: %s", s.target, s.source) 84 | } else { 85 | str := string(decoded) 86 | t.Errorf("target: %-15s\texpected source: %s(%d)\tactual source: %s(%d)", s.target, s.source, len(s.source), str, len(str)) 87 | } 88 | } 89 | } 90 | 91 | func Test_DecodeError(t *testing.T) { 92 | for _, s := range SamplesErr { 93 | decoded, err := StdEncoding.Decode(s.targetBytes) 94 | if err != nil { 95 | t.Logf("%s: \"%c\"", err.Error(), err) 96 | continue 97 | } 98 | 99 | str := string(decoded) 100 | t.Errorf("An error should have occurred, instead of returning \"%s\"", str) 101 | } 102 | } 103 | 104 | func Test_CheckEncode(t *testing.T) { 105 | input := []byte("test-date") 106 | version := byte(12) 107 | 108 | res := CheckEncode(input, version) 109 | 110 | decoded, ver, _ := CheckDecode(res) 111 | 112 | if !bytes.Equal(decoded, input) { 113 | t.Errorf("input got: %s(%d), want: %s(%d)", string(decoded), len(decoded), string(input), len(input)) 114 | } 115 | 116 | if ver != version { 117 | t.Errorf("version got: %d, want: %d", ver, version) 118 | } 119 | } 120 | 121 | func NewSample(source, target string) *Sample { 122 | return &Sample{source: source, target: target, sourceBytes: []byte(source), targetBytes: []byte(target)} 123 | } 124 | 125 | func NewSampleWithAlphabet(source, target, alphabet string) *Sample { 126 | return &Sample{source: source, target: target, sourceBytes: []byte(source), targetBytes: []byte(target), alphabet: alphabet} 127 | } 128 | 129 | type Sample struct { 130 | source string 131 | target string 132 | sourceBytes []byte 133 | targetBytes []byte 134 | alphabet string 135 | } 136 | 137 | var SamplesStd = []*Sample{ 138 | NewSample("", ""), 139 | NewSample("f", "2m"), 140 | NewSample("fo", "8o8"), 141 | NewSample("foo", "bQbp"), 142 | NewSample("foob", "3csAg9"), 143 | NewSample("fooba", "CZJRhmz"), 144 | NewSample("foobar", "t1Zv2yaZ"), 145 | 146 | NewSample("su", "9nc"), 147 | NewSample("sur", "fnKT"), 148 | NewSample("sure", "3xB2TW"), 149 | NewSample("sure.", "E2XFRyo"), 150 | NewSample("asure.", "qXcNm9C1"), 151 | NewSample("easure.", "4qq4WqChgZ"), 152 | NewSample("leasure.", "K8aUZhGUNaR"), 153 | 154 | NewSample("=", "24"), 155 | NewSample(">", "25"), 156 | NewSample("?", "26"), 157 | NewSample("11", "4k8"), 158 | NewSample("111", "HXLk"), 159 | NewSample("1111", "2Fvv9e"), 160 | NewSample("11111", "6Ytyb9A"), 161 | NewSample("111111", "RVnQmh1a"), 162 | 163 | NewSample("Hello, World!", "72k1xXWG59fYdzSNoA"), 164 | NewSample("你好,世界!", "AVGu5T9j8gbKjDaBawMj5iGit"), 165 | NewSample("こんにちは", "7NAasPYBzpyEe5hmwr1KL"), 166 | NewSample("안녕하십니까", "Ap9GxMvMvB9xzEbvcweFMBLEX"), 167 | } 168 | 169 | var SamplesWithAlphabet = []*Sample{ 170 | NewSampleWithAlphabet("", "", "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijklmnpqrstuvwxyz123456789"), 171 | NewSampleWithAlphabet("f", "Bv", "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijklmnpqrstuvwxyz123456789"), 172 | NewSampleWithAlphabet("fo", "HxH", "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijklmnpqrstuvwxyz123456789"), 173 | NewSampleWithAlphabet("foo", "kZky", "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijklmnpqrstuvwxyz123456789"), 174 | NewSampleWithAlphabet("foob", "Cl2KqJ", "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijklmnpqrstuvwxyz123456789"), 175 | NewSampleWithAlphabet("fooba", "MiTarv9", "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijklmnpqrstuvwxyz123456789"), 176 | NewSampleWithAlphabet("foobar", "3Ai5B8ji", "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijklmnpqrstuvwxyz123456789"), 177 | 178 | NewSampleWithAlphabet("su", "Jwl", "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijklmnpqrstuvwxyz123456789"), 179 | NewSampleWithAlphabet("sur", "pwUc", "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijklmnpqrstuvwxyz123456789"), 180 | NewSampleWithAlphabet("sure", "C7LBcf", "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijklmnpqrstuvwxyz123456789"), 181 | NewSampleWithAlphabet("sure.", "PBgQa8x", "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijklmnpqrstuvwxyz123456789"), 182 | NewSampleWithAlphabet("asure.", "zglXvJMA", "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijklmnpqrstuvwxyz123456789"), 183 | NewSampleWithAlphabet("easure.", "DzzDfzMrqi", "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijklmnpqrstuvwxyz123456789"), 184 | NewSampleWithAlphabet("leasure.", "UHjdirRdXja", "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijklmnpqrstuvwxyz123456789"), 185 | 186 | NewSampleWithAlphabet("=", "BD", "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijklmnpqrstuvwxyz123456789"), 187 | NewSampleWithAlphabet(">", "BE", "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijklmnpqrstuvwxyz123456789"), 188 | NewSampleWithAlphabet("?", "BF", "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijklmnpqrstuvwxyz123456789"), 189 | NewSampleWithAlphabet("11", "DuH", "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijklmnpqrstuvwxyz123456789"), 190 | NewSampleWithAlphabet("111", "SgVu", "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijklmnpqrstuvwxyz123456789"), 191 | NewSampleWithAlphabet("1111", "BQ55Jn", "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijklmnpqrstuvwxyz123456789"), 192 | NewSampleWithAlphabet("11111", "Fh38kJK", "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijklmnpqrstuvwxyz123456789"), 193 | NewSampleWithAlphabet("111111", "aewZvrAj", "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijklmnpqrstuvwxyz123456789"), 194 | 195 | NewSampleWithAlphabet("Hello, World!", "GBuA7gfREJphm9bXxK", "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijklmnpqrstuvwxyz123456789"), 196 | NewSampleWithAlphabet("你好,世界!", "KeR4EcJtHqkUtNjLj6WtEsRs3", "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijklmnpqrstuvwxyz123456789"), 197 | NewSampleWithAlphabet("こんにちは", "GXKj2YhL9y8PnErv61AUV", "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijklmnpqrstuvwxyz123456789"), 198 | NewSampleWithAlphabet("안녕하십니까", "KyJR7W5W5LJ79Pk5l6nQWLVPg", "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijklmnpqrstuvwxyz123456789"), 199 | } 200 | 201 | var SamplesErr = []*Sample{ 202 | NewSample("", "Hello, World!"), 203 | NewSample("", "哈哈"), 204 | NewSample("", "はは"), 205 | } 206 | -------------------------------------------------------------------------------- /base58/base58check.go: -------------------------------------------------------------------------------- 1 | package base58 2 | 3 | import ( 4 | "errors" 5 | "crypto/sha256" 6 | ) 7 | 8 | var ErrChecksum = errors.New("checksum error") 9 | var ErrInvalidFormat = errors.New("invalid format: version and/or checksum bytes missing") 10 | 11 | func checksum(input []byte) (cksum [4]byte) { 12 | h := sha256.Sum256(input) 13 | h2 := sha256.Sum256(h[:]) 14 | copy(cksum[:], h2[:4]) 15 | return 16 | } 17 | 18 | // Check Encode 19 | func CheckEncode(input []byte, version byte) string { 20 | b := make([]byte, 0, 1+len(input)+4) 21 | b = append(b, version) 22 | b = append(b, input...) 23 | 24 | cksum := checksum(b) 25 | 26 | b = append(b, cksum[:]...) 27 | 28 | return StdEncoding.EncodeToString(b) 29 | } 30 | 31 | // Check Decode 32 | func CheckDecode(input string) (result []byte, version byte, err error) { 33 | decoded, _ := StdEncoding.DecodeString(input) 34 | if len(decoded) < 5 { 35 | return nil, 0, ErrInvalidFormat 36 | } 37 | 38 | version = decoded[0] 39 | var cksum [4]byte 40 | copy(cksum[:], decoded[len(decoded)-4:]) 41 | if checksum(decoded[:len(decoded)-4]) != cksum { 42 | return nil, 0, ErrChecksum 43 | } 44 | 45 | payload := decoded[1 : len(decoded)-4] 46 | result = append(result, payload...) 47 | 48 | return 49 | } 50 | -------------------------------------------------------------------------------- /base62/base62.go: -------------------------------------------------------------------------------- 1 | package base62 2 | 3 | import ( 4 | "math" 5 | "unsafe" 6 | "reflect" 7 | "strconv" 8 | ) 9 | 10 | type CorruptInputError int64 11 | 12 | func (e CorruptInputError) Error() string { 13 | return "go-encoding/base62: illegal base62 data at input byte " + strconv.FormatInt(int64(e), 10) 14 | } 15 | 16 | const encodeStd = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 17 | 18 | // StdEncoding is the standard base62 encoding. 19 | var StdEncoding = NewEncoding(encodeStd) 20 | 21 | /* 22 | * Encodings 23 | */ 24 | 25 | // An Encoding is a radix 62 encoding/decoding scheme, defined by a 62-character alphabet. 26 | type Encoding struct { 27 | encode [62]byte 28 | decodeMap [256]byte 29 | } 30 | 31 | // NewEncoding returns a new padded Encoding defined by the given alphabet, 32 | // which must be a 62-byte string that does not contain the padding character 33 | // or CR / LF ('\r', '\n'). 34 | func NewEncoding(encoder string) *Encoding { 35 | if len(encoder) != 62 { 36 | panic("go-encoding/base62: encoding alphabet is not 62-bytes long") 37 | } 38 | 39 | for i := 0; i < len(encoder); i++ { 40 | if encoder[i] == '\n' || encoder[i] == '\r' { 41 | panic("go-encoding/base62: encoding alphabet contains newline character") 42 | } 43 | } 44 | 45 | e := new(Encoding) 46 | copy(e.encode[:], encoder) 47 | 48 | for i := 0; i < len(e.decodeMap); i++ { 49 | e.decodeMap[i] = 0xFF 50 | } 51 | 52 | for i := 0; i < len(encoder); i++ { 53 | e.decodeMap[encoder[i]] = byte(i) 54 | } 55 | 56 | return e 57 | } 58 | 59 | /* 60 | * Encoder 61 | */ 62 | 63 | // Encode encodes src using the encoding enc. 64 | func (enc *Encoding) Encode(src []byte) []byte { 65 | if len(src) == 0 { 66 | return nil 67 | } 68 | 69 | // enc is a pointer receiver, so the use of enc.encode within the hot 70 | // loop below means a nil check at every operation. Lift that nil check 71 | // outside of the loop to speed up the encoder. 72 | _ = enc.encode 73 | 74 | rs := 0 75 | cs := int(math.Ceil(math.Log(256) / math.Log(62) * float64(len(src)))) 76 | dst := make([]byte, cs) 77 | 78 | for i := range src { 79 | c := 0 80 | v := int(src[i]) 81 | 82 | for j := cs - 1; j >= 0 && (v != 0 || c < rs); j-- { 83 | v += 256 * int(dst[j]) 84 | dst[j] = byte(v % 62) 85 | v /= 62 86 | c++ 87 | } 88 | 89 | rs = c 90 | } 91 | 92 | for i := range dst { 93 | dst[i] = enc.encode[dst[i]] 94 | } 95 | 96 | if cs > rs { 97 | return dst[cs-rs:] 98 | } 99 | 100 | return dst 101 | } 102 | 103 | // EncodeToString returns the base62 encoding of src. 104 | func (enc *Encoding) EncodeToString(src []byte) string { 105 | buf := enc.Encode(src) 106 | return string(buf) 107 | } 108 | 109 | /* 110 | * Decoder 111 | */ 112 | 113 | // Decode decodes src using the encoding enc. 114 | // If src contains invalid base62 data, it will return the 115 | // number of bytes successfully written and CorruptInputError. 116 | // New line characters (\r and \n) are ignored. 117 | func (enc *Encoding) Decode(src []byte) ([]byte, error) { 118 | if len(src) == 0 { 119 | return nil, nil 120 | } 121 | 122 | // Lift the nil check outside of the loop. enc.decodeMap is directly 123 | // used later in this function, to let the compiler know that the 124 | // receiver can't be nil. 125 | _ = enc.decodeMap 126 | 127 | rs := 0 128 | cs := int(math.Ceil(math.Log(62) / math.Log(256) * float64(len(src)))) 129 | dst := make([]byte, cs) 130 | for i := range src { 131 | if src[i] == '\n' || src[i] == '\r' { 132 | continue 133 | } 134 | 135 | c := 0 136 | v := int(enc.decodeMap[src[i]]) 137 | if v == 255 { 138 | return nil, CorruptInputError(src[i]) 139 | } 140 | 141 | for j := cs - 1; j >= 0 && (v != 0 || c < rs); j-- { 142 | v += 62 * int(dst[j]) 143 | dst[j] = byte(v % 256) 144 | v /= 256 145 | c++ 146 | } 147 | 148 | rs = c 149 | } 150 | 151 | if cs > rs { 152 | return dst[cs-rs:], nil 153 | } 154 | 155 | return dst, nil 156 | } 157 | 158 | // DecodeString returns the bytes represented by the base62 string s. 159 | func (enc *Encoding) DecodeString(s string) ([]byte, error) { 160 | sh := (*reflect.StringHeader)(unsafe.Pointer(&s)) 161 | bh := reflect.SliceHeader{Data: sh.Data, Len: sh.Len, Cap: sh.Len} 162 | return enc.Decode(*(*[]byte)(unsafe.Pointer(&bh))) 163 | } 164 | -------------------------------------------------------------------------------- /base62/base62_test.go: -------------------------------------------------------------------------------- 1 | package base62 2 | 3 | import ( 4 | "bytes" 5 | "testing" 6 | ) 7 | 8 | func TestEncode(t *testing.T) { 9 | for _, s := range SamplesStd { 10 | encoded := StdEncoding.Encode([]byte(s.source)) 11 | if bytes.Equal(encoded, s.targetBytes) { 12 | t.Logf("source: %-15s\ttarget: %s", s.source, s.target) 13 | } else { 14 | str := string(encoded) 15 | t.Errorf("source: %-15s\texpected target: %s(%d)\tactual target: %s(%d)", s.source, s.target, len(s.target), str, len(str)) 16 | } 17 | } 18 | } 19 | 20 | func TestEncodeToString(t *testing.T) { 21 | for _, s := range SamplesStd { 22 | encoded := StdEncoding.EncodeToString([]byte(s.source)) 23 | if len(encoded) == len(s.target) && encoded == s.target { 24 | t.Logf("source: %-15s\ttarget: %s", s.source, s.target) 25 | } else { 26 | t.Errorf("source: %-15s\texpected target: %s(%d)\tactual target: %s(%d)", s.source, s.target, len(s.target), encoded, len(encoded)) 27 | } 28 | } 29 | } 30 | 31 | func TestDecode(t *testing.T) { 32 | for _, s := range SamplesStd { 33 | decoded, err := StdEncoding.Decode(s.targetBytes) 34 | if err != nil { 35 | t.Error(err) 36 | continue 37 | } 38 | if bytes.Equal(decoded, s.sourceBytes) { 39 | t.Logf("target: %-15s\tsource: %s", s.target, s.source) 40 | } else { 41 | str := string(decoded) 42 | t.Errorf("target: %-15s\texpected source: %s(%d)\tactual source: %s(%d)", s.target, s.source, len(s.source), str, len(str)) 43 | } 44 | } 45 | } 46 | 47 | func TestDecodeString(t *testing.T) { 48 | for _, s := range SamplesStd { 49 | decoded, err := StdEncoding.DecodeString(s.target) 50 | if err != nil { 51 | t.Error(err) 52 | continue 53 | } 54 | if bytes.Equal(decoded, s.sourceBytes) { 55 | t.Logf("target: %-15s\tsource: %s", s.target, s.source) 56 | } else { 57 | str := string(decoded) 58 | t.Errorf("target: %-15s\texpected source: %s(%d)\tactual source: %s(%d)", s.target, s.source, len(s.source), str, len(str)) 59 | } 60 | } 61 | } 62 | 63 | func TestDecodeWithNewLine(t *testing.T) { 64 | for _, s := range SamplesWithNewLine { 65 | decoded, err := StdEncoding.Decode(s.targetBytes) 66 | if err != nil { 67 | t.Error(err) 68 | continue 69 | } 70 | if bytes.Equal(decoded, s.sourceBytes) { 71 | t.Logf("target: %-15s\tsource: %s", s.target, s.source) 72 | } else { 73 | str := string(decoded) 74 | t.Errorf("target: %-15s\texpected source: %s(%d)\tactual source: %s(%d)", s.target, s.source, len(s.source), str, len(str)) 75 | } 76 | } 77 | } 78 | 79 | func TestDecodeError(t *testing.T) { 80 | for _, s := range SamplesErr { 81 | decoded, err := StdEncoding.Decode(s.targetBytes) 82 | if err != nil { 83 | t.Logf("%s: \"%c\"", err.Error(), err) 84 | continue 85 | } 86 | str := string(decoded) 87 | t.Errorf("An error should have occurred, instead of returning \"%s\"", str) 88 | } 89 | } 90 | 91 | func TestEncodeWithCustomAlphabet(t *testing.T) { 92 | for _, s := range SamplesWithAlphabet { 93 | encoded := NewEncoding(s.alphabet).Encode([]byte(s.source)) 94 | if bytes.Equal(encoded, s.targetBytes) { 95 | t.Logf("source: %-15s\ttarget: %s", s.source, s.target) 96 | } else { 97 | str := string(encoded) 98 | t.Errorf("source: %-15s\texpected target: %s(%d)\tactual target: %s(%d)", s.source, s.target, len(s.target), str, len(str)) 99 | } 100 | } 101 | } 102 | 103 | func TestDecodeWithCustomAlphabet(t *testing.T) { 104 | for _, s := range SamplesWithAlphabet { 105 | decoded, err := NewEncoding(s.alphabet).Decode(s.targetBytes) 106 | if err != nil { 107 | t.Error(err) 108 | continue 109 | } 110 | if bytes.Equal(decoded, s.sourceBytes) { 111 | t.Logf("target: %-15s\tsource: %s", s.target, s.source) 112 | } else { 113 | str := string(decoded) 114 | t.Errorf("target: %-15s\texpected source: %s(%d)\tactual source: %s(%d)", s.target, s.source, len(s.source), str, len(str)) 115 | } 116 | } 117 | } 118 | 119 | func NewSample(source, target string) *Sample { 120 | return &Sample{source: source, target: target, sourceBytes: []byte(source), targetBytes: []byte(target)} 121 | } 122 | 123 | func NewSampleWithAlphabet(source, target, alphabet string) *Sample { 124 | return &Sample{source: source, target: target, sourceBytes: []byte(source), targetBytes: []byte(target), alphabet: alphabet} 125 | } 126 | 127 | type Sample struct { 128 | source string 129 | target string 130 | sourceBytes []byte 131 | targetBytes []byte 132 | alphabet string 133 | } 134 | 135 | var SamplesStd = []*Sample{ 136 | NewSample("", ""), 137 | NewSample("f", "1e"), 138 | NewSample("fo", "6ox"), 139 | NewSample("foo", "SAPP"), 140 | NewSample("foob", "1sIyuo"), 141 | NewSample("fooba", "7kENWa1"), 142 | NewSample("foobar", "VytN8Wjy"), 143 | 144 | NewSample("su", "7gj"), 145 | NewSample("sur", "VkRe"), 146 | NewSample("sure", "275mAn"), 147 | NewSample("sure.", "8jHquZ4"), 148 | NewSample("asure.", "UQPPAab8"), 149 | NewSample("easure.", "26h8PlupSA"), 150 | NewSample("leasure.", "9IzLUOIY2fe"), 151 | 152 | NewSample("=", "z"), 153 | NewSample(">", "10"), 154 | NewSample("?", "11"), 155 | NewSample("11", "3H7"), 156 | NewSample("111", "DWfh"), 157 | NewSample("1111", "tquAL"), 158 | NewSample("11111", "3icRuhV"), 159 | NewSample("111111", "FMElG7cn"), 160 | 161 | NewSample("Hello, World!", "1wJfrzvdbtXUOlUjUf"), 162 | NewSample("你好,世界!", "1ugmIChyMAcCbDRpROpAtpXdp"), 163 | NewSample("こんにちは", "1fyB0pNlcVqP3tfXZ1FmB"), 164 | NewSample("안녕하십니까", "1yl6dfHPaO9hroEXU9qFioFhM"), 165 | } 166 | 167 | var SamplesWithAlphabet = []*Sample{ 168 | NewSampleWithAlphabet("", "", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), 169 | NewSampleWithAlphabet("f", "Bo", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), 170 | NewSampleWithAlphabet("fo", "Gy7", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), 171 | NewSampleWithAlphabet("foo", "cKZZ", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), 172 | NewSampleWithAlphabet("foob", "B2S84y", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), 173 | NewSampleWithAlphabet("fooba", "HuOXgkB", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), 174 | NewSampleWithAlphabet("foobar", "f83XIgt8", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), 175 | 176 | NewSampleWithAlphabet("su", "Hqt", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), 177 | NewSampleWithAlphabet("sur", "fubo", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), 178 | NewSampleWithAlphabet("sure", "CHFwKx", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), 179 | NewSampleWithAlphabet("sure.", "ItR04jE", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), 180 | NewSampleWithAlphabet("asure.", "eaZZKklI", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), 181 | NewSampleWithAlphabet("easure.", "CGrIZv4zcK", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), 182 | NewSampleWithAlphabet("leasure.", "JS9VeYSiCpo", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), 183 | 184 | NewSampleWithAlphabet("=", "9", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), 185 | NewSampleWithAlphabet(">", "BA", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), 186 | NewSampleWithAlphabet("?", "BB", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), 187 | NewSampleWithAlphabet("11", "DRH", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), 188 | NewSampleWithAlphabet("111", "Ngpr", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), 189 | NewSampleWithAlphabet("1111", "304KV", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), 190 | NewSampleWithAlphabet("11111", "Dsmb4rf", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), 191 | NewSampleWithAlphabet("111111", "PWOvQHmx", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), 192 | 193 | NewSampleWithAlphabet("Hello, World!", "B6Tp195nl3heYvetep", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), 194 | NewSampleWithAlphabet("你好,世界!", "B4qwSMr8WKmMlNbzbYzK3zhnz", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), 195 | NewSampleWithAlphabet("こんにちは", "Bp8LAzXvmf0ZD3phjBPwL", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), 196 | NewSampleWithAlphabet("안녕하십니까", "B8vGnpRZkYJr1yOheJ0PsyPrW", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), 197 | } 198 | 199 | var SamplesWithNewLine = []*Sample{ 200 | NewSample("111111", "FMEl\nG7cn"), 201 | NewSample("111111", "FMEl\rG7cn"), 202 | NewSample("Hello, World!", "1wJfrzvdb\ntXUOlUjUf"), 203 | NewSample("Hello, World!", "1wJfrzvdb\rtXUOlUjUf"), 204 | NewSample("你好,世界!", "1ugmIChyMAcC\nbDRpROpAtpXdp"), 205 | NewSample("你好,世界!", "1ugmIChyMAcC\rbDRpROpAtpXdp"), 206 | } 207 | 208 | var SamplesErr = []*Sample{ 209 | NewSample("", "Hello, World!"), 210 | NewSample("", "哈哈"), 211 | NewSample("", "はは"), 212 | } 213 | -------------------------------------------------------------------------------- /base91/base91.go: -------------------------------------------------------------------------------- 1 | package base91 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | ) 7 | 8 | // A CorruptInputError is returned if invalid base91 data is encountered during decoding. 9 | type CorruptInputError int64 10 | 11 | func (e CorruptInputError) Error() string { 12 | return fmt.Sprintf("go-encoding/base91: illegal base91 data at input byte %d", int64(e)) 13 | } 14 | 15 | // encodeStd is the standard base91 encoding alphabet (that is, the one specified 16 | // at http://base91.sourceforge.net). Of the 95 printable ASCII characters, the 17 | // following four are omitted: space (0x20), apostrophe (0x27), hyphen (0x2d), 18 | // and backslash (0x5c). 19 | const encodeStd = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$%&()*+,./:;<=>?@[]^_`{|}~\"" 20 | 21 | // StdEncoding is the standard base91 encoding (that is, the one specified 22 | // at http://base91.sourceforge.net). Of the 95 printable ASCII characters, 23 | // the following four are omitted: space (0x20), apostrophe (0x27), 24 | // hyphen (0x2d), and backslash (0x5c). 25 | var StdEncoding = NewEncoding(encodeStd) 26 | 27 | /* 28 | * Encodings 29 | */ 30 | 31 | // An Encoding is a base 91 encoding/decoding scheme defined by a 91-character alphabet. 32 | type Encoding struct { 33 | encode [91]byte 34 | decodeMap [256]byte 35 | } 36 | 37 | // NewEncoding returns a new Encoding defined by the given alphabet, which must 38 | // be a 91-byte string that does not contain CR or LF ('\r', '\n'). 39 | func NewEncoding(encoder string) *Encoding { 40 | if len(encoder) != 91 { 41 | panic("go-encoding/base91: encoding alphabet is not 91 bytes long") 42 | } 43 | 44 | for i := 0; i < len(encoder); i++ { 45 | if encoder[i] == '\n' || encoder[i] == '\r' { 46 | panic("go-encoding/base91: encoding alphabet contains newline character") 47 | } 48 | } 49 | 50 | e := new(Encoding) 51 | copy(e.encode[:], encoder) 52 | 53 | for i := 0; i < len(e.decodeMap); i++ { 54 | // 0xff indicates that this entry in the decode map is not in the encoding alphabet. 55 | e.decodeMap[i] = 0xff 56 | } 57 | 58 | for i := 0; i < len(encoder); i++ { 59 | e.decodeMap[encoder[i]] = byte(i) 60 | } 61 | 62 | return e 63 | } 64 | 65 | /* 66 | * Encoder 67 | */ 68 | 69 | // Encode encodes src using the encoding enc, writing bytes to dst. 70 | // It returns the number of bytes written, because the exact output size cannot 71 | // be known before encoding takes place. EncodedLen(len(src)) may be used to 72 | // determine an upper bound on the output size when allocating a dst slice. 73 | func (enc *Encoding) Encode(dst, src []byte) int { 74 | var queue, numBits uint 75 | 76 | n := 0 77 | for i := 0; i < len(src); i++ { 78 | queue |= uint(src[i]) << numBits 79 | numBits += 8 80 | if numBits > 13 { 81 | var v uint = queue & 8191 82 | 83 | if v > 88 { 84 | queue >>= 13 85 | numBits -= 13 86 | } else { 87 | // We can take 14 bits. 88 | v = queue & 16383 89 | queue >>= 14 90 | numBits -= 14 91 | } 92 | dst[n] = enc.encode[v%91] 93 | n++ 94 | dst[n] = enc.encode[v/91] 95 | n++ 96 | } 97 | } 98 | 99 | if numBits > 0 { 100 | dst[n] = enc.encode[queue%91] 101 | n++ 102 | 103 | if numBits > 7 || queue > 90 { 104 | dst[n] = enc.encode[queue/91] 105 | n++ 106 | } 107 | } 108 | 109 | return n 110 | } 111 | 112 | // EncodeToString returns the base91 encoding of src. 113 | func (enc *Encoding) EncodeToString(src []byte) string { 114 | buf := make([]byte, enc.EncodedLen(len(src))) 115 | n := enc.Encode(buf, src) 116 | return string(buf[:n]) 117 | } 118 | 119 | // EncodedLen returns an upper bound on the length in bytes of the base91 encoding 120 | // of an input buffer of length n. The true encoded length may be shorter. 121 | func (enc *Encoding) EncodedLen(n int) int { 122 | // At worst, base91 encodes 13 bits into 16 bits. Even though 14 bits can 123 | // sometimes be encoded into 16 bits, assume the worst case to get the upper 124 | // bound on encoded length. 125 | return int(math.Ceil(float64(n) * 16.0 / 13.0)) 126 | } 127 | 128 | /* 129 | * Decoder 130 | */ 131 | 132 | // Decode decodes src using the encoding enc. It writes at most DecodedLen(len(src)) 133 | // bytes to dst and returns the number of bytes written. If src contains invalid base91 134 | // data, it will return the number of bytes successfully written and CorruptInputError. 135 | func (enc *Encoding) Decode(dst, src []byte) (int, error) { 136 | var queue, numBits uint 137 | var v int = -1 138 | 139 | n := 0 140 | for i := 0; i < len(src); i++ { 141 | if enc.decodeMap[src[i]] == 0xff { 142 | // The character is not in the encoding alphabet. 143 | return n, CorruptInputError(i) 144 | } 145 | 146 | if v == -1 { 147 | // Start the next value. 148 | v = int(enc.decodeMap[src[i]]) 149 | } else { 150 | v += int(enc.decodeMap[src[i]]) * 91 151 | queue |= uint(v) << numBits 152 | 153 | if (v & 8191) > 88 { 154 | numBits += 13 155 | } else { 156 | numBits += 14 157 | } 158 | 159 | for ok := true; ok; ok = (numBits > 7) { 160 | dst[n] = byte(queue) 161 | n++ 162 | 163 | queue >>= 8 164 | numBits -= 8 165 | } 166 | 167 | // Mark this value complete. 168 | v = -1 169 | } 170 | } 171 | 172 | if v != -1 { 173 | dst[n] = byte(queue | uint(v)<", "!A"), 112 | NewSample("?", "#A"), 113 | NewSample("11", "hwB"), 114 | NewSample("111", "hwdE"), 115 | NewSample("1111", "hw;aM"), 116 | NewSample("11111", "hw;a2iA"), 117 | NewSample("111111", "hw;a2iHB"), 118 | 119 | NewSample("Hello, World!", ">OwJh>}AQ;r@@Y?F"), 120 | NewSample("你好,世界!", "I_5k7az}Thlz6;n[kjFVUBB"), 121 | NewSample("こんにちは", "cFs@CCLU=(Py|QE@4rF"), 122 | NewSample("안녕하십니까", "99v?OEn?@[]^_`{|}~\""), 127 | NewSampleWithAlphabet("f", "LB", "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz!#$%&()*+,./:;<=>?@[]^_`{|}~\""), 128 | NewSampleWithAlphabet("fo", "3hD", "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz!#$%&()*+,./:;<=>?@[]^_`{|}~\""), 129 | NewSampleWithAlphabet("foo", "3h.J", "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz!#$%&()*+,./:;<=>?@[]^_`{|}~\""), 130 | NewSampleWithAlphabet("foob", "3h/sY", "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz!#$%&()*+,./:;<=>?@[]^_`{|}~\""), 131 | NewSampleWithAlphabet("fooba", "3h/si)A", "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz!#$%&()*+,./:;<=>?@[]^_`{|}~\""), 132 | NewSampleWithAlphabet("foobar", "3h/si)kC", "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz!#$%&()*+,./:;<=>?@[]^_`{|}~\""), 133 | 134 | NewSampleWithAlphabet("su", "5yD", "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz!#$%&()*+,./:;<=>?@[]^_`{|}~\""), 135 | NewSampleWithAlphabet("sur", "5yFK", "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz!#$%&()*+,./:;<=>?@[]^_`{|}~\""), 136 | NewSampleWithAlphabet("sure", "5yp6Z", "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz!#$%&()*+,./:;<=>?@[]^_`{|}~\""), 137 | NewSampleWithAlphabet("sure.", "5yp6v6A", "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz!#$%&()*+,./:;<=>?@[]^_`{|}~\""), 138 | NewSampleWithAlphabet("asure.", "ls4t5,BB", "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz!#$%&()*+,./:;<=>?@[]^_`{|}~\""), 139 | NewSampleWithAlphabet("easure.", "_Dx6j@\"@C", "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz!#$%&()*+,./:;<=>?@[]^_`{|}~\""), 140 | NewSampleWithAlphabet("leasure.", "XPH?@[]^_`{|}~\""), 141 | 142 | NewSampleWithAlphabet("=", "zA", "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz!#$%&()*+,./:;<=>?@[]^_`{|}~\""), 143 | NewSampleWithAlphabet(">", "!A", "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz!#$%&()*+,./:;<=>?@[]^_`{|}~\""), 144 | NewSampleWithAlphabet("?", "#A", "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz!#$%&()*+,./:;<=>?@[]^_`{|}~\""), 145 | NewSampleWithAlphabet("11", "7mB", "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz!#$%&()*+,./:;<=>?@[]^_`{|}~\""), 146 | NewSampleWithAlphabet("111", "7m3E", "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz!#$%&()*+,./:;<=>?@[]^_`{|}~\""), 147 | NewSampleWithAlphabet("1111", "7m;0M", "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz!#$%&()*+,./:;<=>?@[]^_`{|}~\""), 148 | NewSampleWithAlphabet("11111", "7m;0s8A", "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz!#$%&()*+,./:;<=>?@[]^_`{|}~\""), 149 | NewSampleWithAlphabet("111111", "7m;0s8HB", "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz!#$%&()*+,./:;<=>?@[]^_`{|}~\""), 150 | 151 | NewSampleWithAlphabet("Hello, World!", ">OmJ7>}AQ;h@@Y?F", "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz!#$%&()*+,./:;<=>?@[]^_`{|}~\""), 152 | NewSampleWithAlphabet("你好,世界!", "I_vax0p}T7bpw;d[a9FVUBB", "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz!#$%&()*+,./:;<=>?@[]^_`{|}~\""), 153 | NewSampleWithAlphabet("こんにちは", "2Fi@CCLU=(Po|QE@uhF", "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz!#$%&()*+,./:;<=>?@[]^_`{|}~\""), 154 | NewSampleWithAlphabet("안녕하십니까", "zzl?OEd<60&!b!?]DYLh{IB", "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz!#$%&()*+,./:;<=>?@[]^_`{|}~\""), 155 | } 156 | 157 | var SamplesErr = []*Sample{ 158 | NewSample("", "Hello, World!"), 159 | NewSample("", "哈哈"), 160 | NewSample("", "はは"), 161 | } 162 | -------------------------------------------------------------------------------- /base92/base92.go: -------------------------------------------------------------------------------- 1 | package base92 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | const ( 8 | // approximation of ceil(log(256)/log(base)). 9 | // power of two -> speed up DecodeString() 10 | numerator = 16 11 | denominator = 13 12 | ) 13 | 14 | // encodeStd is the standard base92 encoding alphabet 15 | const encodeStd = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-:+=^!/*?&<>()[]{}@%$#|;,_~`\"" 16 | 17 | // StdEncoding is the default encoding enc. 18 | var StdEncoding = NewEncoding(encodeStd) 19 | 20 | /* 21 | * Encodings 22 | */ 23 | 24 | // An Encoding is a base 92 encoding/decoding scheme defined by a 92-character alphabet. 25 | type Encoding struct { 26 | encode [92]byte 27 | decodeMap [128]byte 28 | } 29 | 30 | // NewEncoding returns a new Encoding defined by the given alphabet, which must 31 | // be a 92-byte string that does not contain CR or LF ('\r', '\n'). 32 | func NewEncoding(encoder string) *Encoding { 33 | if len(encoder) != 92 { 34 | panic("go-encoding/base92: encoding alphabet is not 92 bytes long") 35 | } 36 | 37 | for i := 0; i < len(encoder); i++ { 38 | if encoder[i] == '\n' || encoder[i] == '\r' { 39 | panic("go-encoding/base92: encoding alphabet contains newline character") 40 | } 41 | } 42 | 43 | e := new(Encoding) 44 | copy(e.encode[:], encoder) 45 | 46 | for i := 0; i < len(e.decodeMap); i++ { 47 | // 0xff indicates that this entry in the decode map is not in the encoding alphabet. 48 | e.decodeMap[i] = 0xff 49 | } 50 | 51 | for i := 0; i < len(encoder); i++ { 52 | e.decodeMap[encoder[i]] = byte(i) 53 | } 54 | 55 | return e 56 | } 57 | 58 | /* 59 | * Encoder 60 | */ 61 | 62 | // Encode encodes binary bytes. 63 | func (enc *Encoding) Encode(bin []byte) []byte { 64 | size := len(bin) 65 | 66 | zcount := 0 67 | for zcount < size && bin[zcount] == 0 { 68 | zcount++ 69 | } 70 | 71 | // It is crucial to make this as short as possible, especially for 72 | // the usual case of bitcoin addrs 73 | // This is an integer simplification of 74 | // ceil(log(256)/log(base)) 75 | size = zcount + (size-zcount)*numerator/denominator + 1 76 | 77 | out := make([]byte, size) 78 | 79 | var i, high int 80 | var carry uint32 81 | 82 | high = size - 1 83 | for _, b := range bin { 84 | i = size - 1 85 | for carry = uint32(b); i > high || carry != 0; i-- { 86 | carry += 256 * uint32(out[i]) 87 | out[i] = byte(carry % 92) 88 | carry /= 92 89 | } 90 | 91 | high = i 92 | } 93 | 94 | // Determine the additional "zero-gap" in the buffer (aside from zcount) 95 | for i = zcount; i < size && out[i] == 0; i++ { 96 | } 97 | 98 | // Now encode the values with actual alphabet in-place 99 | val := out[i-zcount:] 100 | size = len(val) 101 | for i = 0; i < size; i++ { 102 | out[i] = enc.encode[val[i]] 103 | } 104 | 105 | return out[:size] 106 | } 107 | 108 | // EncodeToString encodes binary bytes into Base92 bytes. 109 | func (enc *Encoding) EncodeToString(bin []byte) string { 110 | return string(enc.Encode(bin)) 111 | } 112 | 113 | /* 114 | * Decoder 115 | */ 116 | 117 | // Decode decodes src using the encoding enc. 118 | func (enc *Encoding) Decode(src []byte) ([]byte, error) { 119 | return enc.DecodeString(string(src)) 120 | } 121 | 122 | // DecodeString decodes a Base92 string into binary bytes. 123 | func (enc *Encoding) DecodeString(str string) ([]byte, error) { 124 | if len(str) == 0 { 125 | return nil, nil 126 | } 127 | 128 | zero := enc.encode[0] 129 | strLen := len(str) 130 | 131 | var zcount int 132 | for i := 0; i < strLen && str[i] == zero; i++ { 133 | zcount++ 134 | } 135 | 136 | var t, c uint64 137 | 138 | // the 32bit algo stretches the result up to 2 times 139 | binu := make([]byte, 2*((strLen*denominator/numerator)+1)) 140 | outi := make([]uint32, (strLen+3)/4) 141 | 142 | for _, r := range str { 143 | if r > 127 { 144 | return nil, fmt.Errorf("go-encoding/base92: high-bit set on invalid digit") 145 | } 146 | 147 | if enc.decodeMap[r] == 0xff { 148 | return nil, fmt.Errorf("go-encoding/base92: invalid digit %q", r) 149 | } 150 | 151 | c = uint64(enc.decodeMap[r]) 152 | 153 | for j := len(outi) - 1; j >= 0; j-- { 154 | t = uint64(outi[j])*92 + c 155 | c = t >> 32 156 | outi[j] = uint32(t & 0xffffffff) 157 | } 158 | } 159 | 160 | // initial mask depends on b92sz, 161 | // on further loops it always starts at 24 bits 162 | mask := (uint(strLen%4) * 8) 163 | if mask == 0 { 164 | mask = 32 165 | } 166 | mask -= 8 167 | 168 | outLen := 0 169 | for j := 0; j < len(outi); j++ { 170 | // loop relies on uint overflow 171 | for mask < 32 { 172 | binu[outLen] = byte(outi[j] >> mask) 173 | mask -= 8 174 | outLen++ 175 | } 176 | 177 | mask = 24 178 | } 179 | 180 | // find the most significant byte post-decode, if any 181 | for msb := zcount; msb < len(binu); msb++ { 182 | if binu[msb] > 0 { 183 | return binu[msb-zcount : outLen], nil 184 | } 185 | } 186 | 187 | return binu[:outLen], nil 188 | } 189 | -------------------------------------------------------------------------------- /base92/base92_test.go: -------------------------------------------------------------------------------- 1 | package base92 2 | 3 | import ( 4 | "bytes" 5 | "reflect" 6 | "testing" 7 | ) 8 | 9 | var cases = []struct { 10 | name string 11 | bin []byte 12 | }{ 13 | {"nil", nil}, 14 | {"empty", []byte{}}, 15 | {"zero", []byte{0}}, 16 | {"one", []byte{1}}, 17 | {"two", []byte{2}}, 18 | {"ten", []byte{10}}, 19 | {"2zeros", []byte{0, 0}}, 20 | {"2ones", []byte{1, 1}}, 21 | {"64zeros", []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 22 | {"65zeros", []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 23 | {"ascii", []byte("c'est une longue chanson")}, 24 | {"utf8", []byte("Garçon, un café très fort !")}, 25 | } 26 | 27 | func Test_Encode(t *testing.T) { 28 | for _, c := range cases { 29 | t.Run(c.name, func(t *testing.T) { 30 | str := StdEncoding.EncodeToString(c.bin) 31 | 32 | ni := len(c.bin) 33 | if ni > 70 { 34 | ni = 70 // print max the first 70 bytes 35 | } 36 | na := len(str) 37 | if na > 70 { 38 | na = 70 // print max the first 70 characters 39 | } 40 | t.Logf("bin len=%d [:%d]=%v", len(c.bin), ni, c.bin[:ni]) 41 | t.Logf("str len=%d [:%d]=%q", len(str), na, str[:na]) 42 | 43 | got, err := StdEncoding.DecodeString(str) 44 | if err != nil { 45 | t.Errorf("Decode() error = %v", err) 46 | return 47 | } 48 | 49 | ng := len(got) 50 | if ng > 70 { 51 | ng = 70 // print max the first 70 bytes 52 | } 53 | t.Logf("got len=%d [:%d]=%v", len(got), ng, got[:ng]) 54 | 55 | if (len(got) == 0) && (len(c.bin) == 0) { 56 | return 57 | } 58 | 59 | if !reflect.DeepEqual(got, c.bin) { 60 | t.Errorf("Decode() = %v, want %v", got, c.bin) 61 | } 62 | }) 63 | } 64 | } 65 | 66 | func Test_Encode2(t *testing.T) { 67 | for _, s := range SamplesStd { 68 | encoded := string(StdEncoding.Encode(s.sourceBytes)) 69 | if len(encoded) == len(s.target) && encoded == s.target { 70 | t.Logf("source: %-15s\ttarget: %s", s.source, s.target) 71 | } else { 72 | t.Errorf("source: %-15s\texpected target: %s(%d)\tactual target: %s(%d)", s.source, s.target, len(s.target), encoded, len(encoded)) 73 | } 74 | } 75 | } 76 | 77 | func Test_Decode2(t *testing.T) { 78 | for _, s := range SamplesStd { 79 | decoded, err := StdEncoding.Decode(s.targetBytes) 80 | if err != nil { 81 | t.Error(err) 82 | continue 83 | } 84 | 85 | if bytes.Equal(decoded, s.sourceBytes) { 86 | t.Logf("target: %-15s\tsource: %s", s.target, s.source) 87 | } else { 88 | str := string(decoded) 89 | t.Errorf("target: %-15s\texpected source: %s(%d)\tactual source: %s(%d)", s.target, s.source, len(s.source), str, len(str)) 90 | } 91 | } 92 | } 93 | 94 | func Test_EncodeToString(t *testing.T) { 95 | for _, s := range SamplesStd { 96 | encoded := StdEncoding.EncodeToString([]byte(s.source)) 97 | if len(encoded) == len(s.target) && encoded == s.target { 98 | t.Logf("source: %-15s\ttarget: %s", s.source, s.target) 99 | } else { 100 | t.Errorf("source: %-15s\texpected target: %s(%d)\tactual target: %s(%d)", s.source, s.target, len(s.target), encoded, len(encoded)) 101 | } 102 | } 103 | } 104 | 105 | func Test_DecodeString(t *testing.T) { 106 | for _, s := range SamplesStd { 107 | decoded, err := StdEncoding.DecodeString(s.target) 108 | if err != nil { 109 | t.Error(err) 110 | continue 111 | } 112 | 113 | if bytes.Equal(decoded, s.sourceBytes) { 114 | t.Logf("target: %-15s\tsource: %s", s.target, s.source) 115 | } else { 116 | str := string(decoded) 117 | t.Errorf("target: %-15s\texpected source: %s(%d)\tactual source: %s(%d)", s.target, s.source, len(s.source), str, len(str)) 118 | } 119 | } 120 | } 121 | 122 | func Test_EncodeWithCustomAlphabet(t *testing.T) { 123 | for _, s := range SamplesWithAlphabet { 124 | encoded := NewEncoding(s.alphabet).EncodeToString(s.sourceBytes) 125 | if encoded == s.target { 126 | t.Logf("source: %-15s\ttarget: %s", s.source, s.target) 127 | } else { 128 | str := string(encoded) 129 | t.Errorf("source: %-15s\texpected target: %s(%d)\tactual target: %s(%d)", s.source, s.target, len(s.target), str, len(str)) 130 | } 131 | } 132 | } 133 | 134 | func Test_DecodeWithCustomAlphabet(t *testing.T) { 135 | for _, s := range SamplesWithAlphabet { 136 | decoded, err := NewEncoding(s.alphabet).DecodeString(s.target) 137 | if err != nil { 138 | t.Error(err) 139 | continue 140 | } 141 | if bytes.Equal(decoded, s.sourceBytes) { 142 | t.Logf("target: %-15s\tsource: %s", s.target, s.source) 143 | } else { 144 | str := string(decoded) 145 | t.Errorf("target: %-15s\texpected source: %s(%d)\tactual source: %s(%d)", s.target, s.source, len(s.source), str, len(str)) 146 | } 147 | } 148 | } 149 | 150 | func Test_DecodeError(t *testing.T) { 151 | for _, s := range SamplesErr { 152 | decoded, err := StdEncoding.DecodeString(s.target) 153 | if err != nil { 154 | t.Logf("%s: \"%c\"", err.Error(), err) 155 | continue 156 | } 157 | 158 | str := string(decoded) 159 | t.Errorf("An error should have occurred, instead of returning \"%s\"", str) 160 | } 161 | } 162 | 163 | func NewSample(source, target string) *Sample { 164 | return &Sample{source: source, target: target, sourceBytes: []byte(source), targetBytes: []byte(target)} 165 | } 166 | 167 | func NewSampleWithAlphabet(source, target, alphabet string) *Sample { 168 | return &Sample{source: source, target: target, sourceBytes: []byte(source), targetBytes: []byte(target), alphabet: alphabet} 169 | } 170 | 171 | // encodeStdTest use encodeStd to replace `;"` to ` '` 172 | const encodeStdTest = " !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~" 173 | const encodeStdTest2 = "!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_abcdefghijklmnopqrstuvwxyz{|}~" 174 | 175 | type Sample struct { 176 | source string 177 | target string 178 | sourceBytes []byte 179 | targetBytes []byte 180 | alphabet string 181 | } 182 | 183 | var SamplesStd = []*Sample{ 184 | NewSample("", ""), 185 | NewSample("f", "1a"), 186 | NewSample("fo", "393"), 187 | NewSample("foo", "8VdP"), 188 | NewSample("foob", "n\"1=`"), 189 | NewSample("fooba", "=/o>zJ"), 190 | NewSample("foobar", "21!/2`*G"), 191 | 192 | NewSample("su", "3Jp"), 193 | NewSample("sur", "9+`>"), 194 | NewSample("sure", "r3U-1"), 195 | NewSample("sure.", "(m5^vq"), 196 | NewSample("asure.", "1#+m[Bem"), 197 | NewSample("easure.", "5PN!3(DX>"), 198 | NewSample("leasure.", "gN#iXt$=}e"), 199 | 200 | NewSample("=", "Z"), 201 | NewSample(">", "."), 202 | NewSample("?", "-"), 203 | NewSample("11", "1I@"), 204 | NewSample("111", "4c@|"), 205 | NewSample("1111", "bL{~5"), 206 | NewSample("11111", "w5iL>F"), 207 | NewSample("111111", "~iHN3eV"), 208 | 209 | NewSample("Hello, World!", "k3f/B6!rQL=RhJ?d"), 210 | NewSample("你好,世界!", "1m&5KqaKycjNt]Y8I0FkS:x"), 211 | NewSample("こんにちは", "5rIFEY^zgV@2jOj{s|z"), 212 | NewSample("안녕하십니까", "1q=eNur3aBy#78Cu:Zjn[`A"), 213 | 214 | NewSample(string([]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255}), "01hQh.Jm{XcF^"), 215 | } 216 | 217 | var SamplesWithAlphabet = []*Sample{ 218 | NewSampleWithAlphabet("", "", encodeStdTest), 219 | NewSampleWithAlphabet("f", "!+", encodeStdTest), 220 | NewSampleWithAlphabet("fo", "$*$", encodeStdTest), 221 | NewSampleWithAlphabet("foo", ")[.U", encodeStdTest), 222 | NewSampleWithAlphabet("foob", "8~!e}", encodeStdTest), 223 | NewSampleWithAlphabet("fooba", "eh9mEO", encodeStdTest), 224 | NewSampleWithAlphabet("foobar", "#!gh#}iL", encodeStdTest), 225 | 226 | NewSampleWithAlphabet("su", "$O:", encodeStdTest), 227 | NewSampleWithAlphabet("sur", "*d}m", encodeStdTest), 228 | NewSampleWithAlphabet("sure", "=$Zb!", encodeStdTest), 229 | NewSampleWithAlphabet("sure.", "n7&fA<", encodeStdTest), 230 | NewSampleWithAlphabet("asure.", "!wd7pG/7", encodeStdTest), 231 | NewSampleWithAlphabet("easure.", "&USg$nI^m", encodeStdTest), 232 | NewSampleWithAlphabet("leasure.", "1Sw3^?ves/", encodeStdTest), 233 | 234 | NewSampleWithAlphabet("=", "`", encodeStdTest), 235 | NewSampleWithAlphabet(">", "a", encodeStdTest), 236 | NewSampleWithAlphabet("?", "b", encodeStdTest), 237 | NewSampleWithAlphabet("11", "!Nt", encodeStdTest), 238 | NewSampleWithAlphabet("111", "%-tx", encodeStdTest), 239 | NewSampleWithAlphabet("1111", ",Qr|&", encodeStdTest), 240 | NewSampleWithAlphabet("11111", "B&3QmK", encodeStdTest), 241 | NewSampleWithAlphabet("111111", "|3MS$/[", encodeStdTest), 242 | 243 | NewSampleWithAlphabet("Hello, World!", "5$0hG'g=VQeW2Oj.", encodeStdTest), 244 | NewSampleWithAlphabet("你好,世界!", "!7k&P<+PD-4S?q_)N K5XcC", encodeStdTest), 245 | NewSampleWithAlphabet("こんにちは", "&=NKJ_fE1[t#4T4r>xE", encodeStdTest), 246 | NewSampleWithAlphabet("안녕하십니까", "! 0 { 69 | mod := new(big.Int) 70 | num.DivMod(num, big.NewInt(enc.radix), mod) 71 | output = alphabet[mod.Int64()] + output 72 | } 73 | 74 | for _, i := range input { 75 | if i != 0 { 76 | break 77 | } 78 | 79 | output = alphabet[0] + output 80 | } 81 | 82 | return 83 | } 84 | 85 | /* 86 | * Decoder 87 | */ 88 | 89 | // Decode decodes src using the encoding enc. 90 | func (enc *Encoding) Decode(src []byte) ([]byte, error) { 91 | return enc.DecodeString(string(src)) 92 | } 93 | 94 | // DecodeString decodes src using the encoding enc. 95 | func (enc *Encoding) DecodeString(input string) (output []byte, err error) { 96 | result := big.NewInt(0) 97 | multi := big.NewInt(1) 98 | 99 | currBig := new(big.Int) 100 | for i := len(input) - 1; i >= 0; i-- { 101 | curr := enc.decodeMap[input[i]] 102 | if curr == 0xff { 103 | err = fmt.Errorf("go-encoding/%s: Invalid input string at character \"%s\", position %d", enc.name, string(input[i]), i) 104 | return 105 | } 106 | 107 | currBig.SetInt64(int64(curr)) 108 | currBig.Mul(multi, currBig) 109 | result.Add(result, currBig) 110 | multi.Mul(multi, big.NewInt(enc.radix)) 111 | } 112 | 113 | resultBytes := result.Bytes() 114 | var numZeros int 115 | for numZeros = 0; numZeros < len(input); numZeros++ { 116 | if(input[numZeros] != enc.encode[0]) { 117 | break 118 | } 119 | } 120 | 121 | length := numZeros + len(resultBytes) 122 | output = make([]byte, length) 123 | copy(output[numZeros:], resultBytes) 124 | 125 | return 126 | } 127 | -------------------------------------------------------------------------------- /baseenc/baseenc_test.go: -------------------------------------------------------------------------------- 1 | package baseenc 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | ) 7 | 8 | const encodeBase36 = "0123456789abcdefghijklmnopqrstuvwxyz" 9 | 10 | var cases = []struct { 11 | name string 12 | bin []byte 13 | }{ 14 | {"nil", nil}, 15 | {"empty", []byte{}}, 16 | {"zero", []byte{0}}, 17 | {"one", []byte{1}}, 18 | {"two", []byte{2}}, 19 | {"ten", []byte{10}}, 20 | {"2zeros", []byte{0, 0}}, 21 | {"2ones", []byte{1, 1}}, 22 | {"64zeros", []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 23 | {"65zeros", []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 24 | {"ascii", []byte("c'est une longue chanson")}, 25 | {"utf8", []byte("Garçon, un café très fort !")}, 26 | } 27 | 28 | func Test_Encode(t *testing.T) { 29 | base36 := NewEncoding("base36", 36, encodeBase36) 30 | 31 | for _, c := range cases { 32 | t.Run(c.name, func(t *testing.T) { 33 | str := base36.EncodeToString(c.bin) 34 | 35 | ni := len(c.bin) 36 | if ni > 70 { 37 | ni = 70 // print max the first 70 bytes 38 | } 39 | na := len(str) 40 | if na > 70 { 41 | na = 70 // print max the first 70 characters 42 | } 43 | t.Logf("bin len=%d [:%d]=%v", len(c.bin), ni, c.bin[:ni]) 44 | t.Logf("str len=%d [:%d]=%q", len(str), na, str[:na]) 45 | 46 | got, err := base36.DecodeString(str) 47 | if err != nil { 48 | t.Errorf("Decode() error = %v", err) 49 | return 50 | } 51 | 52 | ng := len(got) 53 | if ng > 70 { 54 | ng = 70 // print max the first 70 bytes 55 | } 56 | t.Logf("got len=%d [:%d]=%v", len(got), ng, got[:ng]) 57 | 58 | if (len(got) == 0) && (len(c.bin) == 0) { 59 | return 60 | } 61 | 62 | if !reflect.DeepEqual(got, c.bin) { 63 | t.Errorf("Decode() = %v, want %v", got, c.bin) 64 | } 65 | }) 66 | } 67 | } 68 | 69 | func Test_Encode_Check(t *testing.T) { 70 | base36 := NewEncoding("base36", 36, encodeBase36) 71 | 72 | var cases = []struct { 73 | name string 74 | src []byte 75 | enc string 76 | }{ 77 | { 78 | "index-1", 79 | []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255}, 80 | "0rwg9z1idsugqv3", 81 | }, 82 | } 83 | 84 | for _, c := range cases { 85 | t.Run(c.name, func(t *testing.T) { 86 | str := base36.EncodeToString(c.src) 87 | if !reflect.DeepEqual(str, c.enc) { 88 | t.Errorf("EncodeToString() = %v, want %v", str, c.enc) 89 | } 90 | 91 | got, err := base36.DecodeString(c.enc) 92 | if err != nil { 93 | t.Fatal(err) 94 | } 95 | 96 | if !reflect.DeepEqual(got, c.src) { 97 | t.Errorf("DecodeString() = %v, want %v", got, c.src) 98 | } 99 | }) 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /basex/basex.go: -------------------------------------------------------------------------------- 1 | package basex 2 | 3 | import ( 4 | "fmt" 5 | "bytes" 6 | "errors" 7 | "unsafe" 8 | "reflect" 9 | "strconv" 10 | "math/big" 11 | ) 12 | 13 | const ( 14 | encodeBase2 = "01" 15 | encodeBase16 = "0123456789ABCDEF" 16 | encodeBase16Invalid = "0123456789abcdef" 17 | encodeBase32 = "0123456789ABCDEFGHJKMNPQRSTVWXYZ" 18 | encodeBase36 = "0123456789abcdefghijklmnopqrstuvwxyz" 19 | encodeBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" 20 | encodeBase62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 21 | encodeBase62Random = "vPh7zZwA2LyU4bGq5tcVfIMxJi6XaSoK9CNp0OWljYTHQ8REnmu31BrdgeDkFs" 22 | encodeBase62Invalid = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 23 | ) 24 | 25 | var ( 26 | Base2Encoding = NewEncoding(encodeBase2) 27 | Base16Encoding = NewEncoding(encodeBase16) 28 | Base16InvalidEncoding = NewEncoding(encodeBase16Invalid) 29 | Base32Encoding = NewEncoding(encodeBase32) 30 | Base36Encoding = NewEncoding(encodeBase36) 31 | Base58Encoding = NewEncoding(encodeBase58) 32 | Base62Encoding = NewEncoding(encodeBase62) 33 | Base62RandomEncoding = NewEncoding(encodeBase62Random) 34 | Base62InvalidEncoding = NewEncoding(encodeBase62Invalid) 35 | ) 36 | 37 | /* 38 | * Encodings 39 | */ 40 | 41 | // An Encoding is a base radix encoding/decoding scheme defined by a radix-character alphabet. 42 | type Encoding struct { 43 | encode []rune 44 | decodeMap map[rune]int 45 | radix *big.Int 46 | } 47 | 48 | // NewEncoding returns a new Encoding defined by the given alphabet, which must 49 | // be a radix-byte string that does not contain CR or LF ('\r', '\n'). 50 | // Example alphabets: 51 | // - base2: 01 52 | // - base16: 0123456789abcdef 53 | // - base32: 0123456789ABCDEFGHJKMNPQRSTVWXYZ 54 | // - base58: 123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz 55 | // - base62: 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 56 | func NewEncoding(encoder string) *Encoding { 57 | for i := 0; i < len(encoder); i++ { 58 | if encoder[i] == '\n' || encoder[i] == '\r' { 59 | panic("go-encoding/basex: encoding alphabet contains newline character") 60 | } 61 | } 62 | 63 | runes := []rune(encoder) 64 | decodeMap := make(map[rune]int) 65 | 66 | enc := &Encoding{} 67 | 68 | for i := 0; i < len(runes); i++ { 69 | if _, ok := decodeMap[runes[i]]; ok { 70 | panic("go-encoding/basex: Ambiguous alphabet.") 71 | } 72 | 73 | decodeMap[runes[i]] = i 74 | } 75 | 76 | enc.encode = runes 77 | enc.decodeMap = decodeMap 78 | enc.radix = big.NewInt(int64(len(runes))) 79 | 80 | return enc 81 | } 82 | 83 | /* 84 | * Encoder 85 | */ 86 | 87 | // Encode encodes binary bytes into bytes. 88 | func (enc *Encoding) Encode(source []byte) []byte { 89 | if len(source) == 0 { 90 | return nil 91 | } 92 | 93 | var ( 94 | res bytes.Buffer 95 | k = 0 96 | ) 97 | 98 | for ; source[k] == 0 && k < len(source)-1; k++ { 99 | res.WriteRune(enc.encode[0]) 100 | } 101 | 102 | var ( 103 | mod big.Int 104 | sourceInt = new(big.Int).SetBytes(source) 105 | ) 106 | 107 | for sourceInt.Uint64() > 0 { 108 | sourceInt.DivMod(sourceInt, enc.radix, &mod) 109 | res.WriteRune(enc.encode[mod.Uint64()]) 110 | } 111 | 112 | var ( 113 | buf = res.Bytes() 114 | j = len(buf) - 1 115 | ) 116 | 117 | for k < j { 118 | buf[k], buf[j] = buf[j], buf[k] 119 | k++ 120 | j-- 121 | } 122 | 123 | return buf 124 | } 125 | 126 | // EncodeToString returns the basex encoding of src. 127 | func (enc *Encoding) EncodeToString(src []byte) string { 128 | buf := enc.Encode(src) 129 | return string(buf) 130 | } 131 | 132 | // Decode decodes src using the encoding enc. 133 | func (enc *Encoding) Decode(source []byte) ([]byte, error) { 134 | if len(source) == 0 { 135 | return nil, nil 136 | } 137 | 138 | var ( 139 | data = []rune(string(source)) 140 | dest = big.NewInt(0) 141 | ) 142 | 143 | for i := 0; i < len(data); i++ { 144 | value, ok := enc.decodeMap[data[i]] 145 | if !ok { 146 | return nil, errors.New("go-encoding/basex: non Base Character") 147 | } 148 | 149 | dest.Mul(dest, enc.radix) 150 | if value > 0 { 151 | dest.Add(dest, big.NewInt(int64(value))) 152 | } 153 | } 154 | 155 | k := 0 156 | for ; data[k] == enc.encode[0] && k < len(data)-1; k++ { 157 | } 158 | 159 | buf := dest.Bytes() 160 | res := make([]byte, k, k+len(buf)) 161 | 162 | return append(res, buf...), nil 163 | } 164 | 165 | // DecodeString returns the bytes represented by the basex string s. 166 | func (enc *Encoding) DecodeString(s string) ([]byte, error) { 167 | sh := (*reflect.StringHeader)(unsafe.Pointer(&s)) 168 | bh := reflect.SliceHeader{Data: sh.Data, Len: sh.Len, Cap: sh.Len} 169 | return enc.Decode(*(*[]byte)(unsafe.Pointer(&bh))) 170 | } 171 | 172 | // 补码 173 | func (enc *Encoding) padding(s string, minlen int) string { 174 | if len(s) >= minlen { 175 | return s 176 | } 177 | 178 | format := fmt.Sprint(`%0`, strconv.Itoa(minlen), "s") 179 | return fmt.Sprintf(format, s) 180 | } 181 | -------------------------------------------------------------------------------- /basex/basex_test.go: -------------------------------------------------------------------------------- 1 | package basex 2 | 3 | import ( 4 | "bytes" 5 | "testing" 6 | "reflect" 7 | ) 8 | 9 | func Test_Encode(t *testing.T) { 10 | for _, s := range SamplesStd { 11 | encoded := Base62Encoding.EncodeToString([]byte(s.source)) 12 | if len(encoded) == len(s.target) && encoded == s.target { 13 | t.Logf("source: %-15s\ttarget: %s", s.source, s.target) 14 | } else { 15 | t.Errorf("source: %-15s\texpected target: %s(%d)\tactual target: %s(%d)", s.source, s.target, len(s.target), encoded, len(encoded)) 16 | } 17 | } 18 | } 19 | 20 | func Test_Decode(t *testing.T) { 21 | for _, s := range SamplesStd { 22 | decoded, err := Base62Encoding.DecodeString(s.target) 23 | if err != nil { 24 | t.Error(err) 25 | continue 26 | } 27 | 28 | if bytes.Equal(decoded, s.sourceBytes) { 29 | t.Logf("target: %-15s\tsource: %s", s.target, s.source) 30 | } else { 31 | str := string(decoded) 32 | t.Errorf("target: %-15s\texpected source: %s(%d)\tactual source: %s(%d)", s.target, s.source, len(s.source), str, len(str)) 33 | } 34 | } 35 | } 36 | 37 | func Test_DecodeError(t *testing.T) { 38 | for _, s := range SamplesErr { 39 | decoded, err := Base62Encoding.DecodeString(s.target) 40 | if err != nil { 41 | t.Logf("%s: \"%c\"", err.Error(), err) 42 | continue 43 | } 44 | 45 | str := string(decoded) 46 | t.Errorf("An error should have occurred, instead of returning \"%s\"", str) 47 | } 48 | } 49 | 50 | func NewSample(source, target string) *Sample { 51 | return &Sample{source: source, target: target, sourceBytes: []byte(source), targetBytes: []byte(target)} 52 | } 53 | 54 | func NewSampleWithAlphabet(source, target, alphabet string) *Sample { 55 | return &Sample{source: source, target: target, sourceBytes: []byte(source), targetBytes: []byte(target), alphabet: alphabet} 56 | } 57 | 58 | type Sample struct { 59 | source string 60 | target string 61 | sourceBytes []byte 62 | targetBytes []byte 63 | alphabet string 64 | } 65 | 66 | var SamplesStd = []*Sample{ 67 | NewSample("", ""), 68 | NewSample("f", "1e"), 69 | NewSample("fo", "6ox"), 70 | NewSample("foo", "SAPP"), 71 | NewSample("foob", "1sIyuo"), 72 | NewSample("fooba", "7kENWa1"), 73 | NewSample("foobar", "VytN8Wjy"), 74 | 75 | NewSample("su", "7gj"), 76 | NewSample("sur", "VkRe"), 77 | NewSample("sure", "275mAn"), 78 | NewSample("sure.", "8jHquZ4"), 79 | NewSample("asure.", "UQPPAab8"), 80 | NewSample("easure.", "26h8PlupSA"), 81 | NewSample("leasure.", "9IzLUOIY2fe"), 82 | 83 | NewSample("=", "z"), 84 | NewSample(">", "10"), 85 | NewSample("?", "11"), 86 | NewSample("11", "3H7"), 87 | NewSample("111", "DWfh"), 88 | NewSample("1111", "tquAL"), 89 | NewSample("11111", "3icRuhV"), 90 | NewSample("111111", "FMElG7cn"), 91 | 92 | NewSample("Hello, World!", "1wJfrzvdbtXUOlUjUf"), 93 | NewSample("你好,世界!", "1ugmIChyMAcCbDRpROpAtpXdp"), 94 | NewSample("こんにちは", "1fyB0pNlcVqP3tfXZ1FmB"), 95 | NewSample("안녕하십니까", "1yl6dfHPaO9hroEXU9qFioFhM"), 96 | } 97 | 98 | var SamplesErr = []*Sample{ 99 | NewSample("", "Hello, World!"), 100 | NewSample("", "哈哈"), 101 | NewSample("", "はは"), 102 | } 103 | 104 | func Test_Encode_Check(t *testing.T) { 105 | var cases = []struct { 106 | name string 107 | src []byte 108 | enc string 109 | }{ 110 | { 111 | "index-1", 112 | []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255}, 113 | "0rwg9z1idsugqv3", 114 | }, 115 | } 116 | 117 | for _, c := range cases { 118 | t.Run(c.name, func(t *testing.T) { 119 | str := Base36Encoding.EncodeToString(c.src) 120 | if !reflect.DeepEqual(str, c.enc) { 121 | t.Errorf("EncodeToString() = %v, want %v", str, c.enc) 122 | } 123 | 124 | got, err := Base36Encoding.DecodeString(c.enc) 125 | if err != nil { 126 | t.Fatal(err) 127 | } 128 | 129 | if !reflect.DeepEqual(got, c.src) { 130 | t.Errorf("DecodeString() = %v, want %v", got, c.src) 131 | } 132 | }) 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /bcd/bcd.go: -------------------------------------------------------------------------------- 1 | package bcd 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | func Encode(dataIn []byte) (out []byte) { 8 | dataInLen := len(dataIn) 9 | 10 | var posIn int = 0 11 | var posOut int = 0 12 | var nibbleFlag byte = 0 13 | var c byte = 0 14 | 15 | out = make([]byte, (dataInLen/2)) 16 | 17 | for ; posIn < dataInLen; posIn++ { 18 | c = dataIn[posIn] 19 | 20 | if c >= '0' && c <= '9' { 21 | c -= '0' 22 | } else { 23 | switch { 24 | case c == 'A' || c == 'a': 25 | c = 0x0a 26 | case c == 'B' || c == 'b': 27 | c = 0x0b 28 | case c == 'C' || c == 'c': 29 | c = 0x0c 30 | case c == 'D' || c == 'd': 31 | c = 0x0d 32 | case c == 'E' || c == 'e': 33 | c = 0x0e 34 | case c == 'F' || c == 'f': 35 | c = 0x0f 36 | default: 37 | return nil 38 | } 39 | } 40 | 41 | if nibbleFlag == 0 { 42 | c <<= 4 43 | out[posOut] |= c 44 | nibbleFlag = 1 45 | } else { 46 | out[posOut] |= c 47 | posOut++ 48 | nibbleFlag = 0 49 | } 50 | } 51 | 52 | return 53 | } 54 | 55 | func Decode(dataIn []byte) (out []byte) { 56 | dataInLen := len(dataIn) 57 | 58 | var posIn int = 0 59 | var posOut int = 0 60 | 61 | out = make([]byte, (dataInLen*2)) 62 | 63 | for ; posIn < dataInLen; posIn++ { 64 | out[posOut] = nibbleToHexChar(dataIn[posIn] >> 4) 65 | posOut++ 66 | 67 | out[posOut] = nibbleToHexChar(dataIn[posIn] & 0x0f) 68 | posOut++ 69 | } 70 | 71 | return 72 | } 73 | 74 | func nibbleToHexChar(nibble byte) byte { 75 | if (nibble >= 0) && (nibble <= 9) { 76 | return nibble + '0' 77 | } else { 78 | switch { 79 | case nibble == 0x0a: 80 | return 'a' 81 | case nibble == 0x0b: 82 | return 'b' 83 | case nibble == 0x0c: 84 | return 'c' 85 | case nibble == 0x0d: 86 | return 'd' 87 | case nibble == 0x0e: 88 | return 'e' 89 | case nibble == 0x0f: 90 | return 'f' 91 | default: 92 | return ' ' 93 | } 94 | } 95 | } 96 | 97 | // ======= 98 | 99 | func CheckBCD(BCDvalue uint32) bool { 100 | for i := 0; i < 8; i++ { 101 | if (BCDvalue & 0x0F) > 0x09 { 102 | return false 103 | } 104 | 105 | BCDvalue >>= 4 106 | } 107 | 108 | return true 109 | } 110 | 111 | func Uint32ToBCD(BinaryValue uint32) (uint32, error) { 112 | if BinaryValue <= 99999999 { 113 | var ValueToReturn uint32 = 0 114 | var factor uint32 = 10000000 115 | 116 | for i := 0; i < 8; i++ { 117 | ValueToReturn <<= 4 118 | 119 | var temp uint32 = BinaryValue 120 | 121 | temp /= factor 122 | ValueToReturn |= temp 123 | 124 | temp *= factor 125 | BinaryValue -= temp 126 | factor /= 10; 127 | } 128 | 129 | return ValueToReturn, nil 130 | } else { 131 | return BinaryValue, errors.New("go-encoding/bcd: bad") 132 | } 133 | } 134 | 135 | func BCDtoUint32(CurrentBCDvalue uint32) (uint32, error) { 136 | if !CheckBCD(CurrentBCDvalue) { 137 | return CurrentBCDvalue, errors.New("go-encoding/bcd: bad") 138 | } 139 | 140 | var ValueToReturn uint32 = 0 141 | var factor uint32 = 1 142 | 143 | for i := 0; i < 8; i++ { 144 | var temp uint32 = CurrentBCDvalue 145 | temp &= 0x0F 146 | temp *= factor 147 | ValueToReturn += temp 148 | CurrentBCDvalue >>= 4 149 | factor *= 10 150 | } 151 | 152 | return ValueToReturn, nil 153 | } 154 | -------------------------------------------------------------------------------- /bcd/bcd8421/bcd.go: -------------------------------------------------------------------------------- 1 | package bcd8421 2 | 3 | import "errors" 4 | 5 | var ErrNotBCD = errors.New("go-encoding/bcd8421: Byte is Not BCD Encoded") 6 | 7 | // uint8 to Packed BCD 8-4-2-1 One digit per nibble 8 | func Uint8toBCD(u uint8) byte { 9 | lsn := u % 10 10 | u /= 10 11 | msn := u % 10 12 | return ((msn & 0xf) << 4) | (lsn & 0xf) 13 | } 14 | 15 | // Packed BCD 8-4-2-1 One digit per nibble to uint8 16 | // Error if not a BCD digits 17 | func BCDtoUint8(bcd byte) (uint8, error) { 18 | digits := uint8((bcd>>4&0xf)*10 + (bcd & 0xf)) 19 | 20 | // Confirm input is BCD encoded as expected 21 | check := Uint8toBCD(digits) 22 | 23 | if bcd != check|bcd { 24 | return digits, ErrNotBCD 25 | } 26 | 27 | return digits, nil 28 | } 29 | -------------------------------------------------------------------------------- /bcd/bcd8421/bcd8421.go: -------------------------------------------------------------------------------- 1 | package bcd8421 2 | 3 | import ( 4 | "fmt" 5 | "bytes" 6 | "strconv" 7 | ) 8 | 9 | func EncodeFromString(number string, bytesLength int) ([]byte, error) { 10 | var numberBytes []byte 11 | var numberLength = len(number) 12 | 13 | if bytesLength*2 < numberLength { 14 | return numberBytes, fmt.Errorf("go-encoding/bcd8421: invalid bytesLength") 15 | } 16 | 17 | nb, err := stringNumberToBytes(number) 18 | if err != nil { 19 | return numberBytes, err 20 | } 21 | if numberLength%2 == 1 { 22 | nb = append([]byte{0x00}, nb...) 23 | } 24 | if fill := bytesLength*2 - len(nb); fill != 0 { 25 | nb = append(bytes.Repeat([]byte{0x00}, fill), nb...) 26 | } 27 | 28 | for i := 0; i < len(nb); i += 2 { 29 | n1 := nb[i] 30 | n2 := nb[i+1] 31 | n3 := n1 << 4 32 | numberBytes = append(numberBytes, n3|n2) 33 | } 34 | 35 | return numberBytes, nil 36 | } 37 | 38 | func DecodeToString(src []byte, skipzero bool) (string, error) { 39 | var s string 40 | var foundFirst bool 41 | 42 | for _, b := range src { 43 | if b == 0x00 && !foundFirst && skipzero { 44 | continue 45 | } 46 | 47 | n1 := b >> 4 48 | 49 | mask := b << 4 50 | n2 := mask<<4 | mask>>4 51 | 52 | if n1 > 9 || n2 > 9 { 53 | return s, fmt.Errorf("go-encoding/bcd8421: invalid BCD 8421 bytes") 54 | } 55 | 56 | if !skipzero { 57 | s += strconv.Itoa(int(n1)) 58 | s += strconv.Itoa(int(n2)) 59 | continue 60 | } 61 | if n1 != 0x00 && !foundFirst { 62 | foundFirst = true 63 | } 64 | if n1 != 0x00 || foundFirst { 65 | s += strconv.Itoa(int(n1)) 66 | } 67 | if n2 != 0x00 && !foundFirst { 68 | foundFirst = true 69 | } 70 | if n2 != 0x00 || foundFirst { 71 | s += strconv.Itoa(int(n2)) 72 | } 73 | } 74 | 75 | return s, nil 76 | } 77 | 78 | func stringNumberToBytes(number string) ([]byte, error) { 79 | const fnAtoi = "stringNumberToBytes" 80 | 81 | var b []byte 82 | for _, ch := range []byte(number) { 83 | ch -= '0' 84 | if ch > 9 { 85 | return b, &strconv.NumError{ 86 | Func: fnAtoi, 87 | Num: number, 88 | Err: strconv.ErrSyntax, 89 | } 90 | } 91 | 92 | b = append(b, ch) 93 | } 94 | 95 | return b, nil 96 | } 97 | -------------------------------------------------------------------------------- /bcd/bcd8421/bcd8421_test.go: -------------------------------------------------------------------------------- 1 | package bcd8421 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | ) 7 | 8 | func TestStringNumberToBytes(t *testing.T) { 9 | should := []byte{0x00, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9} 10 | b, err := stringNumberToBytes("0123456789") 11 | if err != nil { 12 | panic(err) 13 | } 14 | 15 | if !reflect.DeepEqual(b, should) { 16 | t.Errorf("should be %#v", should) 17 | } 18 | } 19 | 20 | var encodeTestcases = []struct { 21 | number string 22 | bytes []byte 23 | bytesLength int 24 | }{ 25 | { 26 | number: "907865438", 27 | bytes: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x07, 0x86, 0x54, 0x38}, 28 | bytesLength: 10, 29 | }, 30 | { 31 | number: "9007865438", 32 | bytes: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x07, 0x86, 0x54, 0x38}, 33 | bytesLength: 10, 34 | }, 35 | { 36 | number: "90007865438", 37 | bytes: []byte{0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x07, 0x86, 0x54, 0x38}, 38 | bytesLength: 10, 39 | }, 40 | { 41 | number: "900007865438", 42 | bytes: []byte{0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x07, 0x86, 0x54, 0x38}, 43 | bytesLength: 10, 44 | }, 45 | { 46 | number: "9000007865438", 47 | bytes: []byte{0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x07, 0x86, 0x54, 0x38}, 48 | bytesLength: 10, 49 | }, 50 | { 51 | number: "3830", 52 | bytes: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x30}, 53 | bytesLength: 10, 54 | }, 55 | { 56 | number: "38300", 57 | bytes: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x83, 0x00}, 58 | bytesLength: 10, 59 | }, 60 | { 61 | number: "383000", 62 | bytes: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x30, 0x00}, 63 | bytesLength: 10, 64 | }, 65 | { 66 | number: "3830000", 67 | bytes: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x83, 0x00, 0x00}, 68 | bytesLength: 10, 69 | }, 70 | } 71 | 72 | var decodeTestcases = []struct { 73 | number string 74 | bytes []byte 75 | skipzero bool 76 | }{ 77 | { 78 | number: "060101150304", 79 | bytes: []byte{0x06, 0x01, 0x01, 0x15, 0x03, 0x04}, 80 | }, 81 | { 82 | number: "00060101150304", 83 | bytes: []byte{0x00, 0x06, 0x01, 0x01, 0x15, 0x03, 0x04}, 84 | }, 85 | { 86 | number: "60101150304", 87 | bytes: []byte{0x06, 0x01, 0x01, 0x15, 0x03, 0x04}, 88 | skipzero: true, 89 | }, 90 | { 91 | number: "60101150304", 92 | bytes: []byte{0x00, 0x06, 0x01, 0x01, 0x15, 0x03, 0x04}, 93 | skipzero: true, 94 | }, 95 | } 96 | 97 | func TestEncodeFromString(t *testing.T) { 98 | for _, tt := range encodeTestcases { 99 | ret, err := EncodeFromString(tt.number, tt.bytesLength) 100 | if err != nil { 101 | panic(err) 102 | } 103 | if !reflect.DeepEqual(ret, tt.bytes) { 104 | t.Errorf("EncodeFromString(%#v) = %#v; should be %#v", tt.number, ret, tt.bytes) 105 | } 106 | } 107 | } 108 | 109 | func TestDecodeToString(t *testing.T) { 110 | for _, tt := range decodeTestcases { 111 | n, err := DecodeToString(tt.bytes, tt.skipzero) 112 | if err != nil { 113 | panic(err) 114 | } 115 | if n != tt.number { 116 | t.Errorf("DecodeToString(%#v) = %s; should be %s", tt.bytes, n, tt.number) 117 | } 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /bcd/bcd8421/bcd_test.go: -------------------------------------------------------------------------------- 1 | package bcd8421 2 | 3 | import "testing" 4 | 5 | func Test_Uint8toBCD(t *testing.T) { 6 | var tests = []struct { 7 | number uint8 8 | want byte 9 | }{ 10 | {0, 0x00}, 11 | {1, 0x01}, 12 | {2, 0x02}, 13 | {3, 0x03}, 14 | {4, 0x04}, 15 | {5, 0x05}, 16 | {6, 0x06}, 17 | {7, 0x07}, 18 | {8, 0x08}, 19 | {9, 0x09}, 20 | {10, 0x10}, 21 | {11, 0x11}, 22 | {12, 0x12}, 23 | {13, 0x13}, 24 | {14, 0x14}, 25 | {15, 0x15}, 26 | {16, 0x16}, 27 | {17, 0x17}, 28 | {18, 0x18}, 29 | {19, 0x19}, 30 | {20, 0x20}, 31 | } 32 | for _, tt := range tests { 33 | res := Uint8toBCD(tt.number) 34 | if res != tt.want { 35 | t.Errorf("number %d; , want %2.2x, got %2.2x\n", tt.number, tt.want, res) 36 | } 37 | } 38 | } 39 | 40 | func Test_BCDtoUint8(t *testing.T) { 41 | var tests = []struct { 42 | input byte 43 | want uint8 44 | err error 45 | }{ 46 | {0x00, 0, nil}, 47 | {0x01, 1, nil}, 48 | {0x02, 2, nil}, 49 | {0x03, 3, nil}, 50 | {0x04, 4, nil}, 51 | {0x05, 5, nil}, 52 | {0x06, 6, nil}, 53 | {0x07, 7, nil}, 54 | {0x08, 8, nil}, 55 | {0x09, 9, nil}, 56 | {0x10, 10, nil}, 57 | {0x11, 11, nil}, 58 | {0x12, 12, nil}, 59 | {0x13, 13, nil}, 60 | {0x14, 14, nil}, 61 | {0x15, 15, nil}, 62 | {0x16, 16, nil}, 63 | {0x17, 17, nil}, 64 | {0x18, 18, nil}, 65 | {0x19, 19, nil}, 66 | {0x20, 20, nil}, 67 | {0x1a, 20, ErrNotBCD}, 68 | } 69 | for _, tt := range tests { 70 | res, err := BCDtoUint8(tt.input) 71 | 72 | if res != tt.want || err != tt.err { 73 | t.Errorf("number %2x; , want %d, error %s got %d\n, err %v", tt.input, tt.want, tt.err, res, err) 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /bcd/bcd_test.go: -------------------------------------------------------------------------------- 1 | package bcd 2 | 3 | import ( 4 | "bytes" 5 | "testing" 6 | "encoding/hex" 7 | ) 8 | 9 | func fromHex(s string) []byte { 10 | h, _ := hex.DecodeString(s) 11 | return h 12 | } 13 | 14 | func toHex(str string) []byte { 15 | s := hex.EncodeToString([]byte(str)) 16 | return []byte(s) 17 | } 18 | 19 | func fromString(s string) []byte { 20 | return []byte(s) 21 | } 22 | 23 | func Test_nibbleToHexChar(t *testing.T) { 24 | var tests = []struct { 25 | bin byte 26 | want byte 27 | }{ 28 | {0x05, '5'}, 29 | {0x0c, 'c'}, 30 | } 31 | 32 | for i, tt := range tests { 33 | got := nibbleToHexChar(tt.bin) 34 | if got != tt.want { 35 | t.Errorf("[%d] bin %d, got %x, want %x", i, tt.bin, got, tt.want) 36 | } 37 | } 38 | } 39 | 40 | func Test_Encode(t *testing.T) { 41 | var tests = []struct { 42 | in []byte 43 | want []byte 44 | }{ 45 | { 46 | fromString("1231"), 47 | fromHex("1231"), 48 | }, 49 | { 50 | fromString("123ac1"), 51 | fromHex("123ac1"), 52 | }, 53 | { 54 | toHex("ftgyhj"), 55 | fromHex("66746779686a"), 56 | }, 57 | { 58 | toHex("ftgyhj;,klioyuiyt90-[[';lkl"), 59 | fromHex("66746779686a3b2c6b6c696f797569797439302d5b5b273b6c6b6c"), 60 | }, 61 | } 62 | 63 | for i, tt := range tests { 64 | got := Encode(tt.in) 65 | if !bytes.Equal(got, tt.want) { 66 | t.Errorf("[%d] Encode, got %x, want %x", i, got, tt.want) 67 | } 68 | } 69 | 70 | // ======== 71 | 72 | for i, tt := range tests { 73 | got := Decode(tt.want) 74 | if !bytes.Equal(got, tt.in) { 75 | t.Errorf("[%d] Decode, got %s, want %s", i, got, tt.in) 76 | } 77 | } 78 | } 79 | 80 | func Test_Uint32ToBCD(t *testing.T) { 81 | var tests = []struct { 82 | in uint32 83 | want uint32 84 | }{ 85 | {0x05, 5}, 86 | {0x0c, 18}, 87 | } 88 | 89 | for i, tt := range tests { 90 | got, _ := Uint32ToBCD(tt.in) 91 | if got != tt.want { 92 | t.Errorf("[%d] Uint32ToBCD, got %d, want %d", i, got, tt.want) 93 | } 94 | } 95 | 96 | // ======= 97 | 98 | for i, tt := range tests { 99 | got, _ := BCDtoUint32(tt.want) 100 | if got != tt.in { 101 | t.Errorf("[%d] BCDtoUint32, got %d, want %d", i, got, tt.in) 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /chaocipher/chaocipher.go: -------------------------------------------------------------------------------- 1 | package chaocipher 2 | 3 | import ( 4 | "unsafe" 5 | "reflect" 6 | "errors" 7 | "strings" 8 | "unicode/utf8" 9 | ) 10 | 11 | const ( 12 | lEncodeStd = "HXUCZVAMDSLKPEFJRIGTWOBNYQ" 13 | rEncodeStd = "PTLNBQDEOYSFAVZKGJRIHWXUMC" 14 | ) 15 | 16 | // StdEncoding is the standard chaocipher encoding. 17 | var StdEncoding = NewEncoding(lEncodeStd, rEncodeStd) 18 | 19 | /* 20 | * Encodings 21 | */ 22 | 23 | // An Encoding is a radix 62 encoding/decoding scheme, defined by a 62-character alphabet. 24 | type Encoding struct { 25 | lAlphabet string 26 | rAlphabet string 27 | } 28 | 29 | // NewEncoding returns a new padded Encoding defined by the given alphabet, 30 | // which must be a 62-byte string that does not contain the padding character 31 | // or CR / LF ('\r', '\n'). 32 | func NewEncoding(lAlphabet, rAlphabet string) *Encoding { 33 | if len(lAlphabet) != 26 || len(rAlphabet) != 26 { 34 | panic("go-encoding/chaocipher: encoding alphabet is not 26-bytes long") 35 | } 36 | 37 | for i := 0; i < len(lAlphabet); i++ { 38 | if lAlphabet[i] == '\n' || lAlphabet[i] == '\r' { 39 | panic("go-encoding/chaocipher: encoding lAlphabet contains newline character") 40 | } 41 | } 42 | for i := 0; i < len(rAlphabet); i++ { 43 | if rAlphabet[i] == '\n' || rAlphabet[i] == '\r' { 44 | panic("go-encoding/chaocipher: encoding rAlphabet contains newline character") 45 | } 46 | } 47 | 48 | e := new(Encoding) 49 | e.lAlphabet = lAlphabet 50 | e.rAlphabet = rAlphabet 51 | 52 | return e 53 | } 54 | 55 | /* 56 | * Encoder 57 | */ 58 | 59 | // Encode encodes src using the encoding enc. 60 | func (enc *Encoding) Encode(src []byte) []byte { 61 | if len(src) == 0 { 62 | return nil 63 | } 64 | 65 | dst, err := enc.chao(string(src), true) 66 | if err != nil { 67 | return nil 68 | } 69 | 70 | return []byte(dst) 71 | } 72 | 73 | // EncodeToString returns the chao encoding of src. 74 | func (enc *Encoding) EncodeToString(src []byte) string { 75 | buf := enc.Encode(src) 76 | return string(buf) 77 | } 78 | 79 | /* 80 | * Decoder 81 | */ 82 | 83 | // Decode decodes src using the encoding enc. 84 | func (enc *Encoding) Decode(src []byte) ([]byte, error) { 85 | if len(src) == 0 { 86 | return nil, nil 87 | } 88 | 89 | dst, err := enc.chao(string(src), false) 90 | if err != nil { 91 | return nil, err 92 | } 93 | 94 | return []byte(dst), nil 95 | } 96 | 97 | // DecodeString returns the bytes represented by the chao string s. 98 | func (enc *Encoding) DecodeString(s string) ([]byte, error) { 99 | sh := (*reflect.StringHeader)(unsafe.Pointer(&s)) 100 | bh := reflect.SliceHeader{Data: sh.Data, Len: sh.Len, Cap: sh.Len} 101 | return enc.Decode(*(*[]byte)(unsafe.Pointer(&bh))) 102 | } 103 | 104 | func (enc *Encoding) chao(text string, encrypt bool) (string, error) { 105 | len := len(text) 106 | if utf8.RuneCountInString(text) != len { 107 | return "", errors.New("go-cryptobin/chaocipher: Text contains non-ASCII characters") 108 | } 109 | 110 | left := enc.lAlphabet 111 | right := enc.rAlphabet 112 | 113 | eText := make([]byte, len) 114 | temp := make([]byte, 26) 115 | 116 | for i := 0; i < len; i++ { 117 | var index int 118 | if encrypt { 119 | index = strings.IndexByte(right, text[i]) 120 | eText[i] = left[index] 121 | } else { 122 | index = strings.IndexByte(left, text[i]) 123 | eText[i] = right[index] 124 | } 125 | 126 | if i == len-1 { 127 | break 128 | } 129 | 130 | for j := index; j < 26; j++ { 131 | temp[j-index] = left[j] 132 | } 133 | for j := 0; j < index; j++ { 134 | temp[26-index+j] = left[j] 135 | } 136 | 137 | store := temp[1] 138 | for j := 2; j < 14; j++ { 139 | temp[j-1] = temp[j] 140 | } 141 | 142 | temp[13] = store 143 | left = string(temp[:]) 144 | 145 | for j := index; j < 26; j++ { 146 | temp[j-index] = right[j] 147 | } 148 | for j := 0; j < index; j++ { 149 | temp[26-index+j] = right[j] 150 | } 151 | 152 | store = temp[0] 153 | for j := 1; j < 26; j++ { 154 | temp[j-1] = temp[j] 155 | } 156 | 157 | temp[25] = store 158 | store = temp[2] 159 | for j := 3; j < 14; j++ { 160 | temp[j-1] = temp[j] 161 | } 162 | 163 | temp[13] = store 164 | right = string(temp[:]) 165 | } 166 | 167 | return string(eText[:]), nil 168 | } 169 | -------------------------------------------------------------------------------- /chaocipher/chaocipher_test.go: -------------------------------------------------------------------------------- 1 | package chaocipher 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func Test_Check(t *testing.T) { 8 | ciphertext := "OAHQHCNYNXTSZJRRHJBYHQKSOUJY" 9 | plaintext := "WELLDONEISBETTERTHANWELLSAID" 10 | 11 | encoded := StdEncoding.EncodeToString([]byte(plaintext)) 12 | if ciphertext != encoded { 13 | t.Errorf("Encrypt error: act=%s, old=%s\n", encoded, ciphertext) 14 | } 15 | 16 | // ========== 17 | 18 | decoded, err := StdEncoding.DecodeString(ciphertext) 19 | if err != nil { 20 | t.Fatal(err) 21 | } 22 | 23 | if plaintext != string(decoded) { 24 | t.Errorf("Decrypt error: act=%s, old=%s\n", string(decoded), plaintext) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /encoding/asn1.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "encoding/asn1" 5 | ) 6 | 7 | // Asn1 Encode 8 | func (this Encoding) Asn1Encode(data any) Encoding { 9 | this.data, this.Error = asn1.Marshal(data) 10 | 11 | return this 12 | } 13 | 14 | // Asn1 Decode 15 | func (this Encoding) Asn1Decode(val any) Encoding { 16 | this.data, this.Error = asn1.Unmarshal(this.data, val) 17 | 18 | return this 19 | } 20 | 21 | // ============= 22 | 23 | // Asn1 Encode 24 | func (this Encoding) Asn1EncodeWithParams(data any, params string) Encoding { 25 | this.data, this.Error = asn1.MarshalWithParams(data, params) 26 | 27 | return this 28 | } 29 | 30 | // Asn1 Decode 31 | func (this Encoding) Asn1DecodeWithParams(val any, params string) Encoding { 32 | this.data, this.Error = asn1.UnmarshalWithParams(this.data, val, params) 33 | 34 | return this 35 | } 36 | -------------------------------------------------------------------------------- /encoding/asn1_test.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func Test_Asn1(t *testing.T) { 8 | assert := assertT(t) 9 | assertError := assertErrorT(t) 10 | 11 | name := "Asn1" 12 | data := "test-pass" 13 | 14 | en := FromString("").Asn1Encode(data) 15 | enStr := en.ToString() 16 | 17 | assertError(en.Error, name + " Encode error") 18 | 19 | var deStr string 20 | de := FromString(enStr).Asn1Decode(&deStr) 21 | 22 | assertError(de.Error, name + " Decode error") 23 | 24 | assert(data, deStr, name) 25 | } 26 | 27 | func Test_Asn1Params(t *testing.T) { 28 | assert := assertT(t) 29 | assertError := assertErrorT(t) 30 | 31 | name := "Asn1Params" 32 | data := "test-pass" 33 | params := "testparams" 34 | 35 | en := FromString("").Asn1EncodeWithParams(data, params) 36 | enStr := en.ToString() 37 | 38 | assertError(en.Error, name + " Encode error") 39 | 40 | var deStr string 41 | de := FromString(enStr).Asn1DecodeWithParams(&deStr, params) 42 | 43 | assertError(de.Error, name + " Decode error") 44 | 45 | assert(data, deStr, name) 46 | } 47 | -------------------------------------------------------------------------------- /encoding/base100.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "github.com/deatil/go-encoding/base100" 5 | ) 6 | 7 | // Base100 Decode 8 | func (this Encoding) Base100Decode() Encoding { 9 | data := string(this.data) 10 | this.data, this.Error = base100.Decode(data) 11 | 12 | return this 13 | } 14 | 15 | // Base100 Encode 16 | func (this Encoding) Base100Encode() Encoding { 17 | data := base100.Encode(this.data) 18 | this.data = []byte(data) 19 | 20 | return this 21 | } 22 | -------------------------------------------------------------------------------- /encoding/base100_test.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func Test_Base100(t *testing.T) { 8 | assert := assertT(t) 9 | assertError := assertErrorT(t) 10 | 11 | name := "Base100" 12 | data := "test-pass" 13 | 14 | en := FromString(data).Base100Encode() 15 | enStr := en.ToString() 16 | 17 | assertError(en.Error, name + " Encode error") 18 | 19 | de := FromString(enStr).Base100Decode() 20 | deStr := de.ToString() 21 | 22 | assertError(de.Error, name + " Decode error") 23 | 24 | assert(data, deStr, name) 25 | } 26 | -------------------------------------------------------------------------------- /encoding/base32.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "encoding/base32" 5 | ) 6 | 7 | var ( 8 | // newStr := NewBase32Encoding(encoder string).WithPadding(NoPadding).EncodeToString(src []byte) 9 | // newStr, err := NewBase32Encoding(encoder string).WithPadding(NoPadding).DecodeString(src string) 10 | NewBase32Encoding = base32.NewEncoding 11 | ) 12 | 13 | // Decode Base32 14 | func (this Encoding) Base32Decode() Encoding { 15 | data := string(this.data) 16 | this.data, this.Error = base32.StdEncoding.DecodeString(data) 17 | 18 | return this 19 | } 20 | 21 | // Encode Base32 22 | func (this Encoding) Base32Encode() Encoding { 23 | data := base32.StdEncoding.EncodeToString(this.data) 24 | this.data = []byte(data) 25 | 26 | return this 27 | } 28 | 29 | // =========== 30 | 31 | // Decode Base32 raw 32 | func (this Encoding) Base32RawDecode() Encoding { 33 | data := string(this.data) 34 | this.data, this.Error = base32.StdEncoding.WithPadding(base32.NoPadding).DecodeString(data) 35 | 36 | return this 37 | } 38 | 39 | // Encode Base32 raw 40 | func (this Encoding) Base32RawEncode() Encoding { 41 | data := base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(this.data) 42 | this.data = []byte(data) 43 | 44 | return this 45 | } 46 | 47 | // =========== 48 | 49 | // Decode Base32 Hex 50 | func (this Encoding) Base32HexDecode() Encoding { 51 | data := string(this.data) 52 | this.data, this.Error = base32.HexEncoding.DecodeString(data) 53 | 54 | return this 55 | } 56 | 57 | // Encode Base32 Hex 58 | func (this Encoding) Base32HexEncode() Encoding { 59 | data := base32.HexEncoding.EncodeToString(this.data) 60 | this.data = []byte(data) 61 | 62 | return this 63 | } 64 | 65 | // =========== 66 | 67 | // Decode Base32Hex raw 68 | func (this Encoding) Base32RawHexDecode() Encoding { 69 | data := string(this.data) 70 | this.data, this.Error = base32.HexEncoding.WithPadding(base32.NoPadding).DecodeString(data) 71 | 72 | return this 73 | } 74 | 75 | // Encode Base32Hex raw 76 | func (this Encoding) Base32RawHexEncode() Encoding { 77 | data := base32.HexEncoding.WithPadding(base32.NoPadding).EncodeToString(this.data) 78 | this.data = []byte(data) 79 | 80 | return this 81 | } 82 | 83 | // =========== 84 | 85 | // Decode Base32Encoder 86 | func (this Encoding) Base32DecodeWithEncoder(encoder string) Encoding { 87 | data := string(this.data) 88 | this.data, this.Error = base32.NewEncoding(encoder).DecodeString(data) 89 | 90 | return this 91 | } 92 | 93 | // Encode Base32Encoder 94 | func (this Encoding) Base32EncodeWithEncoder(encoder string) Encoding { 95 | data := base32.NewEncoding(encoder).EncodeToString(this.data) 96 | this.data = []byte(data) 97 | 98 | return this 99 | } 100 | 101 | // =========== 102 | 103 | // Decode Base32Encoder raw 104 | func (this Encoding) Base32RawDecodeWithEncoder(encoder string) Encoding { 105 | data := string(this.data) 106 | this.data, this.Error = base32.NewEncoding(encoder).WithPadding(base32.NoPadding).DecodeString(data) 107 | 108 | return this 109 | } 110 | 111 | // Encode Base32Encoder raw 112 | func (this Encoding) Base32RawEncodeWithEncoder(encoder string) Encoding { 113 | data := base32.NewEncoding(encoder).WithPadding(base32.NoPadding).EncodeToString(this.data) 114 | this.data = []byte(data) 115 | 116 | return this 117 | } 118 | -------------------------------------------------------------------------------- /encoding/base32_test.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func Test_Base32(t *testing.T) { 8 | assert := assertT(t) 9 | assertError := assertErrorT(t) 10 | 11 | name := "Base32" 12 | data := "test-pass" 13 | 14 | en := FromString(data).Base32Encode() 15 | enStr := en.ToString() 16 | 17 | assertError(en.Error, name + " Encode error") 18 | 19 | de := FromString(enStr).Base32Decode() 20 | deStr := de.ToString() 21 | 22 | assertError(de.Error, name + " Decode error") 23 | 24 | assert(data, deStr, name) 25 | } 26 | 27 | func Test_Base32Raw(t *testing.T) { 28 | assert := assertT(t) 29 | assertError := assertErrorT(t) 30 | 31 | name := "Base32" 32 | data := "test-pass" 33 | 34 | en := FromString(data).Base32RawEncode() 35 | enStr := en.ToString() 36 | 37 | assertError(en.Error, name + "Base32Raw- Encode error") 38 | 39 | de := FromString(enStr).Base32RawDecode() 40 | deStr := de.ToString() 41 | 42 | assertError(de.Error, name + "Base32Raw- Decode error") 43 | 44 | assert(data, deStr, name) 45 | } 46 | 47 | func Test_Base32Hex(t *testing.T) { 48 | assert := assertT(t) 49 | assertError := assertErrorT(t) 50 | 51 | name := "Base32Hex" 52 | data := "test-pass" 53 | 54 | en := FromString(data).Base32HexEncode() 55 | enStr := en.ToString() 56 | 57 | assertError(en.Error, name + " Encode error") 58 | 59 | de := FromString(enStr).Base32HexDecode() 60 | deStr := de.ToString() 61 | 62 | assertError(de.Error, name + " Decode error") 63 | 64 | assert(data, deStr, name) 65 | } 66 | 67 | func Test_Base32RawHex(t *testing.T) { 68 | assert := assertT(t) 69 | assertError := assertErrorT(t) 70 | 71 | name := "Base32Hex" 72 | data := "test-pass" 73 | 74 | en := FromString(data).Base32RawHexEncode() 75 | enStr := en.ToString() 76 | 77 | assertError(en.Error, name + "Base32RawHex- Encode error") 78 | 79 | de := FromString(enStr).Base32RawHexDecode() 80 | deStr := de.ToString() 81 | 82 | assertError(de.Error, name + "Base32RawHex- Decode error") 83 | 84 | assert(data, deStr, name) 85 | } 86 | 87 | func Test_Base32Encoder(t *testing.T) { 88 | assert := assertT(t) 89 | assertError := assertErrorT(t) 90 | 91 | name := "Base32Encoder" 92 | data := "test-pass" 93 | 94 | const encodeTest = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234569" 95 | 96 | en := FromString(data).Base32EncodeWithEncoder(encodeTest) 97 | enStr := en.ToString() 98 | 99 | assertError(en.Error, name + " Encode error") 100 | 101 | de := FromString(enStr).Base32DecodeWithEncoder(encodeTest) 102 | deStr := de.ToString() 103 | 104 | assertError(de.Error, name + " Decode error") 105 | 106 | assert(data, deStr, name) 107 | } 108 | 109 | func Test_Base32RawEncoder(t *testing.T) { 110 | assert := assertT(t) 111 | assertError := assertErrorT(t) 112 | 113 | name := "Base32Encoder" 114 | data := "test-pass" 115 | 116 | const encodeTest = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234569" 117 | 118 | en := FromString(data).Base32RawEncodeWithEncoder(encodeTest) 119 | enStr := en.ToString() 120 | 121 | assertError(en.Error, name + "Base32RawEncoder- Encode error") 122 | 123 | de := FromString(enStr).Base32RawDecodeWithEncoder(encodeTest) 124 | deStr := de.ToString() 125 | 126 | assertError(de.Error, name + "Base32RawEncoder- Decode error") 127 | 128 | assert(data, deStr, name) 129 | } 130 | -------------------------------------------------------------------------------- /encoding/base36.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "github.com/deatil/go-encoding/base36" 5 | ) 6 | 7 | // Decode Base36 8 | func (this Encoding) Base36Decode() Encoding { 9 | data := string(this.data) 10 | this.data, this.Error = base36.StdEncoding.DecodeString(data) 11 | 12 | return this 13 | } 14 | 15 | // Encode Base36 16 | func (this Encoding) Base36Encode() Encoding { 17 | data := base36.StdEncoding.EncodeToString(this.data) 18 | this.data = []byte(data) 19 | 20 | return this 21 | } 22 | -------------------------------------------------------------------------------- /encoding/base36_test.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func Test_Base36(t *testing.T) { 8 | assert := assertT(t) 9 | assertError := assertErrorT(t) 10 | 11 | name := "Base36" 12 | data := "test-pass" 13 | 14 | en := FromString(data).Base36Encode() 15 | enStr := en.ToString() 16 | 17 | assertError(en.Error, name + " Encode error") 18 | 19 | de := FromString(enStr).Base36Decode() 20 | deStr := de.ToString() 21 | 22 | assertError(de.Error, name + " Decode error") 23 | 24 | assert(data, deStr, name) 25 | } 26 | -------------------------------------------------------------------------------- /encoding/base45.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "github.com/deatil/go-encoding/base45" 5 | ) 6 | 7 | // Base45 Decode 8 | func (this Encoding) Base45Decode() Encoding { 9 | decoded, err := base45.StdEncoding.DecodeString(string(this.data)) 10 | 11 | this.data = decoded 12 | this.Error = err 13 | 14 | return this 15 | } 16 | 17 | // Base45 Encode 18 | func (this Encoding) Base45Encode() Encoding { 19 | data := base45.StdEncoding.EncodeToString(this.data) 20 | this.data = []byte(data) 21 | 22 | return this 23 | } 24 | -------------------------------------------------------------------------------- /encoding/base45_test.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func Test_Base45(t *testing.T) { 8 | assert := assertT(t) 9 | assertError := assertErrorT(t) 10 | 11 | name := "Base45" 12 | data := "test-pass" 13 | 14 | en := FromString(data).Base45Encode() 15 | enStr := en.ToString() 16 | 17 | assertError(en.Error, name + " Encode error") 18 | 19 | de := FromString(enStr).Base45Decode() 20 | deStr := de.ToString() 21 | 22 | assertError(de.Error, name + " Decode error") 23 | 24 | assert(data, deStr, name) 25 | } 26 | -------------------------------------------------------------------------------- /encoding/base58.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "github.com/deatil/go-encoding/base58" 5 | ) 6 | 7 | // Base58 Decode 8 | func (this Encoding) Base58Decode() Encoding { 9 | data := string(this.data) 10 | this.data, this.Error = base58.StdEncoding.DecodeString(data) 11 | 12 | return this 13 | } 14 | 15 | // Base58 Encode 16 | func (this Encoding) Base58Encode() Encoding { 17 | data := base58.StdEncoding.EncodeToString(this.data) 18 | this.data = []byte(data) 19 | 20 | return this 21 | } 22 | -------------------------------------------------------------------------------- /encoding/base58_test.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func Test_Base58(t *testing.T) { 8 | assert := assertT(t) 9 | assertError := assertErrorT(t) 10 | 11 | name := "Base58" 12 | data := "test-pass" 13 | 14 | en := FromString(data).Base58Encode() 15 | enStr := en.ToString() 16 | 17 | assertError(en.Error, name + " Encode error") 18 | 19 | de := FromString(enStr).Base58Decode() 20 | deStr := de.ToString() 21 | 22 | assertError(de.Error, name + " Decode error") 23 | 24 | assert(data, deStr, name) 25 | } 26 | -------------------------------------------------------------------------------- /encoding/base62.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "github.com/deatil/go-encoding/base62" 5 | ) 6 | 7 | // Base62 Decode 8 | func (this Encoding) Base62Decode() Encoding { 9 | data := string(this.data) 10 | this.data, this.Error = base62.StdEncoding.DecodeString(data) 11 | 12 | return this 13 | } 14 | 15 | // Base62 Encode 16 | func (this Encoding) Base62Encode() Encoding { 17 | data := base62.StdEncoding.EncodeToString(this.data) 18 | this.data = []byte(data) 19 | 20 | return this 21 | } 22 | -------------------------------------------------------------------------------- /encoding/base62_test.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func Test_Base62(t *testing.T) { 8 | assert := assertT(t) 9 | assertError := assertErrorT(t) 10 | 11 | data := "test-pass" 12 | name := "Base62" 13 | 14 | en := FromString(data).Base62Encode() 15 | enStr := en.ToString() 16 | 17 | assertError(en.Error, name + " Encode error") 18 | 19 | de := FromString(enStr).Base62Decode() 20 | deStr := de.ToString() 21 | 22 | assertError(de.Error, name + " Decode error") 23 | 24 | assert(data, deStr, name) 25 | } 26 | -------------------------------------------------------------------------------- /encoding/base64.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "strings" 5 | "encoding/base64" 6 | ) 7 | 8 | var ( 9 | // newStr := NewBase64Encoding(encoder string).WithPadding(NoPadding).EncodeToString(src []byte) 10 | // newStr, err := NewBase64Encoding(encoder string).WithPadding(NoPadding).DecodeString(src string) 11 | NewBase64Encoding = base64.NewEncoding 12 | ) 13 | 14 | // Base64 Decode 15 | func (this Encoding) Base64Decode() Encoding { 16 | data := string(this.data) 17 | this.data, this.Error = base64.StdEncoding.DecodeString(data) 18 | 19 | return this 20 | } 21 | 22 | // Base64 Encode 23 | func (this Encoding) Base64Encode() Encoding { 24 | data := base64.StdEncoding.EncodeToString(this.data) 25 | this.data = []byte(data) 26 | 27 | return this 28 | } 29 | 30 | // ==================== 31 | 32 | // Base64 URL Decode 33 | func (this Encoding) Base64URLDecode() Encoding { 34 | data := string(this.data) 35 | this.data, this.Error = base64.URLEncoding.DecodeString(data) 36 | 37 | return this 38 | } 39 | 40 | // Base64 URL Encode 41 | func (this Encoding) Base64URLEncode() Encoding { 42 | data := base64.URLEncoding.EncodeToString(this.data) 43 | this.data = []byte(data) 44 | 45 | return this 46 | } 47 | 48 | // ==================== 49 | 50 | // Base64 Raw Decode 51 | func (this Encoding) Base64RawDecode() Encoding { 52 | data := string(this.data) 53 | this.data, this.Error = base64.RawStdEncoding.DecodeString(data) 54 | 55 | return this 56 | } 57 | 58 | // Base64 Raw Encode 59 | func (this Encoding) Base64RawEncode() Encoding { 60 | data := base64.RawStdEncoding.EncodeToString(this.data) 61 | this.data = []byte(data) 62 | 63 | return this 64 | } 65 | 66 | // ==================== 67 | 68 | // Base64RawURL Decode 69 | func (this Encoding) Base64RawURLDecode() Encoding { 70 | data := string(this.data) 71 | this.data, this.Error = base64.RawURLEncoding.DecodeString(data) 72 | 73 | return this 74 | } 75 | 76 | // Base64RawURL Encode 77 | func (this Encoding) Base64RawURLEncode() Encoding { 78 | data := base64.RawURLEncoding.EncodeToString(this.data) 79 | this.data = []byte(data) 80 | 81 | return this 82 | } 83 | 84 | // ==================== 85 | 86 | // Base64Segment Decode 87 | func (this Encoding) Base64SegmentDecode(paddingAllowed ...bool) Encoding { 88 | data := string(this.data) 89 | 90 | if len(paddingAllowed) > 0 && paddingAllowed[0] { 91 | if l := len(data) % 4; l > 0 { 92 | data += strings.Repeat("=", 4-l) 93 | } 94 | 95 | this.data, this.Error = base64.URLEncoding.DecodeString(data) 96 | 97 | return this 98 | } 99 | 100 | this.data, this.Error = base64.RawURLEncoding.DecodeString(data) 101 | 102 | return this 103 | } 104 | 105 | // Base64Segment Encode 106 | func (this Encoding) Base64SegmentEncode() Encoding { 107 | data := base64.RawURLEncoding.EncodeToString(this.data) 108 | this.data = []byte(data) 109 | 110 | return this 111 | } 112 | 113 | // ==================== 114 | 115 | // Base64 Decode With Encoder 116 | func (this Encoding) Base64DecodeWithEncoder(encoder string) Encoding { 117 | data := string(this.data) 118 | this.data, this.Error = base64.NewEncoding(encoder).DecodeString(data) 119 | 120 | return this 121 | } 122 | 123 | // Base64 Encode With Encoder 124 | func (this Encoding) Base64EncodeWithEncoder(encoder string) Encoding { 125 | data := base64.NewEncoding(encoder).EncodeToString(this.data) 126 | this.data = []byte(data) 127 | 128 | return this 129 | } 130 | -------------------------------------------------------------------------------- /encoding/base64_test.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func Test_Base64(t *testing.T) { 8 | assert := assertT(t) 9 | assertError := assertErrorT(t) 10 | 11 | data := "test-pass" 12 | 13 | en := FromString(data).Base64Encode() 14 | enStr := en.ToString() 15 | 16 | assertError(en.Error, "Base64 Encode error") 17 | 18 | de := FromString(enStr).Base64Decode() 19 | deStr := de.ToString() 20 | 21 | assertError(de.Error, "Base64 Decode error") 22 | 23 | assert(data, deStr, "Base64") 24 | } 25 | 26 | func Test_Base64URL(t *testing.T) { 27 | assert := assertT(t) 28 | assertError := assertErrorT(t) 29 | 30 | data := "test-pass" 31 | 32 | en := FromString(data).Base64URLEncode() 33 | enStr := en.ToString() 34 | 35 | assertError(en.Error, "Base64URL Encode error") 36 | 37 | de := FromString(enStr).Base64URLDecode() 38 | deStr := de.ToString() 39 | 40 | assertError(de.Error, "Base64URL Decode error") 41 | 42 | assert(data, deStr, "Base64URL") 43 | } 44 | 45 | func Test_Base64Raw(t *testing.T) { 46 | assert := assertT(t) 47 | assertError := assertErrorT(t) 48 | 49 | data := "test-pass" 50 | 51 | en := FromString(data).Base64RawEncode() 52 | enStr := en.ToString() 53 | 54 | assertError(en.Error, "Base64Raw Encode error") 55 | 56 | de := FromString(enStr).Base64RawDecode() 57 | deStr := de.ToString() 58 | 59 | assertError(de.Error, "Base64Raw Decode error") 60 | 61 | assert(data, deStr, "Base64Raw") 62 | } 63 | 64 | func Test_Base64RawURL(t *testing.T) { 65 | assert := assertT(t) 66 | assertError := assertErrorT(t) 67 | 68 | data := "test-pass" 69 | 70 | en := FromString(data).Base64RawURLEncode() 71 | enStr := en.ToString() 72 | 73 | assertError(en.Error, "Base64RawURL Encode error") 74 | 75 | de := FromString(enStr).Base64RawURLDecode() 76 | deStr := de.ToString() 77 | 78 | assertError(de.Error, "Base64RawURL Decode error") 79 | 80 | assert(data, deStr, "Base64RawURL") 81 | } 82 | 83 | func Test_Base64Segment(t *testing.T) { 84 | assert := assertT(t) 85 | assertError := assertErrorT(t) 86 | 87 | data := "test-pass" 88 | 89 | en := FromString(data).Base64SegmentEncode() 90 | enStr := en.ToString() 91 | 92 | assertError(en.Error, "Base64Segment Encode error") 93 | 94 | de := FromString(enStr).Base64SegmentDecode() 95 | deStr := de.ToString() 96 | 97 | assertError(de.Error, "Base64Segment Decode error") 98 | 99 | assert(data, deStr, "Base64Segment") 100 | } 101 | 102 | func Test_Base64Encoder(t *testing.T) { 103 | assert := assertT(t) 104 | assertError := assertErrorT(t) 105 | 106 | data := "test-pass" 107 | const encodeTest = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789;/" 108 | 109 | en := FromString(data).Base64EncodeWithEncoder(encodeTest) 110 | enStr := en.ToString() 111 | 112 | assertError(en.Error, "Base64Encoder Encode error") 113 | 114 | de := FromString(enStr).Base64DecodeWithEncoder(encodeTest) 115 | deStr := de.ToString() 116 | 117 | assertError(de.Error, "Base64Encoder Decode error") 118 | 119 | assert(data, deStr, "Base64Encoder") 120 | } 121 | 122 | -------------------------------------------------------------------------------- /encoding/base85.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "bytes" 5 | "encoding/ascii85" 6 | ) 7 | 8 | // Base85 Decode 9 | func (this Encoding) Base85Decode() Encoding { 10 | src := this.data 11 | 12 | decodedText := make([]byte, len(src)) 13 | decoded, _, err := ascii85.Decode(decodedText, src, true) 14 | if err != nil { 15 | this.Error = err 16 | return this 17 | } 18 | 19 | decodedText = decodedText[:decoded] 20 | 21 | this.data = bytes.Trim(decodedText, "\x00") 22 | 23 | return this 24 | } 25 | 26 | // Base85 Encode 27 | func (this Encoding) Base85Encode() Encoding { 28 | text := this.data 29 | 30 | dest := make([]byte, ascii85.MaxEncodedLen(len(text))) 31 | ascii85.Encode(dest, text) 32 | 33 | this.data = dest 34 | 35 | return this 36 | } 37 | -------------------------------------------------------------------------------- /encoding/base85_test.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func Test_Base85(t *testing.T) { 8 | assert := assertT(t) 9 | assertError := assertErrorT(t) 10 | 11 | data := "test-pass" 12 | name := "Base85" 13 | 14 | en := FromString(data).Base85Encode() 15 | enStr := en.ToString() 16 | 17 | assertError(en.Error, name + " Encode error") 18 | 19 | de := FromString(enStr).Base85Decode() 20 | deStr := de.ToString() 21 | 22 | assertError(de.Error, name + " Decode error") 23 | 24 | assert(data, deStr, name) 25 | } 26 | -------------------------------------------------------------------------------- /encoding/base91.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "github.com/deatil/go-encoding/base91" 5 | ) 6 | 7 | // Base91 Decode 8 | func (this Encoding) Base91Decode() Encoding { 9 | data := string(this.data) 10 | this.data, this.Error = base91.StdEncoding.DecodeString(data) 11 | 12 | return this 13 | } 14 | 15 | // Base91 Encode 16 | func (this Encoding) Base91Encode() Encoding { 17 | data := base91.StdEncoding.EncodeToString(this.data) 18 | this.data = []byte(data) 19 | 20 | return this 21 | } 22 | -------------------------------------------------------------------------------- /encoding/base91_test.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func Test_Base91(t *testing.T) { 8 | assert := assertT(t) 9 | assertError := assertErrorT(t) 10 | 11 | name := "Base91" 12 | data := "test-pass" 13 | 14 | en := FromString(data).Base91Encode() 15 | enStr := en.ToString() 16 | 17 | assertError(en.Error, name + " Encode error") 18 | 19 | de := FromString(enStr).Base91Decode() 20 | deStr := de.ToString() 21 | 22 | assertError(de.Error, name + " Decode error") 23 | 24 | assert(data, deStr, name) 25 | } 26 | -------------------------------------------------------------------------------- /encoding/base92.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "github.com/deatil/go-encoding/base92" 5 | ) 6 | 7 | // Base92 Decode 8 | func (this Encoding) Base92Decode() Encoding { 9 | data := string(this.data) 10 | this.data, this.Error = base92.StdEncoding.DecodeString(data) 11 | 12 | return this 13 | } 14 | 15 | // Base92 Encode 16 | func (this Encoding) Base92Encode() Encoding { 17 | data := base92.StdEncoding.EncodeToString(this.data) 18 | this.data = []byte(data) 19 | 20 | return this 21 | } 22 | -------------------------------------------------------------------------------- /encoding/base92_test.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func Test_Base92(t *testing.T) { 8 | assert := assertT(t) 9 | assertError := assertErrorT(t) 10 | 11 | name := "Base92" 12 | data := "test-pass" 13 | 14 | en := FromString(data).Base92Encode() 15 | enStr := en.ToString() 16 | 17 | assertError(en.Error, name + " Encode error") 18 | 19 | de := FromString(enStr).Base92Decode() 20 | deStr := de.ToString() 21 | 22 | assertError(de.Error, name + " Decode error") 23 | 24 | assert(data, deStr, name) 25 | } 26 | -------------------------------------------------------------------------------- /encoding/basex.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "github.com/deatil/go-encoding/basex" 5 | ) 6 | 7 | // Basex2 Decode 8 | func (this Encoding) Basex2Decode() Encoding { 9 | data := string(this.data) 10 | this.data, this.Error = basex.Base2Encoding.DecodeString(data) 11 | 12 | return this 13 | } 14 | 15 | // Base2 Encode 16 | func (this Encoding) Basex2Encode() Encoding { 17 | data := basex.Base2Encoding.EncodeToString(this.data) 18 | this.data = []byte(data) 19 | 20 | return this 21 | } 22 | 23 | // ==================== 24 | 25 | // Basex16 Decode 26 | func (this Encoding) Basex16Decode() Encoding { 27 | data := string(this.data) 28 | this.data, this.Error = basex.Base16Encoding.DecodeString(data) 29 | 30 | return this 31 | } 32 | 33 | // Base16 Encode 34 | func (this Encoding) Basex16Encode() Encoding { 35 | data := basex.Base16Encoding.EncodeToString(this.data) 36 | this.data = []byte(data) 37 | 38 | return this 39 | } 40 | 41 | // ==================== 42 | 43 | // Basex62 Decode 44 | func (this Encoding) Basex62Decode() Encoding { 45 | data := string(this.data) 46 | this.data, this.Error = basex.Base62Encoding.DecodeString(data) 47 | 48 | return this 49 | } 50 | 51 | // Basex62 Encode 52 | func (this Encoding) Basex62Encode() Encoding { 53 | data := basex.Base62Encoding.EncodeToString(this.data) 54 | this.data = []byte(data) 55 | 56 | return this 57 | } 58 | 59 | // ==================== 60 | 61 | // Basex Decode With Encoder 62 | func (this Encoding) BasexDecodeWithEncoder(encoder string) Encoding { 63 | data := string(this.data) 64 | this.data, this.Error = basex.NewEncoding(encoder).DecodeString(data) 65 | 66 | return this 67 | } 68 | 69 | // Basex Encode With Encoder 70 | func (this Encoding) BasexEncodeWithEncoder(encoder string) Encoding { 71 | data := basex.NewEncoding(encoder).EncodeToString(this.data) 72 | this.data = []byte(data) 73 | 74 | return this 75 | } 76 | -------------------------------------------------------------------------------- /encoding/basex_test.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func Test_Basex2(t *testing.T) { 8 | assert := assertT(t) 9 | assertError := assertErrorT(t) 10 | 11 | name := "Basex2" 12 | data := "test-pass" 13 | 14 | en := FromString(data).Basex2Encode() 15 | enStr := en.ToString() 16 | 17 | assertError(en.Error, name + " Encode error") 18 | 19 | de := FromString(enStr).Basex2Decode() 20 | deStr := de.ToString() 21 | 22 | assertError(de.Error, name + " Decode error") 23 | 24 | assert(data, deStr, name) 25 | } 26 | 27 | func Test_Basex16(t *testing.T) { 28 | assert := assertT(t) 29 | assertError := assertErrorT(t) 30 | 31 | name := "Basex16" 32 | data := "test-pass" 33 | 34 | en := FromString(data).Basex16Encode() 35 | enStr := en.ToString() 36 | 37 | assertError(en.Error, name + " Encode error") 38 | 39 | de := FromString(enStr).Basex16Decode() 40 | deStr := de.ToString() 41 | 42 | assertError(de.Error, name + " Decode error") 43 | 44 | assert(data, deStr, name) 45 | } 46 | 47 | func Test_Basex62(t *testing.T) { 48 | assert := assertT(t) 49 | assertError := assertErrorT(t) 50 | 51 | name := "Basex62" 52 | data := "test-pass" 53 | 54 | en := FromString(data).Basex62Encode() 55 | enStr := en.ToString() 56 | 57 | assertError(en.Error, name + " Encode error") 58 | 59 | de := FromString(enStr).Basex62Decode() 60 | deStr := de.ToString() 61 | 62 | assertError(de.Error, name + " Decode error") 63 | 64 | assert(data, deStr, name) 65 | } 66 | 67 | func Test_BasexEncoder(t *testing.T) { 68 | assert := assertT(t) 69 | assertError := assertErrorT(t) 70 | 71 | name := "Base32Encoder" 72 | data := "test-pass" 73 | 74 | const encodeTest = "ACDEFGHIJKLMNOPQRSTUVWXYZ234569" 75 | 76 | en := FromString(data).BasexEncodeWithEncoder(encodeTest) 77 | enStr := en.ToString() 78 | 79 | assertError(en.Error, name + " Encode error") 80 | 81 | de := FromString(enStr).BasexDecodeWithEncoder(encodeTest) 82 | deStr := de.ToString() 83 | 84 | assertError(de.Error, name + " Decode error") 85 | 86 | assert(data, deStr, name) 87 | } 88 | -------------------------------------------------------------------------------- /encoding/binary.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "bytes" 5 | "encoding/binary" 6 | ) 7 | 8 | // Binary Little Endian Encode 9 | func (this Encoding) BinaryLittleEndianEncode(data any) Encoding { 10 | buf := bytes.NewBuffer(nil) 11 | 12 | err := binary.Write(buf, binary.LittleEndian, data) 13 | if err != nil { 14 | this.Error = err 15 | return this 16 | } 17 | 18 | this.data = buf.Bytes() 19 | 20 | return this 21 | } 22 | 23 | // Binary Little Endian Decode 24 | func (this Encoding) BinaryLittleEndianDecode(dst any) Encoding { 25 | buf := bytes.NewBuffer(this.data) 26 | 27 | this.Error = binary.Read(buf, binary.LittleEndian, dst) 28 | 29 | return this 30 | } 31 | 32 | // ==================== 33 | 34 | // Binary Big Endian Encode 35 | func (this Encoding) BinaryBigEndianEncode(data any) Encoding { 36 | buf := bytes.NewBuffer(nil) 37 | 38 | err := binary.Write(buf, binary.BigEndian, data) 39 | if err != nil { 40 | this.Error = err 41 | return this 42 | } 43 | 44 | this.data = buf.Bytes() 45 | 46 | return this 47 | } 48 | 49 | // Binary Big Endian Decode 50 | func (this Encoding) BinaryBigEndianDecode(dst any) Encoding { 51 | buf := bytes.NewBuffer(this.data) 52 | 53 | this.Error = binary.Read(buf, binary.BigEndian, dst) 54 | 55 | return this 56 | } 57 | -------------------------------------------------------------------------------- /encoding/binary_test.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func Test_BinaryLittleEndian(t *testing.T) { 8 | assert := assertT(t) 9 | assertError := assertErrorT(t) 10 | 11 | data := uint16(61375) 12 | name := "BinaryLittleEndian" 13 | 14 | en := FromString("").BinaryLittleEndianEncode(data) 15 | enStr := en.ToString() 16 | 17 | assertError(en.Error, name + " Encode error") 18 | 19 | var deStr uint16 20 | de := FromString(enStr).BinaryLittleEndianDecode(&deStr) 21 | 22 | assertError(de.Error, name + " Decode error") 23 | 24 | assert(data, deStr, name) 25 | } 26 | 27 | func Test_BinaryBigEndian(t *testing.T) { 28 | assert := assertT(t) 29 | assertError := assertErrorT(t) 30 | 31 | data := uint16(61375) 32 | name := "BinaryBigEndian" 33 | 34 | en := FromString("").BinaryBigEndianEncode(data) 35 | enStr := en.ToString() 36 | 37 | assertError(en.Error, name + " Encode error") 38 | 39 | var deStr uint16 40 | de := FromString(enStr).BinaryBigEndianDecode(&deStr) 41 | 42 | assertError(de.Error, name + " Decode error") 43 | 44 | assert(data, deStr, name) 45 | } 46 | 47 | func Test_BinaryBigEndianBase64(t *testing.T) { 48 | assert := assertT(t) 49 | assertError := assertErrorT(t) 50 | 51 | data := uint16(61375) 52 | name := "BinaryBigEndianBase64" 53 | 54 | en := FromString("").BinaryBigEndianEncode(data).Base64Encode() 55 | enStr := en.ToString() 56 | 57 | assertError(en.Error, name + " Encode error") 58 | 59 | var deStr uint16 60 | de := FromString(enStr).Base64Decode().BinaryBigEndianDecode(&deStr) 61 | 62 | assertError(de.Error, name + " Decode error") 63 | 64 | assert(data, deStr, name) 65 | } 66 | -------------------------------------------------------------------------------- /encoding/convert.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "errors" 5 | "strconv" 6 | ) 7 | 8 | // 十进制转二进制 9 | // dec to bin 10 | func Decbin(number int64) string { 11 | return strconv.FormatInt(number, 2) 12 | } 13 | 14 | // 二进制转十进制 15 | // bin to dec 16 | func Bindec(str string) int64 { 17 | data, _ := strconv.ParseInt(str, 2, 0) 18 | 19 | return data 20 | } 21 | 22 | // 十进制转八进制 23 | // dec to oct 24 | func Decoct(number int64) string { 25 | return strconv.FormatInt(number, 8) 26 | } 27 | 28 | // 八进制转十进制 29 | // oct to dec 30 | func Octdec(str string) int64 { 31 | data, _ := strconv.ParseInt(str, 8, 0) 32 | 33 | return data 34 | } 35 | 36 | // 十进制转十六进制 37 | // dec to hex 38 | func Dechex(number int64) string { 39 | return strconv.FormatInt(number, 16) 40 | } 41 | 42 | // 十六进制转十进制 43 | // hex to dec 44 | func Hexdec(str string) int64 { 45 | data, _ := strconv.ParseInt(str, 16, 0) 46 | 47 | return data 48 | } 49 | 50 | // 各种进制互转 51 | // 十进制转十六进制 52 | // Base Convert 53 | // BaseConvert("12312", 10, 16) 54 | // [2- 36] 进制 55 | func BaseConvert(number string, frombase, tobase int) string { 56 | i, err := strconv.ParseInt(number, frombase, 0) 57 | if err != nil { 58 | return "" 59 | } 60 | 61 | return strconv.FormatInt(i, tobase) 62 | } 63 | 64 | // ==================== 65 | 66 | // ConvertDecode 67 | // 给定类型数据格式化为string类型数据 68 | // bitSize 限制长度 69 | // ParseBool()、ParseFloat()、ParseInt()、ParseUint()。 70 | // FormatBool()、FormatInt()、FormatUint()、FormatFloat()、 71 | func (this Encoding) ConvertDecode(input any, base int, bitSize ...int) Encoding { 72 | newBitSize := 0 73 | if len(bitSize) > 0 { 74 | newBitSize = bitSize[0] 75 | } 76 | 77 | var number int64 78 | var err error 79 | 80 | switch input.(type) { 81 | case int: 82 | number = int64(input.(int)) 83 | case int8: 84 | number = int64(input.(int8)) 85 | case int16: 86 | number = int64(input.(int16)) 87 | case int32: 88 | number = int64(input.(int32)) 89 | case int64: 90 | number = input.(int64) 91 | case string: 92 | number, err = strconv.ParseInt(input.(string), base, newBitSize) 93 | if err != nil { 94 | this.Error = err 95 | return this 96 | } 97 | default: 98 | this.Error = errors.New("data error.") 99 | return this 100 | } 101 | 102 | // 转为10进制字符 103 | data := strconv.FormatInt(number, 10) 104 | 105 | this.data = []byte(data) 106 | 107 | return this 108 | } 109 | 110 | // 二进制 111 | // ConvertBinDecode 112 | func (this Encoding) ConvertBinDecode(data string) Encoding { 113 | return this.ConvertDecode(data, 2) 114 | } 115 | 116 | // 八进制 117 | // ConvertOctDecode 118 | func (this Encoding) ConvertOctDecode(data string) Encoding { 119 | return this.ConvertDecode(data, 8) 120 | } 121 | 122 | // 十进制 123 | // ConvertDecDecode 124 | func (this Encoding) ConvertDecDecode(data int64) Encoding { 125 | return this.ConvertDecode(data, 10) 126 | } 127 | 128 | // 十进制字符 129 | // ConvertDecStringDecode 130 | func (this Encoding) ConvertDecStringDecode(data string) Encoding { 131 | return this.ConvertDecode(data, 10) 132 | } 133 | 134 | // 十六进制 135 | // ConvertHexDecode 136 | func (this Encoding) ConvertHexDecode(data string) Encoding { 137 | return this.ConvertDecode(data, 16) 138 | } 139 | 140 | // ==================== 141 | 142 | // 输出进制Encode 143 | // ConvertEncode 144 | func (this Encoding) ConvertEncode(base int) string { 145 | number, err := strconv.ParseInt(string(this.data), 10, 0) 146 | if err != nil { 147 | return "" 148 | } 149 | 150 | return strconv.FormatInt(number, base) 151 | } 152 | 153 | // 输出 二进制 154 | // ConvertBinEncode 155 | func (this Encoding) ConvertBinEncode() string { 156 | return this.ConvertEncode(2) 157 | } 158 | 159 | // 输出 八进制 160 | // ConvertOctEncode 161 | func (this Encoding) ConvertOctEncode() string { 162 | return this.ConvertEncode(8) 163 | } 164 | 165 | // 输出 十进制 166 | // ConvertDecEncode 167 | func (this Encoding) ConvertDecEncode() int64 { 168 | number, err := strconv.ParseInt(string(this.data), 10, 0) 169 | if err != nil { 170 | return 0 171 | } 172 | 173 | return number 174 | } 175 | 176 | // 输出 十进制 177 | // ConvertDecStringEncode 178 | func (this Encoding) ConvertDecStringEncode() string { 179 | return this.ConvertEncode(10) 180 | } 181 | 182 | // 输出 十六进制 183 | // ConvertHexEncode 184 | func (this Encoding) ConvertHexEncode() string { 185 | return this.ConvertEncode(16) 186 | } 187 | -------------------------------------------------------------------------------- /encoding/csv.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "bytes" 5 | "errors" 6 | "strings" 7 | "reflect" 8 | "encoding/csv" 9 | ) 10 | 11 | // Csv Encode 12 | func (this Encoding) CsvEncode(data [][]string) Encoding { 13 | buf := bytes.NewBuffer(nil) 14 | 15 | w := csv.NewWriter(buf) 16 | w.WriteAll(data) 17 | 18 | if err := w.Error(); err != nil { 19 | this.Error = err 20 | return this 21 | } 22 | 23 | this.data = buf.Bytes() 24 | 25 | return this 26 | } 27 | 28 | // Csv Decode 29 | func (this Encoding) CsvDecode(dst any, opts ...rune) Encoding { 30 | buf := strings.NewReader(string(this.data)) 31 | r := csv.NewReader(buf) 32 | 33 | if len(opts) > 0 { 34 | // ';' 35 | r.Comma = opts[0] 36 | } 37 | 38 | if len(opts) > 1 { 39 | // '#' 40 | r.Comment = opts[1] 41 | } 42 | 43 | csvs, err := r.ReadAll() 44 | if err != nil { 45 | this.Error = err 46 | return this 47 | } 48 | 49 | // 获取最后指针 50 | dstValue := reflect.ValueOf(dst) 51 | for dstValue.Kind() == reflect.Pointer { 52 | dstValue = dstValue.Elem() 53 | } 54 | 55 | if !dstValue.IsValid() || dstValue.Kind() != reflect.Slice { 56 | this.Error = errors.New("Decode to data type is not slice") 57 | return this 58 | } 59 | 60 | if !dstValue.CanSet() { 61 | this.Error = errors.New("Decode to data not set") 62 | return this 63 | } 64 | 65 | dstData := make([]reflect.Value, 0) 66 | for _, csv := range csvs { 67 | dstData = append(dstData, reflect.ValueOf(csv)) 68 | } 69 | 70 | dstDataArr := reflect.Append(dstValue, dstData...) 71 | 72 | dstValue.Set(dstDataArr) 73 | 74 | return this 75 | } 76 | -------------------------------------------------------------------------------- /encoding/csv_test.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func Test_Csv(t *testing.T) { 8 | assert := assertT(t) 9 | assertError := assertErrorT(t) 10 | 11 | name := "Csv" 12 | 13 | records := [][]string{ 14 | {"first_name", "last_name", "username"}, 15 | {"Rob", "Pike", "rob"}, 16 | {"Ken", "Thompson", "ken"}, 17 | {"Robert", "Griesemer", "gri"}, 18 | } 19 | in := `first_name,last_name,username 20 | Rob,Pike,rob 21 | Ken,Thompson,ken 22 | Robert,Griesemer,gri 23 | ` 24 | 25 | en := FromString("").CsvEncode(records) 26 | enStr := en.ToString() 27 | 28 | assertError(en.Error, name + " Encode error") 29 | assert(in, enStr, name + " Encode") 30 | 31 | var deStr [][]string 32 | de := FromString(in).CsvDecode(&deStr) 33 | 34 | assertError(de.Error, name + " Decode error") 35 | assert(records, deStr, name + " Decode") 36 | } 37 | -------------------------------------------------------------------------------- /encoding/data_set.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "sync" 5 | ) 6 | 7 | type DataName interface { 8 | ~uint | ~int | ~string 9 | } 10 | 11 | /** 12 | * Data Set 13 | * 14 | * @create 2023-3-31 15 | * @author deatil 16 | */ 17 | type DataSet[N DataName, M any] struct { 18 | // 锁定 19 | mu sync.RWMutex 20 | 21 | // 数据 22 | data map[N]func() M 23 | } 24 | 25 | // NewDataSet 26 | func NewDataSet[N DataName, M any]() *DataSet[N, M] { 27 | return &DataSet[N, M]{ 28 | data: make(map[N]func() M), 29 | } 30 | } 31 | 32 | // Add 33 | func (this *DataSet[N, M]) Add(name N, data func() M) *DataSet[N, M] { 34 | this.mu.Lock() 35 | defer this.mu.Unlock() 36 | 37 | this.data[name] = data 38 | 39 | return this 40 | } 41 | 42 | // Has 43 | func (this *DataSet[N, M]) Has(name N) bool { 44 | this.mu.RLock() 45 | defer this.mu.RUnlock() 46 | 47 | if _, ok := this.data[name]; ok { 48 | return true 49 | } 50 | 51 | return false 52 | } 53 | 54 | // Get 55 | func (this *DataSet[N, M]) Get(name N) func() M { 56 | this.mu.RLock() 57 | defer this.mu.RUnlock() 58 | 59 | if data, ok := this.data[name]; ok { 60 | return data 61 | } 62 | 63 | return nil 64 | } 65 | 66 | // Remove 67 | func (this *DataSet[N, M]) Remove(name N) *DataSet[N, M] { 68 | this.mu.Lock() 69 | defer this.mu.Unlock() 70 | 71 | delete(this.data, name) 72 | 73 | return this 74 | } 75 | 76 | // Names 77 | func (this *DataSet[N, M]) Names() []N { 78 | names := make([]N, 0) 79 | for name, _ := range this.data { 80 | names = append(names, name) 81 | } 82 | 83 | return names 84 | } 85 | 86 | // All 87 | func (this *DataSet[N, M]) All() map[N]func() M { 88 | return this.data 89 | } 90 | 91 | // Clean 92 | func (this *DataSet[N, M]) Clean() { 93 | this.mu.Lock() 94 | defer this.mu.Unlock() 95 | 96 | for name, _ := range this.data { 97 | delete(this.data, name) 98 | } 99 | } 100 | 101 | // Len 102 | func (this *DataSet[N, M]) Len() int { 103 | return len(this.data) 104 | } 105 | -------------------------------------------------------------------------------- /encoding/encoding.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | /** 4 | * Encode 5 | * 6 | * @create 2022-4-3 7 | * @author deatil 8 | */ 9 | type Encoding struct { 10 | // data bytes 11 | data []byte 12 | 13 | // Error 14 | Error error 15 | } 16 | 17 | // NewEncoding 18 | func NewEncoding() Encoding { 19 | return Encoding{} 20 | } 21 | 22 | // New 23 | func New() Encoding { 24 | return NewEncoding() 25 | } 26 | 27 | // default Encoding 28 | var defaultEncoding = NewEncoding() 29 | -------------------------------------------------------------------------------- /encoding/encoding_from.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "io" 5 | "bytes" 6 | ) 7 | 8 | // From Bytes 9 | func (this Encoding) FromBytes(data []byte) Encoding { 10 | this.data = data 11 | 12 | return this 13 | } 14 | 15 | // FromBytes 16 | func FromBytes(data []byte) Encoding { 17 | return defaultEncoding.FromBytes(data) 18 | } 19 | 20 | // FromString 21 | func (this Encoding) FromString(data string) Encoding { 22 | this.data = []byte(data) 23 | 24 | return this 25 | } 26 | 27 | // FromString 28 | func FromString(data string) Encoding { 29 | return defaultEncoding.FromString(data) 30 | } 31 | 32 | // FromReader 33 | func (this Encoding) FromReader(reader io.Reader) Encoding { 34 | buf := bytes.NewBuffer(nil) 35 | 36 | if _, err := io.Copy(buf, reader); err != nil { 37 | this.Error = err 38 | 39 | return this 40 | } 41 | 42 | this.data = buf.Bytes() 43 | 44 | return this 45 | } 46 | 47 | // FromReader 48 | func FromReader(reader io.Reader) Encoding { 49 | return defaultEncoding.FromReader(reader) 50 | } 51 | -------------------------------------------------------------------------------- /encoding/encoding_test.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "testing" 5 | "reflect" 6 | ) 7 | 8 | func assertT(t *testing.T) func(any, any, string) { 9 | return func(actual any, expected any, msg string) { 10 | if !reflect.DeepEqual(actual, expected) { 11 | t.Errorf("Failed %s: actual: %v, expected: %v", msg, actual, expected) 12 | } 13 | } 14 | } 15 | 16 | func assertErrorT(t *testing.T) func(error, string) { 17 | return func(err error, msg string) { 18 | if err != nil { 19 | t.Errorf("Failed %s: error: %+v", msg, err) 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /encoding/encoding_to.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "io" 5 | "bytes" 6 | ) 7 | 8 | // output String 9 | func (this Encoding) String() string { 10 | return this.ToString() 11 | } 12 | 13 | // output Bytes 14 | func (this Encoding) ToBytes() []byte { 15 | return this.data 16 | } 17 | 18 | // output String 19 | func (this Encoding) ToString() string { 20 | return string(this.data) 21 | } 22 | 23 | // output io.Reader 24 | func (this Encoding) ToReader() io.Reader { 25 | return bytes.NewBuffer(this.data) 26 | } 27 | -------------------------------------------------------------------------------- /encoding/encoding_use.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // EncodeDecode接口 8 | type IEncoding interface { 9 | // Encode 10 | Encode([]byte, ...map[string]any) ([]byte, error) 11 | 12 | // Decode 13 | Decode([]byte, ...map[string]any) ([]byte, error) 14 | } 15 | 16 | // EncodeDecode 17 | var UseEncoding = NewDataSet[string, IEncoding]() 18 | 19 | // get Encoding 20 | func getEncoding(name string) (IEncoding, error) { 21 | if !UseEncoding.Has(name) { 22 | err := fmt.Errorf("Encoding: Encoding type [%s] is error.", name) 23 | return nil, err 24 | } 25 | 26 | // EncodeDecode 27 | newEncoding := UseEncoding.Get(name) 28 | 29 | return newEncoding(), nil 30 | } 31 | 32 | // Encode 33 | func (this Encoding) EncodeBy(name string, cfg ...map[string]any) Encoding { 34 | newEncoding, err := getEncoding(name) 35 | if err != nil { 36 | this.Error = err 37 | return this 38 | } 39 | 40 | this.data, this.Error = newEncoding.Encode(this.data, cfg...) 41 | 42 | return this 43 | } 44 | 45 | // Decode 46 | func (this Encoding) DecodeBy(name string, cfg ...map[string]any) Encoding { 47 | newEncoding, err := getEncoding(name) 48 | if err != nil { 49 | this.Error = err 50 | return this 51 | } 52 | 53 | this.data, this.Error = newEncoding.Decode(this.data, cfg...) 54 | 55 | return this 56 | } 57 | -------------------------------------------------------------------------------- /encoding/encoding_use_test.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "testing" 5 | "encoding/base64" 6 | ) 7 | 8 | type testEncoding struct {} 9 | 10 | // Encode 11 | func (this testEncoding) Encode(data []byte, cfg ...map[string]any) ([]byte, error) { 12 | newData := base64.StdEncoding.EncodeToString(data) 13 | 14 | return []byte(newData), nil 15 | } 16 | 17 | // Decode 18 | func (this testEncoding) Decode(data []byte, cfg ...map[string]any) ([]byte, error) { 19 | return base64.StdEncoding.DecodeString(string(data)) 20 | } 21 | 22 | func init() { 23 | UseEncoding.Add("TestEncoding", func() IEncoding { 24 | return testEncoding{} 25 | }) 26 | } 27 | 28 | func Test_UseEncoding(t *testing.T) { 29 | assert := assertT(t) 30 | assertError := assertErrorT(t) 31 | 32 | data := "test-pass123" 33 | 34 | en := FromString(data).EncodeBy("TestEncoding") 35 | enStr := en.ToString() 36 | 37 | assertError(en.Error, "UseEncoding Encode error") 38 | 39 | de := FromString(enStr).DecodeBy("TestEncoding") 40 | deStr := de.ToString() 41 | 42 | assertError(de.Error, "UseEncoding Decode error") 43 | 44 | assert(data, deStr, "UseEncoding") 45 | } 46 | -------------------------------------------------------------------------------- /encoding/gob.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "bytes" 5 | "encoding/gob" 6 | ) 7 | 8 | // Gob Encode 9 | func (this Encoding) GobEncode(data any) Encoding { 10 | buf := bytes.NewBuffer(nil) 11 | 12 | enc := gob.NewEncoder(buf) 13 | err := enc.Encode(data) 14 | if err != nil { 15 | this.Error = err 16 | return this 17 | } 18 | 19 | this.data = buf.Bytes() 20 | 21 | return this 22 | } 23 | 24 | // Gob Decode 25 | func (this Encoding) GobDecode(dst any) Encoding { 26 | buf := bytes.NewBuffer(this.data) 27 | dec := gob.NewDecoder(buf) 28 | 29 | this.Error = dec.Decode(dst) 30 | 31 | return this 32 | } 33 | -------------------------------------------------------------------------------- /encoding/gob_test.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func Test_Gob(t *testing.T) { 8 | assert := assertT(t) 9 | assertError := assertErrorT(t) 10 | 11 | name := "Gob" 12 | data := map[string]string{ 13 | "key": "test-pass", 14 | "key2": "test-pass-Gob", 15 | } 16 | 17 | en := FromString("").GobEncode(data) 18 | enStr := en.ToString() 19 | 20 | assertError(en.Error, name + " Encode error") 21 | 22 | var deData map[string]string 23 | de := FromString(enStr).GobDecode(&deData) 24 | 25 | assertError(de.Error, name + " Decode error") 26 | 27 | assert(data["key"], deData["key"], name) 28 | assert(data["key2"], deData["key2"], name) 29 | } 30 | -------------------------------------------------------------------------------- /encoding/hex.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "encoding/hex" 5 | ) 6 | 7 | // Hex Decode 8 | func (this Encoding) HexDecode() Encoding { 9 | data := string(this.data) 10 | this.data, this.Error = hex.DecodeString(data) 11 | 12 | return this 13 | } 14 | 15 | // Hex Encode 16 | func (this Encoding) HexEncode() Encoding { 17 | data := hex.EncodeToString(this.data) 18 | this.data = []byte(data) 19 | 20 | return this 21 | } 22 | -------------------------------------------------------------------------------- /encoding/hex_test.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func Test_Hex(t *testing.T) { 8 | assert := assertT(t) 9 | assertError := assertErrorT(t) 10 | 11 | name := "Hex" 12 | data := "test-pass" 13 | 14 | en := FromString(data).HexEncode() 15 | enStr := en.ToString() 16 | 17 | assertError(en.Error, name + " Encode error") 18 | 19 | de := FromString(enStr).HexDecode() 20 | deStr := de.ToString() 21 | 22 | assertError(de.Error, name + " Decode error") 23 | 24 | assert(data, deStr, name) 25 | } 26 | -------------------------------------------------------------------------------- /encoding/json.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "encoding/json" 5 | 6 | jsoniter "github.com/json-iterator/go" 7 | ) 8 | 9 | // JSON Encode 10 | func (this Encoding) JSONEncode(data any) Encoding { 11 | this.data, this.Error = json.Marshal(data) 12 | 13 | return this 14 | } 15 | 16 | // JSON Decode 17 | func (this Encoding) JSONDecode(dst any) Encoding { 18 | this.Error = json.Unmarshal(this.data, dst) 19 | 20 | return this 21 | } 22 | 23 | // ==================== 24 | 25 | // JSONIterator Encode 26 | func (this Encoding) JSONIteratorEncode(data any) Encoding { 27 | this.data, this.Error = jsoniter.Marshal(data) 28 | 29 | return this 30 | } 31 | 32 | // JSONIterator Indent Encode 33 | func (this Encoding) JSONIteratorIndentEncode(v any, prefix, indent string) Encoding { 34 | this.data, this.Error = jsoniter.MarshalIndent(v, prefix, indent) 35 | 36 | return this 37 | } 38 | 39 | // JSONIterator Decode 40 | func (this Encoding) JSONIteratorDecode(dst any) Encoding { 41 | this.Error = jsoniter.Unmarshal(this.data, dst) 42 | 43 | return this 44 | } 45 | -------------------------------------------------------------------------------- /encoding/json_test.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func Test_JSON(t *testing.T) { 8 | assert := assertT(t) 9 | assertError := assertErrorT(t) 10 | 11 | name := "JSON" 12 | data := map[string]string{ 13 | "key": "test-pass", 14 | "key2": "test-pass-JSON", 15 | } 16 | 17 | en := FromString("").JSONEncode(data) 18 | enStr := en.ToString() 19 | 20 | assertError(en.Error, name + " Encode error") 21 | 22 | var deData map[string]string 23 | de := FromString(enStr).JSONDecode(&deData) 24 | 25 | assertError(de.Error, name + " Decode error") 26 | 27 | assert(data["key"], deData["key"], name) 28 | assert(data["key2"], deData["key2"], name) 29 | } 30 | 31 | func Test_JSONIterator(t *testing.T) { 32 | assert := assertT(t) 33 | assertError := assertErrorT(t) 34 | 35 | name := "JSONIterator" 36 | data := map[string]string{ 37 | "key": "test-pass", 38 | "key2": "test-pass-JSONIterator", 39 | } 40 | 41 | en := FromString("").JSONIteratorEncode(data) 42 | enStr := en.ToString() 43 | 44 | assertError(en.Error, name + " Encode error") 45 | 46 | var deData map[string]string 47 | de := FromString(enStr).JSONIteratorDecode(&deData) 48 | 49 | assertError(de.Error, name + " Decode error") 50 | 51 | assert(data["key"], deData["key"], name) 52 | assert(data["key2"], deData["key2"], name) 53 | } 54 | -------------------------------------------------------------------------------- /encoding/morse.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "github.com/deatil/go-encoding/morse" 5 | ) 6 | 7 | // MorseITU Decode 8 | func (this Encoding) MorseITUDecode() Encoding { 9 | data, err := morse.ITUEncoding.DecodeString(string(this.data)) 10 | 11 | this.data = data 12 | this.Error = err 13 | 14 | return this 15 | } 16 | 17 | // MorseITU Encode 18 | func (this Encoding) MorseITUEncode() Encoding { 19 | data := morse.ITUEncoding.EncodeToString(this.data) 20 | this.data = []byte(data) 21 | 22 | return this 23 | } 24 | -------------------------------------------------------------------------------- /encoding/morse_test.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func Test_MorseITU(t *testing.T) { 8 | assert := assertT(t) 9 | assertError := assertErrorT(t) 10 | 11 | name := "MorseITU" 12 | data := "testpass" 13 | 14 | en := FromString(data).MorseITUEncode() 15 | enStr := en.ToString() 16 | 17 | assertError(en.Error, name + " Encode error") 18 | 19 | de := FromString(enStr).MorseITUDecode() 20 | deStr := de.ToString() 21 | 22 | assertError(de.Error, name + " Decode error") 23 | 24 | assert(data, deStr, name) 25 | } 26 | -------------------------------------------------------------------------------- /encoding/puny.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "github.com/deatil/go-encoding/puny" 5 | ) 6 | 7 | // PunyDecode Decode 8 | func (this Encoding) PunyDecode() Encoding { 9 | this.data, this.Error = puny.StdEncoding.Decode(this.data) 10 | 11 | return this 12 | } 13 | 14 | // Puny Encode 15 | func (this Encoding) PunyEncode() Encoding { 16 | this.data, this.Error = puny.StdEncoding.Encode(this.data) 17 | 18 | return this 19 | } 20 | -------------------------------------------------------------------------------- /encoding/puny_test.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func Test_Puny(t *testing.T) { 8 | assert := assertT(t) 9 | assertError := assertErrorT(t) 10 | 11 | name := "Puny" 12 | data := "ó チツチノハフヘキキξεζοреё┢┣┮┐┑ 《《" 13 | 14 | en := FromString(data).PunyEncode() 15 | enStr := en.ToString() 16 | 17 | assertError(en.Error, name + " Encode error") 18 | 19 | de := FromString(enStr).PunyDecode() 20 | deStr := de.ToString() 21 | 22 | assertError(de.Error, name + " Decode error") 23 | 24 | assert(data, deStr, name) 25 | } 26 | -------------------------------------------------------------------------------- /encoding/quotedprintable.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "github.com/deatil/go-encoding/quotedprintable" 5 | ) 6 | 7 | // quotedprintable Decode 8 | func (this Encoding) QuotedprintableDecode() Encoding { 9 | this.data, this.Error = quotedprintable.StdEncoding.Decode(this.data) 10 | 11 | return this 12 | } 13 | 14 | // quotedprintable Encode 15 | func (this Encoding) QuotedprintableEncode() Encoding { 16 | this.data, this.Error = quotedprintable.StdEncoding.Encode(this.data) 17 | 18 | return this 19 | } 20 | -------------------------------------------------------------------------------- /encoding/quotedprintable_test.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func Test_Quotedprintable(t *testing.T) { 8 | assert := assertT(t) 9 | assertError := assertErrorT(t) 10 | 11 | name := "Quotedprintable" 12 | data := `quoted\nprin\rtabl e gt\tdf` 13 | 14 | en := FromString(data).QuotedprintableEncode() 15 | enStr := en.ToString() 16 | 17 | assertError(en.Error, name + " Encode error") 18 | 19 | de := FromString(enStr).QuotedprintableDecode() 20 | deStr := de.ToString() 21 | 22 | assertError(de.Error, name + " Decode error") 23 | 24 | assert(data, deStr, name) 25 | } 26 | -------------------------------------------------------------------------------- /encoding/safe_url.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "net/url" 5 | ) 6 | 7 | // SafeURL Decode 8 | func (this Encoding) SafeURLDecode() Encoding { 9 | data := string(this.data) 10 | dst, err := url.QueryUnescape(data) 11 | 12 | this.data = []byte(dst) 13 | this.Error = err 14 | 15 | return this 16 | } 17 | 18 | // SafeURL Encode 19 | func (this Encoding) SafeURLEncode() Encoding { 20 | data := url.QueryEscape(string(this.data)) 21 | this.data = []byte(data) 22 | 23 | return this 24 | } 25 | -------------------------------------------------------------------------------- /encoding/safe_url_test.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | var safeUrlTests = []struct { 9 | input string 10 | output string 11 | }{ 12 | {"", ""}, 13 | {"www.github.com?tab=star&open=lt", "www.github.com%3Ftab%3Dstar%26open%3Dlt"}, 14 | } 15 | 16 | func TestSafeURL_From(t *testing.T) { 17 | assert := assertT(t) 18 | assertError := assertErrorT(t) 19 | 20 | for index, test := range safeUrlTests { 21 | e := FromString(test.output).SafeURLDecode() 22 | 23 | t.Run(fmt.Sprintf("test_%d", index), func(t *testing.T) { 24 | assertError(e.Error, "SafeURL_From") 25 | assert(test.input, e.ToString(), "SafeURL_From") 26 | }) 27 | } 28 | } 29 | 30 | func TestSafeURL_To(t *testing.T) { 31 | assert := assertT(t) 32 | assertError := assertErrorT(t) 33 | 34 | for index, test := range safeUrlTests { 35 | e := FromString(test.input).SafeURLEncode() 36 | 37 | t.Run(fmt.Sprintf("test_%d", index), func(t *testing.T) { 38 | assertError(e.Error, "SafeURL_To") 39 | assert(test.output, e.ToString(), "SafeURL_To") 40 | }) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /encoding/serialize.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "bytes" 5 | "reflect" 6 | "strconv" 7 | "encoding/gob" 8 | ) 9 | 10 | // Serialize Encode 11 | func (this Encoding) SerializeEncode(data any) Encoding { 12 | this.data, this.Error = serialize(data) 13 | 14 | return this 15 | } 16 | 17 | // Serialize Decode 18 | func (this Encoding) SerializeDecode(val any) Encoding { 19 | this.Error = unserialize(this.data, val) 20 | 21 | return this 22 | } 23 | 24 | // serialize 25 | func serialize(value any) ([]byte, error) { 26 | if bytes, ok := value.([]byte); ok { 27 | return bytes, nil 28 | } 29 | 30 | switch v := reflect.ValueOf(value); v.Kind() { 31 | case reflect.Int, 32 | reflect.Int8, 33 | reflect.Int16, 34 | reflect.Int32, 35 | reflect.Int64: 36 | return []byte(strconv.FormatInt(v.Int(), 10)), nil 37 | case reflect.Uint, 38 | reflect.Uint8, 39 | reflect.Uint16, 40 | reflect.Uint32, 41 | reflect.Uint64: 42 | return []byte(strconv.FormatUint(v.Uint(), 10)), nil 43 | } 44 | 45 | var b bytes.Buffer 46 | encoder := gob.NewEncoder(&b) 47 | 48 | if err := encoder.Encode(value); err != nil { 49 | return nil, err 50 | } 51 | 52 | return b.Bytes(), nil 53 | } 54 | 55 | // unserialize 56 | func unserialize(data []byte, ptr any) (err error) { 57 | if bytes, ok := ptr.(*[]byte); ok { 58 | *bytes = data 59 | return nil 60 | } 61 | 62 | if v := reflect.ValueOf(ptr); v.Kind() == reflect.Ptr { 63 | switch p := v.Elem(); p.Kind() { 64 | case reflect.Int, 65 | reflect.Int8, 66 | reflect.Int16, 67 | reflect.Int32, 68 | reflect.Int64: 69 | var i int64 70 | i, err = strconv.ParseInt(string(data), 10, 64) 71 | if err != nil { 72 | return err 73 | } 74 | 75 | p.SetInt(i) 76 | return nil 77 | 78 | case reflect.Uint, 79 | reflect.Uint8, 80 | reflect.Uint16, 81 | reflect.Uint32, 82 | reflect.Uint64: 83 | var i uint64 84 | i, err = strconv.ParseUint(string(data), 10, 64) 85 | if err != nil { 86 | return err 87 | } 88 | 89 | p.SetUint(i) 90 | return nil 91 | } 92 | } 93 | 94 | b := bytes.NewBuffer(data) 95 | decoder := gob.NewDecoder(b) 96 | 97 | if err = decoder.Decode(ptr); err != nil { 98 | return err 99 | } 100 | 101 | return nil 102 | } 103 | -------------------------------------------------------------------------------- /encoding/serialize_test.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func Test_Serialize(t *testing.T) { 8 | assert := assertT(t) 9 | assertError := assertErrorT(t) 10 | 11 | name := "Serialize" 12 | data := map[string]string{ 13 | "key": "test-pass", 14 | "key2": "test-pass-key2", 15 | } 16 | 17 | en := FromString("").SerializeEncode(data) 18 | enStr := en.ToString() 19 | 20 | assertError(en.Error, name + " Encode error") 21 | 22 | var deData map[string]string 23 | de := FromString(enStr).SerializeDecode(&deData) 24 | 25 | assertError(de.Error, name + " Decode error") 26 | 27 | assert(data["key"], deData["key"], name) 28 | assert(data["key2"], deData["key2"], name) 29 | } 30 | -------------------------------------------------------------------------------- /encoding/xml.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "bytes" 5 | "encoding/xml" 6 | ) 7 | 8 | // Xml Decode 9 | func (this Encoding) XmlDecode(dst any) Encoding { 10 | buf := bytes.NewBuffer(this.data) 11 | dec := xml.NewDecoder(buf) 12 | 13 | this.Error = dec.Decode(dst) 14 | 15 | return this 16 | } 17 | 18 | // Xml Encode 19 | func (this Encoding) XmlEncode(data any) Encoding { 20 | buf := bytes.NewBuffer(nil) 21 | 22 | enc := xml.NewEncoder(buf) 23 | err := enc.Encode(data) 24 | if err != nil { 25 | this.Error = err 26 | return this 27 | } 28 | 29 | this.data = buf.Bytes() 30 | 31 | return this 32 | } 33 | -------------------------------------------------------------------------------- /encoding/xml_test.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func Test_Xml(t *testing.T) { 8 | assert := assertT(t) 9 | assertError := assertErrorT(t) 10 | 11 | type Per struct { 12 | Name string 13 | Age int 14 | } 15 | 16 | name := "Xml" 17 | data := Per{ 18 | Name: "kkk", 19 | Age: 12, 20 | } 21 | 22 | en := FromString("").XmlEncode(data) 23 | enStr := en.ToString() 24 | 25 | assertError(en.Error, name + " Encode error") 26 | 27 | var deData Per 28 | de := FromString(enStr).XmlDecode(&deData) 29 | 30 | assertError(de.Error, name + " Decode error") 31 | 32 | assert(data.Name, deData.Name, name) 33 | assert(data.Age, data.Age, name) 34 | } 35 | -------------------------------------------------------------------------------- /example.md: -------------------------------------------------------------------------------- 1 | ### 使用 2 | 3 | ~~~go 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "github.com/deatil/go-encoding/encoding" 9 | ) 10 | 11 | type Per struct { 12 | Name string 13 | Age int 14 | } 15 | 16 | func main() { 17 | // Base64 编码后结果 18 | base64Data := encoding. 19 | FromString("use-data"). // 数据来源 20 | Base64Encode(). // 编码或者解码方式 21 | ToString() // 输出结果 22 | fmt.Println("Base64 编码后结果:", base64Data) 23 | 24 | // ===== 25 | 26 | // Asn1 编码 27 | var p string 28 | encodeStr := encoding.Asn1Encode("test-data").Base64Encode().ToString() 29 | encoding.FromString("Ewl0ZXN0LWRhdGE=").Base64Decode().Asn1Decode(&p) 30 | encodeStr2 := p 31 | 32 | // XML 编码 33 | p := Per{ 34 | Name: "kkk", 35 | Age: 12, 36 | } 37 | 38 | var p2 Per 39 | 40 | // 编码 41 | encodeStr := encoding.XmlEncode(p).Base64Encode().ToString() 42 | encoding.FromString("PFBlcj48TmFtZT5ra2s8L05hbWU+PEFnZT4xMjwvQWdlPjwvUGVyPg==").Base64Decode().XmlDecode(&p2) 43 | 44 | encodeStr2 := p2.Name 45 | 46 | // Binary 编码 47 | var p uint16 48 | encodeStr := encoding.BinaryLittleEndianEncode(uint16(61374)).Base64Encode().ToString() 49 | encoding.FromString("vu8=").Base64Decode().XmlDecode(&p) 50 | 51 | // Csv 编码 52 | records := [][]string{ 53 | {"first_name", "last_name", "username"}, 54 | {"Rob", "Pike", "rob"}, 55 | {"Ken", "Thompson", "ken"}, 56 | {"Robert", "Griesemer", "gri"}, 57 | } 58 | in := `first_name,last_name,username 59 | "Rob","Pike",rob 60 | Ken,Thompson,ken 61 | "Robert","Griesemer","gri" 62 | ` 63 | encodeStr := encoding.CsvEncode(records).ToString() 64 | 65 | var encodeStr2 [][]string 66 | encoding.FromString(in).CsvDecode(&encodeStr2) 67 | 68 | 69 | // Csv 编码2 70 | records := [][]string{ 71 | {"first_name", "last_name", "username"}, 72 | {"Rob", "Pike", "rob"}, 73 | {"Ken", "Thompson", "ken"}, 74 | {"Robert", "Griesemer", "gri"}, 75 | } 76 | in := `first_name;last_name;username 77 | "Rob";"Pike";rob 78 | # lines beginning with a # character are ignored 79 | Ken;Thompson;ken 80 | "Robert";"Griesemer";"gri" 81 | ` 82 | encodeStr := encoding.CsvEncode(records).ToString() 83 | 84 | var encodeStr2 [][]string 85 | encoding.FromString(in).CsvDecode(&encodeStr2, ';', '#') 86 | } 87 | 88 | ~~~ 89 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/deatil/go-encoding 2 | 3 | go 1.20 4 | 5 | require github.com/json-iterator/go v1.1.12 6 | 7 | require ( 8 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect 9 | github.com/modern-go/reflect2 v1.0.2 // indirect 10 | ) 11 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 2 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 3 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 4 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 5 | github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= 6 | github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= 7 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= 8 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 9 | github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= 10 | github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= 11 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 12 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 13 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 14 | github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= 15 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 16 | -------------------------------------------------------------------------------- /leb128/leb128.go: -------------------------------------------------------------------------------- 1 | package leb128 2 | 3 | // EncodeInt32 encodes the `value` as leb128 encoded byte array 4 | func EncodeInt32(value int32) []byte { 5 | result := make([]byte, 0) 6 | val := value 7 | i := 0 8 | 9 | for { 10 | b := byte(val & 0x7f) 11 | val >>= 7 12 | if (val == 0 && b & 0x40 == 0) || (val == -1 && b & 0x40 != 0) { 13 | result = append(result, b) 14 | break 15 | } 16 | 17 | result = append(result, b | 0x80) 18 | i++ 19 | } 20 | 21 | return result 22 | } 23 | 24 | // DecodeInt32 decodes an int32 and returns the number of bytes used from the given leb128 encoded array `value` 25 | func DecodeInt32(value []byte) (int32, int) { 26 | result := uint32(0) 27 | shift := 0 28 | 29 | for _, b := range value { 30 | result |= uint32(b & 0x7f) << shift 31 | shift += 7 32 | if b & 0x80 == 0 { 33 | if shift < 32 && b & 0x40 != 0 { 34 | result |= ^uint32(0) << shift 35 | } 36 | 37 | break 38 | } 39 | } 40 | 41 | return int32(result), shift / 7 42 | } 43 | 44 | // EncodeInt64 encodes the `value` as leb128 encoded byte array 45 | func EncodeInt64(value int64) []byte { 46 | result := make([]byte, 0) 47 | val := value 48 | 49 | for { 50 | b := byte(val & 0x7f) 51 | val >>= 7 52 | if (val == 0 && b & 0x40 == 0) || (val == -1 && b & 0x40 != 0) { 53 | result = append(result, b) 54 | break 55 | } 56 | 57 | result = append(result, b | 0x80) 58 | } 59 | 60 | return result 61 | } 62 | 63 | // DecodeInt64 decodes an int64 and returns the number of bytes used from the given leb128 encoded array `value` 64 | func DecodeInt64(value []byte) (int64, int) { 65 | result := uint64(0) 66 | shift := 0 67 | 68 | for _, b := range value { 69 | result |= uint64(b & 0x7f) << shift 70 | shift += 7 71 | 72 | if b & 0x80 == 0 { 73 | if shift < 64 && b & 0x40 != 0 { 74 | result |= ^uint64(0) << shift 75 | } 76 | 77 | break 78 | } 79 | } 80 | 81 | return int64(result), shift / 7 82 | } 83 | 84 | // EncodeUint32 encodes the `value` as leb128 encoded byte array 85 | func EncodeUint32(value uint32) []byte { 86 | result := make([]byte, 0) 87 | val := value 88 | 89 | for { 90 | b := byte(val & 0x7f) 91 | val >>= 7 92 | if val == 0 { 93 | result = append(result, b) 94 | break 95 | } 96 | 97 | result = append(result, b | 0x80) 98 | } 99 | 100 | return result 101 | } 102 | 103 | // DecodeUint32 decodes an uint32 and returns the number of bytes used from the given leb128 encoded array `value` 104 | func DecodeUint32(value []byte) (uint32, int) { 105 | result := uint32(0) 106 | shift := 0 107 | 108 | for _, b := range value { 109 | result |= uint32(b & 0x7f) << shift 110 | if b & 0x80 == 0 { 111 | break 112 | } 113 | 114 | shift += 7 115 | } 116 | 117 | return result, shift / 7 + 1 118 | } 119 | 120 | // EncodeUint64 encodes the `value` as leb128 encoded byte array 121 | func EncodeUint64(value uint64) []byte { 122 | result := make([]byte, 0) 123 | val := value 124 | 125 | for { 126 | b := byte(val & 0x7f) 127 | val >>= 7 128 | if val == 0 { 129 | result = append(result, b) 130 | break 131 | } 132 | 133 | result = append(result, b | 0x80) 134 | } 135 | 136 | return result 137 | } 138 | 139 | // DecodeUint64 decodes an uint64 and returns the number of bytes used from the given leb128 encoded array `value` 140 | func DecodeUint64(value []byte) (uint64, int) { 141 | result := uint64(0) 142 | shift := 0 143 | 144 | for _, b := range value { 145 | result |= uint64(b & 0x7f) << shift 146 | if b & 0x80 == 0 { 147 | break 148 | } 149 | 150 | shift += 7 151 | } 152 | 153 | return result, shift / 7 + 1 154 | } 155 | -------------------------------------------------------------------------------- /leb128/leb128_test.go: -------------------------------------------------------------------------------- 1 | package leb128 2 | 3 | import ( 4 | "bytes" 5 | "testing" 6 | "encoding/hex" 7 | ) 8 | 9 | type PairU struct { 10 | value uint64 11 | encoded string 12 | } 13 | 14 | type PairI struct { 15 | value int64 16 | encoded string 17 | } 18 | 19 | func fromHex(s string) []byte { 20 | h, _ := hex.DecodeString(s) 21 | return h 22 | } 23 | 24 | func Test_Basic(t *testing.T) { 25 | { 26 | if !bytes.Equal(EncodeUint64(624485), []byte{0xe5, 0x8e, 0x26}) { 27 | t.Error("EncodeUint64 fail") 28 | } 29 | 30 | uval, ulen := DecodeUint64([]byte{0xe5, 0x8e, 0x26}) 31 | if uval != 624485 { 32 | t.Error("DecodeUint64 uval error") 33 | } 34 | if ulen != 3 { 35 | t.Error("DecodeUint64 ulen error") 36 | } 37 | } 38 | 39 | { 40 | if !bytes.Equal(EncodeUint32(624485), []byte{0xe5, 0x8e, 0x26}) { 41 | t.Error("EncodeUint32 fail") 42 | } 43 | 44 | uval, ulen := DecodeUint32([]byte{0xe5, 0x8e, 0x26}) 45 | if uval != 624485 { 46 | t.Error("DecodeUint32 uval error") 47 | } 48 | if ulen != 3 { 49 | t.Error("DecodeUint32 ulen error") 50 | } 51 | } 52 | 53 | // ===== 54 | 55 | { 56 | if !bytes.Equal(EncodeInt64(-123456), []byte{0xc0, 0xbb, 0x78}) { 57 | t.Error("EncodeInt64 fail") 58 | } 59 | 60 | uval, ulen := DecodeInt64([]byte{0xc0, 0xbb, 0x78}) 61 | if uval != -123456 { 62 | t.Error("DecodeInt64 uval error") 63 | } 64 | if ulen != 3 { 65 | t.Error("DecodeInt64 ulen error") 66 | } 67 | } 68 | 69 | { 70 | if !bytes.Equal(EncodeInt32(-123456), []byte{0xc0, 0xbb, 0x78}) { 71 | t.Error("EncodeInt32 fail") 72 | } 73 | 74 | uval, ulen := DecodeInt32([]byte{0xc0, 0xbb, 0x78}) 75 | if uval != -123456 { 76 | t.Error("DecodeInt32 uval error") 77 | } 78 | if ulen != 3 { 79 | t.Error("DecodeInt32 ulen error") 80 | } 81 | } 82 | } 83 | 84 | func Test_Unsigned_Data(t *testing.T) { 85 | for _, tt := range unsigned_data { 86 | got := EncodeUint64(tt.value) 87 | if !bytes.Equal(got, fromHex(tt.encoded)) { 88 | t.Error("EncodeUint64 fail") 89 | } 90 | 91 | bytes := fromHex(tt.encoded) 92 | uval, ulen := DecodeUint64(bytes) 93 | if uval != tt.value { 94 | t.Error("DecodeUint64 uval error") 95 | } 96 | if ulen != len(bytes) { 97 | t.Error("DecodeUint64 ulen error") 98 | } 99 | 100 | } 101 | } 102 | 103 | func Test_Signed_Data(t *testing.T) { 104 | for _, tt := range signed_data { 105 | got := EncodeInt64(tt.value) 106 | if !bytes.Equal(got, fromHex(tt.encoded)) { 107 | t.Error("EncodeInt64 fail") 108 | } 109 | 110 | bytes := fromHex(tt.encoded) 111 | uval, ulen := DecodeInt64(bytes) 112 | if uval != tt.value { 113 | t.Error("DecodeInt64 uval error") 114 | } 115 | if ulen != len(bytes) { 116 | t.Error("DecodeInt64 ulen error") 117 | } 118 | 119 | } 120 | } 121 | 122 | var unsigned_data = []PairU{ 123 | {217, "d901"}, 124 | {34, "22"}, 125 | {233, "e901"}, 126 | {2049800081, "91efb5d107"}, 127 | {3884507512, "f8c2a3bc0e"}, 128 | } 129 | 130 | var signed_data = []PairI{ 131 | {71, "c700"}, 132 | {-57, "47"}, 133 | {58, "3a"}, 134 | {1961805726, "9e8fbba707"}, 135 | {-1567520880, "908fc6947a"}, 136 | } 137 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deatil/go-encoding/6b5727ddf8219384079c6e8eb9ea36a73a86c8de/logo.png -------------------------------------------------------------------------------- /morse/morse.go: -------------------------------------------------------------------------------- 1 | package morse 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | "reflect" 7 | "strings" 8 | ) 9 | 10 | var morseITU = map[string]string{ 11 | "a": ".-", 12 | "b": "-...", 13 | "c": "-.-.", 14 | "d": "-..", 15 | "e": ".", 16 | "f": "..-.", 17 | "g": "--.", 18 | "h": "....", 19 | "i": "..", 20 | "j": ".---", 21 | "k": "-.-", 22 | "l": ".-..", 23 | "m": "--", 24 | "n": "-.", 25 | "o": "---", 26 | "p": ".--.", 27 | "q": "--.-", 28 | "r": ".-.", 29 | "s": "...", 30 | "t": "-", 31 | "u": "..-", 32 | "v": "...-", 33 | "w": ".--", 34 | "x": "-..-", 35 | "y": "-.--", 36 | "z": "--..", 37 | "ä": ".-.-", 38 | "ö": "---.", 39 | "ü": "..--", 40 | "Ch": "----", 41 | "0": "-----", 42 | "1": ".----", 43 | "2": "..---", 44 | "3": "...--", 45 | "4": "....-", 46 | "5": ".....", 47 | "6": "-....", 48 | "7": "--...", 49 | "8": "---..", 50 | "9": "----.", 51 | ".": ".-.-.-", 52 | ",": "--..--", 53 | "?": "..--..", 54 | "!": "..--.", 55 | ":": "---...", 56 | "\"": ".-..-.", 57 | "'": ".----.", 58 | "=": "-...-", 59 | } 60 | 61 | // ITUEncoding is the standard morse ITU encoding. 62 | var ITUEncoding = NewEncoding(morseITU, " ", "/") 63 | 64 | /* 65 | * Encodings 66 | */ 67 | 68 | // An Encoding is a radix 62 encoding/decoding scheme, defined by a 62-character alphabet. 69 | type Encoding struct { 70 | alphabet map[string]string 71 | letterSeparator string 72 | wordSeparator string 73 | } 74 | 75 | func NewEncoding(alphabet map[string]string, letterSeparator, wordSeparator string) *Encoding { 76 | e := new(Encoding) 77 | e.alphabet = alphabet 78 | e.letterSeparator = letterSeparator 79 | e.wordSeparator = wordSeparator 80 | 81 | return e 82 | } 83 | 84 | /* 85 | * Encoder 86 | */ 87 | 88 | // Encode encodes clear text in `s` using `alphabet` mapping 89 | func (enc *Encoding) Encode(s []byte) []byte { 90 | res := "" 91 | for _, part := range string(s) { 92 | p := string(part) 93 | if p == " " { 94 | if enc.wordSeparator != "" { 95 | res += enc.wordSeparator + enc.letterSeparator 96 | } 97 | } else if enc.alphabet[p] != "" { 98 | res += enc.alphabet[p] + enc.letterSeparator 99 | } 100 | } 101 | 102 | return []byte(strings.TrimSpace(res)) 103 | } 104 | 105 | // EncodeToString returns the base62 encoding of src. 106 | func (enc *Encoding) EncodeToString(src []byte) string { 107 | buf := enc.Encode(src) 108 | return string(buf) 109 | } 110 | 111 | /* 112 | * Decoder 113 | */ 114 | 115 | // Decode decodes morse code in `s` using `alphabet` mapping 116 | func (enc *Encoding) Decode(s []byte) ([]byte, error) { 117 | res := "" 118 | for _, part := range strings.Split(string(s), enc.letterSeparator) { 119 | found := false 120 | for key, val := range enc.alphabet { 121 | if val == part { 122 | res += key 123 | found = true 124 | break 125 | } 126 | } 127 | 128 | if part == enc.wordSeparator { 129 | res += " " 130 | found = true 131 | } 132 | 133 | if !found { 134 | return []byte(res), fmt.Errorf("go-encoding/morse: unknown character " + part) 135 | } 136 | } 137 | 138 | return []byte(res), nil 139 | } 140 | 141 | // DecodeString returns the bytes represented by the base62 string s. 142 | func (enc *Encoding) DecodeString(s string) ([]byte, error) { 143 | sh := (*reflect.StringHeader)(unsafe.Pointer(&s)) 144 | bh := reflect.SliceHeader{Data: sh.Data, Len: sh.Len, Cap: sh.Len} 145 | return enc.Decode(*(*[]byte)(unsafe.Pointer(&bh))) 146 | } 147 | 148 | // LooksLikeMorse returns true if string seems to be a morse encoded string 149 | func LooksLikeMorse(s string) bool { 150 | if len(s) < 1 { 151 | return false 152 | } 153 | 154 | for _, b := range s { 155 | if b != '-' && b != '.' && b != ' ' { 156 | return false 157 | } 158 | } 159 | 160 | return true 161 | } 162 | -------------------------------------------------------------------------------- /morse/morse_test.go: -------------------------------------------------------------------------------- 1 | package morse 2 | 3 | import "testing" 4 | 5 | func Test_LooksLikeMorse(t *testing.T) { 6 | if !LooksLikeMorse("- .... . .-..") { 7 | t.Error("fail 1") 8 | } 9 | 10 | if LooksLikeMorse("one one one...") { 11 | t.Error("fail 2") 12 | } 13 | 14 | if LooksLikeMorse("") { 15 | t.Error("fail 3") 16 | } 17 | } 18 | 19 | func Test_DecodeBrokenITU(t *testing.T) { 20 | _, err := ITUEncoding.DecodeString("-- ?.. ...") 21 | if err == nil { 22 | t.Error("expected error") 23 | } 24 | } 25 | 26 | func Test_EncodeToString(t *testing.T) { 27 | in := []byte("test:date") 28 | 29 | encoded := ITUEncoding.EncodeToString(in) 30 | if len(encoded) == 0 { 31 | t.Error("EncodeToString fail") 32 | } 33 | 34 | decoded, err := ITUEncoding.DecodeString(encoded) 35 | if err != nil { 36 | t.Error("DecodeString fail") 37 | } 38 | 39 | if string(decoded) != string(in) { 40 | t.Errorf("DecodeString, got %s, want %s", string(decoded), string(in)) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /puny/puny.go: -------------------------------------------------------------------------------- 1 | package puny 2 | 3 | import ( 4 | "fmt" 5 | "bytes" 6 | "errors" 7 | "unsafe" 8 | "reflect" 9 | ) 10 | 11 | const ( 12 | // Bootstring parameters specified in RFC 3492 13 | baseC = 36 14 | tMin = 1 15 | tMax = 26 16 | skew = 38 17 | damp = 700 18 | initialBias = 72 19 | initialN = 128 // 0x80 20 | delimiter byte = 0x2D // hyphen 21 | maxRune = '\U0010FFFF' 22 | ) 23 | 24 | var ( 25 | invalidCharaterErr = errors.New("go-encoding/puny: Non-ASCCI codepoint found in src") 26 | overFlowErr = errors.New("go-encoding/puny: Overflow") 27 | inputError = errors.New("go-encoding/puny: Bad Input") 28 | digit2codepointErr = errors.New("go-encoding/puny: digit2codepoint") 29 | ) 30 | 31 | // std Encoding 32 | var StdEncoding = NewEncoding() 33 | 34 | /* 35 | * Encodings 36 | */ 37 | 38 | type Encoding struct{} 39 | 40 | func NewEncoding() *Encoding { 41 | return &Encoding{} 42 | } 43 | 44 | /* 45 | * Encoder 46 | */ 47 | 48 | // Encode returns the puny encoding of src. 49 | func (p *Encoding) Encode(src []byte) ([]byte, error) { 50 | n := initialN 51 | delta := 0 52 | bias := initialBias 53 | runes := bytes.Runes(src) 54 | 55 | var result bytes.Buffer 56 | var err error 57 | 58 | basicRunes := 0 59 | for i := 0; i < len(runes); i++ { 60 | // Write all basic codepoints to result 61 | if runes[i] < 0x80 { 62 | result.WriteRune(runes[i]) 63 | 64 | basicRunes++ 65 | } 66 | } 67 | 68 | // Append delimiter 69 | if basicRunes > 0 { 70 | err = result.WriteByte(delimiter) 71 | if err != nil { 72 | return nil, err 73 | } 74 | } 75 | 76 | for h := basicRunes; h < len(runes); { 77 | minRune := maxRune 78 | 79 | // Find the minimum rune >= n in the input 80 | for i := 0; i < len(runes); i++ { 81 | if int(runes[i]) >= n && runes[i] < minRune { 82 | minRune = runes[i] 83 | } 84 | } 85 | 86 | delta = delta + (int(minRune)-n)*(h+1) // ?? 87 | n = int(minRune) 88 | 89 | for i := 0; i < len(runes); i++ { 90 | if int(runes[i]) < n { 91 | delta++ 92 | } 93 | if int(runes[i]) == n { 94 | q := delta 95 | for k := baseC; true; k += baseC { 96 | var t int 97 | 98 | switch { 99 | case k <= bias: 100 | t = tMin 101 | break 102 | case k >= (bias + tMax): 103 | t = tMax 104 | break 105 | default: 106 | t = k - bias 107 | } 108 | 109 | if q < t { 110 | break 111 | } 112 | 113 | result, err = writeBytesDigitToCodepoint(result, t+(q-t)%(baseC-t)) 114 | if err != nil { 115 | return nil, err 116 | } 117 | q = (q - t) / (baseC - t) 118 | } 119 | result, err = writeBytesDigitToCodepoint(result, q) 120 | if err != nil { 121 | return nil, err 122 | } 123 | 124 | bias = adapt(delta, h == basicRunes, h+1) 125 | delta = 0 126 | h++ 127 | } 128 | } 129 | delta++ 130 | n++ 131 | } 132 | 133 | return result.Bytes(), nil 134 | } 135 | 136 | // EncodeToString returns the puny encoding of src. 137 | func (p *Encoding) EncodeToString(src []byte) (string, error) { 138 | buf, err := p.Encode(src) 139 | return string(buf), err 140 | } 141 | 142 | func (p *Encoding) EncodedLen(n int) int { 143 | return n 144 | } 145 | 146 | /* 147 | * Decoder 148 | */ 149 | 150 | // Decode returns the bytes represented by the puny string s. 151 | func (p *Encoding) Decode(src []byte) ([]byte, error) { 152 | // Decoding procedure explained in detail in RFC 3492. 153 | n := initialN 154 | i := 0 155 | bias := initialBias 156 | 157 | pos := 0 158 | delimIndex := -1 159 | 160 | result := make([]rune, 0, len(src)) 161 | 162 | // Only ASCII allowed in decoding procedure 163 | for j := 0; j < len(src); j++ { 164 | if src[j] >= 0x80 { 165 | return nil, invalidCharaterErr 166 | 167 | } 168 | } 169 | 170 | // Consume all codepoints before the last delimiter 171 | delimIndex = bytes.LastIndex(src, []byte{delimiter}) 172 | for pos = 0; pos < delimIndex; pos++ { 173 | result = append(result, rune(src[pos])) 174 | } 175 | 176 | // Consume delimiter 177 | pos = delimIndex + 1 178 | 179 | for pos < len(src) { 180 | oldi := i 181 | w := 1 182 | for k := baseC; true; k += baseC { 183 | var t int 184 | 185 | if pos == len(src) { 186 | return nil, inputError 187 | } 188 | 189 | // consume a code point, or fail if there was none to consume 190 | cp := rune(src[pos]) 191 | pos++ 192 | 193 | digit := codepoint2digit(cp) 194 | 195 | if digit > ((maxRune - i) / w) { 196 | return nil, inputError 197 | } 198 | 199 | i = i + digit*w 200 | 201 | switch { 202 | case k <= bias: 203 | t = tMin 204 | break 205 | case k >= bias+tMax: 206 | t = tMax 207 | break 208 | default: 209 | t = k - bias 210 | } 211 | 212 | if digit < t { 213 | break 214 | } 215 | w = w * (baseC - t) 216 | } 217 | bias = adapt(i-oldi, oldi == 0, len(result)+1) 218 | 219 | if i/(len(result)+1) > (maxRune - n) { 220 | return nil, overFlowErr 221 | } 222 | 223 | n = n + i/(len(result)+1) 224 | i = i % (len(result) + 1) 225 | 226 | if n < 0x80 { 227 | return nil, fmt.Errorf("%v is a basic code point.", n) 228 | } 229 | 230 | result = insert(result, i, rune(n)) 231 | i++ 232 | } 233 | 234 | return writeRune(result), nil 235 | } 236 | 237 | // DecodeString returns the bytes represented by the puny string s. 238 | func (p *Encoding) DecodeString(s string) ([]byte, error) { 239 | sh := (*reflect.StringHeader)(unsafe.Pointer(&s)) 240 | bh := reflect.SliceHeader{Data: sh.Data, Len: sh.Len, Cap: sh.Len} 241 | return p.Decode(*(*[]byte)(unsafe.Pointer(&bh))) 242 | } 243 | 244 | func (p *Encoding) DecodedLen(n int) int { 245 | return n 246 | } 247 | -------------------------------------------------------------------------------- /puny/puny_test.go: -------------------------------------------------------------------------------- 1 | package puny 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | type testPair struct { 8 | decoded string 9 | encoded string 10 | } 11 | 12 | type malformedTestPair struct { 13 | encoded string 14 | error error 15 | } 16 | 17 | var pairs = []testPair{ 18 | { 19 | decoded: "∏∪∩", 20 | encoded: "q9g0cc", 21 | }, 22 | { 23 | decoded: "Hello!!", 24 | encoded: "Hello!!-", 25 | }, 26 | { 27 | decoded: "puny Encoding,?:+【‘;’", 28 | encoded: "puny Encoding+-yb3hqa1950e6u24cvhaxa3f", 29 | }, 30 | { 31 | decoded: "测试!", 32 | encoded: "!-rq9bs28f", 33 | }, 34 | { 35 | decoded: "ǐǒó チツチノハフヘキキξεζοреё┢┣┮┐┑ 《《‖∶", 36 | encoded: " -4ja79fka410aha6dl49ipd3io866avhg1plqa10asa3sp25sa586aa29ba1fto2a8opd", 37 | }, 38 | } 39 | 40 | func testEqual(t *testing.T, msg string, args ...any) bool { 41 | if args[len(args)-2] != args[len(args)-1] { 42 | t.Errorf(msg, args...) 43 | return false 44 | } 45 | 46 | return true 47 | } 48 | 49 | func TestEncode(t *testing.T) { 50 | for _, p := range pairs { 51 | got, err := StdEncoding.EncodeToString([]byte(p.decoded)) 52 | if err != nil { 53 | t.Fatal(err) 54 | } 55 | 56 | testEqual(t, "Encode(%q) = %q, want %q", p.decoded, got, p.encoded) 57 | } 58 | } 59 | 60 | func TestDecode(t *testing.T) { 61 | for _, p := range pairs { 62 | got, err := StdEncoding.DecodeString(p.encoded) 63 | if err != nil { 64 | t.Fatal(err) 65 | } 66 | 67 | testEqual(t, "Decode(%q) = %q, want %q", p.encoded, string(got), p.decoded) 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /puny/utils.go: -------------------------------------------------------------------------------- 1 | package puny 2 | 3 | import ( 4 | "bytes" 5 | ) 6 | 7 | func adapt(delta int, first bool, numchars int) (bias int) { 8 | if first { 9 | delta = delta / damp 10 | } else { 11 | delta = delta / 2 12 | } 13 | 14 | delta = delta + (delta / numchars) 15 | 16 | k := 0 17 | for delta > ((baseC-tMin)*tMax)/2 { 18 | delta = delta / (baseC - tMin) 19 | k = k + baseC 20 | } 21 | 22 | bias = k + ((baseC-tMin+1)*delta)/(delta+skew) 23 | return 24 | } 25 | 26 | func codepoint2digit(r rune) int { 27 | switch { 28 | case r-48 < 10: 29 | return int(r - 22) 30 | case r-65 < 26: 31 | return int(r - 65) 32 | case r-97 < 26: 33 | return int(r - 97) 34 | } 35 | 36 | return baseC 37 | } 38 | 39 | func writeBytesDigitToCodepoint(bytes bytes.Buffer, d int) (bytes.Buffer, error) { 40 | var val rune 41 | switch { 42 | case d < 26: 43 | // 0..25 : 'a'..'z' 44 | val = rune(d + 'a') 45 | case d < 36: 46 | // 26..35 : '0'..'9'; 47 | val = rune(d - 26 + '0') 48 | default: 49 | return bytes, digit2codepointErr 50 | } 51 | 52 | err := bytes.WriteByte(byte(val)) 53 | return bytes, err 54 | } 55 | 56 | func writeRune(r []rune) []byte { 57 | str := string(r) 58 | return []byte(str) 59 | } 60 | 61 | func insert(s []rune, pos int, r rune) []rune { 62 | return append(s[:pos], append([]rune{r}, s[pos:]...)...) 63 | } 64 | -------------------------------------------------------------------------------- /quotedprintable/quotedprintable.go: -------------------------------------------------------------------------------- 1 | package quotedprintable 2 | 3 | import ( 4 | "io" 5 | "fmt" 6 | "bytes" 7 | "unsafe" 8 | "reflect" 9 | ) 10 | 11 | // encodeStd is the standard quotedprintable encoding alphabet 12 | const encodeStd = "0123456789ABCDEF" 13 | 14 | // StdEncoding is the standard quotedprintable encoding 15 | var StdEncoding = NewEncoding(encodeStd) 16 | 17 | /* 18 | * Encodings 19 | */ 20 | 21 | // An Encoding is a quotedprintable encoding/decoding scheme defined by a 16-character alphabet. 22 | type Encoding struct { 23 | encode string 24 | } 25 | 26 | // NewEncoding returns a new Encoding defined by the given alphabet 27 | func NewEncoding(encoder string) *Encoding { 28 | if len(encoder) != 16 { 29 | panic("go-encoding/quotedprintable: encoding alphabet is not 16 bytes long") 30 | } 31 | 32 | enc := new(Encoding) 33 | enc.encode = encoder 34 | 35 | return enc 36 | } 37 | 38 | /* 39 | * Encoder 40 | */ 41 | 42 | func (e *Encoding) Encode(src []byte) ([]byte, error) { 43 | dst := make([]byte, e.EncodedLen(len(src))) 44 | 45 | n := 0 46 | for i, c := range src { 47 | switch { 48 | case c != '=' && (c >= '!' && c <= '~' || c == '\n' || c == '\r'): 49 | dst[n] = c 50 | n++ 51 | case c == ' ' || c == '\t': 52 | if isLastChar(i, src) { 53 | e.encodeByte(dst[n:], c) 54 | n += 3 55 | } else { 56 | dst[n] = c 57 | n++ 58 | } 59 | default: 60 | e.encodeByte(dst[n:], c) 61 | n += 3 62 | } 63 | } 64 | 65 | return dst[:n], nil 66 | } 67 | 68 | // EncodeToString returns the PunyEncoding encoding of src. 69 | func (e *Encoding) EncodeToString(src []byte) (string, error) { 70 | buf, err := e.Encode(src) 71 | return string(buf), err 72 | } 73 | 74 | func (e *Encoding) EncodedLen(n int) int { 75 | return 3 * n 76 | } 77 | 78 | /* 79 | * Decoder 80 | */ 81 | 82 | func (e *Encoding) Decode(src []byte) ([]byte, error) { 83 | dst := make([]byte, e.DecodedLen(len(src))) 84 | 85 | var eol, trimLen, eolLen, n int 86 | var err error 87 | 88 | for i := 0; i < len(src); i++ { 89 | if i == eol { 90 | eol = bytes.IndexByte(src[i:], '\n') + i + 1 91 | if eol == i { 92 | eol = len(src) 93 | eolLen = 0 94 | } else if eol-2 >= i && src[eol-2] == '\r' { 95 | eolLen = 2 96 | } else { 97 | eolLen = 1 98 | } 99 | 100 | // Count the number of bytes to trim 101 | trimLen = 0 102 | for { 103 | if trimLen == eol-eolLen-i { 104 | break 105 | } 106 | 107 | switch src[eol-eolLen-trimLen-1] { 108 | case '\n', '\r', ' ', '\t': 109 | trimLen++ 110 | continue 111 | case '=': 112 | if trimLen > 0 { 113 | trimLen += eolLen + 1 114 | eolLen = 0 115 | err = fmt.Errorf("quotedprintable: invalid bytes after =: %q", src[eol-trimLen+1:eol]) 116 | } else { 117 | trimLen = eolLen + 1 118 | eolLen = 0 119 | } 120 | } 121 | 122 | break 123 | } 124 | } 125 | 126 | // Skip trimmable bytes 127 | if trimLen > 0 && i == eol-trimLen-eolLen { 128 | if err != nil { 129 | return nil, err 130 | } 131 | 132 | i += trimLen - 1 133 | continue 134 | } 135 | 136 | switch c := src[i]; { 137 | case c == '=': 138 | if i+2 >= len(src) { 139 | return nil, io.ErrUnexpectedEOF 140 | } 141 | b, convErr := readHexByte(src[i+1:]) 142 | if convErr != nil { 143 | return nil, convErr 144 | } 145 | dst[n] = b 146 | n++ 147 | i += 2 148 | case (c >= ' ' && c <= '~') || c == '\n' || c == '\r' || c == '\t': 149 | dst[n] = c 150 | n++ 151 | default: 152 | return nil, fmt.Errorf("quotedprintable: invalid unescaped byte 0x%02x in quoted-printable body", c) 153 | } 154 | } 155 | 156 | return dst[:n], nil 157 | } 158 | 159 | // DecodeString returns the bytes represented by the PunyEncoding string s. 160 | func (e *Encoding) DecodeString(s string) ([]byte, error) { 161 | sh := (*reflect.StringHeader)(unsafe.Pointer(&s)) 162 | bh := reflect.SliceHeader{Data: sh.Data, Len: sh.Len, Cap: sh.Len} 163 | return e.Decode(*(*[]byte)(unsafe.Pointer(&bh))) 164 | } 165 | 166 | func (e *Encoding) DecodedLen(n int) int { 167 | return n 168 | } 169 | 170 | func (e *Encoding) encodeByte(dst []byte, b byte) { 171 | dst[0] = '=' 172 | dst[1] = e.encode[b>>4] 173 | dst[2] = e.encode[b&0x0f] 174 | } 175 | -------------------------------------------------------------------------------- /quotedprintable/quotedprintable_test.go: -------------------------------------------------------------------------------- 1 | package quotedprintable 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | type testPair struct { 8 | decoded string 9 | encoded string 10 | } 11 | 12 | type malformedTestPair struct { 13 | encoded string 14 | error error 15 | } 16 | 17 | var pairs = []testPair{ 18 | { 19 | decoded: `AB== fr gt\tdf`, 20 | encoded: "AB=3D=3D fr gt\\tdf", 21 | }, 22 | { 23 | decoded: "Hello!! gt\tdf", 24 | encoded: "Hello!! gt\tdf", 25 | }, 26 | { 27 | decoded: `quoted\nprin\rtabl e gt\tdf`, 28 | encoded: "quoted\\nprin\\rtabl e gt\\tdf", 29 | }, 30 | { 31 | decoded: `ietf!\rjj`, 32 | encoded: "ietf!\\rjj", 33 | }, 34 | { 35 | decoded: `test tyu\nikl dolor sit ametf5.h`, 36 | encoded: "test tyu\\nikl dolor sit ametf5.h", 37 | }, 38 | } 39 | 40 | func testEqual(t *testing.T, msg string, args ...any) bool { 41 | if args[len(args)-2] != args[len(args)-1] { 42 | t.Errorf(msg, args...) 43 | return false 44 | } 45 | 46 | return true 47 | } 48 | 49 | func TestEncode(t *testing.T) { 50 | for _, p := range pairs { 51 | got, err := StdEncoding.EncodeToString([]byte(p.decoded)) 52 | if err != nil { 53 | t.Fatal(err) 54 | } 55 | 56 | testEqual(t, "Encode(%q) = %q, want %q", p.decoded, got, p.encoded) 57 | } 58 | } 59 | 60 | func TestDecode(t *testing.T) { 61 | for _, p := range pairs { 62 | got, err := StdEncoding.DecodeString(p.encoded) 63 | if err != nil { 64 | t.Fatal(err) 65 | } 66 | 67 | testEqual(t, "Decode(%q) = %q, want %q", p.encoded, string(got), p.decoded) 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /quotedprintable/utils.go: -------------------------------------------------------------------------------- 1 | package quotedprintable 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func fromHex(b byte) (byte, error) { 8 | switch { 9 | case b >= '0' && b <= '9': 10 | return b - '0', nil 11 | case b >= 'A' && b <= 'F': 12 | return b - 'A' + 10, nil 13 | // Accept badly encoded bytes 14 | case b >= 'a' && b <= 'f': 15 | return b - 'a' + 10, nil 16 | } 17 | 18 | return 0, fmt.Errorf("quotedprintable: invalid quoted-printable hex byte %#02x", b) 19 | } 20 | 21 | func readHexByte(v []byte) (b byte, err error) { 22 | var hb, lb byte 23 | if hb, err = fromHex(v[0]); err != nil { 24 | return 0, err 25 | } 26 | 27 | if lb, err = fromHex(v[1]); err != nil { 28 | return 0, err 29 | } 30 | 31 | return hb<<4 | lb, nil 32 | } 33 | 34 | func isLastChar(i int, src []byte) bool { 35 | return i == len(src)-1 || 36 | (i < len(src)-1 && src[i+1] == '\n') || 37 | (i < len(src)-2 && src[i+1] == '\r' && src[i+2] == '\n') 38 | } 39 | --------------------------------------------------------------------------------