github.com/robotn/xgb@v0.0.0-20190912153532-2cb92d044934/xgbgen/xml_fields.go (about) 1 package main 2 3 import ( 4 "encoding/xml" 5 "log" 6 ) 7 8 type XMLField struct { 9 XMLName xml.Name 10 11 // For 'pad' element 12 Bytes uint `xml:"bytes,attr"` 13 14 // For 'field', 'list', 'localfield', 'exprfield' and 'switch' elements. 15 Name string `xml:"name,attr"` 16 17 // For 'field', 'list', 'localfield', and 'exprfield' elements. 18 Type string `xml:"type,attr"` 19 20 // For 'list', 'exprfield' and 'switch' elements. 21 Expr *XMLExpression `xml:",any"` 22 23 // For 'valueparm' element. 24 ValueMaskType string `xml:"value-mask-type,attr"` 25 ValueMaskName string `xml:"value-mask-name,attr"` 26 ValueListName string `xml:"value-list-name,attr"` 27 28 // For 'switch' element. 29 Bitcases []*XMLBitcase `xml:"bitcase"` 30 31 // I don't know which elements these are for. The documentation is vague. 32 // They also seem to be completely optional. 33 OptEnum string `xml:"enum,attr"` 34 OptMask string `xml:"mask,attr"` 35 OptAltEnum string `xml:"altenum,attr"` 36 } 37 38 // Bitcase represents a single expression followed by any number of fields. 39 // Namely, if the switch's expression (all bitcases are inside a switch), 40 // and'd with the bitcase's expression is equal to the bitcase expression, 41 // then the fields should be included in its parent structure. 42 // Note that since a bitcase is unique in that expressions and fields are 43 // siblings, we must exhaustively search for one of them. Essentially, 44 // it's the closest thing to a Union I can get to in Go without interfaces. 45 // Would an '<expression>' tag have been too much to ask? :-( 46 type XMLBitcase struct { 47 Fields []*XMLField `xml:",any"` 48 49 // All the different expressions. 50 // When it comes time to choose one, use the 'Expr' method. 51 ExprOp *XMLExpression `xml:"op"` 52 ExprUnOp *XMLExpression `xml:"unop"` 53 ExprField *XMLExpression `xml:"fieldref"` 54 ExprValue *XMLExpression `xml:"value"` 55 ExprBit *XMLExpression `xml:"bit"` 56 ExprEnum *XMLExpression `xml:"enumref"` 57 ExprSum *XMLExpression `xml:"sumof"` 58 ExprPop *XMLExpression `xml:"popcount"` 59 } 60 61 // Expr chooses the only non-nil Expr* field from Bitcase. 62 // Panic if there is more than one non-nil expression. 63 func (b *XMLBitcase) Expr() *XMLExpression { 64 choices := []*XMLExpression{ 65 b.ExprOp, b.ExprUnOp, b.ExprField, b.ExprValue, 66 b.ExprBit, b.ExprEnum, b.ExprSum, b.ExprPop, 67 } 68 69 var choice *XMLExpression = nil 70 numNonNil := 0 71 for _, c := range choices { 72 if c != nil { 73 numNonNil++ 74 choice = c 75 } 76 } 77 78 if choice == nil { 79 log.Panicf("No top level expression found in a bitcase.") 80 } 81 if numNonNil > 1 { 82 log.Panicf("More than one top-level expression was found in a bitcase.") 83 } 84 return choice 85 }