func VectorFromString(str string) (Vector, error) {
	var v Vector
	str = strings.ToUpper(str)
	if !strings.HasPrefix(str, prefix) {
		return v, fmt.Errorf("vector missing %q prefix: %q", prefix, str)
	}
	str = strings.TrimPrefix(str, prefix)
	slashIdx := strings.IndexByte(str, '/')
	var err error
	if v.version, err = versionFromString(str[:slashIdx]); err != nil {
		return v, err
	}
	str = str[slashIdx+1:]
	parseables := v.parseables()
	for _, part := range strings.Split(str, partSeparator) {
		tmp := strings.Split(part, metricSeparator)
		if len(tmp) != 2 {
			return v, fmt.Errorf("need two values separated by %s, got %q", metricSeparator, part)
		}
		metric, value := tmp[0], tmp[1]
		if p, ok := parseables[metric]; !ok {
			return v, fmt.Errorf("undefined metric %s with value %s", metric, value)
		} else if err := p.parse(value); err != nil {
			return v, fmt.Errorf("error occurred while parsing metric %s: %v", metric, err)
		}
	}
	return v, nil
}
VectorFromString will parse a string into a Vector, or return an error if it can't be parsed
package cvss3
import (
	"fmt"
	"strings"
)
const (
	prefix          = "CVSS:"
	partSeparator   = "/"
	metricSeparator = ":"
)
type version int
func (v version) String() string {
	return fmt.Sprintf("3.%d", int(v))
}
func versionFromString(v string) (version, error) {
	switch v {
	case "3.0":
		return version(0), nil
	case "3.1":
		return version(1), nil
	default:
		return version(0), fmt.Errorf("cvss v3 version %s not supported", v)
	}
}
type Vector struct {
	version version
	BaseMetrics
	TemporalMetrics
	EnvironmentalMetrics
}
var undefinedEquivalent = map[string]string{
	"E":  "H",
	"RL": "U",
	"RC": "C",
	"CR": "M",
	"IR": "M",
	"AR": "M",
}
func equivalent(metric, value string) string {
	if value != "X" {
		return value
	}
	e, ok := undefinedEquivalent[metric]
	if !ok {
		return value
	}
	return e
}
func (v Vector) Equal(o Vector) bool {
	vDefs := v.definables()
	oDefs := o.definables()
	for _, metric := range order {
		a := equivalent(metric, vDefs[metric].String())
		b := equivalent(metric, oDefs[metric].String())
		if a != b {
			return false
		}
	}
	return true
}
func (v Vector) String() string {
	var sb strings.Builder
	fmt.Fprintf(&sb, "%s%s/", prefix, v.version)
	defineables := v.definables()
	first := true
	for _, metric := range order {
		def := defineables[metric]
		if !def.defined() {
			continue
		}
		if !first {
			fmt.Fprint(&sb, partSeparator)
		} else {
			first = false
		}
		fmt.Fprintf(&sb, "%s%s%s", metric, metricSeparator, def)
	}
	return sb.String()
}