Browse Source

💥 real go types instead of string values

master
n0m1s 6 years ago
parent
commit
58aba161ac
Signed by: nomis GPG Key ID: BC0454CAD76FE803
1 changed files with 103 additions and 99 deletions
  1. +103
    -99
      jdr/type.go

+ 103
- 99
jdr/type.go View File

@ -8,16 +8,17 @@ import(
"strings" "strings"
"strconv" "strconv"
"regexp" "regexp"
"encoding/json"
) )
var regexp_d = regexp.MustCompile(`^[1-9][0-9]*d([468]|1[02]|20|100)$`) var regexp_d = regexp.MustCompile(`^[1-9][0-9]*d([468]|1[02]|20|100)$`)
type JsonValue interface{}
type VariableType interface { type VariableType interface {
Name() string Name() string
Validate(value string) bool
ToHTML(value string) (template.HTML, error)
DefaultValue() string
Validate(value JsonValue) bool
ToHTML(value JsonValue) (template.HTML, error)
DefaultValue() JsonValue
} }
type VariableType_badType struct {} type VariableType_badType struct {}
@ -26,15 +27,15 @@ func (*VariableType_badType) Name() string {
return "unknown type" return "unknown type"
} }
func (*VariableType_badType) Validate(s string) bool {
func (*VariableType_badType) Validate(s JsonValue) bool {
return false return false
} }
func (*VariableType_badType) ToHTML(value string) (template.HTML, error) {
func (*VariableType_badType) ToHTML(value JsonValue) (template.HTML, error) {
return template.HTML(""), errors.New("unknown type") return template.HTML(""), errors.New("unknown type")
} }
func (*VariableType_badType) DefaultValue() string {
func (*VariableType_badType) DefaultValue() JsonValue {
return "" return ""
} }
@ -44,23 +45,21 @@ func (*VariableType_bool) Name() string {
return "bool" return "bool"
} }
func (*VariableType_bool) ToBool(value string) (bool, error) {
switch strings.ToLower(value) {
case "true":
return true, nil
case "false":
return false, nil
default:
return false, errors.New("unknown bool value")
func (*VariableType_bool) ToBool(value JsonValue) (bool, error) {
val, isBool := value.(bool)
if !isBool {
return false, errors.New("Non boolean value")
} }
return val, nil
} }
func (self *VariableType_bool) Validate(value string) bool {
func (self *VariableType_bool) Validate(value JsonValue) bool {
_, err := self.ToBool(value) _, err := self.ToBool(value)
return err == nil return err == nil
} }
func (self *VariableType_bool) ToHTML(value string) (template.HTML, error) {
func (self *VariableType_bool) ToHTML(value JsonValue) (template.HTML, error) {
val, err := self.ToBool(value) val, err := self.ToBool(value)
if err != nil { if err != nil {
return template.HTML(""), err return template.HTML(""), err
@ -75,8 +74,8 @@ func (self *VariableType_bool) ToHTML(value string) (template.HTML, error) {
return template.HTML(ret), nil return template.HTML(ret), nil
} }
func (self *VariableType_bool) DefaultValue() string {
return "false"
func (self *VariableType_bool) DefaultValue() JsonValue {
return false
} }
type VariableType_int struct {} type VariableType_int struct {}
@ -85,16 +84,26 @@ func (*VariableType_int) Name() string {
return "int" return "int"
} }
func (self *VariableType_int) ToInt(value string) (int64, error) {
return strconv.ParseInt(value, 10, 64)
func (self *VariableType_int) ToInt(value JsonValue) (int64, error) {
val, isInt := value.(int64)
if !isInt {
val2, isInt := value.(int)
if isInt {
val = int64(val2)
} else {
return 0, errors.New("Not int"))
}
}
return val, nil
} }
func (self *VariableType_int) Validate(value string) bool {
func (self *VariableType_int) Validate(value JsonValue) bool {
_, err := self.ToInt(value) _, err := self.ToInt(value)
return err == nil return err == nil
} }
func (self *VariableType_int) ToHTML(value string) (template.HTML, error) {
func (self *VariableType_int) ToHTML(value JsonValue) (template.HTML, error) {
val, err := self.ToInt(value) val, err := self.ToInt(value)
if err != nil { if err != nil {
return template.HTML(""), err return template.HTML(""), err
@ -104,8 +113,8 @@ func (self *VariableType_int) ToHTML(value string) (template.HTML, error) {
return template.HTML(ret), nil return template.HTML(ret), nil
} }
func (self *VariableType_int) DefaultValue() string {
return "0"
func (self *VariableType_int) DefaultValue() JsonValue {
return 0
} }
type VariableType_float struct {} type VariableType_float struct {}
@ -114,16 +123,21 @@ func (*VariableType_float) Name() string {
return "float" return "float"
} }
func (*VariableType_float) ToFloat(value string) (float64, error) {
return strconv.ParseFloat(value, 64)
func (*VariableType_float) ToFloat(value JsonValue) (float64, error) {
val, isFloat := value.(float64)
if !isFloat {
return 0.0, errors.New("Not a float")
}
return val, nil
} }
func (self *VariableType_float) Validate(value string) bool {
func (self *VariableType_float) Validate(value JsonValue) bool {
_, err := self.ToFloat(value) _, err := self.ToFloat(value)
return err == nil return err == nil
} }
func (self *VariableType_float) ToHTML(value string) (template.HTML, error) {
func (self *VariableType_float) ToHTML(value JsonValue) (template.HTML, error) {
val, err := self.ToFloat(value) val, err := self.ToFloat(value)
if err != nil { if err != nil {
return template.HTML(""), err return template.HTML(""), err
@ -134,8 +148,8 @@ func (self *VariableType_float) ToHTML(value string) (template.HTML, error) {
return template.HTML(ret), nil return template.HTML(ret), nil
} }
func (self *VariableType_float) DefaultValue() string {
return "0.0"
func (self *VariableType_float) DefaultValue() JsonValue {
return 0.0
} }
type VariableType_string struct {} type VariableType_string struct {}
@ -144,16 +158,31 @@ func (*VariableType_string) Name() string {
return "string" return "string"
} }
func (*VariableType_string) Validate(s string) bool {
return true
func (self *VariableType_string) ToString(value JsonValue) (string, error) {
val, isString := value.(string)
if !isString {
return "", errors.New("Not a string")
}
return val, nil
} }
func (self *VariableType_string) ToHTML(value string) (template.HTML, error) {
ret := `<input type="text" value="` + template.HTMLEscapeString(value) + `"/>`
func (self *VariableType_string) Validate(value JsonValue) bool {
_, err := self.ToString(value)
return err != nil
}
func (self *VariableType_string) ToHTML(value JsonValue) (template.HTML, error) {
str, err := self.ToString(value)
if err != nil {
return template.HTML(""), err
}
ret := `<input type="text" value="` + template.HTMLEscapeString(str) + `"/>`
return template.HTML(ret), nil return template.HTML(ret), nil
} }
func (self *VariableType_string) DefaultValue() string {
func (self *VariableType_string) DefaultValue() JsonValue {
return "" return ""
} }
@ -163,18 +192,19 @@ func (*VariableType_d) Name() string {
return "d" return "d"
} }
func (*VariableType_d) Validate(s string) bool {
return regexp_d.MatchString(s)
func (*VariableType_d) Validate(value JsonValue) bool {
//FIXME
return false
} }
func (self *VariableType_d) ToHTML(value string) (template.HTML, error) {
func (self *VariableType_d) ToHTML(value JsonValue) (template.HTML, error) {
//FIXME: non-generic version //FIXME: non-generic version
ret := `<input type="text" value="` + template.HTMLEscapeString(value) +`"/>`
ret := `<input type="text" value="` /*+ template.HTMLEscapeString(value)*/ +`"/>`
return template.HTML(ret), nil return template.HTML(ret), nil
} }
func (self *VariableType_d) DefaultValue() string {
func (self *VariableType_d) DefaultValue() JsonValue {
//FIXME: non-generic version //FIXME: non-generic version
return "" return ""
} }
@ -199,7 +229,6 @@ func makeVariableType(s string) VariableType {
type CustomEnum struct { type CustomEnum struct {
name string name string
BaseType VariableType
Values []string Values []string
} }
@ -207,13 +236,14 @@ func (self *CustomEnum) Name() string {
return self.name return self.name
} }
func (self *CustomEnum) ToId(value string) (int, error) {
if !self.BaseType.Validate(value) {
return 0, errors.New("Invalid value")
func (self *CustomEnum) ToId(value JsonValue) (int, error) {
val, isString := value.(string)
if !isString {
return 0, errors.New("Enum value not a string")
} }
for i := 0; i < len(self.Values); i++ { for i := 0; i < len(self.Values); i++ {
if self.Values[i] == value {
if self.Values[i] == val {
return i, nil return i, nil
} }
} }
@ -221,13 +251,17 @@ func (self *CustomEnum) ToId(value string) (int, error) {
return 0, errors.New("No such element") return 0, errors.New("No such element")
} }
func (self *CustomEnum) Validate(value string) bool {
func (self *CustomEnum) Validate(value JsonValue) bool {
_, err := self.ToId(value) _, err := self.ToId(value)
return err == nil return err == nil
} }
func (self *CustomEnum) ToHTML(value string) (template.HTML, error) {
selectItem := value != ""
func (self *CustomEnum) ToHTML(value JsonValue) (template.HTML, error) {
val, isString := value.(string)
if !isString {
return template.HTML(""), errors.New("Bad enum value")
}
selectItem := val != ""
value_id := 0 value_id := 0
if selectItem { if selectItem {
@ -253,10 +287,12 @@ func (self *CustomEnum) ToHTML(value string) (template.HTML, error) {
return template.HTML(ret), nil return template.HTML(ret), nil
} }
func (self *CustomEnum) DefaultValue() string {
func (self *CustomEnum) DefaultValue() JsonValue {
return "" return ""
} }
type JsonObject map[string]interface{}
type CustomStruct struct { type CustomStruct struct {
name string name string
Variables []*Variable Variables []*Variable
@ -266,17 +302,16 @@ func (self *CustomStruct) Name() string {
return self.name return self.name
} }
func (self *CustomStruct) Validate(s string) bool {
var jsonValue map[string]interface{}
err := json.Unmarshal([]byte(s), &jsonValue)
if err != nil {
log.Fatal(err)
func (self *CustomStruct) Validate(value JsonValue) bool {
obj, isObj := value.(JsonObject)
if !isObj {
log.Println("Struct \"" + self.Name() + "\": value is not a JSON object")
return false return false
} }
for _, v := range self.Variables { for _, v := range self.Variables {
jsonVal, isString := jsonValue[v.Name()].(string)
if !isString || ! v.Type.Validate(jsonVal) {
if !v.Type.Validate(obj[v.Name()]) {
log.Println("Struct \"" + self.Name() + "\": value \"" + v.Name() + "\" was not validated")
return false return false
} }
} }
@ -284,25 +319,19 @@ func (self *CustomStruct) Validate(s string) bool {
return true return true
} }
func (self *CustomStruct) ToHTML(value string) (template.HTML, error) {
var jsonValue map[string]interface{}
err := json.Unmarshal([]byte(value), &jsonValue)
if err != nil {
log.Fatal(err)
return template.HTML(""), errors.New("Cannot unmarshal JSON")
func (self *CustomStruct) ToHTML(value JsonValue) (template.HTML, error) {
if !self.Validate(value) {
return template.HTML(""), errors.New("Cannot validate struct")
} }
obj, _ := value.(JsonObject)
ret := template.HTML("") ret := template.HTML("")
ret += `<div>` ret += `<div>`
for _, v := range self.Variables { for _, v := range self.Variables {
log.Println("variable:", v.Name()) log.Println("variable:", v.Name())
jsonVal, isString := jsonValue[v.Name()].(string)
if !isString {
return template.HTML(""), errors.New("Variable " + v.Name() + " is not a string")
}
html, err := v.Type.ToHTML(jsonVal)
html, err := v.Type.ToHTML(obj[v.Name()])
if err != nil { if err != nil {
return template.HTML(""), err return template.HTML(""), err
} }
@ -314,19 +343,11 @@ func (self *CustomStruct) ToHTML(value string) (template.HTML, error) {
return ret, nil return ret, nil
} }
func (self *CustomStruct) DefaultValue() string {
ret := `{`
for i, v := range self.Variables {
if i > 0 {
ret += ","
}
ret += `"`
ret += v.Name()
ret += `":"`
ret += v.Type.DefaultValue()
ret += `"`
func (self *CustomStruct) DefaultValue() JsonValue {
ret := make(JsonObject)
for _, v := range self.Variables {
ret[v.Name()] = v.Type.DefaultValue()
} }
ret += `}`
return ret return ret
} }
@ -334,7 +355,6 @@ func parseCustomEnum(root xmlNode) (*CustomEnum, error) {
customEnum := CustomEnum {} customEnum := CustomEnum {}
nameOk := false; nameOk := false;
typeOk := false;
for i := 0; i < len(root.Attrs); i++ { for i := 0; i < len(root.Attrs); i++ {
attrName := root.Attrs[i].Name.Local attrName := root.Attrs[i].Name.Local
attrVal := root.Attrs[i].Value attrVal := root.Attrs[i].Value
@ -343,35 +363,19 @@ func parseCustomEnum(root xmlNode) (*CustomEnum, error) {
case "name": case "name":
nameOk = true nameOk = true
customEnum.name = attrVal customEnum.name = attrVal
case "base-type":
typeOk = true
customEnum.BaseType = makeVariableType(attrVal)
switch customEnum.BaseType.(type) {
case *VariableType_badType:
typeOk = false
}
} }
} }
if !nameOk { if !nameOk {
return nil, errors.New("Unnamed custom enum") return nil, errors.New("Unnamed custom enum")
} }
if !typeOk {
return nil, errors.New("Bad base type for " + customEnum.Name())
}
for i := 0; i < len(root.Nodes); i++ { for i := 0; i < len(root.Nodes); i++ {
node := root.Nodes[i] node := root.Nodes[i]
switch node.XMLName.Local { switch node.XMLName.Local {
case "value": case "value":
value := string(node.Content)
if customEnum.BaseType.Validate(value) {
customEnum.Values = append(customEnum.Values, value)
} else {
log.Println("Cannot validate value enum \"" + value + "\" with type \"" +
customEnum.BaseType.Name() + "\". Discarded")
}
customEnum.Values = append(customEnum.Values, string(node.Content))
} }
} }


Loading…
Cancel
Save