From 559d57776bdcb4b0e55ea639b2682f2cdc4096e1 Mon Sep 17 00:00:00 2001 From: spf13 Date: Sat, 5 Apr 2014 15:18:23 -0400 Subject: [PATCH] Writing the README. Handling a few more cases, adding more tests. --- README.md | 70 +++++++++++++++++++++++- cast_test.go | 10 ++++ caste.go | 151 ++++++++++++++++++++++++++------------------------- 3 files changed, 157 insertions(+), 74 deletions(-) diff --git a/README.md b/README.md index 7ba7be9..e35f373 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,72 @@ cast ==== -easy casting from one type to another in Go +Easy and safe casting from one type to another in Go + +Don’t Panic! ... Cast + +## What is Cast? + +Cast is a library to convert between different go types in a consistent and easy way. + +Cast provides simple functions to easily convert a number to a string, an +interface into a bool, etc. Cast does this intelligently when an obvious +conversion is possible. It doesn’t make any attempts to guess what you meant, +for example you can only convert a string to an int when it is a string +representation of an int such as “8”. Cast was developed for use in +[Hugo](http://hugo.spf13.com), a website engine which uses YAML, TOML or JSON +for meta data. + +## Why use Cast? + +When working with dynamic data in Go you often need to cast or convert the data +from one type into another. Cast goes beyond just using type assertion (though +it uses that when possible) to provide a very straightforward and convenient +library. + +If you are working with interfaces to handle things like dynamic content +you’ll need an easy way to convert an interface into a given type. This +is the library for you. + +If you are taking in data from YAML, TOML or JSON or other formats which lack +full types, then Cast is the library for you. + +## Usage + +Cast provides a handful of To_____ methods. These methods will always return +the desired type. **If input is provided that will not convert to that type, the +0 or nil value for that type will be returned**. + +Cast also provides identical methods To_____E. These return the same result as +the To_____ methods, plus an additional bool which tells you if it successfully +converted. Using these methods you can tell the difference between when the +input matched the zero value or when the conversion failed and the zero value +was returned. + +The following examples are merely a sample of what is available. Please review +the code for a complete set. + +### Example ‘ToString’: + + cast.ToString("mayonegg") // "mayonegg" + cast.ToString(8) // "8" + cast.ToString(8.31) // "8.31" + cast.ToString([]byte("one time")) // "one time" + cast.ToString(nil) // "" + + var foo interface{} = "one more time" + cast.ToString(foo) // "one more time" + + +### Example ‘ToInt’: + + cast.ToInt(8) // 8 + cast.ToInt(8.31) // 8 + cast.ToInt("8") // 8 + cast.ToInt(true) // 1 + cast.ToInt(false) // 0 + + var eight interface{} = 8 + cast.ToInt(eight) // 8 + cast.ToInt(nil) // 0 + diff --git a/cast_test.go b/cast_test.go index 5a6dc3d..c9f642c 100644 --- a/cast_test.go +++ b/cast_test.go @@ -14,12 +14,22 @@ import ( func TestToInt(t *testing.T) { var eight interface{} = 8 assert.Equal(t, ToInt(8), 8) + assert.Equal(t, ToInt(8.31), 8) assert.Equal(t, ToInt("8"), 8) assert.Equal(t, ToInt(true), 1) assert.Equal(t, ToInt(false), 0) assert.Equal(t, ToInt(eight), 8) } +func TestToString(t *testing.T) { + var foo interface{} = "one more time" + assert.Equal(t, ToString(8), "8") + assert.Equal(t, ToString(8.12), "8.12") + assert.Equal(t, ToString([]byte("one time")), "one time") + assert.Equal(t, ToString(foo), "one more time") + assert.Equal(t, ToString(nil), "") +} + func TestMaps(t *testing.T) { var taxonomies = map[interface{}]interface{}{"tag": "tags", "group": "groups"} assert.Equal(t, ToStringMap(taxonomies), map[string]interface{}{"tag": "tags", "group": "groups"}) diff --git a/caste.go b/caste.go index 49025fc..80be149 100644 --- a/caste.go +++ b/caste.go @@ -53,6 +53,84 @@ func ToBoolE(i interface{}) (bool, bool) { return false, false } +func ToFloat64E(i interface{}) (float64, bool) { + switch s := i.(type) { + case float64: + return s, true + case float32: + return float64(s), true + case string: + v, err := strconv.ParseFloat(s, 64) + if err == nil { + return float64(v), true + } else { + jww.ERROR.Printf("Unable to Cast %#v to float", i) + jww.ERROR.Println(err) + } + + default: + jww.ERROR.Printf("Unable to Cast %#v to float", i) + } + + return 0.0, false +} + +func ToIntE(i interface{}) (int, bool) { + switch s := i.(type) { + case int: + return s, true + case int64: + return int(s), true + case int32: + return int(s), true + case int16: + return int(s), true + case int8: + return int(s), true + case string: + v, err := strconv.ParseInt(s, 0, 0) + if err == nil { + return int(v), true + } else { + jww.ERROR.Printf("Unable to Cast %#v to int", i) + jww.ERROR.Println(err) + } + case float64: + return int(s), true + case bool: + if bool(s) { + return 1, true + } else { + return 0, true + } + case nil: + return 0, true + default: + jww.ERROR.Printf("Unable to Cast %#v to int", i) + } + + return 0, false +} + +func ToStringE(i interface{}) (string, bool) { + switch s := i.(type) { + case string: + return s, true + case float64: + return strconv.FormatFloat(i.(float64), 'f', -1, 64), true + case int: + return strconv.FormatInt(int64(i.(int)), 10), true + case []byte: + return string(s), true + case nil: + return "", true + default: + jww.ERROR.Printf("Unable to Cast %#v to string", i) + } + + return "", false +} + func ToStringMapStringE(i interface{}) (map[string]string, bool) { var m = map[string]string{} @@ -98,79 +176,6 @@ func ToStringSliceE(i interface{}) ([]string, bool) { return a, true } -func ToFloat64E(i interface{}) (float64, bool) { - switch s := i.(type) { - case float64: - return s, true - case float32: - return float64(s), true - - case string: - v, err := strconv.ParseFloat(s, 64) - if err == nil { - return float64(v), true - } else { - jww.ERROR.Printf("Unable to Cast %#v to float", i) - jww.ERROR.Println(err) - } - - default: - jww.ERROR.Printf("Unable to Cast %#v to float", i) - } - - return 0.0, false -} - -func ToIntE(i interface{}) (int, bool) { - switch s := i.(type) { - case int: - return s, true - case int64: - return int(s), true - case int32: - return int(s), true - case int16: - return int(s), true - case int8: - return int(s), true - case string: - v, err := strconv.ParseInt(s, 0, 0) - if err == nil { - return int(v), true - } else { - jww.ERROR.Printf("Unable to Cast %#v to int", i) - jww.ERROR.Println(err) - } - case bool: - if bool(s) { - return 1, true - } else { - return 0, true - } - default: - jww.ERROR.Printf("Unable to Cast %#v to int", i) - } - - return 0, false -} - -func ToStringE(i interface{}) (string, bool) { - switch s := i.(type) { - case string: - return s, true - case float64: - return strconv.FormatFloat(i.(float64), 'f', -1, 64), true - case int: - return strconv.FormatInt(int64(i.(int)), 10), true - case nil: - return "", true - default: - jww.ERROR.Printf("Unable to Cast %#v to string", i) - } - - return "", false -} - func StringToDate(s string) (time.Time, error) { return parseDateWith(s, []string{ time.RFC3339,