2021-11-10 14:28:45 +00:00
|
|
|
package protocol
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
2023-10-30 14:56:26 +00:00
|
|
|
type WakuPubSubTopic interface {
|
2023-03-07 22:11:52 +00:00
|
|
|
String() string
|
|
|
|
}
|
|
|
|
|
2023-10-30 14:56:26 +00:00
|
|
|
const defaultPubsubTopic = "/waku/2/default-waku/proto"
|
2023-03-07 22:11:52 +00:00
|
|
|
|
2023-10-30 14:56:26 +00:00
|
|
|
type DefaultPubsubTopic struct{}
|
2023-03-07 22:11:52 +00:00
|
|
|
|
2023-10-30 14:56:26 +00:00
|
|
|
func (DefaultPubsubTopic) String() string {
|
|
|
|
return defaultPubsubTopic
|
2023-03-07 22:11:52 +00:00
|
|
|
}
|
|
|
|
|
2023-10-30 14:56:26 +00:00
|
|
|
// StaticShardingPubsubTopicPrefix is the expected prefix to be used for static sharding pubsub topics
|
|
|
|
const StaticShardingPubsubTopicPrefix = "/waku/2/rs"
|
2023-03-07 22:11:52 +00:00
|
|
|
|
2023-10-30 14:56:26 +00:00
|
|
|
// waku pubsub topic errors
|
|
|
|
var ErrNotWakuPubsubTopic = errors.New("not a waku pubsub topic")
|
2023-03-07 22:11:52 +00:00
|
|
|
|
2023-10-30 14:56:26 +00:00
|
|
|
// shard pubsub topic errors
|
|
|
|
var ErrNotShardPubsubTopic = errors.New("not a shard pubsub topic")
|
|
|
|
var ErrInvalidStructure = errors.New("invalid topic structure")
|
|
|
|
var ErrInvalidShardedTopicPrefix = errors.New("must start with " + StaticShardingPubsubTopicPrefix)
|
|
|
|
var ErrMissingClusterIndex = errors.New("missing shard_cluster_index")
|
|
|
|
var ErrMissingShardNumber = errors.New("missing shard_number")
|
2023-03-07 22:11:52 +00:00
|
|
|
|
2023-10-30 14:56:26 +00:00
|
|
|
// ErrInvalidNumberFormat indicates that a number exceeds the allowed range
|
|
|
|
var ErrInvalidNumberFormat = errors.New("only 2^16 numbers are allowed")
|
2021-11-10 14:28:45 +00:00
|
|
|
|
2023-08-25 04:25:38 +00:00
|
|
|
// StaticShardingPubsubTopic describes a pubSub topic as per StaticSharding
|
2023-03-07 22:11:52 +00:00
|
|
|
type StaticShardingPubsubTopic struct {
|
2023-10-31 10:50:13 +00:00
|
|
|
clusterID uint16
|
|
|
|
shardID uint16
|
2021-11-10 14:28:45 +00:00
|
|
|
}
|
|
|
|
|
2023-08-25 04:25:38 +00:00
|
|
|
// NewStaticShardingPubsubTopic creates a new pubSub topic
|
2023-09-06 04:37:21 +00:00
|
|
|
func NewStaticShardingPubsubTopic(cluster uint16, shard uint16) StaticShardingPubsubTopic {
|
2023-03-07 22:11:52 +00:00
|
|
|
return StaticShardingPubsubTopic{
|
2023-10-31 10:50:13 +00:00
|
|
|
clusterID: cluster,
|
|
|
|
shardID: shard,
|
2021-11-10 14:28:45 +00:00
|
|
|
}
|
2023-03-07 22:11:52 +00:00
|
|
|
}
|
2021-11-10 14:28:45 +00:00
|
|
|
|
2023-08-25 04:25:38 +00:00
|
|
|
// Cluster returns the sharded cluster index
|
|
|
|
func (s StaticShardingPubsubTopic) Cluster() uint16 {
|
2023-10-31 10:50:13 +00:00
|
|
|
return s.clusterID
|
2023-03-07 22:11:52 +00:00
|
|
|
}
|
|
|
|
|
2023-09-11 14:24:05 +00:00
|
|
|
// Shard returns the shard number
|
2023-08-25 04:25:38 +00:00
|
|
|
func (s StaticShardingPubsubTopic) Shard() uint16 {
|
2023-10-31 10:50:13 +00:00
|
|
|
return s.shardID
|
2023-03-07 22:11:52 +00:00
|
|
|
}
|
|
|
|
|
2023-08-25 04:25:38 +00:00
|
|
|
// Equal compares StaticShardingPubsubTopic
|
2023-10-30 14:56:26 +00:00
|
|
|
func (s StaticShardingPubsubTopic) Equal(t2 StaticShardingPubsubTopic) bool {
|
2023-03-07 22:11:52 +00:00
|
|
|
return s.String() == t2.String()
|
|
|
|
}
|
|
|
|
|
2023-08-25 04:25:38 +00:00
|
|
|
// String formats StaticShardingPubsubTopic to RFC 23 specific string format for pubsub topic.
|
|
|
|
func (s StaticShardingPubsubTopic) String() string {
|
2023-10-31 10:50:13 +00:00
|
|
|
return fmt.Sprintf("%s/%d/%d", StaticShardingPubsubTopicPrefix, s.clusterID, s.shardID)
|
2023-03-07 22:11:52 +00:00
|
|
|
}
|
|
|
|
|
2023-08-25 04:25:38 +00:00
|
|
|
// Parse parses a topic string into a StaticShardingPubsubTopic
|
2023-03-07 22:11:52 +00:00
|
|
|
func (s *StaticShardingPubsubTopic) Parse(topic string) error {
|
|
|
|
if !strings.HasPrefix(topic, StaticShardingPubsubTopicPrefix) {
|
|
|
|
return ErrInvalidShardedTopicPrefix
|
|
|
|
}
|
|
|
|
|
|
|
|
parts := strings.Split(topic[11:], "/")
|
|
|
|
if len(parts) != 2 {
|
|
|
|
return ErrInvalidStructure
|
|
|
|
}
|
|
|
|
|
|
|
|
clusterPart := parts[0]
|
|
|
|
if len(clusterPart) == 0 {
|
|
|
|
return ErrMissingClusterIndex
|
|
|
|
}
|
|
|
|
|
|
|
|
clusterInt, err := strconv.ParseUint(clusterPart, 10, 16)
|
|
|
|
if err != nil {
|
|
|
|
return ErrInvalidNumberFormat
|
|
|
|
}
|
|
|
|
|
|
|
|
shardPart := parts[1]
|
|
|
|
if len(shardPart) == 0 {
|
|
|
|
return ErrMissingShardNumber
|
|
|
|
}
|
|
|
|
|
|
|
|
shardInt, err := strconv.ParseUint(shardPart, 10, 16)
|
|
|
|
if err != nil {
|
|
|
|
return ErrInvalidNumberFormat
|
|
|
|
}
|
|
|
|
|
2023-10-31 10:50:13 +00:00
|
|
|
s.shardID = uint16(shardInt)
|
|
|
|
s.clusterID = uint16(clusterInt)
|
2023-03-07 22:11:52 +00:00
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-10-30 14:56:26 +00:00
|
|
|
func ToShardPubsubTopic(topic WakuPubSubTopic) (StaticShardingPubsubTopic, error) {
|
2023-10-31 10:50:13 +00:00
|
|
|
result, ok := topic.(StaticShardingPubsubTopic)
|
|
|
|
if !ok {
|
|
|
|
return StaticShardingPubsubTopic{}, ErrNotShardPubsubTopic
|
|
|
|
}
|
|
|
|
return result, nil
|
2023-10-30 14:56:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ToWakuPubsubTopic takes a pubSub topic string and creates a WakuPubsubTopic object.
|
|
|
|
func ToWakuPubsubTopic(topic string) (WakuPubSubTopic, error) {
|
|
|
|
if topic == defaultPubsubTopic {
|
|
|
|
return DefaultPubsubTopic{}, nil
|
|
|
|
}
|
2023-03-07 22:11:52 +00:00
|
|
|
if strings.HasPrefix(topic, StaticShardingPubsubTopicPrefix) {
|
|
|
|
s := StaticShardingPubsubTopic{}
|
|
|
|
err := s.Parse(topic)
|
|
|
|
if err != nil {
|
2023-10-30 14:56:26 +00:00
|
|
|
return s, err
|
2023-03-07 22:11:52 +00:00
|
|
|
}
|
|
|
|
return s, nil
|
|
|
|
}
|
2023-10-30 14:56:26 +00:00
|
|
|
return nil, ErrNotWakuPubsubTopic
|
2021-11-10 14:28:45 +00:00
|
|
|
}
|