diff --git a/go.mod b/go.mod index 2de99f4f..46b78fb2 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.18 require ( github.com/PretendoNetwork/plogger-go v1.0.4 github.com/superwhiskers/crunch/v3 v3.5.7 + golang.org/x/mod v0.12.0 ) require ( @@ -12,6 +13,6 @@ require ( github.com/jwalton/go-supportscolor v1.2.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect - golang.org/x/sys v0.10.0 // indirect - golang.org/x/term v0.10.0 // indirect + golang.org/x/sys v0.11.0 // indirect + golang.org/x/term v0.11.0 // indirect ) diff --git a/go.sum b/go.sum index 73a5ec75..2c9138aa 100644 --- a/go.sum +++ b/go.sum @@ -12,12 +12,14 @@ github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APP github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/superwhiskers/crunch/v3 v3.5.7 h1:N9RLxaR65C36i26BUIpzPXGy2f6pQ7wisu2bawbKNqg= github.com/superwhiskers/crunch/v3 v3.5.7/go.mod h1:4ub2EKgF1MAhTjoOCTU4b9uLMsAweHEa89aRrfAypXA= +golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= -golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c= -golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= +golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0= +golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= diff --git a/nex_version.go b/nex_version.go index 2f19eb35..dd1e9630 100644 --- a/nex_version.go +++ b/nex_version.go @@ -1,24 +1,59 @@ package nex +import ( + "fmt" + "strings" + + "golang.org/x/mod/semver" +) + // NEXVersion represents a NEX library version type NEXVersion struct { Major int Minor int Patch int GameSpecificPatch string + semver string } // Copy returns a new copied instance of NEXVersion func (nexVersion *NEXVersion) Copy() *NEXVersion { - var copied *NEXVersion + return &NEXVersion{ + Major: nexVersion.Major, + Minor: nexVersion.Minor, + Patch: nexVersion.Patch, + GameSpecificPatch: nexVersion.GameSpecificPatch, + semver: fmt.Sprintf("v%d.%d.%d", nexVersion.Major, nexVersion.Minor, nexVersion.Patch), + } +} + +func (nexVersion *NEXVersion) semverCompare(compare string) int { + if !strings.HasPrefix(compare, "v") { + // * Faster than doing "v" + string(compare) + var b strings.Builder + + b.WriteString("v") + b.WriteString(compare) - if nexVersion.GameSpecificPatch != "" { - copied = NewPatchedNEXVersion(nexVersion.Major, nexVersion.Minor, nexVersion.Patch, nexVersion.GameSpecificPatch) - } else { - copied = NewNEXVersion(nexVersion.Major, nexVersion.Minor, nexVersion.Patch) + compare = b.String() } - return copied + if !semver.IsValid(compare) { + // * The semver package returns 0 (equal) for invalid semvers in semver.Compare + return 0 + } + + return semver.Compare(nexVersion.semver, compare) +} + +// GreaterOrEqual compares if the given semver is greater than or equal to the current version +func (nexVersion *NEXVersion) GreaterOrEqual(compare string) bool { + return nexVersion.semverCompare(compare) != -1 +} + +// LessOrEqual compares if the given semver is lesser than or equal to the current version +func (nexVersion *NEXVersion) LessOrEqual(compare string) bool { + return nexVersion.semverCompare(compare) != 1 } // NewPatchedNEXVersion returns a new NEXVersion with a game specific patch @@ -28,14 +63,16 @@ func NewPatchedNEXVersion(major, minor, patch int, gameSpecificPatch string) *NE Minor: minor, Patch: patch, GameSpecificPatch: gameSpecificPatch, + semver: fmt.Sprintf("v%d.%d.%d", major, minor, patch), } } // NewNEXVersion returns a new NEXVersion func NewNEXVersion(major, minor, patch int) *NEXVersion { return &NEXVersion{ - Major: major, - Minor: minor, - Patch: patch, + Major: major, + Minor: minor, + Patch: patch, + semver: fmt.Sprintf("v%d.%d.%d", major, minor, patch), } } diff --git a/stream_in.go b/stream_in.go index c9c2b93d..122b2c3b 100644 --- a/stream_in.go +++ b/stream_in.go @@ -246,7 +246,7 @@ func (stream *StreamIn) ReadStructure(structure StructureInterface) (StructureIn nexVersion := stream.Server.NEXVersion() - if nexVersion.Major >= 3 && nexVersion.Minor >= 5 { + if nexVersion.GreaterOrEqual("3.5.0") { version, err := stream.ReadUInt8() if err != nil { return nil, fmt.Errorf("Failed to read NEX Structure version. %s", err.Error()) diff --git a/stream_out.go b/stream_out.go index 8bff39c5..4425e2c2 100644 --- a/stream_out.go +++ b/stream_out.go @@ -179,7 +179,7 @@ func (stream *StreamOut) WriteStructure(structure StructureInterface) { nexVersion := stream.Server.NEXVersion() - if nexVersion.Major >= 3 && nexVersion.Minor >= 5 { + if nexVersion.GreaterOrEqual("3.5.0") { stream.WriteUInt8(structure.StructureVersion()) stream.WriteUInt32LE(uint32(len(content))) } diff --git a/types.go b/types.go index 830a8345..a1bb8f5d 100644 --- a/types.go +++ b/types.go @@ -69,12 +69,16 @@ func (data *Data) Bytes(stream *StreamOut) []byte { // Copy returns a new copied instance of Data func (data *Data) Copy() StructureInterface { - return NewData() // * Has no fields, nothing to copy + copied := NewData() + + copied.SetStructureVersion(data.StructureVersion()) + + return copied } // Equals checks if the passed Structure contains the same data as the current instance func (data *Data) Equals(structure StructureInterface) bool { - return true // * Has no fields, always equal + return data.StructureVersion() == structure.StructureVersion() } // String returns a string representation of the struct @@ -301,7 +305,7 @@ func (rvConnectionData *RVConnectionData) Bytes(stream *StreamOut) []byte { stream.WriteListUInt8(rvConnectionData.specialProtocols) stream.WriteString(rvConnectionData.stationURLSpecialProtocols) - if nexVersion.Major >= 3 && nexVersion.Minor >= 5 { + if nexVersion.GreaterOrEqual("3.5.0") { rvConnectionData.SetStructureVersion(1) stream.WriteDateTime(rvConnectionData.time) } @@ -313,6 +317,7 @@ func (rvConnectionData *RVConnectionData) Bytes(stream *StreamOut) []byte { func (rvConnectionData *RVConnectionData) Copy() StructureInterface { copied := NewRVConnectionData() + copied.SetStructureVersion(rvConnectionData.StructureVersion()) copied.parentType = rvConnectionData.parentType copied.stationURL = rvConnectionData.stationURL copied.specialProtocols = make([]byte, len(rvConnectionData.specialProtocols)) @@ -332,6 +337,10 @@ func (rvConnectionData *RVConnectionData) Copy() StructureInterface { func (rvConnectionData *RVConnectionData) Equals(structure StructureInterface) bool { other := structure.(*RVConnectionData) + if rvConnectionData.StructureVersion() == other.StructureVersion() { + return false + } + if rvConnectionData.stationURL != other.stationURL { return false } @@ -1060,6 +1069,7 @@ func (resultRange *ResultRange) ExtractFromStream(stream *StreamIn) error { func (resultRange *ResultRange) Copy() StructureInterface { copied := NewResultRange() + copied.SetStructureVersion(resultRange.StructureVersion()) copied.Offset = resultRange.Offset copied.Length = resultRange.Length @@ -1070,6 +1080,10 @@ func (resultRange *ResultRange) Copy() StructureInterface { func (resultRange *ResultRange) Equals(structure StructureInterface) bool { other := structure.(*ResultRange) + if resultRange.StructureVersion() == other.StructureVersion() { + return false + } + if resultRange.Offset != other.Offset { return false }