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  }