xref: /php-src/ext/random/tests/engines.inc (revision ac0b9bff)
1<?php
2
3namespace Random\Engine\Test;
4
5use Random\Engine;
6
7final class TestShaEngine implements Engine
8{
9    private string $state;
10
11    public function __construct(?string $state = null)
12    {
13        if ($state !== null) {
14            $this->state = $state;
15        } else {
16            $this->state = random_bytes(20);
17        }
18    }
19
20    public function generate(): string
21    {
22        $this->state = sha1($this->state, true);
23
24        return substr($this->state, 0, 8);
25    }
26}
27
28final class TestWrapperEngine implements Engine
29{
30    private int $count = 0;
31
32    public function __construct(private readonly Engine $engine)
33    {
34    }
35
36    public function generate(): string
37    {
38        $this->count++;
39
40        return $this->engine->generate();
41    }
42
43    public function getCount(): int
44    {
45        return $this->count;
46    }
47}
48
49final class TestXoshiro128PlusPlusEngine implements Engine
50{
51    public function __construct(
52        private int $s0,
53        private int $s1,
54        private int $s2,
55        private int $s3
56    ) {
57    }
58
59    private static function rotl($x, $k)
60    {
61        return (($x << $k) | ($x >> (32 - $k))) & 0xFFFFFFFF;
62    }
63
64    public function generate(): string
65    {
66        $result = (self::rotl(($this->s0 + $this->s3) & 0xFFFFFFFF, 7) + $this->s0) & 0xFFFFFFFF;
67
68        $t = ($this->s1 << 9)  & 0xFFFFFFFF;
69
70        $this->s2 ^= $this->s0;
71        $this->s3 ^= $this->s1;
72        $this->s1 ^= $this->s2;
73        $this->s0 ^= $this->s3;
74
75        $this->s2 ^= $t;
76
77        $this->s3 = self::rotl($this->s3, 11);
78
79        return pack('V', $result);
80    }
81}
82
83final class TestCountingEngine32 implements Engine
84{
85    private int $count = 0;
86
87    public function generate(): string
88    {
89        return pack('V', $this->count++);
90    }
91}
92
93final class TestCountingEngine64 implements Engine
94{
95    private int $count = 0;
96
97    public function generate(): string
98    {
99        if ($this->count > 2147483647 || $this->count < 0) {
100            throw new \Exception('Overflow');
101        }
102        return pack('V', $this->count++) . "\x00\x00\x00\x00";
103    }
104}
105
106?>
107