packages/sql-faker/src/Generation/Lexeme/SpacingConstraint.php

1<?php
2
3declare(strict_types=1);
4
5namespace SqlFaker\Generation\Lexeme;
6
7/**
8 * Allowed boundary spellings with every contributing rule retained for diagnostics.
9 */
10final class SpacingConstraint
11{
12    /**
13     * Allows adjacent lexemes with no separator.
14     */
15    public const JOIN = 1;
16    /**
17     * Allows a single space between lexemes.
18     */
19    public const SPACE = 2;
20    /**
21     * Allows either supported separator form.
22     */
23    public const EITHER = 3;
24
25    /**
26     * @param list<string> $rules
27     */
28    public function __construct(public readonly int $allowed = self::EITHER, public readonly array $rules = [])
29    {
30    }
31
32    /**
33     * Keeps only separators allowed by both constraints and retains both sources.
34     */
35    public function intersect(self $other): self
36    {
37        return new self($this->allowed & $other->allowed, array_values(array_unique([...$this->rules, ...$other->rules])));
38    }
39
40    /**
41     * Selects the default single space when permitted, a join otherwise, or null on contradiction.
42     */
43    public function separator(): ?string
44    {
45        if (($this->allowed & self::SPACE) !== 0) {
46            return ' ';
47        }
48        return ($this->allowed & self::JOIN) !== 0 ? '' : null;
49    }
50}
51