Skip to content

Commit

Permalink
Merge pull request #16 from ulfox/feat/convert-utils
Browse files Browse the repository at this point in the history
include convert-utils
  • Loading branch information
ulfox authored Sep 5, 2021
2 parents 829c0a4 + cea373e commit c606367
Show file tree
Hide file tree
Showing 7 changed files with 397 additions and 12 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@
main.go
local
ops
test.*

138 changes: 138 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ Table of Contents
- [Without trailing array](#without-trailing-array)
- [With trailing array](#with-trailing-array)
* [Delete Key By Path](#delete-key-by-path)
* [Convert Utils](#convert-utils)
+ [Get map of strings from interface](#get-map-of-strings-from-interface)
- [Get map directly from a GetPath object](#get-map-directly-from-a-getpath-object)
- [Get map manually](#get-map-manually)
+ [Get array of string from interface](#get-array-of-string-from-interface)
- [Get array directly from a GetPath object](#get-array-directly-from-a-getpath-object)
- [Get array manually](#get-array-manually)

## Features

Expand Down Expand Up @@ -194,3 +201,134 @@ if err != nil {
logger.Fatalf(err.Error())
}
```

### Convert Utils

Convert simply automate the need to
explicitly do assertion each time we need to access
an interface object.

Let us assume we have the following YAML structure

```yaml

to:
array-1:
key-1:
- key-2: 2
- key-3: 3
- key-4: 4
array-2:
- 1
- 2
- 3
- 4
- 5
array-3:
- key-1: 1
- key-2: 2

```

#### Get map of strings from interface

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

##### Get map directly from a GetPath object

To get map **key-2: 2**, first get object via GetPath

```go

obj, err := state.GetPath("to.array-1.key-1.[0]")
if err != nil {
logger.Fatalf(err.Error())
}
logger.Info(val)

```

Next, assert **obj** as `map[string]string`

```go

assertData := db.NewConvertFactory()

assertData.Input(val)
if assertData.Error != nil {
logger.Fatalf(assertData.Error.Error())
}
vMap := assertData.GetMap()
logger.Info(vMap["key-2"])

```

##### Get map manually

We can get the map manually by using only **Convert** operations

```go

assertData := db.NewConvertFactory()

assertData.Input(state.Data).
Key("to").
Key("array-1").
Key("key-1").Index(0)
if assertData.Error != nil {
logger.Fatalf(assertData.Error.Error())
}
vMap := assertData.GetMap()
logger.Info(vMap["key-2"])

```

#### Get array of string from interface

Again here we can do it two ways as with the map example

##### Get array directly from a GetPath object

To get **array-2** as **[]string**, first get object via GetPath

```go

obj, err = state.GetPath("to.array-2")
if err != nil {
logger.Fatalf(err.Error())
}
logger.Info(obj)

```

Next, assert **obj** as `[]string`

```go

assertData := db.NewConvertFactory()

assertData.Input(obj)
if assertData.Error != nil {
logger.Fatalf(assertData.Error.Error())
}
vArray := assertData.GetArray()
logger.Info(vArray)

```

##### Get array manually

We can get the array manually by using only **Convert** operations

```go

assertData.Input(state.Data).
Key("to").
Key("array-2")
if assertData.Error != nil {
logger.Fatalf(assertData.Error.Error())
}
vArray := assertData.GetArray()
logger.Info(vArray)

```
18 changes: 17 additions & 1 deletion db/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,32 @@ package db
// to keep track and derive the right path.
type Cache struct {
V1, V2 interface{}
V3 []interface{}
B []byte
E error
C1, C2, C3 int
Keys []string
}

// NewCacheFactory for creating a new Cache
func NewCacheFactory() Cache {
cache := Cache{
V3: make([]interface{}, 0),
B: make([]byte, 0),
Keys: make([]string, 0),
}
return cache
}

// Clear for clearing the cache and setting all
// content to nil
func (c *Cache) Clear() *Cache {
c.V1, c.V2 = nil, nil
c.V3 = make([]interface{}, 0)
c.C1, c.C2, c.C3 = 0, 0, 0
c.Keys = nil
c.B = make([]byte, 0)
c.E = nil
c.Keys = make([]string, 0)

return c
}
Expand Down
5 changes: 5 additions & 0 deletions db/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,10 @@ func getObjectType(o interface{}) objectType {
return 2
}

_, isMapStringInterface := o.(map[string]interface{})
if isMapStringInterface {
return 5
}

return unknownObj
}
133 changes: 133 additions & 0 deletions db/convert.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package db

import (
"fmt"

"gopkg.in/yaml.v2"
)

// AssertData is used to for converting interface objects to
// map of interfaces or array of interfaces
type AssertData struct {
D0 map[string]string
A0 []string
Error error
Cache Cache
}

// NewConvertFactory for initializing AssertData
func NewConvertFactory() *AssertData {
assertData := &AssertData{
D0: make(map[string]string),
A0: make([]string, 0),
Cache: NewCacheFactory(),
}
return assertData
}

// Clear for resetting AssertData
func (s *AssertData) Clear() {
s.Cache.Clear()
s.D0 = make(map[string]string)
s.A0 = make([]string, 0)
}

// Input sets a data source that can be used for assertion
func (s *AssertData) Input(o interface{}) *AssertData {
s.Clear()
s.Cache.V1 = o
return s
}

func (s *AssertData) toBytes() {
s.Cache.B, s.Cache.E = yaml.Marshal(s.Cache.V1)
if s.Cache.E != nil {
s.Error = s.Cache.E
}
}

// GetMap for converting a map[interface{}]interface{} into a map[string]string
func (s *AssertData) GetMap() map[string]string {
if s.Cache.E != nil {
s.Error = s.Cache.E
return nil
}

s.toBytes()
if s.Cache.E != nil {
return nil
}

s.Cache.E = yaml.Unmarshal(s.Cache.B, &s.D0)
if s.Cache.E != nil {
s.Error = s.Cache.E
return nil
}
return s.D0
}

// GetArray for converting a []interface{} to []string
func (s *AssertData) GetArray() []string {
if s.Cache.E != nil {
s.Error = s.Cache.E
return nil
}

_, isArray := s.Cache.V1.([]interface{})
if !isArray {
s.Cache.E = wrapErr(fmt.Errorf(notArrayObj), getFn())
s.Error = s.Cache.E
return nil
}

s.toBytes()
if s.Cache.E != nil {
return nil
}

s.Cache.E = yaml.Unmarshal(s.Cache.B, &s.A0)
if s.Cache.E != nil {
s.Error = s.Cache.E
return nil
}

return s.A0
}

// Key copies initial interface object and returns a map of interfaces{}
// Used to easily pipe interfaces
func (s *AssertData) Key(k string) *AssertData {
if s.Cache.E != nil {
s.Error = s.Cache.E
return s
}

_, isMap := s.Cache.V1.(map[interface{}]interface{})
if !isMap {
s.Cache.E = wrapErr(fmt.Errorf(notAMap), getFn())
s.Error = s.Cache.E
return s
}

s.Cache.V1 = s.Cache.V1.(map[interface{}]interface{})[k]

return s
}

// Index getting an interface{} from a []interface{}
func (s *AssertData) Index(i int) *AssertData {
if s.Cache.E != nil {
s.Error = s.Cache.E
return s
}

_, isArray := s.Cache.V1.([]interface{})
if !isArray {
s.Cache.E = wrapErr(fmt.Errorf(notArrayObj), getFn())
s.Error = s.Cache.E
return s
}
s.Cache.V1 = s.Cache.V1.([]interface{})[i]

return s
}
Loading

0 comments on commit c606367

Please sign in to comment.