From 73da673ed1ce4905ff7228b0395e930e3d50884b Mon Sep 17 00:00:00 2001 From: Jeff Bailey Date: Wed, 24 Jul 2024 10:32:53 -0700 Subject: [PATCH] fix: include segmentationUpidFormat when encoding to json/xml (#61) --- .github/workflows/check.yml | 29 ++++----------- .golangci.yaml | 46 +++++++++++++++++++++++ README.md | 7 ++-- cmd/decode.go | 4 +- cmd/encode.go | 4 +- go.mod | 4 +- pkg/scte35/audio_descriptor.go | 2 +- pkg/scte35/delivery_restrictions.go | 1 + pkg/scte35/encrypted_packet.go | 4 +- pkg/scte35/scte35_test.go | 53 +++++++++++++++------------ pkg/scte35/segmentation_descriptor.go | 2 +- pkg/scte35/segmentation_upid.go | 34 ++++++++++++----- pkg/scte35/splice_descriptor.go | 1 - pkg/scte35/splice_insert.go | 3 +- pkg/scte35/splice_schedule.go | 4 +- pkg/scte35/table.go | 2 +- 16 files changed, 129 insertions(+), 71 deletions(-) create mode 100644 .golangci.yaml diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 4f9d362d0..4c0b0ee7d 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -17,29 +17,16 @@ jobs: - name: Check out code uses: actions/checkout@v3 - - name: Install Go + - name: Setup Go uses: actions/setup-go@v4 with: - go-version: "1.20" check-latest: true - - name: Go Format - run: gofmt -s -w . && git diff --exit-code - - - name: Go Tidy - run: go mod tidy && git diff --exit-code - - - name: Go Mod - run: go mod download - - - name: Go Mod Verify - run: go mod verify - - - name: Go Vet - run: go vet ./... - - - name: Go Build - run: go build -o /dev/null ./... + - name: Run linters + uses: golangci/golangci-lint-action@v6 + with: + version: latest + args: -v --timeout=5m - - name: Go Test - run: go test -v -count=1 -race -shuffle=on ./... + - name: Run Test + run: go test --race ./... diff --git a/.golangci.yaml b/.golangci.yaml new file mode 100644 index 000000000..44c489ac4 --- /dev/null +++ b/.golangci.yaml @@ -0,0 +1,46 @@ +--- +run: + tests: false + timeout: 5m + +linters-settings: + errcheck: + check-type-assertions: true + +linters: + enable: + - bodyclose + - containedctx + - contextcheck + - copyloopvar + - decorder + - errname + - errorlint + - exhaustive + - exportloopref + - gci + - gochecknoinits + - gocritic + - godox + - gofmt + - goimports + - goprintffuncname + - gosec + - intrange + - misspell + - noctx + - nosprintfhostport + - revive + - sqlclosecheck + - stylecheck + - testpackage + - unparam + - wastedassign + - whitespace + +issues: + include: + - EXC0012 + - EXC0013 + - EXC0014 + - EXC0015 diff --git a/README.md b/README.md index a38c03fcc..32bda70ff 100644 --- a/README.md +++ b/README.md @@ -112,12 +112,13 @@ avail_descriptor() { } XML: - + + - - WU1XRjA0NTIwMDBI + + WU1XRjA0NTIwMDBI diff --git a/cmd/decode.go b/cmd/decode.go index 5dbc2f4fc..46e42b309 100644 --- a/cmd/decode.go +++ b/cmd/decode.go @@ -33,13 +33,13 @@ func decodeCommand() *cobra.Command { cmd := &cobra.Command{ Use: "decode", Short: "Decode a splice_info_section from binary", - Args: func(cmd *cobra.Command, args []string) error { + Args: func(_ *cobra.Command, args []string) error { if len(args) != 1 { return fmt.Errorf("requires a binary signal") } return nil }, - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, args []string) { bin := args[0] var sis *scte35.SpliceInfoSection var err error diff --git a/cmd/encode.go b/cmd/encode.go index 1cd3abb11..cd3850dc1 100644 --- a/cmd/encode.go +++ b/cmd/encode.go @@ -33,13 +33,13 @@ func encodeCommand() *cobra.Command { cmd := &cobra.Command{ Use: "encode < filename or encode {\"protocolVersion\"... ", Short: "Encode a splice_info_section to binary being provided from stdin or as a parameter", - Args: func(cmd *cobra.Command, args []string) error { + Args: func(_ *cobra.Command, args []string) error { if len(args) > 1 { return fmt.Errorf("invalid number of parameter provided") } return nil }, - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, args []string) { var err error var input string var sis *scte35.SpliceInfoSection diff --git a/go.mod b/go.mod index cb6a11f4e..9191fa672 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,8 @@ module github.com/Comcast/scte35-go -go 1.18 +go 1.22.0 + +toolchain go1.22.5 require ( github.com/bamiaux/iobit v0.0.0-20170418073505-498159a04883 diff --git a/pkg/scte35/audio_descriptor.go b/pkg/scte35/audio_descriptor.go index c1b4e36a0..4ad6c18b3 100644 --- a/pkg/scte35/audio_descriptor.go +++ b/pkg/scte35/audio_descriptor.go @@ -55,7 +55,7 @@ func (sd *AudioDescriptor) decode(b []byte) error { audioCount := int(r.Uint32(4)) r.Skip(4) // reserved sd.AudioChannels = make([]AudioChannel, audioCount) - for i := 0; i < audioCount; i++ { + for i := range audioCount { ac := AudioChannel{} ac.ComponentTag = r.Uint32(8) ac.ISOCode = r.String(3) diff --git a/pkg/scte35/delivery_restrictions.go b/pkg/scte35/delivery_restrictions.go index 93b125c2a..9d41da655 100644 --- a/pkg/scte35/delivery_restrictions.go +++ b/pkg/scte35/delivery_restrictions.go @@ -49,6 +49,7 @@ func (dr *DeliveryRestrictions) deviceRestrictionsName() string { case DeviceRestrictionsNone: return "None" default: + // nolint:goconst return "Unknown" } } diff --git a/pkg/scte35/encrypted_packet.go b/pkg/scte35/encrypted_packet.go index 348b4c884..1f157bf7c 100644 --- a/pkg/scte35/encrypted_packet.go +++ b/pkg/scte35/encrypted_packet.go @@ -31,8 +31,8 @@ const ( // EncryptedPacket contains the encryption details if this payload has been // encrypted. type EncryptedPacket struct { - EncryptionAlgorithm uint32 `xml:"encryptionAlgorithm,attr,omitempty" json:"encryptionAlgorithm,omitempty"` - CWIndex uint32 `xml:"cwIndex,attr,omitempty" json:"cwIndex,omitempty"` + EncryptionAlgorithm uint32 `xml:"encryptionAlgorithm,attr" json:"encryptionAlgorithm"` + CWIndex uint32 `xml:"cwIndex,attr" json:"cwIndex"` } // encryptionAlgorithmName returns the user-friendly encryption algorithm name diff --git a/pkg/scte35/scte35_test.go b/pkg/scte35/scte35_test.go index b66509ab0..a0aa92af9 100644 --- a/pkg/scte35/scte35_test.go +++ b/pkg/scte35/scte35_test.go @@ -362,8 +362,9 @@ func TestDecodeBase64(t *testing.T) { }, SegmentationUPIDs: []scte35.SegmentationUPID{ { - Type: 8, - Value: "791755781", + Type: 8, + Format: scte35.SegmentationUPIDFormatText, + Value: "791755781", }, }, SegmentationTypeID: 53, @@ -378,8 +379,9 @@ func TestDecodeBase64(t *testing.T) { }, SegmentationUPIDs: []scte35.SegmentationUPID{ { - Type: 8, - Value: "791755998", + Type: 8, + Format: scte35.SegmentationUPIDFormatText, + Value: "791755998", }, }, SegmentationTypeID: 35, @@ -423,16 +425,19 @@ func TestDecodeBase64(t *testing.T) { &scte35.SegmentationDescriptor{ SegmentationUPIDs: []scte35.SegmentationUPID{ { - Type: scte35.SegmentationUPIDTypeEIDR, - Value: "10.5239/8BE5-E3F6-0000-0000-0000", + Type: scte35.SegmentationUPIDTypeEIDR, + Format: scte35.SegmentationUPIDFormatText, + Value: "10.5239/8BE5-E3F6-0000-0000-0000", }, { - Type: scte35.SegmentationUPIDTypeEIDR, - Value: "10.5239/8BE5-E3F6-0000-0000-0000", + Type: scte35.SegmentationUPIDTypeEIDR, + Format: scte35.SegmentationUPIDFormatText, + Value: "10.5239/8BE5-E3F6-0000-0000-0000", }, { - Type: scte35.SegmentationUPIDTypeADI, - Value: "SIGNAL:Ly9EMGxKR0hFZUtpMHdCUVZnRUFnZz1", + Type: scte35.SegmentationUPIDTypeADI, + Format: scte35.SegmentationUPIDFormatText, + Value: "SIGNAL:Ly9EMGxKR0hFZUtpMHdCUVZnRUFnZz1", }, }, SegmentationEventID: 2, @@ -454,6 +459,7 @@ func TestDecodeBase64(t *testing.T) { SegmentationUPIDs: []scte35.SegmentationUPID{ { Type: scte35.SegmentationUPIDTypeMPU, + Format: scte35.SegmentationUPIDFormatBase64, FormatIdentifier: uint32ptr(1145656131), Value: "WU1XRjA0NTIwMDBI", }, @@ -486,8 +492,9 @@ func TestDecodeBase64(t *testing.T) { &scte35.SegmentationDescriptor{ SegmentationUPIDs: []scte35.SegmentationUPID{ { - Type: scte35.SegmentationUPIDTypeURI, - Value: "urn:nbcuni.com:brc:499866434", + Type: scte35.SegmentationUPIDTypeURI, + Format: scte35.SegmentationUPIDFormatText, + Value: "urn:nbcuni.com:brc:499866434", }, }, SegmentationDuration: uint64ptr(1347087), @@ -546,7 +553,7 @@ func TestDecodeBase64(t *testing.T) { DeviceRestrictions: 3, }, SegmentationUPIDs: []scte35.SegmentationUPID{ - {Type: scte35.SegmentationUPIDTypeTI, Value: "1044285552"}, + {Type: scte35.SegmentationUPIDTypeTI, Format: scte35.SegmentationUPIDFormatText, Value: "1044285552"}, }, }, &scte35.SegmentationDescriptor{ @@ -559,7 +566,7 @@ func TestDecodeBase64(t *testing.T) { DeviceRestrictions: 3, }, SegmentationUPIDs: []scte35.SegmentationUPID{ - {Type: scte35.SegmentationUPIDTypeTI, Value: "1044285552"}, + {Type: scte35.SegmentationUPIDTypeTI, Format: scte35.SegmentationUPIDFormatText, Value: "1044285552"}, }, }, &scte35.SegmentationDescriptor{ @@ -572,7 +579,7 @@ func TestDecodeBase64(t *testing.T) { DeviceRestrictions: 3, }, SegmentationUPIDs: []scte35.SegmentationUPID{ - {Type: scte35.SegmentationUPIDTypeTI, Value: "1044285622"}, + {Type: scte35.SegmentationUPIDTypeTI, Format: scte35.SegmentationUPIDFormatText, Value: "1044285622"}, }, }, &scte35.SegmentationDescriptor{ @@ -586,7 +593,7 @@ func TestDecodeBase64(t *testing.T) { DeviceRestrictions: 3, }, SegmentationUPIDs: []scte35.SegmentationUPID{ - {Type: scte35.SegmentationUPIDTypeTI, Value: "1044285622"}, + {Type: scte35.SegmentationUPIDTypeTI, Format: scte35.SegmentationUPIDFormatText, Value: "1044285622"}, }, }, &scte35.SegmentationDescriptor{ @@ -602,13 +609,13 @@ func TestDecodeBase64(t *testing.T) { DeviceRestrictions: 3, }, SegmentationUPIDs: []scte35.SegmentationUPID{ - {Type: scte35.SegmentationUPIDTypeEIDR, Value: "10.5239/F9B9-7B34-0000-0000-0000"}, - {Type: scte35.SegmentationUPIDTypeADS, Value: "type=LA&dur=60000&tierĂ¼0"}, - {Type: uint32(199)}, - {Type: uint32(0)}, - {Type: uint32(0)}, - {Type: uint32(0)}, - {Type: uint32(255)}, + {Type: scte35.SegmentationUPIDTypeEIDR, Format: scte35.SegmentationUPIDFormatText, Value: "10.5239/F9B9-7B34-0000-0000-0000"}, + {Type: scte35.SegmentationUPIDTypeADS, Format: scte35.SegmentationUPIDFormatText, Value: "type=LA&dur=60000&tierĂ¼0"}, + {Type: uint32(199), Format: scte35.SegmentationUPIDFormatText}, + {Type: uint32(0), Format: scte35.SegmentationUPIDFormatText}, + {Type: uint32(0), Format: scte35.SegmentationUPIDFormatText}, + {Type: uint32(0), Format: scte35.SegmentationUPIDFormatText}, + {Type: uint32(255), Format: scte35.SegmentationUPIDFormatText}, }, }, }, diff --git a/pkg/scte35/segmentation_descriptor.go b/pkg/scte35/segmentation_descriptor.go index 7144662e5..bcce9b3d4 100644 --- a/pkg/scte35/segmentation_descriptor.go +++ b/pkg/scte35/segmentation_descriptor.go @@ -354,7 +354,7 @@ func (sd *SegmentationDescriptor) decode(b []byte) error { if !programSegmentationFlag { componentCount := int(r.Uint32(8)) sd.Components = make([]SegmentationDescriptorComponent, componentCount) - for i := 0; i < componentCount; i++ { + for i := range componentCount { c := SegmentationDescriptorComponent{} c.Tag = r.Uint32(8) r.Skip(7) // reserved diff --git a/pkg/scte35/segmentation_upid.go b/pkg/scte35/segmentation_upid.go index b1458832c..5f1164125 100644 --- a/pkg/scte35/segmentation_upid.go +++ b/pkg/scte35/segmentation_upid.go @@ -69,6 +69,16 @@ const ( SegmentationUPIDTypeUUID = 0x10 // SegmentationUPIDTypeSCR is the segmentation_upid_type for SCR. SegmentationUPIDTypeSCR = 0x11 + + // SegmentationUPIDFormatText is the text segmentation upid value format. + SegmentationUPIDFormatText = "text" + // SegmentationUPIDFormatHex is the hex segmentation upid value format. + SegmentationUPIDFormatHex = "hex" + // SegmentationUPIDFormatBase64 is the hex segmentation upid value format. + SegmentationUPIDFormatBase64 = "base-64" + // SegmentationUPIDFormatPrivatePrefix is the private segmentation upid value + // format. + SegmentationUPIDFormatPrivatePrefix = "private:" ) // NewSegmentationUPID construct a new SegmentationUPID @@ -79,36 +89,41 @@ func NewSegmentationUPID(upidType uint32, buf []byte) SegmentationUPID { // EIDR - custom case SegmentationUPIDTypeEIDR: return SegmentationUPID{ - Type: upidType, - Value: canonicalEIDR(r.LeftBytes()), + Type: upidType, + Format: SegmentationUPIDFormatText, + Value: canonicalEIDR(r.LeftBytes()), } // ISAN - base64 case SegmentationUPIDTypeISAN, SegmentationUPIDTypeISANDeprecated: return SegmentationUPID{ - Type: upidType, - Value: base64.StdEncoding.EncodeToString(r.LeftBytes()), + Type: upidType, + Format: SegmentationUPIDFormatBase64, + Value: base64.StdEncoding.EncodeToString(r.LeftBytes()), } // MPU - custom case SegmentationUPIDTypeMPU: fi := r.Uint32(32) return SegmentationUPID{ Type: upidType, + Format: SegmentationUPIDFormatBase64, FormatIdentifier: &fi, Value: base64.StdEncoding.EncodeToString(r.LeftBytes()), } // TI - unsigned int case SegmentationUPIDTypeTI: return SegmentationUPID{ - Type: upidType, - Value: strconv.FormatUint(r.Uint64(r.LeftBits()), 10), + Format: SegmentationUPIDFormatText, + Type: upidType, + Value: strconv.FormatUint(r.Uint64(r.LeftBits()), 10), } // everything else - plain text default: // decode troublesome Latin1 characters to their UTF8 equivalents b, _ := charmap.ISO8859_1.NewDecoder().Bytes(r.LeftBytes()) return SegmentationUPID{ - Type: upidType, - Value: string(b), + Type: upidType, + Format: SegmentationUPIDFormatText, + Value: string(b), } } } @@ -116,10 +131,9 @@ func NewSegmentationUPID(upidType uint32, buf []byte) SegmentationUPID { // SegmentationUPID is used to express a UPID in an XML document. type SegmentationUPID struct { Type uint32 `xml:"segmentationUpidType,attr" json:"segmentationUpidType"` + Format string `xml:"segmentationUpidFormat,attr,omitempty" json:"segmentationUpidFormat,omitempty"` FormatIdentifier *uint32 `xml:"formatIdentifier,attr,omitempty" json:"formatIdentifier,omitempty"` Value string `xml:",chardata" json:"value"` - // Deprecated: no longer used and will be removed in a future release - Format string `xml:"-" json:"-"` } // Name returns the name for the segmentation_upid_type. diff --git a/pkg/scte35/splice_descriptor.go b/pkg/scte35/splice_descriptor.go index a44d98d95..d95cfa0f4 100644 --- a/pkg/scte35/splice_descriptor.go +++ b/pkg/scte35/splice_descriptor.go @@ -52,7 +52,6 @@ func NewSpliceDescriptor(identifier uint32, tag uint32) SpliceDescriptor { // as a last resort, fall back to private_descriptor. This is not strictly // compliant but allows us to deal with a wider array of quirky signals. return &PrivateDescriptor{Identifier: identifier} - } // SpliceDescriptor is a prototype for adding new fields to the diff --git a/pkg/scte35/splice_insert.go b/pkg/scte35/splice_insert.go index 18869b6d3..bb7efee35 100644 --- a/pkg/scte35/splice_insert.go +++ b/pkg/scte35/splice_insert.go @@ -109,6 +109,7 @@ func (cmd *SpliceInsert) writeTo(t *table) { } // decode a binary splice_insert. +// nolint: nestif func (cmd *SpliceInsert) decode(b []byte) error { r := iobit.NewReader(b) @@ -136,7 +137,7 @@ func (cmd *SpliceInsert) decode(b []byte) error { } else { componentCount := int(r.Uint32(8)) cmd.Components = make([]SpliceInsertComponent, componentCount) - for i := 0; i < componentCount; i++ { + for i := range componentCount { c := SpliceInsertComponent{} c.Tag = r.Uint32(8) if !cmd.SpliceImmediateFlag { diff --git a/pkg/scte35/splice_schedule.go b/pkg/scte35/splice_schedule.go index e9611c1cd..86b12a2ef 100644 --- a/pkg/scte35/splice_schedule.go +++ b/pkg/scte35/splice_schedule.go @@ -51,7 +51,7 @@ func (cmd *SpliceSchedule) decode(b []byte) error { spliceCount := int(r.Uint32(8)) cmd.Events = make([]Event, spliceCount) - for i := 0; i < spliceCount; i++ { + for i := range spliceCount { e := Event{} e.SpliceEventID = r.Uint32(32) e.SpliceEventCancelIndicator = r.Bit() @@ -66,7 +66,7 @@ func (cmd *SpliceSchedule) decode(b []byte) error { } else { componentCount := int(r.Uint32(8)) e.Components = make([]EventComponent, componentCount) - for j := 0; j < componentCount; j++ { + for j := range componentCount { c := EventComponent{} c.Tag = r.Uint32(8) c.UTCSpliceTime = NewUTCSpliceTime(r.Uint32(32)) diff --git a/pkg/scte35/table.go b/pkg/scte35/table.go index ed80971b8..702e16efa 100644 --- a/pkg/scte35/table.go +++ b/pkg/scte35/table.go @@ -26,7 +26,7 @@ type table struct { // row0 writes a new row with 0 indents. func (t *table) row(indents int, key string, value any) { _, _ = t.b.WriteString(t.prefix) - for i := 0; i < indents; i++ { + for range indents { _, _ = t.b.WriteString(t.indent) } _, _ = t.b.WriteString(key)