Skip to content

Commit aeafc32

Browse files
Merge pull request #29 from armada45-pixel/test
1.0.7
2 parents 78aff60 + 5da770b commit aeafc32

File tree

7 files changed

+266
-193
lines changed

7 files changed

+266
-193
lines changed

README.md

+46-8
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ For now you can use only 2 option
5151
* **PutToOs** Put variable from file to os.env variable.
5252
* **OverRide** If already variable in same name in os.env variable will replace.
5353
* **OsFirst** If have os.env and env file will choose os.env.
54+
* **CustomType** Map for write custom default value and parser function.
5455
```go
5556
opt := envstruct.Options{
5657
VarPtr: &cfg,
@@ -62,6 +63,37 @@ For now you can use only 2 option
6263
PutToOs: true,
6364
OverRide: true,
6465
OsFirst: true,
66+
CustomType: map[reflect.Type]TypeDefaultBy{
67+
reflect.TypeOf(Pro): {
68+
ParserFunc: func(v string) (interface{}, error) {
69+
searchDefault, _ := envstruct.DefaultByType[reflect.TypeOf(false)]
70+
value, _ := searchDefault.ParserFunc(v)
71+
if value == true {
72+
return Pro, nil
73+
}
74+
return Dev, nil
75+
},
76+
ValueDefault: modeE(false),
77+
},
78+
},
79+
}
80+
81+
type modeE bool
82+
83+
const (
84+
Pro modeE = false
85+
Dev modeE = true
86+
)
87+
88+
func (m modeE) String() string {
89+
if !m {
90+
return "production"
91+
}
92+
return "development"
93+
}
94+
95+
func (m modeE) Bool() bool {
96+
return bool(m)
6597
}
6698
```
6799
## Return
@@ -75,8 +107,8 @@ Return array of error.
75107
All value from your env file in here now.
76108
```go
77109
fmt.Println(cfg)
78-
fmt.Println(cfg.Port)
79-
fmt.Println(cfg.Mode)
110+
fmt.Println(cfg.Port)
111+
fmt.Println(cfg.Mode)
80112
}
81113

82114
```
@@ -94,17 +126,23 @@ All value from your env file in here now.
94126
* Change function name ( export )
95127
* Remove main function
96128
* Change module name to envstruct
129+
* [a6aa3b2](https://github.com/armada45-pixel/envstruct/commit/a6aa3b27764cdb3c0d810118b258251e60e38b9d#)
97130

98131
1.0.3
99-
* Change set function
132+
* Change set function [0e6505f](https://github.com/armada45-pixel/envstruct/commit/0e6505f9f6297885737fdd774372e0e3f1a0b1d8)
100133

101134
1.0.4
102-
* Add Read OS Env
135+
* Add Read OS Env [#4](https://github.com/armada45-pixel/envstruct/issues/4)
103136

104137
1.0.5
105-
* Add Read OS First
138+
* Add Read OS First [#23](https://github.com/armada45-pixel/envstruct/issues/23)
106139

107140
1.0.6
108-
* Add Read All in File
109-
* Put to OS
110-
* Over Ride OS
141+
* Add Read All in File [#8](https://github.com/armada45-pixel/envstruct/issues/8)
142+
* Put to OS [#5](https://github.com/armada45-pixel/envstruct/issues/5)
143+
* Over Ride OS [#6](https://github.com/armada45-pixel/envstruct/issues/6)
144+
145+
1.0.7
146+
* Add Custom Parser function [#9](https://github.com/armada45-pixel/envstruct/issues/9)
147+
* Fix bug : If open only "Put to os" And "Read all" will not working. [#26](https://github.com/armada45-pixel/envstruct/issues/26)
148+
* Fix bug : If have any error in process prepare Variable Pointer Data won't set. [#27](https://github.com/armada45-pixel/envstruct/issues/27)

envstruct.go

+50-30
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// version 1.0.6
1+
// version 1.0.7
22
package envstruct
33

44
import (
@@ -7,6 +7,8 @@ import (
77
"reflect"
88
)
99

10+
type TypeCustomParserFunc func()
11+
1012
type Options struct {
1113
// Type : Variable Pointer
1214
// Pointer Struct Variable to config key,type for read env file or os.env variable
@@ -34,6 +36,9 @@ type Options struct {
3436

3537
// if true = if have os.env and env file will choose os.env
3638
OsFirst bool // default false
39+
40+
// Custom parser function for custom type
41+
CustomType map[reflect.Type]TypeDefaultBy
3742
}
3843

3944
func Setup(optA ...Options) (err []error) {
@@ -42,11 +47,25 @@ func Setup(optA ...Options) (err []error) {
4247

4348
fileName := opt.FileName
4449
var varProp = typeVarProp{}
45-
var errCheckVar []error
50+
var ref reflect.Value
51+
var errCheckVarWrongType error
52+
var allParserFunc = make(map[reflect.Type]TypeDefaultBy)
4653

4754
if opt.VarPtr != nil {
48-
varProp, errCheckVar = prepareVar(opt.VarPtr)
49-
err = append(err, errCheckVar...)
55+
ref, errCheckVarWrongType = checkVarType(opt.VarPtr)
56+
if errCheckVarWrongType != nil {
57+
err = append(err, errCheckVarWrongType)
58+
} else {
59+
var errCheckVar []error
60+
allParserFunc = DefaultByType
61+
if len(opt.CustomType) != 0 {
62+
for key, value := range opt.CustomType {
63+
allParserFunc[key] = value
64+
}
65+
}
66+
varProp, errCheckVar = prepareVar(opt.VarPtr, ref, allParserFunc)
67+
err = append(err, errCheckVar...)
68+
}
5069
}
5170

5271
var envMap map[string]string
@@ -58,24 +77,24 @@ func Setup(optA ...Options) (err []error) {
5877
defer file.Close()
5978
var errParser []error
6079
varProp, envMap, errParser = parserFile(file, opt, parserFileOption{
61-
varProp: varProp,
62-
envMap: make(map[string]string),
80+
varProp: varProp,
81+
allParserFunc: allParserFunc,
6382
})
6483
err = append(err, errParser...)
6584
}
6685
}
6786

68-
// if opt.ReadOS {
69-
var errParser []error
70-
varProp, errParser = parserOSEnv(parserOSOption{
71-
varProp: varProp,
72-
opt: opt,
73-
envMap: envMap,
74-
})
75-
err = append(err, errParser...)
76-
// }
77-
78-
if len(errCheckVar) == 0 {
87+
if opt.ReadOS || opt.ReadAll || opt.PutToOs || opt.OsFirst {
88+
var errParser []error
89+
varProp, errParser = parserOSEnv(parserOSOption{
90+
varProp: varProp,
91+
opt: opt,
92+
envMap: envMap,
93+
})
94+
err = append(err, errParser...)
95+
}
96+
97+
if opt.VarPtr != nil && errCheckVarWrongType == nil {
7998
if errSet := setVar(varProp); len(errSet) != 0 {
8099
err = append(err, errSet...)
81100
}
@@ -90,20 +109,21 @@ func setVar(newVarProp typeVarProp) (err []error) {
90109
for i := 0; i < refType.NumField(); i++ {
91110
newProp := newVarProp.prop[i]
92111
refField := ref.Field(i)
93-
value := newProp.defaultValue
94-
fieldee := refField
95-
if newProp.didRead {
96-
refTypeField := newProp.refTypeField
97-
typee := refTypeField.Type
98-
if typee.Kind() == reflect.Ptr {
99-
typee = typee.Elem()
100-
fieldee = refField.Elem()
112+
if newProp.defaultIsSet || newProp.didRead {
113+
value := newProp.defaultValue
114+
fieldee := refField
115+
if newProp.didRead {
116+
refTypeField := newProp.refTypeField
117+
typee := refTypeField.Type
118+
if typee.Kind() == reflect.Ptr {
119+
typee = typee.Elem()
120+
fieldee = refField.Elem()
121+
}
122+
value = newProp.readValue
101123
}
102-
value = newProp.readValue
103-
}
104-
refValue := reflect.ValueOf(value)
105-
fieldee.Set(refValue)
106-
if !newProp.didRead && newProp.required && refValue.IsZero() {
124+
refValue := reflect.ValueOf(value)
125+
fieldee.Set(refValue)
126+
} else if newProp.required && (refField.IsZero() && reflect.Bool != refField.Kind()) {
107127
err = append(err, errors.New("Field "+refField.Type().Name()+" Required is True, But can't get any value."))
108128
}
109129
}

osenv.go

+19-15
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
1+
// version 1.0.7
12
package envstruct
23

34
import (
45
"os"
6+
"reflect"
57
"strings"
68
)
79

810
type parserOSOption struct {
9-
varProp typeVarProp
10-
envMap map[string]string
11-
opt Options
11+
varProp typeVarProp
12+
envMap map[string]string
13+
opt Options
14+
allParserFunc map[reflect.Kind]TypeDefaultBy
1215
}
1316

1417
func parserOSEnv(opts ...parserOSOption) (varProp typeVarProp, err []error) {
@@ -28,26 +31,27 @@ func parserOSEnv(opts ...parserOSOption) (varProp typeVarProp, err []error) {
2831
if opt.ReadOS {
2932
prop := varProp.prop[keyProp]
3033
typeVar := prop.refTypeField
31-
newValue, errParserData := parserData(varProp, typeVar, keyProp, value)
34+
newValue, errParserData := parserData(prop.typeProp, typeVar, value, opt.CustomType)
3235
if len(errParserData) != 0 {
3336
err = append(err, errParserData...)
34-
}
35-
if !prop.didRead || opt.OsFirst {
36-
varProp.prop[keyProp] = varFieldProp{
37-
defaultValue: prop.defaultValue,
38-
required: prop.required,
37+
} else {
38+
if !prop.didRead || opt.OsFirst {
39+
varProp.prop[keyProp] = varFieldProp{
40+
defaultIsSet: prop.defaultIsSet,
41+
defaultValue: prop.defaultValue,
42+
required: prop.required,
43+
typeProp: prop.typeProp,
3944

40-
didRead: true,
41-
readValue: newValue,
42-
refTypeField: typeVar,
45+
didRead: true,
46+
readValue: newValue,
47+
refTypeField: typeVar,
48+
}
4349
}
4450
}
4551
}
46-
// if foundEnv && opt.OverRide {
47-
// os.Setenv(key, fileValue)
48-
// }
4952
} else if foundEnv {
5053
os.Setenv(key, fileValue)
54+
delete(envMap, key)
5155
}
5256
}
5357
return

parserfile.go

+19-15
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
1+
// version 1.0.7
12
package envstruct
23

34
import (
45
"bufio"
56
"errors"
67
"io"
78
"os"
9+
"reflect"
810
"regexp"
911
"strings"
1012
)
1113

1214
type parserFileOption struct {
13-
varProp typeVarProp
14-
envMap map[string]string
15+
varProp typeVarProp
16+
allParserFunc map[reflect.Type]TypeDefaultBy
1517
}
1618

1719
func parserFile(file io.Reader, opt Options, opts ...parserFileOption) (varProp typeVarProp, envMap map[string]string, err []error) {
1820
varProp = opts[0].varProp
19-
envMap = opts[0].envMap
21+
envMap = make(map[string]string)
2022

2123
scanner := bufio.NewScanner(file)
2224
for scanner.Scan() {
@@ -28,26 +30,28 @@ func parserFile(file io.Reader, opt Options, opts ...parserFileOption) (varProp
2830
err = append(err, errLine)
2931
} else {
3032
keyProp, found := varProp.ENVname[key]
31-
if opt.PutToOs && (found || opt.ReadAll) {
32-
envMap[key] = value
33-
}
3433
if opt.PutToOs && opt.OverRide {
3534
os.Setenv(key, value)
35+
} else if opt.PutToOs && (found || opt.ReadAll) {
36+
envMap[key] = value
3637
}
3738
if found {
3839
prop := varProp.prop[keyProp]
3940
typeVar := prop.refTypeField
40-
newValue, errParserData := parserData(varProp, typeVar, keyProp, value)
41+
newValue, errParserData := parserData(prop.typeProp, typeVar, value, opts[0].allParserFunc)
4142
if len(errParserData) != 0 {
4243
err = append(err, errParserData...)
43-
}
44-
varProp.prop[keyProp] = varFieldProp{
45-
defaultValue: varProp.prop[keyProp].defaultValue,
46-
required: varProp.prop[keyProp].required,
47-
48-
didRead: true,
49-
readValue: newValue,
50-
refTypeField: typeVar,
44+
} else {
45+
varProp.prop[keyProp] = varFieldProp{
46+
defaultIsSet: prop.defaultIsSet,
47+
defaultValue: prop.defaultValue,
48+
required: prop.required,
49+
typeProp: prop.typeProp,
50+
51+
didRead: true,
52+
readValue: newValue,
53+
refTypeField: typeVar,
54+
}
5155
}
5256
}
5357
}

parservalue.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
1+
// version 1.0.7
12
package envstruct
23

34
import (
45
"errors"
56
"reflect"
67
)
78

8-
func parserData(varProp typeVarProp, typeVar reflect.StructField, keyProp int, value string) (newValue any, err []error) {
9+
func parserData(typeKind reflect.Type, typeVar reflect.StructField, value string, allParserFunc map[reflect.Type]TypeDefaultBy) (newValue any, err []error) {
910

1011
typeVarKind := typeVar.Type.Kind()
11-
parserFunc, foundFunc := defaultBuiltInParsers[typeVarKind]
12-
if !foundFunc {
12+
searchDefault, found := allParserFunc[typeKind]
13+
if !found {
1314
err = append(err, errors.New("Parser Function For Type "+typeVarKind.String()+" In Field "+typeVar.Name+""))
1415
} else {
15-
parseValue, errParse := parserFunc(value)
16+
parseValue, errParse := searchDefault.ParserFunc(value)
1617
if errParse != nil {
1718
err = append(err, errParse)
18-
newValue = varProp.prop[keyProp].defaultValue
1919
} else {
2020
newValue = parseValue
2121
}

0 commit comments

Comments
 (0)