package relayproto

import 

// Datagrams is one or multiple datagrams transferred via the relay, modeled
// after the QUIC transmit structure.
type Datagrams struct {
	// Ecn is the explicit congestion notification codepoint, or 0 for Not-ECT.
	Ecn EcnCodepoint
	// SegmentSize is the per-datagram segment size when this transmit carries
	// multiple datagrams (a batch); 0 means a single datagram.
	SegmentSize uint16
	// Contents holds the datagram bytes.
	Contents []byte
}

// DatagramsFromBytes wraps b as a single (non-batch) datagram.
func ( []byte) Datagrams {
	return Datagrams{Contents: bytes.Clone()}
}

// isBatch reports whether the datagram is a batch (has a segment size).
func ( Datagrams) () bool { return .SegmentSize != 0 }

// appendTo appends the wire encoding of d (ECN byte, optional segment size,
// then contents) to dst.
func ( Datagrams) ( []byte) []byte {
	 = append(, byte(.Ecn))
	if .SegmentSize != 0 {
		 = append(, byte(.SegmentSize>>8), byte(.SegmentSize))
	}
	return append(, .Contents...)
}

// encodedLen returns the number of bytes appendTo writes.
func ( Datagrams) () int {
	 := 1 + len(.Contents)
	if .SegmentSize != 0 {
		 += 2
	}
	return 
}

// datagramsFromBytes decodes a Datagrams payload. isBatch selects whether a
// 2-byte segment size precedes the contents.
func datagramsFromBytes( []byte,  bool) (Datagrams, error) {
	return datagramsFromBytesCopy(, , true)
}

func datagramsFromBytesNoCopy( []byte,  bool) (Datagrams, error) {
	return datagramsFromBytesCopy(, , false)
}

func datagramsFromBytesCopy( []byte, ,  bool) (Datagrams, error) {
	if  {
		if len() < 3 {
			return Datagrams{}, ErrInvalidFrame
		}
	} else if len() < 1 {
		return Datagrams{}, ErrInvalidFrame
	}
	,  := ecnFromBits([0])
	 = [1:]
	var  uint16
	if  {
		 = uint16([0])<<8 | uint16([1])
		 = [2:]
	}
	if  {
		 = bytes.Clone()
	}
	return Datagrams{Ecn: , SegmentSize: , Contents: }, nil
}