1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
// Copyright (c) 2022 Tulir Asokan
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package mautrix
import (
"fmt"
"regexp"
"strconv"
)
// RespVersions is the JSON response for https://spec.matrix.org/v1.2/client-server-api/#get_matrixclientversions
type RespVersions struct {
Versions []SpecVersion `json:"versions"`
UnstableFeatures map[string]bool `json:"unstable_features"`
}
func (versions *RespVersions) ContainsFunc(match func(found SpecVersion) bool) bool {
for _, found := range versions.Versions {
if match(found) {
return true
}
}
return false
}
func (versions *RespVersions) Contains(version SpecVersion) bool {
return versions.ContainsFunc(func(found SpecVersion) bool {
return found == version
})
}
func (versions *RespVersions) ContainsGreaterOrEqual(version SpecVersion) bool {
return versions.ContainsFunc(func(found SpecVersion) bool {
return found.GreaterThan(version) || found == version
})
}
type SpecVersionFormat int
const (
SpecVersionFormatUnknown SpecVersionFormat = iota
SpecVersionFormatR
SpecVersionFormatV
)
var (
SpecR010 = MustParseSpecVersion("r0.1.0")
SpecR020 = MustParseSpecVersion("r0.2.0")
SpecR030 = MustParseSpecVersion("r0.3.0")
SpecR040 = MustParseSpecVersion("r0.4.0")
SpecR050 = MustParseSpecVersion("r0.5.0")
SpecR060 = MustParseSpecVersion("r0.6.0")
SpecR061 = MustParseSpecVersion("r0.6.1")
SpecV11 = MustParseSpecVersion("v1.1")
SpecV12 = MustParseSpecVersion("v1.2")
)
func (svf SpecVersionFormat) String() string {
switch svf {
case SpecVersionFormatR:
return "r"
case SpecVersionFormatV:
return "v"
default:
return ""
}
}
type SpecVersion struct {
Format SpecVersionFormat
Major int
Minor int
Patch int
Raw string
}
var legacyVersionRegex = regexp.MustCompile(`^r(\d+)\.(\d+)\.(\d+)$`)
var modernVersionRegex = regexp.MustCompile(`^v(\d+)\.(\d+)$`)
func MustParseSpecVersion(version string) SpecVersion {
sv, err := ParseSpecVersion(version)
if err != nil {
panic(err)
}
return sv
}
func ParseSpecVersion(version string) (sv SpecVersion, err error) {
sv.Raw = version
if parts := modernVersionRegex.FindStringSubmatch(version); parts != nil {
sv.Major, _ = strconv.Atoi(parts[1])
sv.Minor, _ = strconv.Atoi(parts[2])
sv.Format = SpecVersionFormatV
} else if parts = legacyVersionRegex.FindStringSubmatch(version); parts != nil {
sv.Major, _ = strconv.Atoi(parts[1])
sv.Minor, _ = strconv.Atoi(parts[2])
sv.Patch, _ = strconv.Atoi(parts[3])
sv.Format = SpecVersionFormatR
} else {
err = fmt.Errorf("version '%s' doesn't match either known syntax", version)
}
return
}
func (sv *SpecVersion) UnmarshalText(version []byte) error {
*sv, _ = ParseSpecVersion(string(version))
return nil
}
func (sv *SpecVersion) MarshalText() ([]byte, error) {
return []byte(sv.String()), nil
}
func (sv *SpecVersion) String() string {
switch sv.Format {
case SpecVersionFormatR:
return fmt.Sprintf("r%d.%d.%d", sv.Major, sv.Minor, sv.Patch)
case SpecVersionFormatV:
return fmt.Sprintf("v%d.%d", sv.Major, sv.Minor)
default:
return sv.Raw
}
}
func (sv SpecVersion) LessThan(other SpecVersion) bool {
return sv != other && !sv.GreaterThan(other)
}
func (sv SpecVersion) GreaterThan(other SpecVersion) bool {
return sv.Format > other.Format ||
(sv.Format == other.Format && sv.Major > other.Major) ||
(sv.Format == other.Format && sv.Major == other.Major && sv.Minor > other.Minor) ||
(sv.Format == other.Format && sv.Major == other.Major && sv.Minor == other.Minor && sv.Patch > other.Patch)
}
|