package pgproto3

import (
	
	
	

	
)

type DataRow struct {
	Values [][]byte
}

// Backend identifies this message as sendable by the PostgreSQL backend.
func (*DataRow) () {}

// Decode decodes src into dst. src must contain the complete message with the exception of the initial 1 byte message
// type identifier and 4 byte message length.
func ( *DataRow) ( []byte) error {
	if len() < 2 {
		return &invalidMessageFormatErr{messageType: "DataRow"}
	}
	 := 0
	 := int(binary.BigEndian.Uint16([:]))
	 += 2

	// If the capacity of the values slice is too small OR substantially too
	// large reallocate. This is too avoid one row with many columns from
	// permanently allocating memory.
	if cap(.Values) <  || cap(.Values)- > 32 {
		 := 32
		if  <  {
			 = 
		}
		.Values = make([][]byte, , )
	} else {
		.Values = .Values[:]
	}

	for  := 0;  < ; ++ {
		if len([:]) < 4 {
			return &invalidMessageFormatErr{messageType: "DataRow"}
		}

		 := int(int32(binary.BigEndian.Uint32([:])))
		 += 4

		// null
		if  == -1 {
			.Values[] = nil
		} else {
			if len([:]) <  ||  < 0 {
				return &invalidMessageFormatErr{messageType: "DataRow"}
			}

			.Values[] = [ : + : +]
			 += 
		}
	}

	return nil
}

// Encode encodes src into dst. dst will include the 1 byte message type identifier and the 4 byte message length.
func ( *DataRow) ( []byte) []byte {
	 = append(, 'D')
	 := len()
	 = pgio.AppendInt32(, -1)

	 = pgio.AppendUint16(, uint16(len(.Values)))
	for ,  := range .Values {
		if  == nil {
			 = pgio.AppendInt32(, -1)
			continue
		}

		 = pgio.AppendInt32(, int32(len()))
		 = append(, ...)
	}

	pgio.SetInt32([:], int32(len([:])))

	return 
}

// MarshalJSON implements encoding/json.Marshaler.
func ( DataRow) () ([]byte, error) {
	 := make([]map[string]string, len(.Values))
	for ,  := range .Values {
		if  == nil {
			continue
		}

		var  bool
		for ,  := range  {
			if  < 32 {
				 = true
				break
			}
		}

		if  {
			[] = map[string]string{"binary": hex.EncodeToString()}
		} else {
			[] = map[string]string{"text": string()}
		}
	}

	return json.Marshal(struct {
		   string
		 []map[string]string
	}{
		:   "DataRow",
		: ,
	})
}

// UnmarshalJSON implements encoding/json.Unmarshaler.
func ( *DataRow) ( []byte) error {
	// Ignore null, like in the main JSON package.
	if string() == "null" {
		return nil
	}

	var  struct {
		 []map[string]string
	}
	if  := json.Unmarshal(, &);  != nil {
		return 
	}

	.Values = make([][]byte, len(.))
	for ,  := range . {
		var  error
		.Values[],  = getValueFromJSON()
		if  != nil {
			return 
		}
	}
	return nil
}