Skip to content

Commit

Permalink
Add native types to public API
Browse files Browse the repository at this point in the history
This changeset adds native types to the public API as discussed in #219.

Once merged, I'm planning to add PHPStan in a follow-up PR which would take advantage of these types.

Builds on top of #222, #223 and reactphp/cache#60
  • Loading branch information
WyriHaximus committed Jun 13, 2024
1 parent 30c5e43 commit 6c7b3af
Show file tree
Hide file tree
Showing 20 changed files with 101 additions and 117 deletions.
9 changes: 6 additions & 3 deletions src/Config/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ final class Config
* @return self
* @codeCoverageIgnore
*/
public static function loadSystemConfigBlocking()
public static function loadSystemConfigBlocking(): self
{
// Use WMIC output on Windows
if (DIRECTORY_SEPARATOR === '\\') {
Expand Down Expand Up @@ -71,7 +71,7 @@ public static function loadSystemConfigBlocking()
* @return self
* @throws RuntimeException if the path can not be loaded (does not exist)
*/
public static function loadResolvConfBlocking($path = null)
public static function loadResolvConfBlocking(?string $path = null): self
{
if ($path === null) {
$path = '/etc/resolv.conf';
Expand Down Expand Up @@ -122,7 +122,7 @@ public static function loadResolvConfBlocking($path = null)
* @return self
* @link https://ss64.com/nt/wmic.html
*/
public static function loadWmicBlocking($command = null)
public static function loadWmicBlocking(?string $command = null): self
{
$contents = shell_exec($command === null ? 'wmic NICCONFIG get "DNSServerSearchOrder" /format:CSV' : $command);
preg_match_all('/(?<=[{;,"])([\da-f.:]{4,})(?=[};,"])/i', $contents, $matches);
Expand All @@ -133,5 +133,8 @@ public static function loadWmicBlocking($command = null)
return $config;
}

/**
* @var array<string>
*/
public $nameservers = [];
}
17 changes: 7 additions & 10 deletions src/Config/HostsFile.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,9 @@ class HostsFile
/**
* Returns the default path for the hosts file on this system
*
* @return string
* @codeCoverageIgnore
*/
public static function getDefaultPath()
public static function getDefaultPath(): string
{
// use static path for all Unix-based systems
if (DIRECTORY_SEPARATOR !== '\\') {
Expand Down Expand Up @@ -59,7 +58,7 @@ public static function getDefaultPath()
* @return self
* @throws RuntimeException if the path can not be loaded (does not exist)
*/
public static function loadFromPathBlocking($path = null)
public static function loadFromPathBlocking(?string $path = null): self
{
if ($path === null) {
$path = self::getDefaultPath();
Expand All @@ -77,10 +76,8 @@ public static function loadFromPathBlocking($path = null)

/**
* Instantiate new hosts file with the given hosts file contents
*
* @param string $contents
*/
public function __construct($contents)
public function __construct(string $contents)
{
// remove all comments from the contents
$contents = preg_replace('/[ \t]*#.*/', '', strtolower($contents));
Expand All @@ -92,9 +89,9 @@ public function __construct($contents)
* Returns all IPs for the given hostname
*
* @param string $name
* @return string[]
* @return array<string>
*/
public function getIpsForHost($name)
public function getIpsForHost(string $name): array
{
$name = strtolower($name);

Expand All @@ -121,9 +118,9 @@ public function getIpsForHost($name)
* Returns all hostnames for the given IPv4 or IPv6 address
*
* @param string $ip
* @return string[]
* @return array<string>
*/
public function getHostsForIp($ip)
public function getHostsForIp(string $ip): array
{
// check binary representation of IP to avoid string case and short notation
$ip = @inet_pton($ip);
Expand Down
22 changes: 8 additions & 14 deletions src/Model/Message.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,8 @@ final class Message

/**
* Creates a new request message for the given query
*
* @param Query $query
* @return self
*/
public static function createRequestForQuery(Query $query)
public static function createRequestForQuery(Query $query): self
{
$request = new Message();
$request->id = self::generateId();
Expand All @@ -99,11 +96,9 @@ public static function createRequestForQuery(Query $query)
/**
* Creates a new response message for the given query with the given answer records
*
* @param Query $query
* @param Record[] $answers
* @return self
* @param array<Record> $answers
*/
public static function createResponseWithAnswersForQuery(Query $query, array $answers)
public static function createResponseWithAnswersForQuery(Query $query, array $answers): self
{
$response = new Message();
$response->id = self::generateId();
Expand All @@ -126,11 +121,10 @@ public static function createResponseWithAnswersForQuery(Query $query, array $an
* DNS response messages can not guess the message ID to avoid possible
* cache poisoning attacks.
*
* @return int
* @see self::getId()
* @codeCoverageIgnore
*/
private static function generateId()
private static function generateId(): int
{
return random_int(0, 0xffff);
}
Expand Down Expand Up @@ -199,22 +193,22 @@ private static function generateId()
* ];
* ```
*
* @var Query[]
* @var array<Query>
*/
public $questions = [];

/**
* @var Record[]
* @var array<Record>
*/
public $answers = [];

/**
* @var Record[]
* @var array<Record>
*/
public $authority = [];

/**
* @var Record[]
* @var array<Record>
*/
public $additional = [];
}
10 changes: 3 additions & 7 deletions src/Model/Record.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,18 +131,14 @@ final class Record
* considered a BC break. See the format definition of known types above
* for more details.
*
* @var string|string[]|array
* @var string|array<string>
*/
public $data;

/**
* @param string $name
* @param int $type
* @param int $class
* @param int $ttl
* @param string|string[]|array $data
* @param string|array<string> $data
*/
public function __construct($name, $type, $class, $ttl, $data)
public function __construct(string $name, int $type, int $class, int $ttl, $data)
{
$this->name = $name;
$this->type = $type;
Expand Down
32 changes: 9 additions & 23 deletions src/Protocol/BinaryDumper.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,7 @@

final class BinaryDumper
{
/**
* @param Message $message
* @return string
*/
public function toBinary(Message $message)
public function toBinary(Message $message): string
{
$data = '';

Expand All @@ -25,11 +21,7 @@ public function toBinary(Message $message)
return $data;
}

/**
* @param Message $message
* @return string
*/
private function headerToBinary(Message $message)
private function headerToBinary(Message $message): string
{
$data = '';

Expand All @@ -56,10 +48,9 @@ private function headerToBinary(Message $message)
}

/**
* @param Query[] $questions
* @return string
* @param array<Query> $questions
*/
private function questionToBinary(array $questions)
private function questionToBinary(array $questions): string
{
$data = '';

Expand All @@ -72,10 +63,10 @@ private function questionToBinary(array $questions)
}

/**
* @param Record[] $records
* @param array<Record> $records
* @return string
*/
private function recordsToBinary(array $records)
private function recordsToBinary(array $records): string
{
$data = '';

Expand Down Expand Up @@ -163,10 +154,9 @@ private function recordsToBinary(array $records)
}

/**
* @param string[] $texts
* @return string
* @param array<string> $texts
*/
private function textsToBinary(array $texts)
private function textsToBinary(array $texts): string
{
$data = '';
foreach ($texts as $text) {
Expand All @@ -175,11 +165,7 @@ private function textsToBinary(array $texts)
return $data;
}

/**
* @param string $host
* @return string
*/
private function domainNameToBinary($host)
private function domainNameToBinary(string $host): string
{
if ($host === '') {
return "\0";
Expand Down
33 changes: 13 additions & 20 deletions src/Protocol/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,9 @@ final class Parser
/**
* Parses the given raw binary message into a Message object
*
* @param string $data
* @throws InvalidArgumentException
* @return Message
*/
public function parseMessage($data)
public function parseMessage(string $data): Message
{
$message = $this->parse($data, 0);
if ($message === null) {
Expand All @@ -32,11 +30,9 @@ public function parseMessage($data)
}

/**
* @param string $data
* @param int $consumed
* @return ?Message
*/
private function parse($data, $consumed)
private function parse(string $data, int $consumed)
{
if (!isset($data[12 - 1])) {
return null;
Expand Down Expand Up @@ -99,11 +95,9 @@ private function parse($data, $consumed)
}

/**
* @param string $data
* @param int $consumed
* @return array
* @return array{Query, int}|array{null, null}
*/
private function parseQuestion($data, $consumed)
private function parseQuestion(string $data, int $consumed): array
{
list($labels, $consumed) = $this->readLabels($data, $consumed);

Expand All @@ -125,11 +119,9 @@ private function parseQuestion($data, $consumed)
}

/**
* @param string $data
* @param int $consumed
* @return array An array with a parsed Record on success or array with null if data is invalid/incomplete
* @return array{Record, int}|array{null, null} An array with a parsed Record on success or array with null if data is invalid/incomplete
*/
private function parseRecord($data, $consumed)
private function parseRecord(string $data, int $consumed): array
{
list($name, $consumed) = $this->readDomain($data, $consumed);

Expand Down Expand Up @@ -278,7 +270,10 @@ private function parseRecord($data, $consumed)
];
}

private function readDomain($data, $consumed)
/**
* @return array{string, int}|array{null, null}
*/
private function readDomain(string $data, int $consumed): array
{
list ($labels, $consumed) = $this->readLabels($data, $consumed);

Expand All @@ -302,12 +297,10 @@ function ($label) {
}

/**
* @param string $data
* @param int $consumed
* @param int $compressionDepth maximum depth for compressed labels to avoid unreasonable recursion
* @return array
* @param int $compressionDepth maximum depth for compressed labels to avoid unreasonable recursion
* @return array{array<string>, int}|array{null, null}
*/
private function readLabels($data, $consumed, $compressionDepth = 127)
private function readLabels(string $data, int $consumed, int $compressionDepth = 127): array
{
$labels = [];

Expand Down
3 changes: 2 additions & 1 deletion src/Query/CachingExecutor.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use React\Cache\CacheInterface;
use React\Dns\Model\Message;
use React\Promise\Promise;
use React\Promise\PromiseInterface;

final class CachingExecutor implements ExecutorInterface
{
Expand All @@ -24,7 +25,7 @@ public function __construct(ExecutorInterface $executor, CacheInterface $cache)
$this->cache = $cache;
}

public function query(Query $query)
public function query(Query $query): PromiseInterface
{
$id = $query->name . ':' . $query->type . ':' . $query->class;

Expand Down
3 changes: 2 additions & 1 deletion src/Query/CoopExecutor.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace React\Dns\Query;

use React\Promise\Promise;
use React\Promise\PromiseInterface;

/**
* Cooperatively resolves hosts via the given base executor to ensure same query is not run concurrently
Expand Down Expand Up @@ -45,7 +46,7 @@ public function __construct(ExecutorInterface $base)
$this->executor = $base;
}

public function query(Query $query)
public function query(Query $query): PromiseInterface
{
$key = $this->serializeQueryToIdentity($query);
if (isset($this->pending[$key])) {
Expand Down
7 changes: 5 additions & 2 deletions src/Query/ExecutorInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

namespace React\Dns\Query;

use React\Dns\Model\Message;
use React\Promise\PromiseInterface;

interface ExecutorInterface
{
/**
Expand Down Expand Up @@ -36,8 +39,8 @@ interface ExecutorInterface
* ```
*
* @param Query $query
* @return \React\Promise\PromiseInterface<\React\Dns\Model\Message>
* @return PromiseInterface<Message>
* resolves with response message on success or rejects with an Exception on error
*/
public function query(Query $query);
public function query(Query $query): PromiseInterface;
}
Loading

0 comments on commit 6c7b3af

Please sign in to comment.