summaryrefslogtreecommitdiff
path: root/internal/server/handlers/generation_output.go
blob: aa9d195d9f1b5d9b2a5614faced59ea7e60afa13 (plain)
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
package handlers

import (
	"context"
	"fmt"
	"strconv"
	"strings"
)

type sessionGenerationKey struct{}

const generationOutputPrefix = "\x1egen:"

func withSessionGeneration(ctx context.Context, generation uint64) context.Context {
	if ctx == nil || generation == 0 {
		return ctx
	}
	return context.WithValue(ctx, sessionGenerationKey{}, generation)
}

func sessionGenerationFromContext(ctx context.Context) uint64 {
	if ctx == nil {
		return 0
	}

	generation, _ := ctx.Value(sessionGenerationKey{}).(uint64)
	return generation
}

func encodeGeneratedMessage(generation uint64, message string) string {
	if generation == 0 {
		return message
	}
	return fmt.Sprintf("%s%d\x1e%s", generationOutputPrefix, generation, message)
}

func decodeGeneratedMessage(message string) (uint64, string) {
	if !strings.HasPrefix(message, generationOutputPrefix) {
		return 0, message
	}

	rest := strings.TrimPrefix(message, generationOutputPrefix)
	parts := strings.SplitN(rest, "\x1e", 2)
	if len(parts) != 2 {
		return 0, message
	}

	generation, err := strconv.ParseUint(parts[0], 10, 64)
	if err != nil {
		return 0, message
	}

	return generation, parts[1]
}

func encodeGeneratedBytes(generation uint64, payload []byte) []byte {
	if generation == 0 {
		return payload
	}

	prefix := []byte(fmt.Sprintf("%s%d\x1e", generationOutputPrefix, generation))
	data := make([]byte, 0, len(prefix)+len(payload))
	data = append(data, prefix...)
	data = append(data, payload...)
	return data
}

func decodeGeneratedBytes(payload []byte) (uint64, []byte) {
	message := string(payload)
	generation, decoded := decodeGeneratedMessage(message)
	if generation == 0 {
		return 0, payload
	}
	return generation, []byte(decoded)
}