func isStreamBidi(id uint64) bool {
	return id&0x2 == 0
}
The second least significant bit (0x2) of the stream ID distinguishes between
bidirectional streams (with the bit set to 0) and unidirectional streams (with the bit set to 1).
package transport
import (
	"fmt"
	"io"
)
const (
	maxStreams = 1 << 60
	minStreamBufferWritable = 8 << 10
	maxStreamBuffer         = 128 << 10
)
type deliveryState uint8
const (
	deliveryNone deliveryState = iota
	deliveryReady
	deliverySending
	deliveryConfirmed
)
type Stream struct {
	recv recvStream
	send sendStream
	flow flowControl
	connFlow *flowControl
	updateMaxData bool
	local bool
	bidi  bool
}
func (s *Stream) init(local, bidi bool) {
	s.local = local
	s.bidi = bidi
	if !bidi {
		if local {
			s.recv.setClosed()  
		} else {
			s.send.setClosed()  
		}
	}
}
func (s *Stream) pushRecv(data []byte, offset uint64, fin bool) error {
	if offset+uint64(len(data)) > s.flow.recvMax {
		return newError(FlowControlError, sprint("stream: data exceeded limit ", s.flow.recvMax))
	}
	err := s.recv.push(data, offset, fin)
	if err == nil {
		s.flow.setRecv(s.recv.length)
	}
	return err
}
func (s *Stream) Read(b []byte) (int, error) {
	if s.recv.closed {
		return 0, io.EOF
	}
	n, err := s.recv.Read(b)
	if n > 0 {
		s.consumeRecv(uint64(n))
	}
	return n, err
}
func (s *Stream) Write(b []byte) (int, error) {
	if s.send.closed {
		return 0, io.EOF
	}
	if s.send.stopReceived {
		s.send.setClosed()  
		return 0, newAppError(s.send.resetError, "stop_sending")
	}
	if s.send.buf.size() > maxStreamBuffer {
		return 0, nil
	}
	n := int(s.flow.availSend())
	if n <= 0 {
		return 0, nil
	}
	if n < len(b) {
		b = b[:n]
	}
	n, err := s.send.Write(b)
	if n > 0 {
		s.flow.setSend(s.send.length)
		if s.isSendBlocked() {
			s.flow.setSendBlocked(true)
		}
	}
	return n, err
}
func (s *Stream) WriteString(b string) (int, error) {
	return s.Write([]byte(b))
}
func (s *Stream) WriteTo(w io.Writer) (int64, error) {
	if s.recv.closed {
		return 0, io.EOF
	}
	n, err := s.recv.WriteTo(w)
	if n > 0 {
		s.consumeRecv(uint64(n))
	}
	return n, err
}
func (s *Stream) isReadable() bool {
	if s.recv.closed {
		return false
	}
	if s.recv.resetReceived {
		return true
	}
	return (s.recv.ready() || s.recv.fin) && s.recv.stopSending == deliveryNone
}
func (s *Stream) updateStopSending() (uint64, bool) {
	if s.recv.stopSending == deliveryReady {
		return s.recv.stopError, true
	}
	return 0, false
}
func (s *Stream) setStopSending(state deliveryState) {
	s.recv.stopSending = state
	if state == deliveryConfirmed && !s.recv.resetReceived {
		s.recv.setClosed()
	}
}
func (s *Stream) resetRecv(finalSize, errorCode uint64) error {
	return s.recv.reset(finalSize, errorCode)
}
func (s *Stream) isWritable() bool {
	if s.send.closed {
		return false
	}
	if s.send.stopReceived {
		return true
	}
	return s.flow.availSend() > 0 && s.send.buf.size() < minStreamBufferWritable &&
		!s.send.fin && s.send.resetStream == deliveryNone
}
func (s *Stream) isFlushable() bool {
	if s.send.closed || s.send.stopReceived {
		return false
	}
	return s.send.ready(s.flow.sendMax) || (s.send.fin && !s.send.finSent)
}
func (s *Stream) isSendBlocked() bool {
	if s.send.closed || s.send.stopReceived || s.send.fin || s.send.resetStream != deliveryNone {
		return false
	}
	return s.flow.availSend() == 0
}
func (s *Stream) popSend(max int) (data []byte, offset uint64, fin bool) {
	if s.isFlushable() {
		return s.send.pop(max)
	}
	return nil, 0, false
}
func (s *Stream) pushSend(data []byte, offset uint64, fin bool) error {
	if s.send.stopReceived || s.send.resetStream != deliveryNone {
		return nil
	}
	return s.send.push(data, offset, fin)
}
func (s *Stream) ackSend(offset, length uint64) bool {
	return s.send.ack(offset, length)
}
func (s *Stream) consumeRecv(n uint64) {
	s.flow.addRecvMaxNext(n)
	if s.connFlow != nil {
		s.connFlow.addRecvMaxNext(n)
	}
	if !s.recv.fin && s.flow.shouldUpdateRecvMax() {
		s.updateMaxData = true
	}
}
func (s *Stream) setUpdateMaxData(update bool) {
	s.updateMaxData = update
}
func (s *Stream) updateResetStream() (uint64, bool) {
	if s.send.resetStream == deliveryReady && (s.send.stopReceived || s.send.buf.isEmpty()) {
		return s.send.resetError, true
	}
	return 0, false
}
func (s *Stream) setResetStream(state deliveryState) {
	s.send.resetStream = state
	if state == deliveryConfirmed && !s.send.stopReceived {
		s.send.setClosed()
	}
}
func (s *Stream) stopSend(errorCode uint64) {
	s.send.stop(errorCode)
	if s.flow.sendBlocked {
		s.flow.setSendBlocked(false)
	}
}
func (s *Stream) isClosed() bool {
	return s.recv.closed && s.send.closed
}
func (s *Stream) CloseWrite(errorCode uint64) error {
	if !s.bidi && !s.local {
		return newError(StreamStateError, "cannot close writing of receive-only stream")
	}
	s.send.terminate(errorCode)
	return nil
}
func (s *Stream) CloseRead(errorCode uint64) error {
	if !s.bidi && s.local {
		return newError(StreamStateError, "cannot close reading of send-only stream")
	}
	s.recv.terminate(errorCode)
	return nil
}
func (s *Stream) Close() error {
	if s.bidi || s.local {
		s.send.fin = true
		if s.flow.sendBlocked {
			s.flow.setSendBlocked(false)
		}
	}
	return nil
}
func (s *Stream) String() string {
	return fmt.Sprintf("recv(%s) send(%s)", &s.recv, &s.send)
}
type recvStream struct {
	buf rangeBufferList  
	offset uint64  
	length uint64  
	stopError     uint64         
	stopSending   deliveryState  
	resetReceived bool           
	fin bool
	closed bool
}
func (s *recvStream) push(data []byte, offset uint64, fin bool) error {
	end := offset + uint64(len(data))
	if s.fin {
		if end > s.length {
			return errFinalSize
		}
	}
	if fin {
		if end < s.length {
			return errFinalSize
		}
		s.fin = true
	}
	if end <= s.offset {
		return nil
	}
	if offset < s.offset {
		data = data[s.offset-offset:]
		offset = s.offset
	}
	s.buf.write(data, offset)
	if end > s.length {
		s.length = end
	}
	return nil
}
func (s *recvStream) Read(b []byte) (n int, err error) {
	n = s.buf.read(b, s.offset)
	s.offset += uint64(n)
	if s.resetReceived {
		s.setClosed()  
		err = newAppError(s.stopError, "reset_stream")
	} else if s.fin && s.offset >= s.length {
		s.setClosed()  
		err = io.EOF
	}
	return n, err
}
func (s *recvStream) WriteTo(w io.Writer) (int64, error) {
	n, err := s.buf.consume(s.offset, w.Write)
	s.offset += uint64(n)
	if err == nil {
		if s.resetReceived {
			s.setClosed()  
			err = newAppError(s.stopError, "reset_stream")
		} else if s.fin && s.offset >= s.length {
			s.setClosed()  
			err = io.EOF
		}
	}
	return int64(n), err
}
func (s *recvStream) ready() bool {
	if s.offset < s.length {
		r := s.buf.first()
		return r != nil && r.offset == s.offset
	}
	return false
}
func (s *recvStream) reset(finalSize, errorCode uint64) error {
	if !s.resetReceived {
		if (s.fin && finalSize != s.length) || finalSize < s.length {
			return errFinalSize
		}
		s.resetReceived = true
		s.fin = true
		s.length = finalSize
		if s.stopSending == deliveryNone {
			s.stopError = errorCode
			s.stopSending = deliveryConfirmed
		}
	}
	return nil
}
func (s *recvStream) terminate(errorCode uint64) {
	if s.stopSending == deliveryNone && !s.resetReceived {
		s.stopError = errorCode
		s.stopSending = deliveryReady
	}
}
func (s *recvStream) setClosed() {
	s.closed = true
}
func (s *recvStream) String() string {
	return fmt.Sprintf("offset=%v length=%v fin=%v size=%v %v", s.offset, s.length, s.fin, s.buf.size(), &s.buf)
}
type sendStream struct {
	buf   rangeBufferList  
	acked rangeSet         
	offset uint64  
	length uint64  
	resetError   uint64         
	resetStream  deliveryState  
	stopReceived bool           
	fin     bool
	finSent bool  
	closed bool
}
func (s *sendStream) push(data []byte, offset uint64, fin bool) error {
	end := offset + uint64(len(data))
	if s.fin {
		if end > s.length {
			return errFinalSize
		}
	}
	if fin {
		if end < s.length {
			return errFinalSize
		}
		s.fin = true
		s.finSent = false  
	}
	s.buf.write(data, offset)
	if end > s.length {
		s.length = end
	}
	return nil
}
func (s *sendStream) pop(max int) (data []byte, offset uint64, fin bool) {
	data, offset = s.buf.pop(max)
	if len(data) == 0 {
		offset = s.offset
	}
	end := offset + uint64(len(data))
	fin = s.fin && end >= s.length
	if fin {
		s.finSent = true
	}
	if end > s.offset {
		s.offset = end
	}
	return
}
func (s *sendStream) ready(maxOffset uint64) bool {
	r := s.buf.first()
	return r != nil && r.offset < maxOffset
}
func (s *sendStream) Write(b []byte) (int, error) {
	maxSize := dataBufferSizes[2]  
	n := len(b)
	for len(b) > maxSize {
		err := s.push(b[:maxSize], s.length, false)
		if err != nil {
			return 0, err
		}
		b = b[maxSize:]
	}
	err := s.push(b, s.length, false)
	if err != nil {
		return 0, err
	}
	return n, nil
}
func (s *sendStream) ack(offset, length uint64) bool {
	s.acked.push(offset, offset+length)
	complete := s.complete()
	if complete && s.resetStream == deliveryNone && !s.stopReceived {
		s.setClosed()
	}
	return complete
}
func (s *sendStream) complete() bool {
	return s.fin && s.finSent && s.offset >= s.length && s.acked.equals(0, s.length)
}
func (s *sendStream) stop(errorCode uint64) {
	if !s.stopReceived {
		s.stopReceived = true
		if s.resetStream == deliveryNone {
			s.resetError = errorCode
			if s.fin {
				s.resetStream = deliveryConfirmed
			} else {
				s.resetStream = deliveryReady
			}
		}
	}
}
func (s *sendStream) terminate(errorCode uint64) {
	if s.resetStream == deliveryNone {
		s.fin = true
		if !s.stopReceived {
			s.resetError = errorCode
			s.resetStream = deliveryReady
		}
	}
}
func (s *sendStream) setClosed() {
	s.closed = true
}
func (s *sendStream) String() string {
	return fmt.Sprintf("offset=%v length=%v fin=%v size=%v %v", s.offset, s.length, s.fin, s.buf.size(), &s.buf)
}
type streamMap struct {
	streams map[uint64]*Stream
	closedStreams map[uint64]struct{}
	closedStream Stream
	openedStreams struct {
		peerBidi  uint64
		peerUni   uint64
		localBidi uint64
		localUni  uint64
	}
	maxStreams struct {
		peerBidi  uint64
		peerUni   uint64
		localBidi uint64
		localUni  uint64
	}
	maxStreamsNext struct {
		localBidi uint64
		localUni  uint64
	}
	updateMaxStreamsBidi bool
	updateMaxStreamsUni  bool
}
func (s *streamMap) init(maxBidi, maxUni uint64) {
	s.streams = make(map[uint64]*Stream)
	s.closedStreams = make(map[uint64]struct{})
	s.maxStreams.localBidi = maxBidi
	s.maxStreams.localUni = maxUni
	s.maxStreamsNext.localBidi = maxBidi
	s.maxStreamsNext.localUni = maxUni
	s.closedStream = Stream{
		recv: recvStream{
			fin:           true,
			stopSending:   deliveryConfirmed,
			resetReceived: true,
			closed:        true,
		},
		send: sendStream{
			fin:          true,
			finSent:      true,
			resetStream:  deliveryConfirmed,
			stopReceived: true,
			closed:       true,
		},
		bidi: true,
	}
}
func (s *streamMap) get(id uint64) *Stream {
	if _, ok := s.closedStreams[id]; ok {
		return &s.closedStream
	}
	return s.streams[id]
}
func (s *streamMap) getOpen(id uint64) *Stream {
	return s.streams[id]
}
func (s *streamMap) create(id uint64, isClient bool) (*Stream, error) {
	local := isStreamLocal(id, isClient)
	bidi := isStreamBidi(id)
	if local {
		if bidi {
			if s.openedStreams.localBidi >= s.maxStreams.peerBidi || id > s.maxStreams.peerBidi*4 {
				return nil, newError(StreamLimitError, sprint("local bidirectional streams exceeded ", s.maxStreams.peerBidi))
			}
			s.openedStreams.localBidi++
		} else {
			if s.openedStreams.localUni >= s.maxStreams.peerUni || id > s.maxStreams.peerUni*4 {
				return nil, newError(StreamLimitError, sprint("local unidirectional streams exceeded ", s.maxStreams.peerUni))
			}
			s.openedStreams.localUni++
		}
	} else {
		if bidi {
			if s.openedStreams.peerBidi >= s.maxStreams.localBidi || id > s.maxStreams.localBidi*4 {
				return nil, newError(StreamLimitError, sprint("peer bidirectional streams exceeded ", s.maxStreams.localBidi))
			}
			s.openedStreams.peerBidi++
		} else {
			if s.openedStreams.peerUni >= s.maxStreams.localUni || id > s.maxStreams.localUni*4 {
				return nil, newError(StreamLimitError, sprint("peer unidirectional streams exceeded ", s.maxStreams.localUni))
			}
			s.openedStreams.peerUni++
		}
	}
	st := &Stream{}
	st.init(local, bidi)
	s.streams[id] = st
	return st, nil
}
func (s *streamMap) creatableLocalStreamBidi() bool {
	return s.openedStreams.localBidi < s.maxStreams.peerBidi
}
func (s *streamMap) creatableLocalStreamUni() bool {
	return s.openedStreams.localUni < s.maxStreams.peerUni
}
func (s *streamMap) setPeerMaxStreamsBidi(v uint64) {
	if v > s.maxStreams.peerBidi {
		s.maxStreams.peerBidi = v
	}
}
func (s *streamMap) setPeerMaxStreamsUni(v uint64) {
	if v > s.maxStreams.peerUni {
		s.maxStreams.peerUni = v
	}
}
func (s *streamMap) setUpdateMaxStreamsBidi(update bool) {
	s.updateMaxStreamsBidi = update
}
func (s *streamMap) setUpdateMaxStreamsUni(update bool) {
	s.updateMaxStreamsUni = update
}
func (s *streamMap) shouldUpdateMaxStreamsBidi() bool {
	return s.maxStreamsNext.localBidi != s.maxStreams.localBidi && s.maxStreams.localBidi >= s.openedStreams.peerBidi &&
		s.maxStreamsNext.localBidi/2 > s.maxStreams.localBidi-s.openedStreams.peerBidi
}
func (s *streamMap) shouldUpdateMaxStreamsUni() bool {
	return s.maxStreamsNext.localUni != s.maxStreams.localUni && s.maxStreams.localUni >= s.openedStreams.peerUni &&
		s.maxStreamsNext.localUni/2 > s.maxStreams.localUni-s.openedStreams.peerUni
}
func (s *streamMap) commitMaxStreamsBidi() {
	s.maxStreams.localBidi = s.maxStreamsNext.localBidi
}
func (s *streamMap) commitMaxStreamsUni() {
	s.maxStreams.localUni = s.maxStreamsNext.localUni
}
func (s *streamMap) hasUpdate() bool {
	if s.updateMaxStreamsBidi || s.updateMaxStreamsUni {
		return true
	}
	for _, st := range s.streams {
		if st.isFlushable() || st.updateMaxData ||
			st.flow.shouldUpdateRecvMax() || st.flow.sendBlocked {
			return true
		}
	}
	return false
}
func (s *streamMap) checkClosed(fn func(streamId uint64)) {
	for id, st := range s.streams {
		if st.isClosed() {
			if !st.local {
				if st.bidi {
					s.maxStreamsNext.localBidi++
					if s.shouldUpdateMaxStreamsBidi() {
						s.updateMaxStreamsBidi = true
					}
				} else {
					s.maxStreamsNext.localUni++
					if s.shouldUpdateMaxStreamsUni() {
						s.updateMaxStreamsUni = true
					}
				}
			}
			delete(s.streams, id)
			s.closedStreams[id] = struct{}{}
			debug("stream closed %d", id)
			fn(id)
		}
	}
}
func isStreamLocal(id uint64, isClient bool) bool {
	return (id&0x1 == 0) == isClient
}