github.com/lulzWill/go-agent@v2.1.2+incompatible/internal/cat/txndata.go (about) 1 package cat 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "errors" 7 8 "github.com/lulzWill/go-agent/internal/jsonx" 9 ) 10 11 // TxnDataHeader represents a decoded TxnData header. 12 type TxnDataHeader struct { 13 GUID string 14 TripID string 15 PathHash string 16 } 17 18 var ( 19 errInvalidTxnDataJSON = errors.New("invalid transaction data JSON") 20 errInvalidTxnDataGUID = errors.New("GUID is not a string") 21 errInvalidTxnDataTripID = errors.New("trip ID is not a string or null") 22 errInvalidTxnDataPathHash = errors.New("path hash is not a string or null") 23 ) 24 25 // MarshalJSON marshalls a TxnDataHeader as raw JSON. 26 func (txnData *TxnDataHeader) MarshalJSON() ([]byte, error) { 27 // Note that, although there are two and four element versions of this header 28 // in the wild, we will only ever generate the four element version. 29 30 buf := bytes.NewBufferString("[") 31 32 jsonx.AppendString(buf, txnData.GUID) 33 34 // Write the unused second field. 35 buf.WriteString(",false,") 36 jsonx.AppendString(buf, txnData.TripID) 37 38 buf.WriteString(",") 39 jsonx.AppendString(buf, txnData.PathHash) 40 41 buf.WriteString("]") 42 43 return buf.Bytes(), nil 44 } 45 46 // UnmarshalJSON unmarshalls a TxnDataHeader from raw JSON. 47 func (txnData *TxnDataHeader) UnmarshalJSON(data []byte) error { 48 var ok bool 49 var v interface{} 50 51 if err := json.Unmarshal(data, &v); err != nil { 52 return err 53 } 54 55 arr, ok := v.([]interface{}) 56 if !ok { 57 return errInvalidTxnDataJSON 58 } 59 if len(arr) < 2 { 60 return errUnexpectedArraySize{ 61 label: "unexpected number of transaction data elements", 62 expected: 2, 63 actual: len(arr), 64 } 65 } 66 67 if txnData.GUID, ok = arr[0].(string); !ok { 68 return errInvalidTxnDataGUID 69 } 70 71 // Ignore the unused second field. 72 73 // Set up defaults for the optional values. 74 txnData.TripID = "" 75 txnData.PathHash = "" 76 77 if len(arr) >= 3 { 78 // Per the cross agent tests, an explicit null is valid here. 79 if nil != arr[2] { 80 if txnData.TripID, ok = arr[2].(string); !ok { 81 return errInvalidTxnDataTripID 82 } 83 } 84 85 if len(arr) >= 4 { 86 // Per the cross agent tests, an explicit null is also valid here. 87 if nil != arr[3] { 88 if txnData.PathHash, ok = arr[3].(string); !ok { 89 return errInvalidTxnDataPathHash 90 } 91 } 92 } 93 } 94 95 return nil 96 }