Skip to content
This repository has been archived by the owner on Jun 1, 2023. It is now read-only.

Commit

Permalink
Changed Hack Collections with Hack Arrays
Browse files Browse the repository at this point in the history
  • Loading branch information
Uziel Maximo Luduena committed Apr 13, 2020
1 parent 3b57c2b commit 613d7dd
Show file tree
Hide file tree
Showing 8 changed files with 82 additions and 92 deletions.
24 changes: 11 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,20 @@ A simple typed request router. Example:
* callable, but classname<MyWebControllerBase> is also a
* common choice.
*/
type TResponder = (function(ImmMap<string, string>):string);
type TResponder = (function(dict<string, string>): string);
final class BaseRouterExample extends BaseRouter<TResponder> {
protected function getRoutes(
): ImmMap<HttpMethod, ImmMap<string, TResponder>> {
return ImmMap {
HttpMethod::GET => ImmMap {
'/' =>
($_params) ==> 'Hello, world',
'/user/{user_name}' =>
($params) ==> 'Hello, '.$params['user_name'],
},
HttpMethod::POST => ImmMap {
<<__Override>>
protected function getRoutes(): dict<HttpMethod, dict<string, TResponder>> {
return dict[
HttpMethod::GET => dict[
'/' => ($_params) ==> 'Hello, world',
'/user/{user_name}' => ($params) ==> 'Hello, '.$params['user_name'],
],
HttpMethod::POST => dict[
'/' => ($_params) ==> 'Hello, POST world',
},
};
],
];
}
}
```
Expand Down
36 changes: 14 additions & 22 deletions examples/BaseRouterExample.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,33 +22,30 @@
* callable, but classname<MyWebControllerBase> is also a
* common choice.
*/
type TResponder = (function(dict<string, string>):string);
type TResponder = (function(dict<string, string>): string);

final class BaseRouterExample extends BaseRouter<TResponder> {
<<__Override>>
protected function getRoutes(
): ImmMap<HttpMethod, ImmMap<string, TResponder>> {
return ImmMap {
HttpMethod::GET => ImmMap {
'/' =>
($_params) ==> 'Hello, world',
'/user/{user_name}' =>
($params) ==> 'Hello, '.$params['user_name'],
},
HttpMethod::POST => ImmMap {
protected function getRoutes(): dict<HttpMethod, dict<string, TResponder>> {
return dict[
HttpMethod::GET => dict[
'/' => ($_params) ==> 'Hello, world',
'/user/{user_name}' => ($params) ==> 'Hello, '.$params['user_name'],
],
HttpMethod::POST => dict[
'/' => ($_params) ==> 'Hello, POST world',
},
};
],
];
}
}

function get_example_inputs(): ImmVector<(HttpMethod, string)> {
return ImmVector {
function get_example_inputs(): vec<(HttpMethod, string)> {
return vec[
tuple(HttpMethod::GET, '/'),
tuple(HttpMethod::GET, '/user/foo'),
tuple(HttpMethod::GET, '/user/bar'),
tuple(HttpMethod::POST, '/'),
};
];
}

<<__EntryPoint>>
Expand All @@ -58,12 +55,7 @@ function main(): noreturn {
list($method, $path) = $input;

list($responder, $params) = $router->routeMethodAndPath($method, $path);
\printf(
"%s %s\n\t%s\n",
$method,
$path,
$responder(dict($params)),
);
\printf("%s %s\n\t%s\n", $method, $path, $responder($params));
}
exit(0);
}
37 changes: 15 additions & 22 deletions examples/UriPatternsExample.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@

require_once(__DIR__.'/../vendor/hh_autoload.php');

use type Facebook\HackRouter\{
use type Facebook\HackRouter\{
BaseRouter,
GetFastRoutePatternFromUriPattern,
GetUriBuilderFromUriPattern,
HasUriPattern,
HttpMethod,
RequestParameters,
UriPattern
UriPattern,
};

<<__ConsistentConstruct>>
Expand All @@ -38,12 +38,10 @@ final protected function getRequestParameters(): RequestParameters {
return $this->uriParameters;
}

public function __construct(
ImmMap<string, string> $uri_parameter_values,
) {
public function __construct(dict<string, string> $uri_parameter_values) {
$this->uriParameters = new RequestParameters(
static::getUriPattern()->getParameters(),
ImmVector { },
vec[],
$uri_parameter_values,
);
}
Expand Down Expand Up @@ -78,34 +76,33 @@ public function getResponse(): string {
type TResponder = classname<WebController>;

final class UriPatternsExample extends BaseRouter<TResponder> {
public static function getControllers(): ImmVector<TResponder> {
return ImmVector {
public static function getControllers(): vec<TResponder> {
return vec[
HomePageController::class,
UserPageController::class,
};
];
}

<<__Override>>
public function getRoutes(
): ImmMap<HttpMethod, ImmMap<string, TResponder>> {
public function getRoutes(): dict<HttpMethod, dict<string, TResponder>> {
$urls_to_controllers = dict[];
foreach (self::getControllers() as $controller) {
$pattern = $controller::getFastRoutePattern();
$urls_to_controllers[$pattern] = $controller;
}
return ImmMap {
HttpMethod::GET => new ImmMap($urls_to_controllers),
};
return dict [
HttpMethod::GET => $urls_to_controllers,
];
}
}

function get_example_paths(): ImmVector<string> {
return ImmVector {
function get_example_paths(): vec<string> {
return vec[
HomePageController::getUriBuilder()->getPath(),
UserPageController::getUriBuilder()
->setString('user_name', 'Mr Hankey')
->getPath(),
};
];
}

function main(): void {
Expand All @@ -115,11 +112,7 @@ function main(): void {
HttpMethod::GET,
$path,
);
\printf(
"GET %s\n\t%s\n",
$path,
(new $controller($params))->getResponse(),
);
\printf("GET %s\n\t%s\n", $path, (new $controller($params))->getResponse());
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/request-parameters/RequestParametersBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ abstract class RequestParametersBase {
private dict<string, RequestParameter> $requiredSpecs;
private dict<string, RequestParameter> $optionalSpecs;

protected ImmMap<string, string> $values;
protected dict<string, string> $values;

public function __construct(
Traversable<RequestParameter> $required_specs,
Traversable<RequestParameter> $optional_specs,
KeyedTraversable<string, string> $values,
) {
$this->values = new ImmMap($values);
$this->values = dict($values);
$spec_vector_to_map = (
Traversable<RequestParameter> $specs
) ==> Dict\pull($specs, $it ==> $it, $it ==> $it->getName());
Expand Down
8 changes: 4 additions & 4 deletions src/router/BaseRouter.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ abstract protected function getRoutes(
final public function routeMethodAndPath(
HttpMethod $method,
string $path,
): (TResponder, ImmMap<string, string>) {
): (TResponder, dict<string, string>) {
$resolver = $this->getResolver();
try {
list($responder, $data) = $resolver->resolve($method, $path);
$data = Dict\map($data, $value ==> \urldecode($value));
return tuple($responder, new ImmMap($data));
return tuple($responder, $data);
} catch (NotFoundException $e) {
$allowed = $this->getAllowedMethods($path);
if (C\is_empty($allowed)) {
Expand All @@ -37,7 +37,7 @@ final public function routeMethodAndPath(
) {
list($responder, $data) = $resolver->resolve(HttpMethod::GET, $path);
$data = Dict\map($data, $value ==> \urldecode($value));
return tuple($responder, new ImmMap($data));
return tuple($responder, $data);
}

throw new MethodNotAllowedException($allowed);
Expand All @@ -46,7 +46,7 @@ final public function routeMethodAndPath(

final public function routeRequest(
\Facebook\Experimental\Http\Message\RequestInterface $request,
): (TResponder, ImmMap<string, string>) {
): (TResponder, dict<string, string>) {
$method = HttpMethod::coerce($request->getMethod());
if ($method === null) {
throw new MethodNotAllowedException(
Expand Down
25 changes: 15 additions & 10 deletions src/uri-patterns/UriBuilderBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,23 @@

namespace Facebook\HackRouter;

use namespace HH\Lib\{C, Vec};

abstract class UriBuilderBase {
protected ImmVector<UriPatternPart> $parts;
protected ImmMap<string, RequestParameter> $parameters;
private Map<string, string> $values = Map {};
protected vec<UriPatternPart> $parts;
protected dict<string, RequestParameter> $parameters;
private dict<string, string> $values = dict[];

public function __construct(Traversable<UriPatternPart> $parts) {
$this->parts = new ImmVector($parts);
$parameters = Map {};
$this->parts = vec($parts);
$parameters = dict[];
foreach ($parts as $part) {
if (!$part is RequestParameter) {
continue;
}
$parameters[$part->getName()] = $part;
}
$this->parameters = $parameters->immutable();
$this->parameters = $parameters;
}

final protected function getPathImpl(): string {
Expand All @@ -47,11 +49,11 @@ final protected function getPathImpl(): string {

$name = $part->getName();
invariant(
$this->values->containsKey($name),
C\contains_key($this->values, $name),
'Parameter "%s" must be set',
$name,
);
$uri .= $this->values->at($name);
$uri .= $this->values[$name];
}
invariant(
\substr($uri, 0, 1) === '/',
Expand All @@ -71,7 +73,10 @@ classname<TypedUriParameter<T>> $parameter_type,
$part !== null,
'%s is not a valid parameter - expected one of [%s]',
$name,
\implode(', ', $this->parameters->keys()->map($x ==> "'".$x."'")),
\implode(
', ',
Vec\map_with_key($this->parameters, ($key, $_) ==> "'".$key."'"),
),
);
invariant(
\is_a($part, $parameter_type),
Expand All @@ -81,7 +86,7 @@ classname<TypedUriParameter<T>> $parameter_type,
\get_class($part),
);
invariant(
!$this->values->containsKey($name),
!C\contains_key($this->values, $name),
'trying to set %s twice',
$name,
);
Expand Down
32 changes: 17 additions & 15 deletions src/uri-patterns/UriPattern.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,36 +10,38 @@

namespace Facebook\HackRouter;

use namespace HH\Lib\Vec;

// Non-final so you can extend it with additional convenience
// methods.
class UriPattern implements HasFastRouteFragment {
private Vector<UriPatternPart> $parts = Vector {};
private vec<UriPatternPart> $parts = vec[];

final public function appendPart(UriPatternPart $part): this {
$this->parts[] = $part;
return $this;
}

final public function getFastRouteFragment(): string {
$fragments = $this->parts->map($part ==> $part->getFastRouteFragment());
$fragments = Vec\map($this->parts, $part ==> $part->getFastRouteFragment());
return \implode('', $fragments);
}

final public function getParts(): ImmVector<UriPatternPart> {
return $this->parts->immutable();
final public function getParts(): vec<UriPatternPart> {
return $this->parts;
}

final public function getParameters(): ImmVector<UriParameter> {
return $this
->parts
->filter($x ==> $x is UriParameter)
->map(
$x ==> {
assert($x is UriParameter);
return $x;
},
)
->immutable();
final public function getParameters(): vec<UriParameter> {
return Vec\map(
Vec\filter($this->parts, $part ==> $part is UriParameter),
$part ==> {
invariant(
$part is UriParameter,
"Tell the typechecker what's going on",
);
return $part;
},
);
}

///// Convenience Methods /////
Expand Down
8 changes: 4 additions & 4 deletions tests/lib/TestRouter.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ public function __construct(

<<__Override>>
protected function getRoutes(
): ImmMap<HttpMethod, ImmMap<string, T>> {
return ImmMap {
HttpMethod::GET => new ImmMap($this->routes),
};
): dict<HttpMethod, dict<string, T>> {
return dict[
HttpMethod::GET => $this->routes,
];
}

public function setResolver(IResolver<T> $resolver): this {
Expand Down

0 comments on commit 613d7dd

Please sign in to comment.