Skip to content

Commit c606367

Browse files
authored
Merge pull request #16 from ulfox/feat/convert-utils
include convert-utils
2 parents 829c0a4 + cea373e commit c606367

File tree

7 files changed

+397
-12
lines changed

7 files changed

+397
-12
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,5 @@
1818
main.go
1919
local
2020
ops
21+
test.*
2122

README.md

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@ Table of Contents
1717
- [Without trailing array](#without-trailing-array)
1818
- [With trailing array](#with-trailing-array)
1919
* [Delete Key By Path](#delete-key-by-path)
20+
* [Convert Utils](#convert-utils)
21+
+ [Get map of strings from interface](#get-map-of-strings-from-interface)
22+
- [Get map directly from a GetPath object](#get-map-directly-from-a-getpath-object)
23+
- [Get map manually](#get-map-manually)
24+
+ [Get array of string from interface](#get-array-of-string-from-interface)
25+
- [Get array directly from a GetPath object](#get-array-directly-from-a-getpath-object)
26+
- [Get array manually](#get-array-manually)
2027

2128
## Features
2229

@@ -194,3 +201,134 @@ if err != nil {
194201
logger.Fatalf(err.Error())
195202
}
196203
```
204+
205+
### Convert Utils
206+
207+
Convert simply automate the need to
208+
explicitly do assertion each time we need to access
209+
an interface object.
210+
211+
Let us assume we have the following YAML structure
212+
213+
```yaml
214+
215+
to:
216+
array-1:
217+
key-1:
218+
- key-2: 2
219+
- key-3: 3
220+
- key-4: 4
221+
array-2:
222+
- 1
223+
- 2
224+
- 3
225+
- 4
226+
- 5
227+
array-3:
228+
- key-1: 1
229+
- key-2: 2
230+
231+
```
232+
233+
#### Get map of strings from interface
234+
235+
We can do this in two ways, get object by giving a path and assert the interface to `map[string]string`, or work manually our way to the object
236+
237+
##### Get map directly from a GetPath object
238+
239+
To get map **key-2: 2**, first get object via GetPath
240+
241+
```go
242+
243+
obj, err := state.GetPath("to.array-1.key-1.[0]")
244+
if err != nil {
245+
logger.Fatalf(err.Error())
246+
}
247+
logger.Info(val)
248+
249+
```
250+
251+
Next, assert **obj** as `map[string]string`
252+
253+
```go
254+
255+
assertData := db.NewConvertFactory()
256+
257+
assertData.Input(val)
258+
if assertData.Error != nil {
259+
logger.Fatalf(assertData.Error.Error())
260+
}
261+
vMap := assertData.GetMap()
262+
logger.Info(vMap["key-2"])
263+
264+
```
265+
266+
##### Get map manually
267+
268+
We can get the map manually by using only **Convert** operations
269+
270+
```go
271+
272+
assertData := db.NewConvertFactory()
273+
274+
assertData.Input(state.Data).
275+
Key("to").
276+
Key("array-1").
277+
Key("key-1").Index(0)
278+
if assertData.Error != nil {
279+
logger.Fatalf(assertData.Error.Error())
280+
}
281+
vMap := assertData.GetMap()
282+
logger.Info(vMap["key-2"])
283+
284+
```
285+
286+
#### Get array of string from interface
287+
288+
Again here we can do it two ways as with the map example
289+
290+
##### Get array directly from a GetPath object
291+
292+
To get **array-2** as **[]string**, first get object via GetPath
293+
294+
```go
295+
296+
obj, err = state.GetPath("to.array-2")
297+
if err != nil {
298+
logger.Fatalf(err.Error())
299+
}
300+
logger.Info(obj)
301+
302+
```
303+
304+
Next, assert **obj** as `[]string`
305+
306+
```go
307+
308+
assertData := db.NewConvertFactory()
309+
310+
assertData.Input(obj)
311+
if assertData.Error != nil {
312+
logger.Fatalf(assertData.Error.Error())
313+
}
314+
vArray := assertData.GetArray()
315+
logger.Info(vArray)
316+
317+
```
318+
319+
##### Get array manually
320+
321+
We can get the array manually by using only **Convert** operations
322+
323+
```go
324+
325+
assertData.Input(state.Data).
326+
Key("to").
327+
Key("array-2")
328+
if assertData.Error != nil {
329+
logger.Fatalf(assertData.Error.Error())
330+
}
331+
vArray := assertData.GetArray()
332+
logger.Info(vArray)
333+
334+
```

db/cache.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,32 @@ package db
66
// to keep track and derive the right path.
77
type Cache struct {
88
V1, V2 interface{}
9+
V3 []interface{}
10+
B []byte
11+
E error
912
C1, C2, C3 int
1013
Keys []string
1114
}
1215

16+
// NewCacheFactory for creating a new Cache
17+
func NewCacheFactory() Cache {
18+
cache := Cache{
19+
V3: make([]interface{}, 0),
20+
B: make([]byte, 0),
21+
Keys: make([]string, 0),
22+
}
23+
return cache
24+
}
25+
1326
// Clear for clearing the cache and setting all
1427
// content to nil
1528
func (c *Cache) Clear() *Cache {
1629
c.V1, c.V2 = nil, nil
30+
c.V3 = make([]interface{}, 0)
1731
c.C1, c.C2, c.C3 = 0, 0, 0
18-
c.Keys = nil
32+
c.B = make([]byte, 0)
33+
c.E = nil
34+
c.Keys = make([]string, 0)
1935

2036
return c
2137
}

db/constants.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,10 @@ func getObjectType(o interface{}) objectType {
2727
return 2
2828
}
2929

30+
_, isMapStringInterface := o.(map[string]interface{})
31+
if isMapStringInterface {
32+
return 5
33+
}
34+
3035
return unknownObj
3136
}

db/convert.go

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
package db
2+
3+
import (
4+
"fmt"
5+
6+
"gopkg.in/yaml.v2"
7+
)
8+
9+
// AssertData is used to for converting interface objects to
10+
// map of interfaces or array of interfaces
11+
type AssertData struct {
12+
D0 map[string]string
13+
A0 []string
14+
Error error
15+
Cache Cache
16+
}
17+
18+
// NewConvertFactory for initializing AssertData
19+
func NewConvertFactory() *AssertData {
20+
assertData := &AssertData{
21+
D0: make(map[string]string),
22+
A0: make([]string, 0),
23+
Cache: NewCacheFactory(),
24+
}
25+
return assertData
26+
}
27+
28+
// Clear for resetting AssertData
29+
func (s *AssertData) Clear() {
30+
s.Cache.Clear()
31+
s.D0 = make(map[string]string)
32+
s.A0 = make([]string, 0)
33+
}
34+
35+
// Input sets a data source that can be used for assertion
36+
func (s *AssertData) Input(o interface{}) *AssertData {
37+
s.Clear()
38+
s.Cache.V1 = o
39+
return s
40+
}
41+
42+
func (s *AssertData) toBytes() {
43+
s.Cache.B, s.Cache.E = yaml.Marshal(s.Cache.V1)
44+
if s.Cache.E != nil {
45+
s.Error = s.Cache.E
46+
}
47+
}
48+
49+
// GetMap for converting a map[interface{}]interface{} into a map[string]string
50+
func (s *AssertData) GetMap() map[string]string {
51+
if s.Cache.E != nil {
52+
s.Error = s.Cache.E
53+
return nil
54+
}
55+
56+
s.toBytes()
57+
if s.Cache.E != nil {
58+
return nil
59+
}
60+
61+
s.Cache.E = yaml.Unmarshal(s.Cache.B, &s.D0)
62+
if s.Cache.E != nil {
63+
s.Error = s.Cache.E
64+
return nil
65+
}
66+
return s.D0
67+
}
68+
69+
// GetArray for converting a []interface{} to []string
70+
func (s *AssertData) GetArray() []string {
71+
if s.Cache.E != nil {
72+
s.Error = s.Cache.E
73+
return nil
74+
}
75+
76+
_, isArray := s.Cache.V1.([]interface{})
77+
if !isArray {
78+
s.Cache.E = wrapErr(fmt.Errorf(notArrayObj), getFn())
79+
s.Error = s.Cache.E
80+
return nil
81+
}
82+
83+
s.toBytes()
84+
if s.Cache.E != nil {
85+
return nil
86+
}
87+
88+
s.Cache.E = yaml.Unmarshal(s.Cache.B, &s.A0)
89+
if s.Cache.E != nil {
90+
s.Error = s.Cache.E
91+
return nil
92+
}
93+
94+
return s.A0
95+
}
96+
97+
// Key copies initial interface object and returns a map of interfaces{}
98+
// Used to easily pipe interfaces
99+
func (s *AssertData) Key(k string) *AssertData {
100+
if s.Cache.E != nil {
101+
s.Error = s.Cache.E
102+
return s
103+
}
104+
105+
_, isMap := s.Cache.V1.(map[interface{}]interface{})
106+
if !isMap {
107+
s.Cache.E = wrapErr(fmt.Errorf(notAMap), getFn())
108+
s.Error = s.Cache.E
109+
return s
110+
}
111+
112+
s.Cache.V1 = s.Cache.V1.(map[interface{}]interface{})[k]
113+
114+
return s
115+
}
116+
117+
// Index getting an interface{} from a []interface{}
118+
func (s *AssertData) Index(i int) *AssertData {
119+
if s.Cache.E != nil {
120+
s.Error = s.Cache.E
121+
return s
122+
}
123+
124+
_, isArray := s.Cache.V1.([]interface{})
125+
if !isArray {
126+
s.Cache.E = wrapErr(fmt.Errorf(notArrayObj), getFn())
127+
s.Error = s.Cache.E
128+
return s
129+
}
130+
s.Cache.V1 = s.Cache.V1.([]interface{})[i]
131+
132+
return s
133+
}

0 commit comments

Comments
 (0)