diff --git a/datapoints.go b/datapoints.go deleted file mode 100644 index 7974fd5..0000000 --- a/datapoints.go +++ /dev/null @@ -1,369 +0,0 @@ -package models - -import ( - "errors" - "fmt" - "regexp" - "strings" - "time" - - "github.com/coder/websocket/wsjson" - "github.com/google/uuid" - serverModels "github.com/tecamino/tecamino-dbm/server/models" - "github.com/tecamino/tecamino-dbm/utils" -) - -const ( - OnCreate = "onCreate" - OnChange = "onChange" - OnDelete = "onDelete" -) - -type Datapoint struct { - Datapoints map[string]*Datapoint `json:"-"` - Uuid uuid.UUID `json:"uuid"` - Path string `json:"path"` - Value any `json:"value,omitempty"` - CreateDateTime int64 `json:"createDateTime,omitempty"` - UpdateDateTime int64 `json:"updateDateTime,omitempty"` - Type Type `json:"type"` - ReadWrite Rights `json:"readWrite"` - Drivers Drivers `json:"drivers,omitempty"` - Subscriptions Subscriptions `json:"-"` -} - -func (d *Datapoint) Set(path string, set Set) (bool, error) { - var changed bool - if path != "" { - changed = true - d.Path = path - } - - if set.Type != nil { - changed = true - d.Type = *set.Type - } - - if d.Type != "" { - if d.Value == nil && set.Value == nil { - changed = true - d.Value = d.Type.DefaultValue() - } else if d.Value != d.Type.ConvertValue(set.Value) { - changed = true - d.Value = d.Type.ConvertValue(set.Value) - } - - } - if set.Rights != nil { - changed = true - d.ReadWrite = set.Rights.GetRights() - } - - if changed { - d.UpdateDateTime = time.Now().UnixMilli() - } - - if set.Driver == nil { - return changed, nil - } - if set.Driver.Type == "" { - return changed, errors.New("driver type missing") - } - if set.Driver.Bus == "" { - return changed, errors.New("driver bus name missing") - } - - if d.Drivers == nil { - d.Drivers = NewDrivers() - } - d.Drivers.AddDriver(set.Driver.Type, set.Driver.Bus, set.Driver.Address) - d.UpdateDateTime = time.Now().UnixMilli() - - return changed, nil -} - -func (d *Datapoint) GetValueUint64() uint64 { - return utils.Uint64From(d.Value) -} - -func (d *Datapoint) CreateDatapoints(conns *serverModels.Connections, sets ...Set) (created []Set, err error) { - if len(sets) == 0 { - return - } - for _, dp := range sets { - parts := strings.Split(dp.Path, ":") - - current := d - for i, part := range parts { - if current.Datapoints == nil { - current.Datapoints = make(map[string]*Datapoint) - } - - if i == len(parts)-1 { - // Leaf node: create or update datapoint - if existing, ok := current.Datapoints[part]; ok { - publish, err := existing.Set("", dp) - if err != nil { - return nil, err - } - created = append(created, Set{ - Path: existing.Path, - Type: &existing.Type, - Value: existing.Value, - Rights: &existing.ReadWrite, - Drivers: &existing.Drivers, - Updated: true, - }) - - if publish { - existing.Publish(conns, OnChange) - } - } else { - // Create new - current.Datapoints[part] = &Datapoint{ - Uuid: uuid.New(), - CreateDateTime: time.Now().UnixMilli(), - Subscriptions: InitSubscribtion(), - } - publish, err := current.Datapoints[part].Set(strings.Join(parts, ":"), dp) - if err != nil { - return nil, err - } - created = append(created, Set{ - Path: current.Path, - Type: ¤t.Type, - Value: current.Value, - Rights: ¤t.ReadWrite, - Driver: dp.Driver, - }) - if publish { - current.Publish(conns, OnChange) - } - } - return - } - - // Traverse or create intermediate datapoints - if next, ok := current.Datapoints[part]; ok { - current = next - } else { - newDp := &Datapoint{ - Uuid: uuid.New(), - Path: strings.Join(parts[:i+1], ":"), - Type: NONE, - CreateDateTime: time.Now().UnixMilli(), - UpdateDateTime: time.Now().UnixMilli(), - Subscriptions: InitSubscribtion(), - } - - if dp.Rights != nil { - newDp.ReadWrite = dp.Rights.GetRights() - } - - current.Datapoints[part] = newDp - current = newDp - } - } - } - return -} - -func (d *Datapoint) ImportDatapoint(conns *serverModels.Connections, dp Datapoint, path string) error { - parts := strings.Split(dp.Path, ":") - - current := d - for i, part := range parts { - if current.Datapoints == nil { - current.Datapoints = make(map[string]*Datapoint) - } - - if i == len(parts)-1 { - // Leaf node: import the datapoint - if existing, ok := current.Datapoints[part]; ok { - existing.Type = dp.Type - existing.Value = current.Type.ConvertValue(dp.Value) - existing.ReadWrite = dp.ReadWrite.GetRights() - existing.UpdateDateTime = time.Now().UnixMilli() - dp.Publish(conns, OnChange) - } else { - dp.Path = strings.Join(parts, ":") - dp.ReadWrite = dp.ReadWrite.GetRights() - dp.UpdateDateTime = time.Now().UnixMilli() - dp.Subscriptions = InitSubscribtion() - current.Datapoints[part] = &dp - dp.Publish(conns, OnChange) - } - return nil - } - - // Traverse or create intermediate nodes - if next, ok := current.Datapoints[part]; ok { - current = next - } else { - newDp := &Datapoint{ - Path: strings.Join(parts[:i+1], ":"), - Type: NONE, - ReadWrite: dp.ReadWrite.GetRights(), - UpdateDateTime: time.Now().UnixMilli(), - } - newDp.ReadWrite = newDp.ReadWrite.GetRights() - current.Datapoints[part] = newDp - current = newDp - } - } - return nil -} - -func (d *Datapoint) UpdateDatapointValue(conns *serverModels.Connections, value any, path string) error { - - paths := strings.Split(path, ":") - - current := d - for i, part := range paths { - dp, ok := current.Datapoints[part] - if !ok { - return fmt.Errorf("datapoint path not found: %s (at %s)", path, part) - } - if i == len(paths)-1 { - dp.Value = dp.Type.ConvertValue(value) - dp.UpdateDateTime = time.Now().UnixMilli() - dp.Publish(conns, OnChange) - return nil - } - current = dp - } - return nil -} - -func (d *Datapoint) RemoveDatapoint(conns *serverModels.Connections, set Set) (Set, error) { - parts := strings.Split(set.Path, ":") - - if len(parts) < 1 { - return Set{}, fmt.Errorf("invalid path: '%s'", set.Path) - } - - current := d - for i := range len(parts) - 1 { - next, ok := current.Datapoints[parts[i]] - if !ok { - return Set{}, fmt.Errorf("path not found: '%s'", strings.Join(parts[:i+1], ":")) - } - current = next - } - - toDelete := parts[len(parts)-1] - if dp, ok := current.Datapoints[toDelete]; ok { - dp.Publish(conns, OnDelete) - delete(current.Datapoints, toDelete) - return Set{ - Path: set.Path, - }, nil - } - return Set{}, fmt.Errorf("datapoint '%s' not found", set.Path) -} - -func (d *Datapoint) GetAllDatapoints(depth int) (dps []*Datapoint) { - - var dfs func(dp *Datapoint, currentDepth int) - dfs = func(dp *Datapoint, currentDepth int) { - if depth == 1 { - return - } else if depth == 0 { - // Return all descendants - for _, child := range dp.Datapoints { - dps = append(dps, child) - dfs(child, currentDepth+1) - } - return - } - - if currentDepth == depth-1 { - return - } - - for _, child := range dp.Datapoints { - dps = append(dps, child) - dfs(child, currentDepth+1) - } - } - dps = append(dps, d) - dfs(d, 0) - return -} - -func (d *Datapoint) QueryDatapoints(depth int, path string) (dps []*Datapoint) { - parts := strings.Split(path, ":") - - var dfs func(current *Datapoint, index int) - dfs = func(current *Datapoint, index int) { - - if index == len(parts) { - dps = append(dps, current.GetAllDatapoints(depth)...) - return - } - - pattern := "^" + parts[index] + "$" - re, err := regexp.Compile(pattern) - if err != nil { - return - } - - for name, dp := range current.Datapoints { - if re.MatchString(name) { - dfs(dp, index+1) - } - } - } - - dfs(d, 0) - return -} - -func (d *Datapoint) AddSubscribtion(id string, sub *Subscribe) { - if d.Subscriptions == nil { - return - } - - if s, ok := d.Subscriptions[id]; ok { - s.OnCreate = sub.GetOnCreate() - s.OnChange = sub.GetOnChange() - s.OnDelete = sub.GetOnDelete() - } else { - d.Subscriptions[id] = &Subscription{ - OnCreate: sub.GetOnCreate(), - OnChange: sub.GetOnChange(), - OnDelete: sub.GetOnDelete(), - } - } -} - -func (d *Datapoint) RemoveSubscribtion(id string) { - if _, ok := d.Subscriptions[id]; !ok { - return - } - delete(d.Subscriptions, id) -} - -func (d *Datapoint) Publish(conns *serverModels.Connections, eventType string) error { - if conns.Clients == nil { - return nil - } - conns.RLock() - defer conns.RUnlock() - - for id := range d.Subscriptions { - if client, ok := conns.Clients[id]; !ok { - delete(d.Subscriptions, id) - } else { - err := wsjson.Write(client.Ctx, client.Conn, Publish{ - Event: eventType, - Path: d.Path, - Value: d.Value, - }) - if err != nil { - return err - } - } - } - return nil -} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..24de193 --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module github.com/tecamino/tecamino-dbm-json_data + +go 1.21.0 + +require github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..7790d7c --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= diff --git a/jsonData.go b/jsonData.go deleted file mode 100644 index c7b1955..0000000 --- a/jsonData.go +++ /dev/null @@ -1,37 +0,0 @@ -package models - -type JsonData struct { - Get *[]Get `json:"get,omitempty"` - Set *[]Set `json:"set,omitempty"` - Subscribe *[]Subscribe `json:"subscribe,omitempty"` - Subscribed *[]Subscribed `json:"subscribed,omitempty"` - Unsubscribe *[]Subscribe `json:"unsubscribe,omitempty"` - Publish *[]Publish `json:"publish,omitempty"` -} - -func NewRequest() *JsonData { - return &JsonData{} - -} - -func (r *JsonData) AddGet(path string, query Query) { - if r.Get == nil { - r.Get = &[]Get{} - } - - *r.Get = append(*r.Get, Get{ - Path: path, - Query: &query, - }) -} - -func (r *JsonData) AddSet(path string, value any, create bool) { - if r.Set == nil { - r.Set = &[]Set{} - } - - *r.Set = append(*r.Set, Set{ - Path: path, - Value: value, - }) -} diff --git a/jsonResponse.go b/jsonResponse.go deleted file mode 100644 index c9d7cc3..0000000 --- a/jsonResponse.go +++ /dev/null @@ -1,13 +0,0 @@ -package models - -type JsonResponse struct { - Error *bool `json:"error,omitempty"` - Message string `json:"message,omitempty"` - Data string `json:"data,omitempty"` - Event string `json:"event,omitempty"` - Path string `json:"path,omitempty"` - Value any `json:"value,omitempty"` - Set *[]Set `json:"set,omitempty"` - Subscribe *[]Subscribe `json:"subscribe,omitempty"` - Unubscribe *[]Subscribe `json:"unsubscribe,omitempty"` -} diff --git a/drivers.go b/models/drivers.go similarity index 73% rename from drivers.go rename to models/drivers.go index c1cb37c..253700a 100644 --- a/drivers.go +++ b/models/drivers.go @@ -5,14 +5,14 @@ type Drivers map[string]*Driver type Driver struct { Type string `json:"type,omitempty"` Bus string `json:"bus"` - Address int `json:"address"` + Address uint `json:"address"` } func NewDrivers() Drivers { return make(Drivers) } -func (d *Drivers) AddDriver(typ, bus string, address int) { +func (d *Drivers) AddDriver(typ, bus string, address uint) { (*d)[typ] = &Driver{ Bus: bus, Address: address, diff --git a/models/errorResponse.go b/models/errorResponse.go new file mode 100644 index 0000000..5e9b906 --- /dev/null +++ b/models/errorResponse.go @@ -0,0 +1,6 @@ +package models + +type ErrorResponse struct { + Error bool `json:"error,omitempty"` + Message string `json:"message,omitempty"` +} diff --git a/get.go b/models/get.go similarity index 53% rename from get.go rename to models/get.go index 43c68ba..61cefce 100644 --- a/get.go +++ b/models/get.go @@ -6,8 +6,22 @@ type Get struct { Uuid uuid.UUID `json:"uuid"` Path string `json:"path"` Query *Query `json:"query,omitempty"` - Drivers Drivers `json:"driver,omitempty"` + Drivers *Drivers `json:"driver,omitempty"` Type Type `json:"type,omitempty"` Value any `json:"value,omitempty"` Rights Rights `json:"rights,omitempty"` } + +func (g *Get) ByPath(path string, query *Query) { + g.Path = path + if query != nil { + g.Query = query + } +} + +func (g *Get) ByUuid(uid string, query *Query) { + g.Uuid = uuid.MustParse(uid) + if query != nil { + g.Query = query + } +} diff --git a/models/publish.go b/models/publish.go new file mode 100644 index 0000000..ee3c6ad --- /dev/null +++ b/models/publish.go @@ -0,0 +1,10 @@ +package models + +import "github.com/google/uuid" + +type Publish struct { + Event string `json:"event,omitempty"` + Uuid uuid.UUID `json:"uuid,omitempty"` + Path string `json:"path,omitempty"` + Value any `json:"value,omitempty"` +} diff --git a/query.go b/models/query.go similarity index 100% rename from query.go rename to models/query.go diff --git a/models/request.go b/models/request.go new file mode 100644 index 0000000..13a2379 --- /dev/null +++ b/models/request.go @@ -0,0 +1,56 @@ +package models + +type Request struct { + Get []Get `json:"get,omitempty"` + Set []Set `json:"set,omitempty"` + Subscribe []Subscribe `json:"subscribe,omitempty"` + Unsubscribe []Subscribe `json:"unsubscribe,omitempty"` +} + +func (r *Request) AddGet() *Get { + get := Get{} + r.Get = append(r.Get, get) + return &get +} + +func (r *Request) AddSet() *Set { + set := Set{} + r.Set = append(r.Set, set) + return &set +} + +func (r *Request) AddSubscription(path string, depth uint, onCreate, onChange, onDelete bool) { + r.Subscribe = append(r.Subscribe, Subscribe{ + Path: path, + Depth: depth, + OnCreate: onCreate, + OnDelete: onChange, + OnChange: onDelete, + }) +} + +func (r *Request) AddDriverSubscription(path, driverName string, depth uint, onCreate, onChange, onDelete bool) { + r.Subscribe = append(r.Subscribe, Subscribe{ + Path: path, + Depth: depth, + Driver: driverName, + OnCreate: onCreate, + OnDelete: onChange, + OnChange: onDelete, + }) +} + +func (r *Request) AddUnsubscribe(path string, depth uint) { + r.Unsubscribe = append(r.Unsubscribe, Subscribe{ + Path: path, + Depth: depth, + }) +} + +func (r *Request) AddUnsubscribeDriver(path, driverName string, depth uint) { + r.Unsubscribe = append(r.Unsubscribe, Subscribe{ + Path: path, + Depth: depth, + Driver: driverName, + }) +} diff --git a/models/response.go b/models/response.go new file mode 100644 index 0000000..e5ac64e --- /dev/null +++ b/models/response.go @@ -0,0 +1,57 @@ +package models + +type Response struct { + Error bool `json:"error,omitempty"` + Message string `json:"message,omitempty"` + Get []Get `json:"get,omitempty"` + Set []Set `json:"set,omitempty"` + Subscribe []Subscribe `json:"subscribe,omitempty"` + Unsubscribe []Subscribe `json:"unsubscribe,omitempty"` + Publish []Publish `json:"publish,omitempty"` +} + +func NewResponse() *Response { + return &Response{} +} + +func (r *Response) SendError(msg string) { + r.Error = true + r.Message = msg +} + +func (r *Response) AddGet(get Get) { + get.Query = nil + r.Get = append(r.Get, get) +} + +func (r *Response) AddSet(set Set) { + r.Set = append(r.Set, set) +} + +func (r *Response) AddSubscription(sub Subscribe) { + r.Subscribe = append(r.Subscribe, sub) +} + +func (r *Response) IsValid() bool { + return !r.Error +} + +func (r *Response) FetchGets() []Get { + return r.Get +} + +func (r *Response) FetchSets() []Set { + return r.Set +} + +func (r *Response) FetchSubscribes() []Subscribe { + return r.Subscribe +} + +func (r *Response) FetchUnubscribes() []Subscribe { + return r.Unsubscribe +} + +func (r *Response) FetchPublish() []Publish { + return r.Publish +} diff --git a/rights.go b/models/rights.go similarity index 77% rename from rights.go rename to models/rights.go index 043a69c..fcb550c 100644 --- a/rights.go +++ b/models/rights.go @@ -9,9 +9,7 @@ const ( ) func (r *Rights) GetRights() Rights { - if r == nil { - return ReadWrite - } else if *r == "" { + if *r == "" { return ReadWrite } return *r diff --git a/models/set.go b/models/set.go new file mode 100644 index 0000000..462c4c4 --- /dev/null +++ b/models/set.go @@ -0,0 +1,39 @@ +package models + +import "github.com/google/uuid" + +type Set struct { + Uuid uuid.UUID `json:"uuid,omitempty"` + Path string `json:"path"` + Driver *Driver `json:"driver,omitempty"` + Drivers *Drivers `json:"drivers,omitempty"` + Type Type `json:"type,omitempty"` + Value any `json:"value,omitempty"` + Rights Rights `json:"rights,omitempty"` + Updated bool `json:"-"` +} + +func (s *Set) ValueByPath(path string, value any) { + s.Path = path + s.Value = value +} + +func (s *Set) ValueByUuid(uid string, value any) { + s.Uuid = uuid.MustParse(uid) + s.Value = value +} + +func (s *Set) New(path string, typ Type, value any, rights Rights) { + s.Path = path + s.Type = typ + s.Value = value + s.Rights = rights.GetRights() +} + +func (s *Set) NewDriver(typ, bus string, address uint) { + s.Driver = &Driver{ + Type: typ, + Bus: bus, + Address: address, + } +} diff --git a/models/subscribe.go b/models/subscribe.go new file mode 100644 index 0000000..27fd969 --- /dev/null +++ b/models/subscribe.go @@ -0,0 +1,11 @@ +package models + +type Subscribe struct { + Path string `json:"path"` + Depth uint `json:"depth,omitempty"` + Drivers *Drivers `json:"drivers,omitempty"` + Driver string `json:"driver,omitempty"` + OnCreate bool `json:"onCreate,omitempty"` + OnDelete bool `json:"onDelete,omitempty"` + OnChange bool `json:"onChange,omitempty"` +} diff --git a/models/subscribtion.go b/models/subscribtion.go new file mode 100644 index 0000000..1753d6e --- /dev/null +++ b/models/subscribtion.go @@ -0,0 +1,13 @@ +package models + +//type Subscriptions map[string]*Subscription + +// type Subscription struct { +// OnCreate bool +// OnDelete bool +// OnChange bool +// } + +// func InitSubscribtion() Subscriptions { +// return make(Subscriptions) +// } diff --git a/type.go b/models/type.go similarity index 72% rename from type.go rename to models/type.go index 81f4171..594a1f8 100644 --- a/type.go +++ b/models/type.go @@ -2,9 +2,8 @@ package models import ( "fmt" - "math/rand" - "github.com/tecamino/tecamino-dbm/utils" + "github.com/tecamino/tecamino-dbm-json_data/utils" ) const ( @@ -66,37 +65,3 @@ func (t *Type) ConvertValue(v any) any { } return nil } - -func RandomType() Type { - n := rand.Intn(11) + 1 - - switch n { - case 1: - return "BIT" - case 2: - return "BYU" - case 3: - return "BYS" - case 4: - return "WOS" - case 5: - return "WOU" - case 6: - return "DWS" - case 7: - return "DWU" - case 8: - return "LOS" - case 9: - return "LOU" - case 10: - return "F32" - case 11: - return "F64" - case 12: - return "STRING" - default: - return "NONE" - } - -} diff --git a/port.go b/port.go deleted file mode 100644 index 5394e13..0000000 --- a/port.go +++ /dev/null @@ -1,6 +0,0 @@ -package models - -type Port struct { - Http uint - Https uint -} diff --git a/publish.go b/publish.go deleted file mode 100644 index af35d41..0000000 --- a/publish.go +++ /dev/null @@ -1,11 +0,0 @@ -package models - -import "github.com/google/uuid" - -type Publish struct { - Event string `json:"event,omitempty"` - Uuid uuid.UUID `json:"uuid,omitempty"` - Path string `json:"path,omitempty"` - Value any `json:"value,omitempty"` - Driver *Driver `json:"driver,omitempty"` -} diff --git a/request.go b/request.go new file mode 100644 index 0000000..fb05c00 --- /dev/null +++ b/request.go @@ -0,0 +1,7 @@ +package tecaminodbmjson_data + +import "github.com/tecamino/tecamino-dbm-json_data/models" + +func NewRequest() *models.Request { + return &models.Request{} +} diff --git a/response.go b/response.go new file mode 100644 index 0000000..d9eff38 --- /dev/null +++ b/response.go @@ -0,0 +1,17 @@ +package tecaminodbmjson_data + +import ( + "encoding/json" + + "github.com/tecamino/tecamino-dbm-json_data/models" +) + +func ParseResponse(b []byte) (*models.Response, error) { + r := models.Response{} + + err := json.Unmarshal(b, &r) + if err != nil { + return nil, err + } + return &r, nil +} diff --git a/set.go b/set.go deleted file mode 100644 index 0e4a2d1..0000000 --- a/set.go +++ /dev/null @@ -1,12 +0,0 @@ -package models - -type Set struct { - Path string `json:"path"` - Driver *Driver `json:"driver,omitempty"` - Drivers *Drivers `json:"drivers,omitempty"` - Type *Type `json:"type,omitempty"` - Value any `json:"value,omitempty"` - Rights *Rights `json:"rights,omitempty"` - Create bool `json:"create,omitempty"` - Updated bool `json:"-"` -} diff --git a/subscribe.go b/subscribe.go deleted file mode 100644 index 826f544..0000000 --- a/subscribe.go +++ /dev/null @@ -1,38 +0,0 @@ -package models - -type Subscribe struct { - Path string `json:"path"` - Depth *int `json:"depth,omitempty"` - Driver *string `json:"driver,omitempty"` - OnCreate *bool `json:"onCreate,omitempty"` - OnDelete *bool `json:"onDelete,omitempty"` - OnChange *bool `json:"onChange,omitempty"` -} - -func (s *Subscribe) GetDepth() int { - if s.Depth == nil { - return 0 - } - return *s.Depth -} - -func (s *Subscribe) GetOnCreate() bool { - if s.OnCreate == nil { - return false - } - return *s.OnCreate -} - -func (s *Subscribe) GetOnChange() bool { - if s.OnChange == nil { - return false - } - return *s.OnChange -} - -func (s *Subscribe) GetOnDelete() bool { - if s.OnDelete == nil { - return false - } - return *s.OnDelete -} diff --git a/subscribed.go b/subscribed.go deleted file mode 100644 index bcd7138..0000000 --- a/subscribed.go +++ /dev/null @@ -1,9 +0,0 @@ -package models - -import "github.com/google/uuid" - -type Subscribed struct { - Uuid uuid.UUID `json:"uuid"` - Path string `json:"path"` - Driver *Driver `json:"driver,omitempty"` -} diff --git a/subscribtion.go b/subscribtion.go deleted file mode 100644 index f8542e5..0000000 --- a/subscribtion.go +++ /dev/null @@ -1,13 +0,0 @@ -package models - -type Subscriptions map[string]*Subscription - -type Subscription struct { - OnCreate bool - OnDelete bool - OnChange bool -} - -func InitSubscribtion() Subscriptions { - return make(Subscriptions) -} diff --git a/utils/convert.go b/utils/convert.go new file mode 100644 index 0000000..4970f9a --- /dev/null +++ b/utils/convert.go @@ -0,0 +1,430 @@ +package utils + +import ( + "strconv" + "strings" +) + +func Float32From(v any) float32 { + switch val := v.(type) { + case bool: + if val { + return 1 + } + return 0 + case float32: + return val + case float64: + return float32(val) + case int: + return float32(val) + case int8: + return float32(val) + case int16: + return float32(val) + case int32: + return float32(val) + case int64: + return float32(val) + case uint8: + return float32(val) + case uint16: + return float32(val) + case uint32: + return float32(val) + case uint64: + return float32(val) + case string: + if i, err := strconv.Atoi(val); err == nil { + return float32(i) + } + return 0 + default: + return 0 + } +} + +func Float64From(v any) float64 { + switch val := v.(type) { + case bool: + if val { + return 1 + } + return 0 + case float32: + return float64(val) + case float64: + return val + case int: + return float64(val) + case int8: + return float64(val) + case int16: + return float64(val) + case int32: + return float64(val) + case int64: + return float64(val) + case uint8: + return float64(val) + case uint16: + return float64(val) + case uint32: + return float64(val) + case uint64: + return float64(val) + case string: + if i, err := strconv.Atoi(val); err == nil { + return float64(i) + } + return 0 + default: + return 0 + } +} + +func Int8From(v any) int8 { + switch val := v.(type) { + case bool: + if val { + return 1 + } + return 0 + case int: + return int8(val) + case int8: + return val + case int16: + return int8(val) + case int32: + return int8(val) + case int64: + return int8(val) + case uint8: + return int8(val) + case uint16: + return int8(val) + case uint32: + return int8(val) + case uint64: + return int8(val) + case float32: + return int8(val) + case float64: + return int8(val) + case string: + if i, err := strconv.Atoi(val); err == nil { + return int8(i) + } + return 0 + default: + return 0 + } +} + +func Int16From(v any) int16 { + switch val := v.(type) { + case bool: + if val { + return 1 + } + return 0 + case int: + return int16(val) + case int8: + return int16(val) + case int16: + return val + case int32: + return int16(val) + case int64: + return int16(val) + case uint8: + return int16(val) + case uint16: + return int16(val) + case uint32: + return int16(val) + case uint64: + return int16(val) + case float32: + return int16(val) + case float64: + return int16(val) + case string: + if i, err := strconv.Atoi(val); err == nil { + return int16(i) + } + return 0 + default: + return 0 + } +} + +func Int32From(v any) int32 { + switch val := v.(type) { + case bool: + if val { + return 1 + } + return 0 + case int: + return int32(val) + case int8: + return int32(val) + case int16: + return int32(val) + case int32: + return val + case int64: + return int32(val) + case uint8: + return int32(val) + case uint16: + return int32(val) + case uint32: + return int32(val) + case uint64: + return int32(val) + case float32: + return int32(val) + case float64: + return int32(val) + case string: + if i, err := strconv.Atoi(val); err == nil { + return int32(i) + } + return 0 + default: + return 0 + } +} + +func Int64From(v any) int64 { + switch val := v.(type) { + case bool: + if val { + return 1 + } + return 0 + case int: + return int64(val) + case int8: + return int64(val) + case int16: + return int64(val) + case int32: + return int64(val) + case int64: + return val + case uint8: + return int64(val) + case uint16: + return int64(val) + case uint32: + return int64(val) + case uint64: + return int64(val) + case float32: + return int64(val) + case float64: + return int64(val) + case string: + if i, err := strconv.Atoi(val); err == nil { + return int64(i) + } + return 0 + default: + return 0 + } +} + +func Uint8From(v any) uint8 { + switch val := v.(type) { + case bool: + if val { + return 1 + } + return 0 + case int: + return uint8(val) + case int8: + return uint8(val) + case int16: + return uint8(val) + case int32: + return uint8(val) + case int64: + return uint8(val) + case uint8: + return val + case uint16: + return uint8(val) + case uint32: + return uint8(val) + case uint64: + return uint8(val) + case float32: + return uint8(val) + case float64: + return uint8(val) + case string: + if i, err := strconv.Atoi(val); err == nil { + return uint8(i) + } + return 0 + default: + return 0 + } +} + +func Uint16From(v any) uint16 { + switch val := v.(type) { + case bool: + if val { + return 1 + } + return 0 + case int: + return uint16(val) + case int8: + return uint16(val) + case int16: + return uint16(val) + case int32: + return uint16(val) + case int64: + return uint16(val) + case uint8: + return uint16(val) + case uint16: + return val + case uint32: + return uint16(val) + case uint64: + return uint16(val) + case float32: + return uint16(val) + case float64: + return uint16(val) + case string: + if i, err := strconv.Atoi(val); err == nil { + return uint16(i) + } + return 0 + default: + return 0 + } +} + +func Uint32From(v any) uint32 { + switch val := v.(type) { + case bool: + if val { + return 1 + } + return 0 + case int: + return uint32(val) + case int8: + return uint32(val) + case int16: + return uint32(val) + case int32: + return uint32(val) + case int64: + return uint32(val) + case uint8: + return uint32(val) + case uint16: + return uint32(val) + case uint32: + return val + case uint64: + return uint32(val) + case float32: + return uint32(val) + case float64: + return uint32(val) + case string: + if i, err := strconv.Atoi(val); err == nil { + return uint32(i) + } + return 0 + default: + return 0 + } +} + +func Uint64From(v any) uint64 { + switch val := v.(type) { + case bool: + if val { + return 1 + } + return 0 + case int: + return uint64(val) + case int8: + return uint64(val) + case int16: + return uint64(val) + case int32: + return uint64(val) + case int64: + return uint64(val) + case uint8: + return uint64(val) + case uint16: + return uint64(val) + case uint32: + return uint64(val) + case uint64: + return val + case float32: + return uint64(val) + case float64: + return uint64(val) + case string: + if i, err := strconv.Atoi(val); err == nil { + return uint64(i) + } + return 0 + default: + return 0 + } +} + +func BoolFrom(v any) bool { + switch val := v.(type) { + case bool: + return val + case int: + return val > 0 + case int8: + return val > 0 + case int16: + return val > 0 + case int32: + return val > 0 + case int64: + return val > 0 + case uint8: + return val > 0 + case uint16: + return val > 0 + case uint32: + return val > 0 + case uint64: + return val > 0 + case float32: + return val >= 1 + case float64: + return val >= 1 + case string: + return strings.ToLower(val) == "false" || v == "0" + default: + return false + } + +}