Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PHP TL GEN: PART 2 #60

Draft
wants to merge 20 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions cmd/tlgen/main2.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,23 @@ func parseFlags(opt *tlcodegen.Gen2Options) {
flag.StringVar(&opt.RootCPPNamespace, "cpp-namespace", "",
`c++ root namespace, separated by '::' if more than 1 element`)

// PHP
flag.BoolVar(&opt.AddFunctionBodies, "php-serialization-bodies", false,
`whether to generate body to write/read generated structs and functions`)
flag.BoolVar(&opt.AddMetaData, "php-generate-meta", false,
`whether to generate methods to get meta information about tl objects`)
flag.BoolVar(&opt.AddFactoryData, "php-generate-factory", false,
`whether to generate factory of tl objects`)
flag.BoolVar(&opt.IgnoreUnusedInFunctionsTypes, "php-ignore-unused-types", true,
`whether to not generate types without usages in functions`)
flag.BoolVar(&opt.AddRPCTypes, "php-rpc-support", true,
`whether to generate special rpc types`)
flag.BoolVar(&opt.InplaceSimpleStructs, "php-inplace-simple-structs", true,
`whether to avoid generation of structs with no arguments and only 1 field`)

if opt.AddFactoryData {
opt.AddFunctionBodies = true
}
// .tlo
flag.StringVar(&opt.TLOPath, "tloPath", "",
"whether to serialize TL schema in binary form")
Expand Down
79 changes: 73 additions & 6 deletions internal/tlcodegen/helpers_php.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package tlcodegen

const BasicTlPathPhp = "basictl.php"
const BasicTLCodePHP = `
<?php
include "run.php";
const BasicTlPathPHP = "tl_streams.php"
const BasicTLCodePHP = `<?php

namespace VK\TL;

class tl_constants {
const tinyStringLen = 253;
Expand Down Expand Up @@ -54,6 +54,17 @@ class tl_input_stream {
}
}

/** @return tuple(int, bool) */
public function read_int64() {
$data = unpack('q', $this->data, $this->offset);
if (!$data) {
return [0, false];
} else {
$this->offset += 8;
return [$data[1], true];
}
}

/** @return tuple(bool, bool) */
public function read_bool(int $false_tag, $true_tag) {
[$tag, $success] = $this->read_uint32();
Expand Down Expand Up @@ -117,7 +128,7 @@ class tl_input_stream {
return ["", false];
}
$l64 = (ord($this->data[$this->offset + 7]) << 48) + (ord($this->data[$this->offset + 6]) << 40) + (ord($this->data[$this->offset + 5]) << 32) + (ord($this->data[$this->offset + 4]) << 24) + (ord($this->data[$this->offset + 3]) << 16) + (ord($this->data[$this->offset + 2]) << 8) + (ord($this->data[$this->offset + 1]) << 0);
// TODO: check l64 > maxint
// TODO: check l64 > max int
$l = $l64;
$this->offset += 8;
$p = $l;
Expand Down Expand Up @@ -157,31 +168,48 @@ class tl_output_stream {
public function get_data(): string {
return $this->data;
}


/** @return bool */
public function write_uint32(int $value) {
$this->data .= pack('V', $value);
return true;
}

/** @return bool */
public function write_int32(int $value) {
$this->data .= pack('l', $value);
return true;
}

/** @return bool */
public function write_int64(int $value) {
$this->data .= pack('q', $value);
return true;
}

/** @return bool */
public function write_bool(bool $value, int $false_tag, $true_tag) {
if ($value) {
$this->data .= pack('V', $true_tag);
} else {
$this->data .= pack('V', $false_tag);
}
return true;
}

/** @return bool */
public function write_float(float $value) {
$this->data .= pack('f', $value);
return true;
}

/** @return bool */
public function write_double(float $value) {
$this->data .= pack('d', $value);
return true;
}

/** @return bool */
public function write_string(string $value) {
$l = strlen($value);
$p = 0;
Expand Down Expand Up @@ -220,6 +248,7 @@ class tl_output_stream {
} else if ($p % 4 == 3) {
$this->data .= chr(0);
}
return true;
}
}
?>
Expand Down Expand Up @@ -297,3 +326,41 @@ interface RpcResponse {

#endif
`

const TLInterfacesPathPHP = "tl_interfaces.php"
const TLInterfacesCodePHP = `<?php

namespace VK\TL;

use VK\TL;

interface Readable {
/**
* @param TL\tl_input_stream $stream
* @return bool
*/
public function read($stream);

/**
* @param TL\tl_input_stream $stream
* @return bool
*/
public function read_boxed($stream);
}

interface Writeable {
/**
* @param TL\tl_output_stream $stream
* @return bool
*/
public function write($stream);

/**
* @param TL\tl_output_stream $stream
* @return bool
*/
public function write_boxed($stream);
}

interface TL_Object extends Readable, Writeable {}
`
2 changes: 2 additions & 0 deletions internal/tlcodegen/test/codegen_test/php/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
run-all-tests:
php test_cases.php
90 changes: 90 additions & 0 deletions internal/tlcodegen/test/codegen_test/php/test_cases.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<?php

require_once(__DIR__."/../../gen/cases_php/VK/TL/tl_streams.php");
require_once(__DIR__."/../../gen/cases_php/VK/TL/factory.php");

function bool_to_str($value) {
if ($value) {
return "true";
}
return "false";
}

function digit_to_value(string $char): int {
if (ord('0') <= ord($char) && ord($char) <= ord('9')) {
return ord($char) - ord('0');
} else {
return ord($char) - ord('a') + 10;
}
}

function value_to_digit(int $value): string {
if (0 <= $value && $value <= 9) {
return chr($value + ord('0'));
} else {
return chr($value + ord('a') - 10);
}
}

function hex_to_string(string $data): string {
$result = "";
$chunks = explode(" ", $data);
foreach($chunks as $chunk) {
for($i = 7; $i >= 0; $i -= 2) {
$digit = digit_to_value($chunk[$i]) + 16 * digit_to_value($chunk[$i - 1]);
$result .= chr($digit);
}
}
return $result;
}

function string_to_hex(string $data): string {
$chunks = [];
for($i = 0; $i < strlen($data); $i += 4) {
$chunk = "";
for($s = 3; $s >= 0; $s -= 1) {
$chunk .= value_to_digit(ord($data[$i + $s]) / 16);
$chunk .= value_to_digit(ord($data[$i + $s]) % 16);
}
$chunks []= $chunk;
}
return join(" ", $chunks);
}

$PATH_TO_DATA = "../data/test-objects-bytes.json";

$value = json_decode(file_get_contents($PATH_TO_DATA));
$factory = new VK\TL\tl_factory();

foreach($value->Tests as $test_name => $test_data) {
$testing_type = $test_data->TestingType;
foreach($test_data->Successes as $exact_test) {
$input_data = hex_to_string($exact_test->Bytes);

$stream = new VK\TL\tl_input_stream($input_data);
$output = new VK\TL\tl_output_stream("");

$object = $factory->tl_object_by_name($testing_type);
if ($object == null) {
throw new Exception(sprintf("no such type \"%s\"", $testing_type));
}

$success = $object->read($stream);
if (!$success) {
throw new Exception(sprintf("\nunsuccessfull read for type \"%s\" on data \"%s\"", $testing_type, $exact_test["Bytes"]));
}

$success = $object->write($output);
if (!$success) {
throw new Exception(sprintf("\nunsuccessfull write for type \"%s\" on data \"%s\"", $testing_type, $exact_test["Bytes"]));
}

if ($input_data != $output->get_data()) {
throw new Exception(sprintf("\nread and write result are different on \"%s\":\n\texpected: %s\n\tactual: %s\n", $testing_type, string_to_hex($input_data), string_to_hex($output->get_data())));
}

printf("Test with \"%s\" passed on \"%s\"\n", $testing_type, string_to_hex($input_data));
}
}

printf("\nAll tests are passed!\n");
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php

/**
* AUTOGENERATED, DO NOT EDIT! If you want to modify it, check tl schema.
*
* This autogenerated code represents tl class for typed RPC API.
*/

namespace VK\TL\_common\Types;

use VK\TL;

/**
* @kphp-tl-class
*/
class dictionaryFieldAny__float__int {

/** @var float */
public $key = 0.0;

/** @var int */
public $value = 0;

/**
* @param float $key
* @param int $value
*/
public function __construct($key = 0.0, $value = 0) {
$this->key = $key;
$this->value = $value;
}

/**
* @param TL\tl_input_stream $stream
* @return bool
*/
public function read_boxed($stream) {
[$magic, $success] = $stream->read_uint32();
if (!$success || $magic != 0x2c43a65b) {
return false;
}
return $this->read($stream);
}

/**
* @param TL\tl_input_stream $stream
* @return bool
*/
public function read($stream) {
[$this->key, $success] = $stream->read_double();
if (!$success) {
return false;
}
[$this->value, $success] = $stream->read_int32();
if (!$success) {
return false;
}
return true;
}

/**
* @param TL\tl_output_stream $stream
* @return bool
*/
public function write_boxed($stream) {
$success = $stream->write_uint32(0x2c43a65b);
if (!$success) {
return false;
}
return $this->write($stream);
}

/**
* @param TL\tl_output_stream $stream
* @return bool
*/
public function write($stream) {
$success = $stream->write_double($this->key);
if (!$success) {
return false;
}
$success = $stream->write_int32($this->value);
if (!$success) {
return false;
}
return true;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

/**
* AUTOGENERATED, DO NOT EDIT! If you want to modify it, check tl schema.
*
* This autogenerated code represents tl class for typed RPC API.
*/

namespace VK\TL\benchmarks\Types;

use VK\TL;

/**
* @kphp-tl-class
*/
interface benchmarks_VrutoyTopLevelUnion {

/** Allows kphp implicitly load all available constructors */
const CONSTRUCTORS = [
TL\benchmarks\Types\benchmarks_vrutoytopLevelUnionBig::class,
TL\benchmarks\Types\benchmarks_vrutoytopLevelUnionEmpty::class
];

/**
* @param TL\tl_input_stream $stream
* @return bool
*/
public function read_boxed($stream);

/**
* @param TL\tl_output_stream $stream
* @return bool
*/
public function write_boxed($stream);
}
Loading
Loading