github.com/insolar/vanilla@v0.0.0-20201023172447-248fdf805322/reflectkit/structtag_parser.go (about) 1 // Copyright 2020 Insolar Network Ltd. 2 // All rights reserved. 3 // This material is licensed under the Insolar License version 1.0, 4 // available at https://github.com/insolar/assured-ledger/blob/master/LICENSE.md. 5 6 package reflectkit 7 8 import ( 9 "reflect" 10 "strconv" 11 ) 12 13 func ParseStructTag(tag reflect.StructTag, findFn func(name, qvalue string) bool) (string, string, bool) { 14 for tag != "" { 15 // Skip leading space. 16 i := 0 17 for i < len(tag) && tag[i] == ' ' { 18 i++ 19 } 20 tag = tag[i:] 21 if tag == "" { 22 break 23 } 24 25 // Scan to colon. A space, a quote or a control character is a syntax error. 26 // Strictly speaking, control chars include the range [0x7f, 0x9f], not just 27 // [0x00, 0x1f], but in practice, we ignore the multi-byte control characters 28 // as it is simpler to inspect the tag's bytes than the tag's runes. 29 i = 0 30 for i < len(tag) && tag[i] > ' ' && tag[i] != ':' && tag[i] != '"' && tag[i] != 0x7f { 31 i++ 32 } 33 if i == 0 || i+1 >= len(tag) || tag[i] != ':' || tag[i+1] != '"' { 34 break 35 } 36 name := string(tag[:i]) 37 tag = tag[i+1:] 38 39 // Scan quoted string to find value. 40 i = 1 41 for i < len(tag) && tag[i] != '"' { 42 if tag[i] == '\\' { 43 i++ 44 } 45 i++ 46 } 47 if i >= len(tag) { 48 break 49 } 50 qvalue := string(tag[:i+1]) 51 tag = tag[i+1:] 52 53 if findFn(name, qvalue) { 54 if value, err := strconv.Unquote(qvalue); err == nil { 55 return name, value, true 56 } 57 break 58 } 59 } 60 return "", "", false 61 }