164 lines
2.9 KiB
Go
164 lines
2.9 KiB
Go
package versioning
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
const (
|
|
MaxMajor uint16 = 42948
|
|
MaxMinor uint16 = 999
|
|
MaxPatch uint8 = 99
|
|
)
|
|
|
|
var maxVersion = newVersion(MaxMajor, MaxMinor, MaxPatch)
|
|
|
|
type Version struct {
|
|
major uint16
|
|
minor uint16
|
|
patch uint8
|
|
code uint32
|
|
}
|
|
|
|
func (v Version) Major() uint16 {
|
|
return v.major
|
|
}
|
|
|
|
func (v Version) Minor() uint16 {
|
|
return v.minor
|
|
}
|
|
|
|
func (v Version) Patch() uint8 {
|
|
return v.patch
|
|
}
|
|
|
|
func (v Version) Code() uint32 {
|
|
return v.code
|
|
}
|
|
|
|
func (a Version) Equal(b Version) bool {
|
|
return a.Code() == b.Code()
|
|
}
|
|
|
|
func (a Version) Less(b Version) bool {
|
|
return a.Code() < b.Code()
|
|
}
|
|
|
|
func (a Version) Lte(b Version) bool {
|
|
return a.Code() <= b.Code()
|
|
}
|
|
|
|
func (a Version) Greater(b Version) bool {
|
|
return a.Code() > b.Code()
|
|
}
|
|
|
|
func (a Version) Gte(b Version) bool {
|
|
return a.Code() >= b.Code()
|
|
}
|
|
|
|
func (v Version) String() string {
|
|
return fmt.Sprintf("%d.%d.%d", v.major, v.minor, v.patch)
|
|
}
|
|
|
|
func ParseVersion(str string) (Version, error) {
|
|
parts := strings.Split(str, ".")
|
|
partsLen := len(parts)
|
|
if partsLen > 3 {
|
|
return Version{}, errors.Errorf("invalid game version: '%s'", str)
|
|
}
|
|
|
|
maj, err := parseUint16(parts[0])
|
|
if err != nil {
|
|
return Version{}, err
|
|
}
|
|
|
|
var (
|
|
min uint16
|
|
patch uint8
|
|
)
|
|
if partsLen > 1 {
|
|
min, err = parseUint16(parts[1])
|
|
if err != nil {
|
|
return Version{}, err
|
|
}
|
|
}
|
|
if partsLen > 2 {
|
|
patch, err = parseUint8(parts[2])
|
|
if err != nil {
|
|
return Version{}, err
|
|
}
|
|
}
|
|
|
|
if err := validate(maj, min, patch); err != nil {
|
|
return Version{}, err
|
|
}
|
|
return newVersion(maj, min, patch), nil
|
|
}
|
|
|
|
func MustParseVersion(str string) Version {
|
|
v, err := ParseVersion(str)
|
|
if err != nil {
|
|
return Version{}
|
|
}
|
|
return v
|
|
}
|
|
|
|
func ParseVersionFromCode(code uint32) (Version, error) {
|
|
patch := code % 100
|
|
minor := code%100000 - patch
|
|
major := code - minor - patch
|
|
|
|
maj, min, p := uint16(major/100000), uint16(minor/100), uint8(patch)
|
|
|
|
if err := validate(maj, min, p); err != nil {
|
|
return Version{}, err
|
|
}
|
|
|
|
return Version{
|
|
major: maj,
|
|
minor: min,
|
|
patch: p,
|
|
code: code,
|
|
}, nil
|
|
}
|
|
|
|
func parseUint16(str string) (uint16, error) {
|
|
v, err := strconv.ParseUint(str, 10, 16)
|
|
if err != nil {
|
|
return 0, errors.WithStack(err)
|
|
}
|
|
return uint16(v), nil
|
|
}
|
|
|
|
func parseUint8(str string) (uint8, error) {
|
|
v, err := strconv.ParseUint(str, 10, 8)
|
|
if err != nil {
|
|
return 0, errors.WithStack(err)
|
|
}
|
|
return uint8(v), nil
|
|
}
|
|
|
|
func validate(major, minor uint16, patch uint8) error {
|
|
if major > MaxMajor || minor > MaxMinor || patch > MaxPatch {
|
|
return errors.Errorf("invalid game version. max version: %s", maxVersion)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func newVersion(major, minor uint16, patch uint8) Version {
|
|
return Version{
|
|
major: major,
|
|
minor: minor,
|
|
patch: patch,
|
|
code: calcCode(major, minor, patch),
|
|
}
|
|
}
|
|
|
|
func calcCode(major, minor uint16, patch uint8) uint32 {
|
|
return uint32(major)*100000 + uint32(minor)*100 + uint32(patch)
|
|
}
|