Skip to content

Commit

Permalink
quic: parameterize rangeset
Browse files Browse the repository at this point in the history
Make the rangeset type parameterized, so it can be used for
either packet number or byte ranges without type conversions.

For golang/go#58547

Change-Id: I764913a33ba58222dcfd36f94de01c2249d73551
Reviewed-on: https://go-review.googlesource.com/c/net/+/499284
Run-TryBot: Damien Neil <dneil@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
  • Loading branch information
neild committed May 31, 2023
1 parent f16447c commit ccc217c
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 138 deletions.
10 changes: 5 additions & 5 deletions internal/quic/frame_debug.go
Expand Up @@ -116,15 +116,15 @@ func (f debugFramePing) write(w *packetWriter) bool {
// debugFrameAck is an ACK frame.
type debugFrameAck struct {
ackDelay time.Duration
ranges []i64range
ranges []i64range[packetNumber]
}

func parseDebugFrameAck(b []byte) (f debugFrameAck, n int) {
f.ranges = nil
_, f.ackDelay, n = consumeAckFrame(b, ackDelayExponent, func(start, end packetNumber) {
f.ranges = append(f.ranges, i64range{
start: int64(start),
end: int64(end),
f.ranges = append(f.ranges, i64range[packetNumber]{
start: start,
end: end,
})
})
// Ranges are parsed smallest to highest; reverse ranges slice to order them high to low.
Expand All @@ -144,7 +144,7 @@ func (f debugFrameAck) String() string {
}

func (f debugFrameAck) write(w *packetWriter) bool {
return w.appendAckFrame(rangeset(f.ranges), ackDelayExponent, f.ackDelay)
return w.appendAckFrame(rangeset[packetNumber](f.ranges), ackDelayExponent, f.ackDelay)
}

// debugFrameResetStream is a RESET_STREAM frame.
Expand Down
4 changes: 2 additions & 2 deletions internal/quic/packet_codec_test.go
Expand Up @@ -222,7 +222,7 @@ func TestFrameEncodeDecode(t *testing.T) {
s: "ACK Delay=80µs [0,16) [17,32) [48,64)",
f: debugFrameAck{
ackDelay: (10 << ackDelayExponent) * time.Microsecond,
ranges: []i64range{
ranges: []i64range[packetNumber]{
{0x00, 0x10},
{0x11, 0x20},
{0x30, 0x40},
Expand Down Expand Up @@ -595,7 +595,7 @@ func TestFrameDecode(t *testing.T) {
desc: "ACK frame with ECN counts",
want: debugFrameAck{
ackDelay: (10 << ackDelayExponent) * time.Microsecond,
ranges: []i64range{
ranges: []i64range[packetNumber]{
{0, 1},
},
},
Expand Down
2 changes: 1 addition & 1 deletion internal/quic/packet_writer.go
Expand Up @@ -257,7 +257,7 @@ func (w *packetWriter) appendPingFrame() (added bool) {
// to the peer potentially failing to receive an acknowledgement
// for an older packet during a period of high packet loss or
// reordering. This may result in unnecessary retransmissions.
func (w *packetWriter) appendAckFrame(seen rangeset, ackDelayExponent uint8, delay time.Duration) (added bool) {
func (w *packetWriter) appendAckFrame(seen rangeset[packetNumber], ackDelayExponent uint8, delay time.Duration) (added bool) {
if len(seen) == 0 {
return false
}
Expand Down
41 changes: 19 additions & 22 deletions internal/quic/rangeset.go
Expand Up @@ -11,27 +11,24 @@ package quic
//
// Rangesets are efficient for small numbers of ranges,
// which is expected to be the common case.
//
// Once we're willing to drop support for pre-generics versions of Go, this can
// be made into a parameterized type to permit use with packetNumber without casts.
type rangeset []i64range
type rangeset[T ~int64] []i64range[T]

type i64range struct {
start, end int64 // [start, end)
type i64range[T ~int64] struct {
start, end T // [start, end)
}

// size returns the size of the range.
func (r i64range) size() int64 {
func (r i64range[T]) size() T {
return r.end - r.start
}

// contains reports whether v is in the range.
func (r i64range) contains(v int64) bool {
func (r i64range[T]) contains(v T) bool {
return r.start <= v && v < r.end
}

// add adds [start, end) to the set, combining it with existing ranges if necessary.
func (s *rangeset) add(start, end int64) {
func (s *rangeset[T]) add(start, end T) {
if start == end {
return
}
Expand Down Expand Up @@ -65,11 +62,11 @@ func (s *rangeset) add(start, end int64) {
s.removeranges(i+1, j)
return
}
*s = append(*s, i64range{start, end})
*s = append(*s, i64range[T]{start, end})
}

// sub removes [start, end) from the set.
func (s *rangeset) sub(start, end int64) {
func (s *rangeset[T]) sub(start, end T) {
removefrom, removeto := -1, -1
for i := range *s {
r := &(*s)[i]
Expand Down Expand Up @@ -106,7 +103,7 @@ func (s *rangeset) sub(start, end int64) {
}

// contains reports whether s contains v.
func (s rangeset) contains(v int64) bool {
func (s rangeset[T]) contains(v T) bool {
for _, r := range s {
if v >= r.end {
continue
Expand All @@ -120,7 +117,7 @@ func (s rangeset) contains(v int64) bool {
}

// rangeContaining returns the range containing v, or the range [0,0) if v is not in s.
func (s rangeset) rangeContaining(v int64) i64range {
func (s rangeset[T]) rangeContaining(v T) i64range[T] {
for _, r := range s {
if v >= r.end {
continue
Expand All @@ -130,35 +127,35 @@ func (s rangeset) rangeContaining(v int64) i64range {
}
break
}
return i64range{0, 0}
return i64range[T]{0, 0}
}

// min returns the minimum value in the set, or 0 if empty.
func (s rangeset) min() int64 {
func (s rangeset[T]) min() T {
if len(s) == 0 {
return 0
}
return s[0].start
}

// max returns the maximum value in the set, or 0 if empty.
func (s rangeset) max() int64 {
func (s rangeset[T]) max() T {
if len(s) == 0 {
return 0
}
return s[len(s)-1].end - 1
}

// end returns the end of the last range in the set, or 0 if empty.
func (s rangeset) end() int64 {
func (s rangeset[T]) end() T {
if len(s) == 0 {
return 0
}
return s[len(s)-1].end
}

// isrange reports if the rangeset covers exactly the range [start, end).
func (s rangeset) isrange(start, end int64) bool {
func (s rangeset[T]) isrange(start, end T) bool {
switch len(s) {
case 0:
return start == 0 && end == 0
Expand All @@ -169,7 +166,7 @@ func (s rangeset) isrange(start, end int64) bool {
}

// removeranges removes ranges [i,j).
func (s *rangeset) removeranges(i, j int) {
func (s *rangeset[T]) removeranges(i, j int) {
if i == j {
return
}
Expand All @@ -178,8 +175,8 @@ func (s *rangeset) removeranges(i, j int) {
}

// insert adds a new range at index i.
func (s *rangeset) insertrange(i int, start, end int64) {
*s = append(*s, i64range{})
func (s *rangeset[T]) insertrange(i int, start, end T) {
*s = append(*s, i64range[T]{})
copy((*s)[i+1:], (*s)[i:])
(*s)[i] = i64range{start, end}
(*s)[i] = i64range[T]{start, end}
}

0 comments on commit ccc217c

Please sign in to comment.