Skip to content

Instantly share code, notes, and snippets.

@bnm3k
Created July 21, 2020 14:14
Show Gist options
  • Save bnm3k/6b7dd5e6b73b950481a3914cb10eeb0f to your computer and use it in GitHub Desktop.
Save bnm3k/6b7dd5e6b73b950481a3914cb10eeb0f to your computer and use it in GitHub Desktop.
Most space-efficient MQTT topic generation. This one skips the tree building step entirely and goes straight to emitting. Compare with V1 and V2 gists
package main
import (
"fmt"
"strings"
)
func generateTopicStrings(tokens []string) (generatedTopics []string) {
// the expected no. of generated topics. See either of the previous
// gists for explanation as to why this formula is used
noTopics := (1 << len(tokens)) + (2 << len(tokens)) - 1
generatedTopics = make([]string, 0, noTopics)
// temp
temp := make([]string, 0, len(tokens)+1)
// string builder len
strBLen := 0
for _, t := range tokens {
strBLen += len(t)
}
strBLen += (len(tokens) + 1)
// 'traverse' while emitting
traverse(tokens, temp, func(ts []string) {
var strB strings.Builder
strB.Grow(strBLen)
strB.WriteString(ts[0])
for _, t := range ts[1:] {
strB.WriteByte('/')
strB.WriteString(t)
}
generatedTopics = append(generatedTopics, strB.String())
})
return generatedTopics
}
func traverse(tokens []string, temp []string, emitTokens func([]string)) {
if len(tokens) == 0 {
emitTokens(temp)
} else {
traverse(tokens[1:], append(temp, tokens[0]), emitTokens)
traverse(tokens[1:], append(temp, "+"), emitTokens)
}
emitTokens(append(temp, "#"))
}
func main() {
// assume a given topic 'foo/bar/quz' is already split
// into its constituent tokens
tokens := []string{"foo", "bar", "quz"}
ts := generateTopicStrings(tokens)
for _, t := range ts {
fmt.Println(t)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment