github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/pkg/orchestrator/util/key_utils.go (about) 1 // Copyright 2020 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package util 15 16 import ( 17 "strings" 18 19 "github.com/pingcap/log" 20 ) 21 22 // EtcdKey represents a complete key in Etcd. 23 type EtcdKey struct { 24 keyStr string 25 } 26 27 // NewEtcdKey creates an EtcdKey for the given string. 28 func NewEtcdKey(key string) EtcdKey { 29 return EtcdKey{key} 30 } 31 32 // NewEtcdKeyFromBytes creates an EtcdKey for the given bytes. 33 func NewEtcdKeyFromBytes(key []byte) EtcdKey { 34 return EtcdKey{string(key)} 35 } 36 37 // String returns the string representation of the key. 38 func (key EtcdKey) String() string { 39 return key.keyStr 40 } 41 42 // Bytes returns the bytes representation of the key. 43 func (key EtcdKey) Bytes() []byte { 44 return []byte(key.keyStr) 45 } 46 47 // Head returns a EtcdRelPrefix that is the first segment of the key. 48 // For example, if key.String() == "/a/b/c", then key.Head() == "/a". 49 func (key EtcdKey) Head() EtcdPrefix { 50 if len(key.keyStr) == 0 { 51 log.Panic("Empty EtcdKey") 52 } 53 if index := strings.IndexByte(key.keyStr[1:], '/'); index >= 0 { 54 return EtcdPrefix{key.keyStr[:index+1]} 55 } 56 return EtcdPrefix{""} 57 } 58 59 // Tail returns an EtcdRelKey that is the key without the first segment. 60 // For example, if key.String() == "/a/b/c", then key.Tail() == "/b/c". 61 func (key EtcdKey) Tail() EtcdRelKey { 62 if len(key.keyStr) == 0 { 63 log.Panic("Empty EtcdKey") 64 } 65 if index := strings.IndexByte(key.keyStr[1:], '/'); index >= 0 { 66 return EtcdRelKey{EtcdKey{key.keyStr[index+1:]}} 67 } 68 return EtcdRelKey{EtcdKey{key.keyStr}} 69 } 70 71 // RemovePrefix removes a prefix from the key. 72 // It is a wrapper for strings.TrimPrefix. 73 func (key EtcdKey) RemovePrefix(prefix *EtcdPrefix) EtcdRelKey { 74 return EtcdRelKey{EtcdKey{strings.TrimPrefix(key.keyStr, prefix.prefixStr)}} 75 } 76 77 // AsRelKey casts the EtcdKey to an EtcdRelKey. 78 func (key EtcdKey) AsRelKey() EtcdRelKey { 79 return NewEtcdRelKey(key.keyStr) 80 } 81 82 // EtcdRelKey represents a string that might be used as a suffix of a valid Etcd key. 83 type EtcdRelKey struct { 84 inner EtcdKey 85 } 86 87 // NewEtcdRelKey creates an EtcdRelKey for the given string. 88 func NewEtcdRelKey(key string) EtcdRelKey { 89 return EtcdRelKey{NewEtcdKey(key)} 90 } 91 92 // NewEtcdRelKeyFromBytes creates an EtcdRelKey for the given bytes. 93 func NewEtcdRelKeyFromBytes(key []byte) EtcdRelKey { 94 return EtcdRelKey{NewEtcdKeyFromBytes(key)} 95 } 96 97 // AsPrefix casts EtcdRelKey into EtcdRelPrefix. 98 func (rkey *EtcdRelKey) AsPrefix() EtcdRelPrefix { 99 return EtcdRelPrefix{EtcdPrefix{rkey.String()}} 100 } 101 102 // String returns the string representation of the key. 103 func (rkey EtcdRelKey) String() string { 104 return rkey.inner.String() 105 } 106 107 // Bytes returns the bytes representation of the key. 108 func (rkey EtcdRelKey) Bytes() []byte { 109 return rkey.inner.Bytes() 110 } 111 112 // Head returns an EtcdRelPrefix that is the first segment of the key. 113 // For example, if key.String() == "/a/b/c", then key.Head() == "/a". 114 func (rkey EtcdRelKey) Head() EtcdRelPrefix { 115 return EtcdRelPrefix{rkey.inner.Head()} 116 } 117 118 // Tail returns an EtcdRelKey that is the key without the first segment. 119 // For example, if key.String() == "/a/b/c", then key.Tail() == "/b/c". 120 func (rkey EtcdRelKey) Tail() EtcdRelKey { 121 return rkey.inner.Tail() 122 } 123 124 // RemovePrefix removes a prefix from the key. 125 // It is a wrapper for strings.TrimPrefix. 126 func (rkey EtcdRelKey) RemovePrefix(prefix *EtcdRelPrefix) EtcdRelKey { 127 return EtcdRelKey{EtcdKey{strings.TrimPrefix(rkey.inner.keyStr, prefix.prefixStr)}} 128 } 129 130 // EtcdPrefix represents a string that might be the prefix of a valid key in Etcd. 131 type EtcdPrefix struct { 132 prefixStr string 133 } 134 135 // String returns the string representation of the EtcdPrefix. 136 func (prefix EtcdPrefix) String() string { 137 return prefix.prefixStr 138 } 139 140 // Bytes returns the bytes representation of the EtcdPrefix. 141 func (prefix EtcdPrefix) Bytes() []byte { 142 return []byte(prefix.prefixStr) 143 } 144 145 // Head returns a EtcdPrefix that is the first segment of the given prefix. 146 func (prefix EtcdPrefix) Head() EtcdPrefix { 147 if len(prefix.prefixStr) == 0 { 148 log.Panic("Empty EtcdPrefix") 149 } 150 if index := strings.IndexByte(prefix.prefixStr[1:], '/'); index >= 0 { 151 return EtcdPrefix{prefix.prefixStr[:index+1]} 152 } 153 return EtcdPrefix{""} 154 } 155 156 // Tail returns a EtcdRelPrefix that is the given prefix with its first segment removed. 157 func (prefix EtcdPrefix) Tail() EtcdRelPrefix { 158 if len(prefix.prefixStr) == 0 { 159 log.Panic("Empty EtcdPrefix") 160 } 161 if index := strings.IndexByte(prefix.prefixStr[1:], '/'); index >= 0 { 162 return EtcdRelPrefix{EtcdPrefix{prefix.prefixStr[index+1:]}} 163 } 164 return EtcdRelPrefix{EtcdPrefix{prefix.prefixStr}} 165 } 166 167 // FullKey transforms an EtcdRelKey to an EtcdKey by adding the prefix to it. 168 func (prefix EtcdPrefix) FullKey(key EtcdRelKey) EtcdKey { 169 return EtcdKey{prefix.prefixStr + key.inner.keyStr} 170 } 171 172 // EtcdRelPrefix represents a prefix to a meaningful suffix of a valid EtcdKey. 173 type EtcdRelPrefix struct { 174 EtcdPrefix 175 } 176 177 // NormalizePrefix adds a slash to the beginning of `prefix` if none is present, 178 // and removes a trailing slash, if one is present. 179 func NormalizePrefix(prefix string) EtcdPrefix { 180 ret := prefix 181 if !strings.HasPrefix(prefix, "/") { 182 ret = "/" + prefix 183 } 184 return NewEtcdPrefix(strings.TrimSuffix(ret, "/")) 185 } 186 187 // NewEtcdPrefix creates an EtcdPrefix from the given string. 188 // For a safer version, use NormalizePrefix. 189 func NewEtcdPrefix(prefix string) EtcdPrefix { 190 return EtcdPrefix{prefix} 191 } 192 193 // NewEtcdRelPrefix creates an EtcdRelPrefix from the given string. 194 func NewEtcdRelPrefix(prefix string) EtcdRelPrefix { 195 return EtcdRelPrefix{NewEtcdPrefix(prefix)} 196 } 197 198 // NewEtcdPrefixFromBytes creates an EtcdPrefix from the given bytes. 199 // For a safer version, use NormalizePrefix. 200 func NewEtcdPrefixFromBytes(prefix []byte) EtcdPrefix { 201 return NewEtcdPrefix(string(prefix)) 202 } 203 204 // NewEtcdRelPrefixFromBytes creates an EtcdRelPrefix from the given bytes. 205 func NewEtcdRelPrefixFromBytes(prefix []byte) EtcdRelPrefix { 206 return NewEtcdRelPrefix(string(prefix)) 207 }