1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-02-04 12:52:28 +08:00

publish lancet

This commit is contained in:
dudaodong
2021-11-28 21:28:23 +08:00
parent 37edb0fc8f
commit 3254591ab9
38 changed files with 5163 additions and 0 deletions

210
convertor/convertor.go Normal file
View File

@@ -0,0 +1,210 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package convertor implements some functions to convert data.
package convertor
import (
"bytes"
"encoding/gob"
"encoding/json"
"fmt"
"reflect"
"regexp"
"strconv"
"strings"
)
// ToBool convert string to a boolean
func ToBool(s string) (bool, error) {
return strconv.ParseBool(s)
}
// ToBool convert interface to bytes
func ToBytes(data interface{}) ([]byte, error) {
var buf bytes.Buffer
enc := gob.NewEncoder(&buf)
err := enc.Encode(data)
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// ToChar convert string to char slice
func ToChar(s string) []string {
c := make([]string, 0)
if len(s) == 0 {
c = append(c, "")
}
for _, v := range s {
c = append(c, string(v))
}
return c
}
// ToString convert value to string
func ToString(value interface{}) string {
var res string
if value == nil {
return res
}
switch v := value.(type) {
case float64:
res = strconv.FormatFloat(v, 'f', -1, 64)
case float32:
res = strconv.FormatFloat(float64(v), 'f', -1, 64)
case int:
res = strconv.Itoa(v)
case uint:
res = strconv.Itoa(int(v))
case int8:
res = strconv.Itoa(int(v))
case uint8:
res = strconv.Itoa(int(v))
case int16:
res = strconv.Itoa(int(v))
case uint16:
res = strconv.Itoa(int(v))
case int32:
res = strconv.Itoa(int(v))
case uint32:
res = strconv.Itoa(int(v))
case int64:
res = strconv.FormatInt(v, 10)
case uint64:
res = strconv.FormatUint(v, 10)
case string:
res = value.(string)
case []byte:
res = string(value.([]byte))
default:
newValue, _ := json.Marshal(value)
res = string(newValue)
}
return res
}
// ToJson convert value to a valid json string
func ToJson(value interface{}) (string, error) {
res, err := json.Marshal(value)
if err != nil {
res = []byte("")
}
return string(res), err
}
// ToFloat convert value to a float64, if input is not a float return 0.0 and error
func ToFloat(value interface{}) (float64, error) {
v := reflect.ValueOf(value)
res := 0.0
err := fmt.Errorf("ToInt: unvalid interface type %T", value)
switch value.(type) {
case int, int8, int16, int32, int64:
res = float64(v.Int())
return res, nil
case uint, uint8, uint16, uint32, uint64:
res = float64(v.Uint())
return res, nil
case float32, float64:
res = v.Float()
return res, nil
case string:
res, err = strconv.ParseFloat(v.String(), 64)
if err != nil {
res = 0.0
}
return res, err
default:
return res, err
}
}
// ToInt convert value to a int64, if input is not a numeric format return 0 and error
func ToInt(value interface{}) (int64, error) {
v := reflect.ValueOf(value)
var res int64
err := fmt.Errorf("ToInt: invalid interface type %T", value)
switch value.(type) {
case int, int8, int16, int32, int64:
res = v.Int()
return res, nil
case uint, uint8, uint16, uint32, uint64:
res = int64(v.Uint())
return res, nil
case float32, float64:
res = int64(v.Float())
return res, nil
case string:
res, err = strconv.ParseInt(v.String(), 0, 64)
if err != nil {
res = 0
}
return res, err
default:
return res, err
}
}
// StructToMap convert struct to map, only convert exported struct field
// map key is specified same as struct field tag `json` value
func StructToMap(value interface{}) (map[string]interface{}, error) {
v := reflect.ValueOf(value)
t := reflect.TypeOf(value)
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
if t.Kind() != reflect.Struct {
return nil, fmt.Errorf("data type %T not support, shuld be struct or pointer to struct", value)
}
res := make(map[string]interface{})
fieldNum := t.NumField()
pattern := `^[A-Z]`
regex := regexp.MustCompile(pattern)
for i := 0; i < fieldNum; i++ {
name := t.Field(i).Name
tag := t.Field(i).Tag.Get("json")
if regex.MatchString(name) && tag != "" {
//res[name] = v.Field(i).Interface()
res[tag] = v.Field(i).Interface()
}
}
return res, nil
}
// ColorHexToRGB convert hex color to rgb color
func ColorHexToRGB(colorHex string) (red, green, blue int) {
colorHex = strings.TrimPrefix(colorHex, "#")
color64, err := strconv.ParseInt(colorHex, 16, 32)
if err != nil {
return
}
color := int(color64)
return color >> 16, (color & 0x00FF00) >> 8, color & 0x0000FF
}
// ColorRGBToHex convert rgb color to hex color
func ColorRGBToHex(red, green, blue int) string {
r := strconv.FormatInt(int64(red), 16)
g := strconv.FormatInt(int64(green), 16)
b := strconv.FormatInt(int64(blue), 16)
if len(r) == 1 {
r = "0" + r
}
if len(g) == 1 {
g = "0" + g
}
if len(b) == 1 {
b = "0" + b
}
return "#" + r + g + b
}

210
convertor/convertor_test.go Normal file
View File

@@ -0,0 +1,210 @@
package convertor
import (
"fmt"
"github.com/duke-git/lancet/utils"
"reflect"
"testing"
)
func TestToChar(t *testing.T) {
cases := []string{"", "abc", "1 2#3"}
expected := [][]string{
{""},
{"a", "b", "c"},
{"1", " ", "2", "#", "3"},
}
for i := 0; i < len(cases); i++ {
res := ToChar(cases[i])
if !reflect.DeepEqual(res, expected[i]) {
utils.LogFailedTestInfo(t, "ToChar", cases[i], expected[i], res)
t.FailNow()
}
}
}
func TestToBool(t *testing.T) {
cases := []string{"true", "True", "false", "False", "0", "1", "123"}
expected := []bool{true, true, false, false, false, true, false}
for i := 0; i < len(cases); i++ {
res, _ := ToBool(cases[i])
if res != expected[i] {
utils.LogFailedTestInfo(t, "ToBool", cases[i], expected[i], res)
t.FailNow()
}
}
}
func TestToBytes(t *testing.T) {
cases := []interface{}{
0,
false,
"1",
}
expected := [][]byte{
{3, 4, 0, 0},
{3, 2, 0, 0},
{4, 12, 0, 1, 49},
}
for i := 0; i < len(cases); i++ {
res, _ := ToBytes(cases[i])
fmt.Println(res)
if !reflect.DeepEqual(res, expected[i]) {
utils.LogFailedTestInfo(t, "ToBytes", cases[i], expected[i], res)
t.FailNow()
}
}
}
func TestToInt(t *testing.T) {
cases := []interface{}{"123", "-123", 123, "abc", false, "111111111111111111111111111111111111111"}
expected := []int64{123, -123, 123, 0, 0, 0}
for i := 0; i < len(cases); i++ {
res, _ := ToInt(cases[i])
if res != expected[i] {
utils.LogFailedTestInfo(t, "ToInt", cases[i], expected[i], res)
t.FailNow()
}
}
}
func TestToFloat(t *testing.T) {
cases := []interface{}{"", "-1", "-.11", "1.23e3", ".123e10", "abc"}
expected := []float64{0, -1, -0.11, 1230, 0.123e10, 0}
for i := 0; i < len(cases); i++ {
res, _ := ToFloat(cases[i])
if res != expected[i] {
utils.LogFailedTestInfo(t, "ToFloat", cases[i], expected[i], res)
t.FailNow()
}
}
}
func TestToString(t *testing.T) {
// basic type
toString(t, "a1", "a1")
toString(t, 111, "111")
toString(t, 111.01, "111.01")
toString(t, true, "true")
//toString(t, 1.5+10i, "(1.5+10i)")
// slice
aSlice := []int{1, 2, 3}
toString(t, aSlice, "[1,2,3]")
// map
aMap := make(map[string]int)
aMap["a"] = 1
aMap["b"] = 2
aMap["c"] = 3
toString(t, aMap, "{\"a\":1,\"b\":2,\"c\":3}")
// struct
type TestStruct struct {
Name string
}
aStruct := TestStruct{Name: "TestStruct"}
toString(t, aStruct, "{\"Name\":\"TestStruct\"}")
}
func toString(t *testing.T, test interface{}, expected string) {
res := ToString(test)
if res != expected {
utils.LogFailedTestInfo(t, "ToString", test, expected, res)
t.FailNow()
}
}
func TestToJson(t *testing.T) {
// map
aMap := make(map[string]int)
aMap["a"] = 1
aMap["b"] = 2
aMap["c"] = 3
mapJson := "{\"a\":1,\"b\":2,\"c\":3}"
r1, _ := ToJson(aMap)
if r1 != mapJson {
utils.LogFailedTestInfo(t, "ToJson", aMap, mapJson, r1)
t.FailNow()
}
// struct
type TestStruct struct {
Name string
}
aStruct := TestStruct{Name: "TestStruct"}
structJson := "{\"Name\":\"TestStruct\"}"
r2, _ := ToJson(aStruct)
if r2 != structJson {
utils.LogFailedTestInfo(t, "ToJson", aMap, mapJson, r1)
t.FailNow()
}
}
func TestStructToMap(t *testing.T) {
type People struct {
Name string `json:"name"`
age int
}
p1 := People{
"test",
100,
}
pm1, _ := StructToMap(p1)
m1 := make(map[string]interface{})
m1["name"] = "test"
//exp1["100"] = 100
if !reflect.DeepEqual(pm1, m1) {
utils.LogFailedTestInfo(t, "StructToMap", p1, m1, pm1)
t.FailNow()
}
p2 := People{
"test",
100,
}
pm2, _ := StructToMap(p1)
m2 := make(map[string]interface{})
m2["name"] = "test"
m2["100"] = 100
if reflect.DeepEqual(pm2, m2) {
utils.LogFailedTestInfo(t, "StructToMap", p2, m2, pm2)
t.FailNow()
}
}
func TestColorHexToRGB(t *testing.T) {
colorHex := "#003366"
r, g, b := ColorHexToRGB(colorHex)
colorRGB := fmt.Sprintf("%d,%d,%d", r, g, b)
expected := "0,51,102"
if colorRGB != expected {
utils.LogFailedTestInfo(t, "ColorHexToRGB", colorHex, expected, colorRGB)
t.FailNow()
}
}
func TestColorRGBToHex(t *testing.T) {
r := 0
g := 51
b := 102
colorRGB := fmt.Sprintf("%d,%d,%d", r, g, b)
colorHex := ColorRGBToHex(r, g, b)
expected := "#003366"
if colorHex != expected {
utils.LogFailedTestInfo(t, "ColorHexToRGB", colorRGB, expected, colorHex)
t.FailNow()
}
}