summaryrefslogtreecommitdiff
path: root/lib/src/main/kotlin/TagGenerator.kt
blob: c386b171070b2eba7c23aa8ccdaa25d531ef9635 (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
import kotlin.random.Random

/**
 * Generate tags for 9P messages.
 */
class TagGenerator(val method: TagGenerationMethod, val initial: UShort) {

    private var current: UShort = initial
    private val rng: Random = Random(initial.toInt())
    private val randomReturned: Set<UShort> = emptySet()

    private val generationFunctions: Map<TagGenerationMethod, () -> UShort> = mapOf(
        TagGenerationMethod.INCREMENTAL to this::generateIncremental,
        TagGenerationMethod.RANDOM to this::generateRandom,
        TagGenerationMethod.RANDOM_CHECKED to this::generateRandomChecked
    )

    /**
     * How are tags generated?
     */
    enum class TagGenerationMethod {
        /**
         * Return the initial value on the first generation. Increment the value on each generation.
         */
        INCREMENTAL,

        /**
         * Use the initial value as a seed and generate random values from it.
         */
        RANDOM,

        /**
         * Same as [RANDOM], but checks are added to avoid generating the same value twice.
         */
        RANDOM_CHECKED,
    }

    /**
     * Generate a new tag.
     */
    fun generate(): UShort {
        return this.generationFunctions.getValue(method).invoke()
    }

    private fun generateIncremental(): UShort {
        val tmp = this.current
        this.current++
        return tmp
    }

    private fun generateRandom(): UShort {
        return this.rng.nextBits(16).toUShort()
    }

    private fun generateRandomChecked(): UShort {
        var v: UShort
        do {
            v = generateRandom()
        } while (v in randomReturned)
        randomReturned.plus(v)
        return v
    }
}