-
Notifications
You must be signed in to change notification settings - Fork 0
/
string_encdec.go
249 lines (198 loc) · 5.97 KB
/
string_encdec.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
package g
import (
"encoding/base64"
"encoding/hex"
"encoding/json"
"encoding/xml"
"html"
"net/url"
"strconv"
)
type (
// A struct that wraps an String for encoding.
enc struct{ str String }
// A struct that wraps an String for decoding.
dec struct{ str String }
)
// Enc returns an enc struct wrapping the given String.
func (s String) Enc() enc { return enc{s} }
// Dec returns a dec struct wrapping the given String.
func (s String) Dec() dec { return dec{s} }
// Base64 encodes the wrapped String using Base64 and returns the encoded result as an String.
func (e enc) Base64() String { return String(base64.StdEncoding.EncodeToString(e.str.ToBytes())) }
// Base64 decodes the wrapped String using Base64 and returns the decoded result as an String.
func (d dec) Base64() Result[String] {
decoded, err := base64.StdEncoding.DecodeString(d.str.Std())
if err != nil {
return Err[String](err)
}
return Ok(String(decoded))
}
// JSON encodes the provided data as JSON and returns the result as an String.
func (enc) JSON(data any) Result[String] {
jsonData, err := json.Marshal(data)
if err != nil {
return Err[String](err)
}
return Ok(String(jsonData))
}
// JSON decodes the wrapped String using JSON and unmarshals it into the provided data object.
func (d dec) JSON(data any) Result[String] {
err := json.Unmarshal(d.str.ToBytes(), data)
if err != nil {
return Err[String](err)
}
return Ok(d.str)
}
// XML encodes the provided data as XML and returns the result as an String.
// The optional prefix and indent String values can be provided for XML indentation.
func (enc) XML(data any, s ...String) Result[String] {
var (
prefix string
indent string
)
if len(s) > 1 {
prefix = s[0].Std()
indent = s[1].Std()
}
xmlData, err := xml.MarshalIndent(data, prefix, indent)
if err != nil {
return Err[String](err)
}
return Ok(String(xmlData))
}
// XML decodes the wrapped String using XML and unmarshals it into the provided data object.
func (d dec) XML(data any) Result[String] {
err := xml.Unmarshal(d.str.ToBytes(), data)
if err != nil {
return Err[String](err)
}
return Ok(d.str)
}
// URL encodes the input string, escaping reserved characters as per RFC 2396.
// If safe characters are provided, they will not be encoded.
//
// Parameters:
//
// - safe (String): Optional. Characters to exclude from encoding.
// If provided, the function will not encode these characters.
//
// Returns:
//
// - String: Encoded URL string.
func (e enc) URL(safe ...String) String {
reserved := String(";/?:@&=+$,") // Reserved characters as per RFC 2396
if len(safe) != 0 {
reserved = safe[0]
}
enc := NewBuilder()
for _, r := range e.str {
if reserved.ContainsRune(r) {
enc.WriteRune(r)
continue
}
enc.Write(String(url.QueryEscape(string(r))))
}
return enc.String()
}
// URL URL-decodes the wrapped String and returns the decoded result as an String.
func (d dec) URL() Result[String] {
result, err := url.QueryUnescape(d.str.Std())
if err != nil {
return Err[String](err)
}
return Ok(String(result))
}
// HTML HTML-encodes the wrapped String and returns the encoded result as an String.
func (e enc) HTML() String { return String(html.EscapeString(e.str.Std())) }
// HTML HTML-decodes the wrapped String and returns the decoded result as an String.
func (d dec) HTML() String { return String(html.UnescapeString(d.str.Std())) }
// Rot13 encodes the wrapped String using ROT13 cipher and returns the encoded result as an
// String.
func (e enc) Rot13() String {
rot := func(r rune) rune {
switch {
case r >= 'A' && r <= 'Z':
return 'A' + (r-'A'+13)%26
case r >= 'a' && r <= 'z':
return 'a' + (r-'a'+13)%26
default:
return r
}
}
return e.str.Map(rot)
}
// Rot13 decodes the wrapped String using ROT13 cipher and returns the decoded result as an
// String.
func (d dec) Rot13() String { return d.str.Enc().Rot13() }
// XOR encodes the wrapped String using XOR cipher with the given key and returns the encoded
// result as an String.
func (e enc) XOR(key String) String {
if key.Empty() {
return e.str
}
encrypted := e.str.ToBytes()
for i := range len(e.str) {
encrypted[i] ^= key[i%len(key)]
}
return String(encrypted)
}
// XOR decodes the wrapped String using XOR cipher with the given key and returns the decoded
// result as an String.
func (d dec) XOR(key String) String { return d.str.Enc().XOR(key) }
// Hex hex-encodes the wrapped String and returns the encoded result as an String.
func (e enc) Hex() String {
result := NewBuilder()
for i := range len(e.str) {
result.Write(Int(e.str[i]).ToHex())
}
return result.String()
}
// Hex hex-decodes the wrapped String and returns the decoded result as an String.
func (d dec) Hex() Result[String] {
result, err := hex.DecodeString(d.str.Std())
if err != nil {
return Err[String](err)
}
return Ok(String(result))
}
// Octal returns the octal representation of the encoded string.
func (e enc) Octal() String {
result := NewSlice[String](e.str.LenRunes())
for i, char := range e.str.ToRunes() {
result.Set(Int(i), Int(char).ToOctal())
}
return result.Join(" ")
}
// Octal returns the octal representation of the decimal-encoded string.
func (d dec) Octal() Result[String] {
result := NewBuilder()
for _, v := range d.str.Split(" ").Collect() {
n, err := strconv.ParseUint(v.Std(), 8, 32)
if err != nil {
return Err[String](err)
}
result.WriteRune(rune(n))
}
return Ok(result.String())
}
// Binary converts the wrapped String to its binary representation as an String.
func (e enc) Binary() String {
result := NewBuilder()
for i := range len(e.str) {
result.Write(Int(e.str[i]).ToBinary())
}
return result.String()
}
// Binary converts the wrapped binary String back to its original String representation.
func (d dec) Binary() Result[String] {
var result Bytes
for i := 0; i+8 <= len(d.str); i += 8 {
b, err := strconv.ParseUint(d.str[i:i+8].Std(), 2, 8)
if err != nil {
return Err[String](err)
}
result = append(result, byte(b))
}
return Ok(result.ToString())
}