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  }