diff --git a/cyclonedx.go b/cyclonedx.go index 1ac57f7..f995afe 100644 --- a/cyclonedx.go +++ b/cyclonedx.go @@ -19,10 +19,11 @@ package cyclonedx import ( "encoding/xml" + "fmt" "regexp" ) -//go:generate stringer -linecomment -output cyclonedx_string.go -type SpecVersion +//go:generate stringer -linecomment -output cyclonedx_string.go -type MediaType,SpecVersion const ( BOMFormat = "CycloneDX" @@ -319,6 +320,24 @@ type LicenseChoice struct { Expression string `json:"expression,omitempty" xml:"-"` } +// MediaType defines the official media types for CycloneDX BOMs. +// See https://cyclonedx.org/specification/overview/#registered-media-types +type MediaType int + +const ( + MediaTypeJSON MediaType = iota + 1 // application/vnd.cyclonedx+json + MediaTypeXML // application/vnd.cyclonedx+xml + MediaTypeProtobuf // application/x.vnd.cyclonedx+protobuf +) + +func (mt MediaType) WithVersion(specVersion SpecVersion) (string, error) { + if mt == MediaTypeJSON && specVersion < SpecVersion1_2 { + return "", fmt.Errorf("json format is not supported for specification versions lower than %s", SpecVersion1_2) + } + + return fmt.Sprintf("%s; version=%s", mt, specVersion), nil +} + type Metadata struct { Timestamp string `json:"timestamp,omitempty" xml:"timestamp,omitempty"` Tools *[]Tool `json:"tools,omitempty" xml:"tools>tool,omitempty"` diff --git a/cyclonedx_string.go b/cyclonedx_string.go index 25ccfc9..32e6763 100644 --- a/cyclonedx_string.go +++ b/cyclonedx_string.go @@ -1,9 +1,29 @@ -// Code generated by "stringer -linecomment -output cyclonedx_string.go -type SpecVersion"; DO NOT EDIT. +// Code generated by "stringer -linecomment -output cyclonedx_string.go -type MediaType,SpecVersion"; DO NOT EDIT. package cyclonedx import "strconv" +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[MediaTypeJSON-1] + _ = x[MediaTypeXML-2] + _ = x[MediaTypeProtobuf-3] +} + +const _MediaType_name = "application/vnd.cyclonedx+jsonapplication/vnd.cyclonedx+xmlapplication/x.vnd.cyclonedx+protobuf" + +var _MediaType_index = [...]uint8{0, 30, 59, 95} + +func (i MediaType) String() string { + i -= 1 + if i < 0 || i >= MediaType(len(_MediaType_index)-1) { + return "MediaType(" + strconv.FormatInt(int64(i+1), 10) + ")" + } + return _MediaType_name[_MediaType_index[i]:_MediaType_index[i+1]] +} func _() { // An "invalid array index" compiler error signifies that the constant values have changed. // Re-run the stringer command to generate them again. diff --git a/cyclonedx_test.go b/cyclonedx_test.go index bfcb8fd..54fd861 100644 --- a/cyclonedx_test.go +++ b/cyclonedx_test.go @@ -25,6 +25,7 @@ import ( "github.com/bradleyjkemp/cupaloy/v2" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) var snapShooter = cupaloy.NewDefaultConfig(). @@ -35,6 +36,19 @@ func TestBool(t *testing.T) { assert.Equal(t, false, *Bool(false)) } +func TestMediaType_WithVersion(t *testing.T) { + t.Run("ShouldReturnVersionedMediaType", func(t *testing.T) { + res, err := MediaTypeJSON.WithVersion(SpecVersion1_2) + require.NoError(t, err) + require.Equal(t, "application/vnd.cyclonedx+json; version=1.2", res) + }) + + t.Run("ShouldReturnErrorForSpecLowerThan1.2AndJSON", func(t *testing.T) { + _, err := MediaTypeJSON.WithVersion(SpecVersion1_1) + require.Error(t, err) + }) +} + func TestVulnerability_Properties(t *testing.T) { // GIVEN properties := []Property{} diff --git a/encode.go b/encode.go index b03843d..371c364 100644 --- a/encode.go +++ b/encode.go @@ -52,7 +52,7 @@ type jsonBOMEncoder struct { // Encode implements the BOMEncoder interface. func (j jsonBOMEncoder) Encode(bom *BOM) error { if bom.SpecVersion < SpecVersion1_2 { - return fmt.Errorf("json format is not supported for specification versions lower than 1.2") + return fmt.Errorf("json format is not supported for specification versions lower than %s", SpecVersion1_2) } encoder := json.NewEncoder(j.writer)