diff --git a/.golangci.yml b/.golangci.yml index 43af4c3..1fbb8db 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -41,6 +41,7 @@ linters: - maintidx # maintidx measures the maintainability index of each function. - makezero # Finds slice declarations with non-zero initial length - misspell # Finds commonly misspelled English words in comments + - modernize # Replace and suggests simplifications to code - nakedret # Finds naked returns in functions greater than a specified function length - nestif # Reports deeply nested if statements - nilerr # Finds the code that returns nil even if it checks that the error is not nil. diff --git a/errors.go b/errors.go index 108f733..9f6e4b7 100644 --- a/errors.go +++ b/errors.go @@ -13,6 +13,7 @@ var ( errBadFirstPacket = errors.New("rtcp: first packet in compound must be SR or RR") errMissingCNAME = errors.New("rtcp: compound missing SourceDescription with CNAME") errPacketBeforeCNAME = errors.New("rtcp: feedback packet seen before CNAME") + errTooManySSRCs = errors.New("rtcp: too many SSRCs") errTooManyReports = errors.New("rtcp: too many reports") errTooManyChunks = errors.New("rtcp: too many chunks") errTooManySources = errors.New("rtcp: too many sources") diff --git a/extended_report_test.go b/extended_report_test.go index 1cf8103..ec1cd55 100644 --- a/extended_report_test.go +++ b/extended_report_test.go @@ -229,7 +229,7 @@ func TestEncode(t *testing.T) { assert.NoError(t, err) assert.Equal(t, len(expected), len(rawPacket), "Encoded message length does not match expected length") - for i := 0; i < len(rawPacket); i++ { + for i := range rawPacket { assert.Equalf(t, expected[i], rawPacket[i], "Byte %d of encoded packet does not match", i) } } diff --git a/full_intra_request.go b/full_intra_request.go index 7a26dce..1e6333f 100644 --- a/full_intra_request.go +++ b/full_intra_request.go @@ -6,6 +6,7 @@ package rtcp import ( "encoding/binary" "fmt" + "strings" ) // A FIREntry is a (SSRC, seqno) pair, as carried by FullIntraRequest. @@ -99,13 +100,14 @@ func (p *FullIntraRequest) MarshalSize() int { } func (p *FullIntraRequest) String() string { - out := fmt.Sprintf("FullIntraRequest %x %x", + var out strings.Builder + fmt.Fprintf(&out, "FullIntraRequest %x %x", p.SenderSSRC, p.MediaSSRC) for _, e := range p.FIR { - out += fmt.Sprintf(" (%x %v)", e.SSRC, e.SequenceNumber) + fmt.Fprintf(&out, " (%x %v)", e.SSRC, e.SequenceNumber) } - return out + return out.String() } // DestinationSSRC returns an array of SSRC values that this packet refers to. diff --git a/goodbye.go b/goodbye.go index c9b7661..f3a3324 100644 --- a/goodbye.go +++ b/goodbye.go @@ -6,6 +6,7 @@ package rtcp import ( "encoding/binary" "fmt" + "strings" ) // The Goodbye packet indicates that one or more sources are no longer active. @@ -154,11 +155,12 @@ func (g *Goodbye) DestinationSSRC() []uint32 { } func (g Goodbye) String() string { - out := "Goodbye\n" + var out strings.Builder + out.WriteString("Goodbye\n") for i, s := range g.Sources { - out += fmt.Sprintf("\tSource %d: %x\n", i, s) + fmt.Fprintf(&out, "\tSource %d: %x\n", i, s) } - out += fmt.Sprintf("\tReason: %s\n", g.Reason) + fmt.Fprintf(&out, "\tReason: %s\n", g.Reason) - return out + return out.String() } diff --git a/goodbye_test.go b/goodbye_test.go index 0a77e7b..e7c438a 100644 --- a/goodbye_test.go +++ b/goodbye_test.go @@ -4,6 +4,7 @@ package rtcp import ( + "strings" "testing" "github.com/stretchr/testify/assert" @@ -125,13 +126,13 @@ func TestGoodbyeUnmarshal(t *testing.T) { func TestGoodbyeRoundTrip(t *testing.T) { // a slice with enough sources to overflow an 5-bit int var tooManySources []uint32 - var tooLongText string + var tooLongText strings.Builder - for i := 0; i < (1 << 5); i++ { + for range 1 << 5 { tooManySources = append(tooManySources, 0x00) } - for i := 0; i < (1 << 8); i++ { - tooLongText += "x" + for range 1 << 8 { + tooLongText.WriteString("x") } for _, test := range []struct { @@ -187,7 +188,7 @@ func TestGoodbyeRoundTrip(t *testing.T) { Name: "reason too long", Bye: Goodbye{ Sources: []uint32{}, - Reason: tooLongText, + Reason: tooLongText.String(), }, WantError: errReasonTooLong, }, diff --git a/packet_buffer.go b/packet_buffer.go index 988616b..7f53c71 100644 --- a/packet_buffer.go +++ b/packet_buffer.go @@ -61,7 +61,7 @@ func (b *packetBuffer) write(v any) error { return errWrongMarshalSize } if value.CanInterface() { - b.bytes[0] = byte(value.Uint()) + b.bytes[0] = byte(value.Uint()) //nolint:gosec // value.Kind() == reflect.Uint8 guarantees range } b.bytes = b.bytes[1:] case reflect.Uint16: @@ -109,7 +109,7 @@ func (b *packetBuffer) write(v any) error { return err } } else { - advance := int(value.Field(i).Type().Size()) + advance := int(value.Field(i).Type().Size()) //nolint:gosec // RTCP struct field sizes are small and controlled if len(b.bytes) < advance { return errWrongMarshalSize } @@ -200,7 +200,7 @@ func (b *packetBuffer) read(v any) error { return err } } else { - advance := int(value.Field(i).Type().Size()) + advance := int(value.Field(i).Type().Size()) //nolint:gosec //Size comes from type system and is bounded if len(b.bytes) < advance { return errWrongMarshalSize } @@ -245,7 +245,7 @@ func wireSize(v any) int { if value.Index(i).CanInterface() { size += wireSize(value.Index(i).Interface()) } else { - size += int(value.Index(i).Type().Size()) + size += int(value.Index(i).Type().Size()) //nolint:gosec // RTCP element sizes are small and bounded } } @@ -258,12 +258,12 @@ func wireSize(v any) int { if value.Field(i).CanInterface() { size += wireSize(value.Field(i).Interface()) } else { - size += int(value.Field(i).Type().Size()) + size += int(value.Field(i).Type().Size()) // nolint:gosec // Size comes from type system and is bounded } } default: - size = int(value.Type().Size()) + size = int(value.Type().Size()) // nolint:gosec // Size comes from type system and is bounde } return size diff --git a/packet_stringifier.go b/packet_stringifier.go index 8ca7562..0755eaf 100644 --- a/packet_stringifier.go +++ b/packet_stringifier.go @@ -45,7 +45,7 @@ func formatField(name string, format string, f any, indent string) string { return fmt.Sprintf("%s%s: \n", out, name) } - isPacket := reflect.TypeOf(f).Implements(reflect.TypeOf((*Packet)(nil)).Elem()) + isPacket := reflect.TypeOf(f).Implements(reflect.TypeFor[Packet]()) // Resolve pointers to their underlying values if value.Type().Kind() == reflect.Ptr && !value.IsNil() { diff --git a/receiver_estimated_maximum_bitrate.go b/receiver_estimated_maximum_bitrate.go index deb1149..683db1c 100644 --- a/receiver_estimated_maximum_bitrate.go +++ b/receiver_estimated_maximum_bitrate.go @@ -91,7 +91,11 @@ func (p ReceiverEstimatedMaximumBitrate) MarshalTo(buf []byte) (n int, err error buf[15] = 'B' // Write the length of the ssrcs to follow at the end - buf[16] = byte(len(p.SSRCs)) + if len(p.SSRCs) > math.MaxUint8 { + return 0, errTooManySSRCs + } + + buf[16] = byte(len(p.SSRCs)) //nolint:gosec // length validated above exp := 0 bitrate := p.Bitrate @@ -118,9 +122,9 @@ func (p ReceiverEstimatedMaximumBitrate) MarshalTo(buf []byte) (n int, err error // We can't quite use the binary package because // a) it's a uint24 and b) the exponent is only 6-bits // Just trust me; this is big-endian encoding. - buf[17] = byte(exp<<2) | byte(mantissa>>16) - buf[18] = byte(mantissa >> 8) - buf[19] = byte(mantissa) + buf[17] = byte(exp<<2) | byte(mantissa>>16) //nolint: gosec // mantissa is limited to 18 bits + buf[18] = byte(mantissa >> 8) //nolint: gosec // mantissa is limited to 18 bits + buf[19] = byte(mantissa) // nolint: gosec // mantissa is limited to 18 bits // Write the SSRCs at the very end. n = 20 diff --git a/receiver_report.go b/receiver_report.go index 799638d..7e08a2a 100644 --- a/receiver_report.go +++ b/receiver_report.go @@ -6,6 +6,7 @@ package rtcp import ( "encoding/binary" "fmt" + "strings" ) // A ReceiverReport (RR) packet provides reception quality feedback for an RTP stream. @@ -188,12 +189,13 @@ func (r *ReceiverReport) DestinationSSRC() []uint32 { } func (r ReceiverReport) String() string { - out := fmt.Sprintf("ReceiverReport from %x\n", r.SSRC) - out += "\tSSRC \tLost\tLastSequence\n" + var out strings.Builder + fmt.Fprintf(&out, "ReceiverReport from %x\n", r.SSRC) + out.WriteString("\tSSRC \tLost\tLastSequence\n") for _, i := range r.Reports { - out += fmt.Sprintf("\t%x\t%d/%d\t%d\n", i.SSRC, i.FractionLost, i.TotalLost, i.LastSequenceNumber) + fmt.Fprintf(&out, "\t%x\t%d/%d\t%d\n", i.SSRC, i.FractionLost, i.TotalLost, i.LastSequenceNumber) } - out += fmt.Sprintf("\tProfile Extension Data: %v\n", r.ProfileExtensions) + fmt.Fprintf(&out, "\tProfile Extension Data: %v\n", r.ProfileExtensions) - return out + return out.String() } diff --git a/receiver_report_test.go b/receiver_report_test.go index 40155ab..e65c69a 100644 --- a/receiver_report_test.go +++ b/receiver_report_test.go @@ -169,7 +169,7 @@ func TestReceiverReportUnmarshal(t *testing.T) { func tooManyReports() []ReceptionReport { // a slice with enough ReceptionReports to overflow an 5-bit int var tooManyReports []ReceptionReport - for i := 0; i < (1 << 5); i++ { + for range 1 << 5 { tooManyReports = append(tooManyReports, ReceptionReport{ SSRC: 2, FractionLost: 2, diff --git a/rfc8888.go b/rfc8888.go index 8097be5..dad6b7f 100644 --- a/rfc8888.go +++ b/rfc8888.go @@ -8,6 +8,7 @@ import ( "errors" "fmt" "math" + "strings" ) // https://www.rfc-editor.org/rfc/rfc8888.html#name-rtcp-congestion-control-fee @@ -164,16 +165,17 @@ func (b CCFeedbackReport) Marshal() ([]byte, error) { } func (b CCFeedbackReport) String() string { - out := fmt.Sprintf("CCFB:\n\tHeader %v\n", b.Header()) - out += fmt.Sprintf("CCFB:\n\tSender SSRC %d\n", b.SenderSSRC) - out += fmt.Sprintf("\tReport Timestamp %d\n", b.ReportTimestamp) - out += "\tFeedback Reports \n" + var out strings.Builder + fmt.Fprintf(&out, "CCFB:\n\tHeader %v\n", b.Header()) + fmt.Fprintf(&out, "CCFB:\n\tSender SSRC %d\n", b.SenderSSRC) + fmt.Fprintf(&out, "\tReport Timestamp %d\n", b.ReportTimestamp) + out.WriteString("\tFeedback Reports \n") for _, report := range b.ReportBlocks { - out += fmt.Sprintf("%v ", report) + fmt.Fprintf(&out, "%v ", report) } - out += "\n" + out.WriteString("\n") - return out + return out.String() } // Unmarshal decodes the Congestion Control Feedback Report from binary. @@ -237,22 +239,21 @@ func (b *CCFeedbackReportBlock) len() int { } func (b CCFeedbackReportBlock) String() string { - out := fmt.Sprintf("\tReport Block Media SSRC %d\n", b.MediaSSRC) - out += fmt.Sprintf("\tReport Begin Sequence Nr %d\n", b.BeginSequence) - out += fmt.Sprintf("\tReport length %d\n\t", len(b.MetricBlocks)) + var out strings.Builder + fmt.Fprintf(&out, "\tReport Block Media SSRC %d\n", b.MediaSSRC) + fmt.Fprintf(&out, "\tReport Begin Sequence Nr %d\n", b.BeginSequence) + fmt.Fprintf(&out, "\tReport length %d\n\t", len(b.MetricBlocks)) for i, block := range b.MetricBlocks { //nolint:gosec // G115 - out += fmt.Sprintf( - "{nr: %d, rx: %v, ts: %v, ecn: %v} ", + fmt.Fprintf(&out, "{nr: %d, rx: %v, ts: %v, ecn: %v} ", b.BeginSequence+uint16(i), block.Received, block.ArrivalTimeOffset, - block.ECN, - ) + block.ECN) } - out += "\n" + out.WriteString("\n") - return out + return out.String() } // marshal encodes the Congestion Control Feedback Report Block in binary. @@ -301,7 +302,7 @@ func (b *CCFeedbackReportBlock) unmarshal(rawPacket []byte) error { } b.MetricBlocks = make([]CCFeedbackMetricBlock, numReports) - for i := int(0); i < numReports; i++ { + for i := range numReports { var mb CCFeedbackMetricBlock offset := reportsOffset + 2*i if err := mb.unmarshal(rawPacket[offset : offset+2]); err != nil { diff --git a/rfc8888_test.go b/rfc8888_test.go index 5dc9665..9324db0 100644 --- a/rfc8888_test.go +++ b/rfc8888_test.go @@ -74,7 +74,6 @@ func TestCCFeedbackMetricBlockUnmarshalMarshal(t *testing.T) { }, }, } { - test := test t.Run(fmt.Sprintf("Unmarshal-%v", test.Name), func(t *testing.T) { var block CCFeedbackMetricBlock err := block.unmarshal(test.Data) @@ -112,7 +111,6 @@ func TestCCFeedbackMetricBlockUnmarshalMarshal(t *testing.T) { }, }, } { - test := test t.Run(fmt.Sprintf("Unmarshal-%v", test.Name), func(t *testing.T) { var block CCFeedbackMetricBlock err := block.unmarshal(test.Data) @@ -122,7 +120,6 @@ func TestCCFeedbackMetricBlockUnmarshalMarshal(t *testing.T) { } for _, l := range []int{0, 1, 3} { - l := l t.Run(fmt.Sprintf("shortMetricBlock-%v", l), func(t *testing.T) { var block CCFeedbackMetricBlock data := make([]byte, l) @@ -248,7 +245,6 @@ func TestCCFeedbackReportBlockUnmarshalMarshal(t *testing.T) { }, }, } { - test := test t.Run(fmt.Sprintf("Unmarshal-%v", test.Name), func(t *testing.T) { var block CCFeedbackReportBlock err := block.unmarshal(test.Data) @@ -409,7 +405,6 @@ func TestCCFeedbackReportUnmarshalMarshal(t *testing.T) { }, }, } { - test := test t.Run(fmt.Sprintf("Unmarshal-%v", test.Name), func(t *testing.T) { pkts, err := Unmarshal(test.Data) assert.NoError(t, err) diff --git a/sender_report.go b/sender_report.go index 6c18840..9e5ed57 100644 --- a/sender_report.go +++ b/sender_report.go @@ -6,6 +6,7 @@ package rtcp import ( "encoding/binary" "fmt" + "strings" ) // A SenderReport (SR) packet provides reception quality feedback for an RTP stream. @@ -249,17 +250,18 @@ func (r *SenderReport) Header() Header { } func (r SenderReport) String() string { - out := fmt.Sprintf("SenderReport from %x\n", r.SSRC) - out += fmt.Sprintf("\tNTPTime:\t%d\n", r.NTPTime) - out += fmt.Sprintf("\tRTPTIme:\t%d\n", r.RTPTime) - out += fmt.Sprintf("\tPacketCount:\t%d\n", r.PacketCount) - out += fmt.Sprintf("\tOctetCount:\t%d\n", r.OctetCount) + var out strings.Builder + fmt.Fprintf(&out, "SenderReport from %x\n", r.SSRC) + fmt.Fprintf(&out, "\tNTPTime:\t%d\n", r.NTPTime) + fmt.Fprintf(&out, "\tRTPTIme:\t%d\n", r.RTPTime) + fmt.Fprintf(&out, "\tPacketCount:\t%d\n", r.PacketCount) + fmt.Fprintf(&out, "\tOctetCount:\t%d\n", r.OctetCount) - out += "\tSSRC \tLost\tLastSequence\n" + out.WriteString("\tSSRC \tLost\tLastSequence\n") for _, i := range r.Reports { - out += fmt.Sprintf("\t%x\t%d/%d\t%d\n", i.SSRC, i.FractionLost, i.TotalLost, i.LastSequenceNumber) + fmt.Fprintf(&out, "\t%x\t%d/%d\t%d\n", i.SSRC, i.FractionLost, i.TotalLost, i.LastSequenceNumber) } - out += fmt.Sprintf("\tProfile Extension Data: %v\n", r.ProfileExtensions) + fmt.Fprintf(&out, "\tProfile Extension Data: %v\n", r.ProfileExtensions) - return out + return out.String() } diff --git a/source_description.go b/source_description.go index bac4014..951bf8f 100644 --- a/source_description.go +++ b/source_description.go @@ -6,6 +6,7 @@ package rtcp import ( "encoding/binary" "fmt" + "strings" ) // SDESType is the item type used in the RTCP SDES control packet. @@ -365,10 +366,11 @@ func (s *SourceDescription) DestinationSSRC() []uint32 { } func (s *SourceDescription) String() string { - out := "Source Description:\n" + var out strings.Builder + out.WriteString("Source Description:\n") for _, c := range s.Chunks { - out += fmt.Sprintf("\t%x: %s\n", c.Source, c.Items) + fmt.Fprintf(&out, "\t%x: %s\n", c.Source, c.Items) } - return out + return out.String() } diff --git a/source_description_test.go b/source_description_test.go index 4f2f267..e95a57b 100644 --- a/source_description_test.go +++ b/source_description_test.go @@ -4,6 +4,7 @@ package rtcp import ( + "strings" "testing" "github.com/stretchr/testify/assert" @@ -229,13 +230,13 @@ func TestSourceDescriptionUnmarshal(t *testing.T) { func TestSourceDescriptionRoundTrip(t *testing.T) { // a slice with enough SourceDescriptionChunks to overflow an 5-bit int var tooManyChunks []SourceDescriptionChunk - var tooLongText string + var tooLongText strings.Builder - for i := 0; i < (1 << 5); i++ { + for range 1 << 5 { tooManyChunks = append(tooManyChunks, SourceDescriptionChunk{}) } - for i := 0; i < (1 << 8); i++ { - tooLongText += "x" + for range 1 << 8 { + tooLongText.WriteString("x") } for _, test := range []struct { @@ -314,7 +315,7 @@ func TestSourceDescriptionRoundTrip(t *testing.T) { Chunks: []SourceDescriptionChunk{{ Items: []SourceDescriptionItem{{ Type: SDESCNAME, - Text: tooLongText, + Text: tooLongText.String(), }}, }}, }, diff --git a/transport_layer_cc.go b/transport_layer_cc.go index 8a6d237..f5a3c03 100644 --- a/transport_layer_cc.go +++ b/transport_layer_cc.go @@ -10,6 +10,7 @@ import ( "errors" "fmt" "math" + "strings" ) // https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01#page-5 @@ -223,20 +224,20 @@ func (r *StatusVectorChunk) Unmarshal(rawPacket []byte) error { r.SymbolSize = getNBitsFromByte(rawPacket[0], 1, 1) if r.SymbolSize == TypeTCCSymbolSizeOneBit { - for i := uint16(0); i < 6; i++ { + for i := range uint16(6) { r.SymbolList = append(r.SymbolList, getNBitsFromByte(rawPacket[0], 2+i, 1)) } - for i := uint16(0); i < 8; i++ { + for i := range uint16(8) { r.SymbolList = append(r.SymbolList, getNBitsFromByte(rawPacket[1], i, 1)) } return nil } if r.SymbolSize == TypeTCCSymbolSizeTwoBit { - for i := uint16(0); i < 3; i++ { + for i := range uint16(3) { r.SymbolList = append(r.SymbolList, getNBitsFromByte(rawPacket[0], 2+i*2, 2)) } - for i := uint16(0); i < 4; i++ { + for i := range uint16(4) { r.SymbolList = append(r.SymbolList, getNBitsFromByte(rawPacket[1], i*2, 2)) } @@ -278,7 +279,7 @@ func (r RecvDelta) Marshal() ([]byte, error) { // big delta if r.Type == TypeTCCPacketReceivedLargeDelta && delta >= math.MinInt16 && delta <= math.MaxInt16 { deltaChunk := make([]byte, 2) - binary.BigEndian.PutUint16(deltaChunk, uint16(delta)) + binary.BigEndian.PutUint16(deltaChunk, uint16(delta)) //nolint:gosec //delta is validated to fit in uint16 return deltaChunk, nil } @@ -392,24 +393,25 @@ func (t *TransportLayerCC) MarshalSize() int { } func (t TransportLayerCC) String() string { - out := fmt.Sprintf("TransportLayerCC:\n\tHeader %v\n", t.Header) - out += fmt.Sprintf("TransportLayerCC:\n\tSender Ssrc %d\n", t.SenderSSRC) - out += fmt.Sprintf("\tMedia Ssrc %d\n", t.MediaSSRC) - out += fmt.Sprintf("\tBase Sequence Number %d\n", t.BaseSequenceNumber) - out += fmt.Sprintf("\tStatus Count %d\n", t.PacketStatusCount) - out += fmt.Sprintf("\tReference Time %d\n", t.ReferenceTime) - out += fmt.Sprintf("\tFeedback Packet Count %d\n", t.FbPktCount) - out += "\tPacketChunks " + var out strings.Builder + fmt.Fprintf(&out, "TransportLayerCC:\n\tHeader %v\n", t.Header) + fmt.Fprintf(&out, "TransportLayerCC:\n\tSender Ssrc %d\n", t.SenderSSRC) + fmt.Fprintf(&out, "\tMedia Ssrc %d\n", t.MediaSSRC) + fmt.Fprintf(&out, "\tBase Sequence Number %d\n", t.BaseSequenceNumber) + fmt.Fprintf(&out, "\tStatus Count %d\n", t.PacketStatusCount) + fmt.Fprintf(&out, "\tReference Time %d\n", t.ReferenceTime) + fmt.Fprintf(&out, "\tFeedback Packet Count %d\n", t.FbPktCount) + out.WriteString("\tPacketChunks ") for _, chunk := range t.PacketChunks { - out += fmt.Sprintf("%+v ", chunk) + fmt.Fprintf(&out, "%+v ", chunk) } - out += "\n\tRecvDeltas " + out.WriteString("\n\tRecvDeltas ") for _, delta := range t.RecvDeltas { - out += fmt.Sprintf("%+v ", delta) + fmt.Fprintf(&out, "%+v ", delta) } - out += "\n" + out.WriteString("\n") - return out + return out.String() } // Marshal encodes the TransportLayerCC in binary. @@ -511,7 +513,7 @@ func (t *TransportLayerCC) Unmarshal(rawPacket []byte) error { packetNumberToProcess := localMin(t.PacketStatusCount-processedPacketNum, packetStatus.RunLength) if packetStatus.PacketStatusSymbol == TypeTCCPacketReceivedSmallDelta || packetStatus.PacketStatusSymbol == TypeTCCPacketReceivedLargeDelta { - for j := uint16(0); j < packetNumberToProcess; j++ { + for range packetNumberToProcess { t.RecvDeltas = append(t.RecvDeltas, &RecvDelta{Type: packetStatus.PacketStatusSymbol}) } } diff --git a/transport_layer_cc_test.go b/transport_layer_cc_test.go index 8f75e15..e366f7f 100644 --- a/transport_layer_cc_test.go +++ b/transport_layer_cc_test.go @@ -753,7 +753,6 @@ func TestTransportLayerCC_Unmarshal(t *testing.T) { WantError: errPacketTooShort, }, } { - test := test t.Run(test.Name, func(t *testing.T) { var chunk TransportLayerCC err := chunk.Unmarshal(test.Data) @@ -1159,7 +1158,6 @@ func TestTransportLayerCC_Marshal(t *testing.T) { WantError: nil, }, } { - test := test t.Run(test.Name, func(t *testing.T) { bin, err := test.Data.Marshal() assert.NoError(t, err) diff --git a/transport_layer_nack.go b/transport_layer_nack.go index 7431a64..f728b2d 100644 --- a/transport_layer_nack.go +++ b/transport_layer_nack.go @@ -7,6 +7,7 @@ import ( "encoding/binary" "fmt" "math" + "strings" ) // PacketBitmap shouldn't be used like a normal integral, @@ -171,14 +172,15 @@ func (p *TransportLayerNack) Header() Header { } func (p TransportLayerNack) String() string { - out := fmt.Sprintf("TransportLayerNack from %x\n", p.SenderSSRC) - out += fmt.Sprintf("\tMedia Ssrc %x\n", p.MediaSSRC) - out += "\tID\tLostPackets\n" + var out strings.Builder + fmt.Fprintf(&out, "TransportLayerNack from %x\n", p.SenderSSRC) + fmt.Fprintf(&out, "\tMedia Ssrc %x\n", p.MediaSSRC) + out.WriteString("\tID\tLostPackets\n") for _, i := range p.Nacks { - out += fmt.Sprintf("\t%d\t%b\n", i.PacketID, i.LostPackets) + fmt.Fprintf(&out, "\t%d\t%b\n", i.PacketID, i.LostPackets) } - return out + return out.String() } // DestinationSSRC returns an array of SSRC values that this packet refers to. diff --git a/util_test.go b/util_test.go index 0d97847..83cafa6 100644 --- a/util_test.go +++ b/util_test.go @@ -61,7 +61,6 @@ func TestSetNBitsOfUint16(t *testing.T) { "setOneBitOutOfBounds", 32768, 2, 15, 1, 0, errInvalidSizeOrStartIndex, }, } { - test := test t.Run(test.name, func(t *testing.T) { got, err := setNBitsOfUint16(test.source, test.size, test.index, test.value) if test.expectedErr != nil {