github.com/bookerzzz/grok@v0.0.0/value.go (about) 1 package grok 2 3 import ( 4 "reflect" 5 "fmt" 6 "sort" 7 "sync" 8 ) 9 10 type Values []reflect.Value 11 12 // Len implements sort.Interface 13 func (s Values) Len() int { 14 return len(s) 15 } 16 17 // Swap implements sort.Interface 18 func (s Values) Swap(i, j int) { 19 s[i], s[j] = s[j], s[i] 20 } 21 22 // Less implements sort.Interface 23 func (s Values) Less(i, j int) bool { 24 return fmt.Sprintf("%v", s[i]) < fmt.Sprintf("%v", s[j]) 25 } 26 27 var ( 28 dumpMutex = sync.Mutex{} 29 ) 30 31 // V aliases Value 32 func V(value interface{}, options ...Option) { 33 Value(value, options...) 34 } 35 36 // Value prints a more human readable representation of any value 37 func Value(value interface{}, options ...Option) { 38 c := defaults 39 for _, o := range options { 40 o(&c) 41 } 42 43 // only dump one value at a time to avoid overlap 44 dumpMutex.Lock() 45 defer dumpMutex.Unlock() 46 47 // dump it like you mean it 48 dump("value", reflect.ValueOf(value), c) 49 } 50 51 func dump(name string, v reflect.Value, c Conf) { 52 out := outer(c) 53 colour := colourer(c) 54 55 if !v.IsValid() { 56 out(indent(c) + "<invalid>\n") 57 return 58 } 59 t := v.Type() 60 61 tn := "" 62 switch t.Kind() { 63 case reflect.Interface: 64 name := t.Name() 65 tn = colour("interface{}", colourBlue) + colour(name, colourBlue) 66 if !v.IsNil() { 67 v = v.Elem() 68 t = v.Type() 69 } 70 if t.Kind() == reflect.Ptr { 71 v = v.Elem() 72 t = v.Type() 73 } 74 if t.Name() != name { 75 tn = colour(t.Name(), colourBlue) + colour(" as ", colourRed) + tn 76 } 77 case reflect.Ptr: 78 v = v.Elem() 79 t = t.Elem() 80 tn = colour("*", colourRed) + colour(t.Name(), colourBlue) 81 case reflect.Slice: 82 tn = colour("[]", colourRed) 83 switch t.Elem().Kind() { 84 case reflect.Interface: 85 tn = tn + colour(t.Elem().Name(), colourBlue) 86 case reflect.Ptr: 87 tn = tn + colour("*", colourRed) 88 tn = tn + colour(t.Elem().Elem().Name(), colourBlue) 89 default: 90 tn = tn + colour(t.Elem().Name(), colourBlue) 91 } 92 case reflect.Map: 93 tn = colour("map[", colourRed) 94 switch t.Key().Kind() { 95 case reflect.Interface: 96 tn = tn + colour(t.Key().Name(), colourBlue) 97 case reflect.Ptr: 98 tn = tn + colour("*", colourRed) 99 tn = tn + colour(t.Key().Elem().Name(), colourBlue) 100 default: 101 tn = tn + colour(t.Key().Name(), colourBlue) 102 } 103 tn = tn + colour("]", colourRed) 104 switch t.Elem().Kind() { 105 case reflect.Interface: 106 tn = tn + colour("interface{}", colourBlue) 107 case reflect.Ptr: 108 tn = tn + colour("*", colourRed) 109 tn = tn + colour(t.Elem().Elem().Name(), colourBlue) 110 default: 111 tn = tn + colour(t.Elem().Name(), colourBlue) 112 } 113 case reflect.Chan: 114 tn = colour(t.ChanDir().String(), colourRed) 115 tn = tn + " " + colour(t.Elem().Name(), colourBlue) 116 case reflect.Func: 117 tn = colour("func", colourRed) 118 case reflect.UnsafePointer: 119 tn = colour("unsafe*", colourRed) + colour(t.Name(), colourBlue) 120 default: 121 tn = colour(t.Name(), colourBlue) 122 } 123 124 if len(name) > 0 { 125 out(indent(c) + "%s %s = ", colour(name, colourYellow), tn) 126 } else { 127 out(indent(c)) 128 } 129 130 switch v.Kind() { 131 case reflect.Bool: 132 out(colour("%v", colourGreen), v.Bool()) 133 case reflect.Uintptr: 134 fallthrough 135 case reflect.Int: 136 fallthrough 137 case reflect.Int8: 138 fallthrough 139 case reflect.Int16: 140 fallthrough 141 case reflect.Int32: 142 fallthrough 143 case reflect.Int64: 144 fallthrough 145 case reflect.Uint: 146 fallthrough 147 case reflect.Uint8: 148 fallthrough 149 case reflect.Uint16: 150 fallthrough 151 case reflect.Uint32: 152 fallthrough 153 case reflect.Uint64: 154 fallthrough 155 case reflect.Float32: 156 fallthrough 157 case reflect.Float64: 158 fallthrough 159 case reflect.Complex64: 160 fallthrough 161 case reflect.Complex128: 162 out(colour("%v", colourGreen), v) 163 case reflect.Array: 164 fallthrough 165 case reflect.Slice: 166 if v.Len() == 0 { 167 out("[]\n") 168 return 169 } 170 out("[\n") 171 c.depth = c.depth + 1 172 if c.maxDepth > 0 && c.depth >= c.maxDepth { 173 out(indent(c) + colour("... max depth reached\n", colourGrey)) 174 } else { 175 for i := 0; i < v.Len(); i++ { 176 dump(colour(fmt.Sprintf("%d", i), colourRed), v.Index(i), c) 177 } 178 } 179 c.depth = c.depth - 1 180 out(indent(c) + "]") 181 case reflect.Chan: 182 if v.IsNil() { 183 out(colour("<nil>", colourGrey)) 184 } else { 185 out(colour("%v", colourGreen), v) 186 } 187 case reflect.Func: 188 if v.IsNil() { 189 out(colour("<nil>", colourGrey)) 190 } else { 191 out(colour("%v", colourGreen), v) 192 } 193 case reflect.Map: 194 if !v.IsValid() { 195 out(colour("<nil>", colourGrey)) 196 } else { 197 if v.Len() == 0 { 198 out("[]\n") 199 return 200 } 201 out("[\n") 202 c.depth = c.depth + 1 203 if c.maxDepth > 0 && c.depth >= c.maxDepth { 204 out(indent(c) + colour("... max depth reached\n", colourGrey)) 205 } else { 206 keys := v.MapKeys(); 207 sort.Sort(Values(keys)) 208 for _, k := range v.MapKeys() { 209 dump(fmt.Sprintf("%v", k), v.MapIndex(k), c) 210 } 211 } 212 c.depth = c.depth - 1 213 out(indent(c) + "]") 214 } 215 case reflect.String: 216 s := v.String() 217 slen := len(s) 218 if c.maxLength > 0 && slen > c.maxLength { 219 s = fmt.Sprintf("%s...", string([]byte(s)[0:c.maxLength])) 220 } 221 out(colour("%q ", colourGreen), s) 222 out(colour("%d", colourGrey), slen) 223 case reflect.Struct: 224 if v.NumField() == 0 { 225 out("{}\n") 226 return 227 } 228 out("{\n") 229 c.depth = c.depth + 1 230 if c.maxDepth > 0 && c.depth >= c.maxDepth { 231 out(indent(c) + colour("... max depth reached\n", colourGrey)) 232 } else { 233 for i := 0; i < v.NumField(); i++ { 234 dump(t.Field(i).Name, v.Field(i), c) 235 } 236 } 237 c.depth = c.depth - 1 238 out(indent(c) + "}") 239 case reflect.UnsafePointer: 240 out(colour("%v", colourGreen), v) 241 case reflect.Invalid: 242 out(colour("<nil>", colourGrey)) 243 case reflect.Interface: 244 if v.IsNil() { 245 out(colour("<nil>", colourGrey)) 246 } else { 247 out(colour("%v", colourGreen), v) 248 } 249 default: 250 out(colour("??? %s", colourRed), v.Kind().String()) 251 } 252 out("\n") 253 }