Skip to content

Commit

Permalink
Fixes unsupported AST kind *ast.InterfaceType on the custon Object ty…
Browse files Browse the repository at this point in the history
…pe (#139)

Signed-off-by: Spolti <filippespolti@gmail.com>
  • Loading branch information
spolti authored Feb 8, 2023
1 parent e5760e4 commit 9c2ef9c
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 113 deletions.
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.

0 comments on commit 9c2ef9c

Please sign in to comment.