Copyright 2014 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

package http2

import 
WriteScheduler is the interface implemented by HTTP/2 write schedulers. Methods are never called concurrently.
OpenStream opens a new stream in the write scheduler. It is illegal to call this with streamID=0 or with a streamID that is already open -- the call may panic.
	OpenStream(streamID uint32, options OpenStreamOptions)
CloseStream closes a stream in the write scheduler. Any frames queued on this stream should be discarded. It is illegal to call this on a stream that is not open -- the call may panic.
	CloseStream(streamID uint32)
AdjustStream adjusts the priority of the given stream. This may be called on a stream that has not yet been opened or has been closed. Note that RFC 7540 allows PRIORITY frames to be sent on streams in any state. See: https://tools.ietf.org/html/rfc7540#section-5.1
	AdjustStream(streamID uint32, priority PriorityParam)
Push queues a frame in the scheduler. In most cases, this will not be called with wr.StreamID()!=0 unless that stream is currently open. The one exception is RST_STREAM frames, which may be sent on idle or closed streams.
Pop dequeues the next frame to write. Returns false if no frames can be written. Frames with a given wr.StreamID() are Pop'd in the same order they are Push'd. No frames should be discarded except by CloseStream.
	Pop() (wr FrameWriteRequest, ok bool)
}
OpenStreamOptions specifies extra options for WriteScheduler.OpenStream.
PusherID is zero if the stream was initiated by the client. Otherwise, PusherID names the stream that pushed the newly opened stream.
FrameWriteRequest is a request to write a frame.
write is the interface value that does the writing, once the WriteScheduler has selected this frame to write. The write functions are all defined in write.go.
stream is the stream on which this frame will be written. nil for non-stream frames like PING and SETTINGS.
done, if non-nil, must be a buffered channel with space for 1 message and is sent the return value from write (or an earlier error) when the frame has been written.
	done chan error
}
StreamID returns the id of the stream this frame will be written to. 0 is used for non-stream frames such as PING and SETTINGS.
func ( FrameWriteRequest) () uint32 {
	if .stream == nil {
(*serverConn).resetStream doesn't set stream because it doesn't necessarily have one. So special case this type of write message.
			return .StreamID
		}
		return 0
	}
	return .stream.id
}
isControl reports whether wr is a control frame for MaxQueuedControlFrames purposes. That includes non-stream frames and RST_STREAM frames.
func ( FrameWriteRequest) () bool {
	return .stream == nil
}
DataSize returns the number of flow control bytes that must be consumed to write this entire frame. This is 0 for non-DATA frames.
func ( FrameWriteRequest) () int {
	if ,  := .write.(*writeData);  {
		return len(.p)
	}
	return 0
}
Consume consumes min(n, available) bytes from this frame, where available is the number of flow control bytes available on the stream. Consume returns 0, 1, or 2 frames, where the integer return value gives the number of frames returned. If flow control prevents consuming any bytes, this returns (_, _, 0). If the entire frame was consumed, this returns (wr, _, 1). Otherwise, this returns (consumed, rest, 2), where 'consumed' contains the consumed bytes and 'rest' contains the remaining bytes. The consumed bytes are deducted from the underlying stream's flow control budget.
Non-DATA frames are always consumed whole.
	,  := .write.(*writeData)
	if ! || len(.p) == 0 {
		return , , 1
	}
Might need to split after applying limits.
	 := .stream.flow.available()
	if  <  {
		 = 
	}
	if .stream.sc.maxFrameSize <  {
		 = .stream.sc.maxFrameSize
	}
	if  <= 0 {
		return , , 0
	}
	if len(.p) > int() {
		.stream.flow.take()
		 := FrameWriteRequest{
			stream: .stream,
			write: &writeData{
				streamID: .streamID,
Even if the original had endStream set, there are bytes remaining because len(wd.p) > allowed, so we know endStream is false.
Our caller is blocking on the final DATA frame, not this intermediate frame, so no need to wait.
			done: nil,
		}
		 := FrameWriteRequest{
			stream: .stream,
			write: &writeData{
				streamID:  .streamID,
				p:         .p[:],
				endStream: .endStream,
			},
			done: .done,
		}
		return , , 2
	}
The frame is consumed whole. NB: This cast cannot overflow because allowed is <= math.MaxInt32.
	.stream.flow.take(int32(len(.p)))
	return , , 1
}
String is for debugging only.
func ( FrameWriteRequest) () string {
	var  string
	if ,  := .write.(fmt.Stringer);  {
		 = .String()
	} else {
		 = fmt.Sprintf("%T", .write)
	}
	return fmt.Sprintf("[FrameWriteRequest stream=%d, ch=%v, writer=%v]", .StreamID(), .done != nil, )
}
replyToWriter sends err to wr.done and panics if the send must block This does nothing if wr.done is nil.
func ( *FrameWriteRequest) ( error) {
	if .done == nil {
		return
	}
	select {
	case .done <- :
	default:
		panic(fmt.Sprintf("unbuffered done channel passed in for type %T", .write))
	}
	.write = nil // prevent use (assume it's tainted after wr.done send)
}
writeQueue is used by implementations of WriteScheduler.
type writeQueue struct {
	s []FrameWriteRequest
}

func ( *writeQueue) () bool { return len(.s) == 0 }

func ( *writeQueue) ( FrameWriteRequest) {
	.s = append(.s, )
}

func ( *writeQueue) () FrameWriteRequest {
	if len(.s) == 0 {
		panic("invalid use of queue")
	}
TODO: less copy-happy queue.
	copy(.s, .s[1:])
	.s[len(.s)-1] = FrameWriteRequest{}
	.s = .s[:len(.s)-1]
	return 
}
consume consumes up to n bytes from q.s[0]. If the frame is entirely consumed, it is removed from the queue. If the frame is partially consumed, the frame is kept with the consumed bytes removed. Returns true iff any bytes were consumed.
func ( *writeQueue) ( int32) (FrameWriteRequest, bool) {
	if len(.s) == 0 {
		return FrameWriteRequest{}, false
	}
	, ,  := .s[0].Consume()
	switch  {
	case 0:
		return FrameWriteRequest{}, false
	case 1:
		.shift()
	case 2:
		.s[0] = 
	}
	return , true
}

type writeQueuePool []*writeQueue
put inserts an unused writeQueue into the pool.
func ( *writeQueuePool) ( *writeQueue) {
	for  := range .s {
		.s[] = FrameWriteRequest{}
	}
	.s = .s[:0]
	* = append(*, )
}
get returns an empty writeQueue.
func ( *writeQueuePool) () *writeQueue {
	 := len(*)
	if  == 0 {
		return new(writeQueue)
	}
	 :=  - 1
	 := (*)[]
	(*)[] = nil
	* = (*)[:]
	return