Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes unsupported AST kind *ast.InterfaceType on the custon Object type #139

Merged
merged 1 commit into from
Feb 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion hack/deepcopy-gen.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ if [ "${GENS}" = "all" ] || grep -qw "deepcopy" <<<"${GENS}"; then
echo "Generating deepcopy funcs"
export GO111MODULE=on
# for debug purposes, increase the log level by updating the -v flag to higher numbers, e.g. -v 4
"${GOPATH}/bin/deepcopy-gen" -v 1 \
"${GOPATH}/bin/deepcopy-gen" -v 2 \
--input-dirs ./model -O zz_generated.deepcopy \
--go-header-file "${SCRIPT_ROOT}/hack/boilerplate.txt" \
"$@"
Expand Down
152 changes: 46 additions & 106 deletions model/object.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ import (
"encoding/json"
"fmt"
"math"
"strconv"
"strings"
)

// Object is used to allow integration with DeepCopy tool by replacing 'interface' generic type.
Expand All @@ -32,126 +30,68 @@ import (
// - Integer - holds int32 values, JSON marshal any number to float64 by default, during the marshaling process it is
// parsed to int32
// - raw - holds any not typed value, replaces the interface{} behavior.
//
// +kubebuilder:validation:Type=object
type Object struct {
IObject `json:",inline"`
}

// IObject interface that can converted into one of the three subtypes
type IObject interface {
DeepCopyIObject() IObject
}

// raw generic subtype
type raw struct {
IObject interface{}
Type Type `json:",inline"`
IntVal int32 `json:",inline"`
StrVal string `json:",inline"`
RawValue json.RawMessage `json:",inline"`
}

func (o raw) DeepCopyIObject() IObject {
return o
}
type Type int64

// Integer int32 type
type Integer int
const (
Integer Type = iota
String
Raw
)

func (m Integer) DeepCopyIObject() IObject {
return m
func FromInt(val int) Object {
if val > math.MaxInt32 || val < math.MinInt32 {
fmt.Println(fmt.Errorf("value: %d overflows int32", val))
}
return Object{Type: Integer, IntVal: int32(val)}
}

// String string type
type String string

func (m String) DeepCopyIObject() IObject {
return m
func FromString(val string) Object {
return Object{Type: String, StrVal: val}
}

// MarshalJSON marshal the given json object into the respective Object subtype.
func (obj Object) MarshalJSON() ([]byte, error) {
switch val := obj.IObject.(type) {
case String:
return []byte(fmt.Sprintf(`%q`, val)), nil
case Integer:
return []byte(fmt.Sprintf(`%d`, val)), nil
case raw:
custom, err := json.Marshal(&struct {
raw
}{
val,
})
if err != nil {
return nil, err
}

// remove the field name and the last '}' for marshalling purposes
st := strings.Replace(string(custom), "{\"IObject\":", "", 1)
st = strings.TrimSuffix(st, "}")
return []byte(st), nil
default:
return []byte(fmt.Sprintf("%+v", obj.IObject)), nil
func FromRaw(val interface{}) Object {
custom, err := json.Marshal(val)
if err != nil {
er := fmt.Errorf("failed to parse value to Raw: %w", err)
fmt.Println(er.Error())
return Object{}
}
return Object{Type: Raw, RawValue: custom}
}

// UnmarshalJSON ...
func (obj *Object) UnmarshalJSON(data []byte) error {
var test interface{}
if err := json.Unmarshal(data, &test); err != nil {
return err
if data[0] == '"' {
obj.Type = String
return json.Unmarshal(data, &obj.StrVal)
} else if data[0] == '{' {
obj.Type = Raw
return json.Unmarshal(data, &obj.RawValue)
}
switch val := test.(type) {
case string:
var strVal String
if err := json.Unmarshal(data, &strVal); err != nil {
return err
}
obj.IObject = strVal
return nil

case map[string]interface{}:
var cstVal raw
if err := json.Unmarshal(data, &cstVal.IObject); err != nil {
return err
}
obj.IObject = cstVal
return nil

default:
// json parses all not typed numbers as float64, let's enforce to int32
if valInt, parseErr := strconv.Atoi(fmt.Sprint(val)); parseErr != nil {
return fmt.Errorf("falied to parse %d to int32: %w", valInt, parseErr)
} else {
var intVal Integer
if err := json.Unmarshal(data, &intVal); err != nil {
return err
}
obj.IObject = intVal
return nil
}
}
}

// FromInt creates an Object with an int32 value.
func FromInt(val int) Object {
if val > math.MaxInt32 || val < math.MinInt32 {
panic(fmt.Errorf("value: %d overflows int32", val))
}
return Object{Integer(int32(val))}
}

// FromString creates an Object with a string value.
func FromString(val string) Object {
return Object{String(val)}
obj.Type = Integer
return json.Unmarshal(data, &obj.IntVal)
}

// FromRaw creates an Object with untyped values.
func FromRaw(val interface{}) Object {
var rawVal Object
data, err := json.Marshal(val)
if err != nil {
panic(err)
}
var cstVal raw
if err := json.Unmarshal(data, &cstVal.IObject); err != nil {
panic(err)
// MarshalJSON marshal the given json object into the respective Object subtype.
func (obj Object) MarshalJSON() ([]byte, error) {
switch obj.Type {
case String:
return []byte(fmt.Sprintf(`%q`, obj.StrVal)), nil
case Integer:
return []byte(fmt.Sprintf(`%d`, obj.IntVal)), nil
case Raw:
val, _ := json.Marshal(obj.RawValue)
return val, nil
default:
return []byte(fmt.Sprintf("%+v", obj)), nil
}
rawVal.IObject = cstVal
return rawVal
}
8 changes: 4 additions & 4 deletions model/parallel_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,14 @@ type ParallelState struct {
Timeouts *ParallelStateTimeout `json:"timeouts,omitempty"`
}

func (s *ParallelState) DeepCopyState() State {
return s
func (ps *ParallelState) DeepCopyState() State {
return ps
}

type parallelStateForUnmarshal ParallelState

// UnmarshalJSON unmarshal ParallelState object from json bytes
func (s *ParallelState) UnmarshalJSON(b []byte) error {
func (ps *ParallelState) UnmarshalJSON(b []byte) error {
if len(b) == 0 {
// TODO: Normalize error messages
return fmt.Errorf("no bytes to unmarshal")
Expand All @@ -75,7 +75,7 @@ func (s *ParallelState) UnmarshalJSON(b []byte) error {
return err
}

*s = ParallelState(*v)
*ps = ParallelState(*v)

return nil
}
Expand Down
6 changes: 4 additions & 2 deletions model/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.