2022-12-08 11:40:55 +03:00
|
|
|
<?php
|
|
|
|
namespace metagen_go;
|
2023-06-06 14:37:34 +03:00
|
|
|
|
2022-12-08 11:40:55 +03:00
|
|
|
use Exception;
|
2023-06-06 14:37:34 +03:00
|
|
|
use mtgMetaInfo;
|
|
|
|
use mtgMetaInfoUnit;
|
|
|
|
use mtgMetaEnum;
|
|
|
|
use mtgMetaStruct;
|
|
|
|
use mtgMetaField;
|
|
|
|
use mtgMetaRPC;
|
|
|
|
use mtgType;
|
|
|
|
use mtgTypeRef;
|
|
|
|
use mtgBuiltinType;
|
|
|
|
use mtgArrType;
|
|
|
|
use Twig\{TwigTest, TwigFilter, TwigFunction};
|
2022-12-08 11:40:55 +03:00
|
|
|
|
|
|
|
function get_twig(array $inc_path = [])
|
|
|
|
{
|
|
|
|
array_unshift($inc_path, __DIR__ . "/../tpl/");
|
|
|
|
$loader = new \Twig\Loader\FilesystemLoader($inc_path);
|
|
|
|
|
|
|
|
$twig = new \Twig\Environment($loader, [
|
2023-06-06 14:37:34 +03:00
|
|
|
'debug' => true,
|
|
|
|
'autoescape' => false,
|
|
|
|
'strict_variables' => true,
|
|
|
|
]);
|
2022-12-08 11:40:55 +03:00
|
|
|
$twig->addExtension(new \Twig\Extension\DebugExtension());
|
|
|
|
|
2023-06-06 14:37:34 +03:00
|
|
|
addTwigTests($twig);
|
|
|
|
addTwigFilters($twig);
|
|
|
|
addTwigFunctions($twig);
|
2022-12-08 11:40:55 +03:00
|
|
|
|
|
|
|
return $twig;
|
|
|
|
}
|
|
|
|
|
|
|
|
function supported_tokens()
|
|
|
|
{
|
|
|
|
return [
|
2023-06-06 14:37:34 +03:00
|
|
|
'table',
|
|
|
|
'table_pkey',
|
|
|
|
'table_json_kv',
|
|
|
|
|
2023-07-04 11:05:12 +03:00
|
|
|
'data_root',
|
2023-06-06 14:37:34 +03:00
|
|
|
'bitfields',
|
|
|
|
'diffable',
|
|
|
|
'diff_removed',
|
|
|
|
|
|
|
|
'alias',
|
2022-12-08 11:40:55 +03:00
|
|
|
'default',
|
|
|
|
'optional',
|
|
|
|
'virtual',
|
|
|
|
|
|
|
|
'statist',
|
|
|
|
'statist_skip',
|
2022-12-08 16:51:08 +03:00
|
|
|
'statist_alias',
|
2022-12-08 11:40:55 +03:00
|
|
|
];
|
|
|
|
}
|
|
|
|
|
2023-06-06 14:37:34 +03:00
|
|
|
function addTwigTests(\Twig\Environment $twig)
|
2022-12-08 11:40:55 +03:00
|
|
|
{
|
2023-06-06 14:37:34 +03:00
|
|
|
$twig->addTest(new TwigTest(
|
|
|
|
'metaenum',
|
|
|
|
fn(mtgMetaInfoUnit $u): bool => $u->object instanceof mtgMetaEnum,
|
2022-12-08 11:40:55 +03:00
|
|
|
));
|
2023-06-06 14:37:34 +03:00
|
|
|
$twig->addTest(new TwigTest(
|
|
|
|
'metastruct',
|
|
|
|
fn(mtgMetaInfoUnit $u): bool => $u->object instanceof mtgMetaStruct,
|
2022-12-08 11:40:55 +03:00
|
|
|
));
|
2023-06-06 14:37:34 +03:00
|
|
|
$twig->addTest(new TwigTest(
|
|
|
|
'metarpc',
|
|
|
|
fn(mtgMetaInfoUnit $u): bool => $u->object instanceof mtgMetaRPC,
|
2022-12-08 11:40:55 +03:00
|
|
|
));
|
2023-06-06 14:37:34 +03:00
|
|
|
$twig->addTest(new TwigTest(
|
|
|
|
'enum',
|
|
|
|
fn(mtgType $t): bool => $t instanceof mtgMetaEnum,
|
2022-12-08 11:40:55 +03:00
|
|
|
));
|
2023-06-06 14:37:34 +03:00
|
|
|
$twig->addTest(new TwigTest(
|
|
|
|
'struct',
|
|
|
|
fn(mtgType $t): bool => $t instanceof mtgMetaStruct,
|
|
|
|
));
|
|
|
|
$twig->addTest(new TwigTest(
|
|
|
|
'array',
|
|
|
|
fn(mtgType $t): bool => $t instanceof mtgArrType,
|
|
|
|
));
|
|
|
|
$twig->addTest(new TwigTest(
|
|
|
|
'builtin',
|
|
|
|
fn(mtgType $t): bool => $t instanceof mtgBuiltinType,
|
|
|
|
));
|
|
|
|
$twig->addTest(new TwigTest(
|
|
|
|
'numeric',
|
|
|
|
fn(mtgType $t): bool => $t instanceof mtgBuiltinType && $t->isNumeric(),
|
|
|
|
));
|
|
|
|
$twig->addTest(new TwigTest(
|
|
|
|
'int',
|
|
|
|
fn(mtgType $t): bool => $t instanceof mtgBuiltinType && $t->isInt(),
|
|
|
|
));
|
|
|
|
$twig->addTest(new TwigTest(
|
|
|
|
'uint',
|
|
|
|
fn(mtgType $t): bool => $t instanceof mtgBuiltinType && $t->isUint(),
|
|
|
|
));
|
|
|
|
$twig->addTest(new TwigTest(
|
|
|
|
'bool',
|
|
|
|
fn(mtgType $t): bool => $t instanceof mtgBuiltinType && $t->isBool(),
|
|
|
|
));
|
|
|
|
$twig->addTest(new TwigTest(
|
|
|
|
'float',
|
|
|
|
fn(mtgType $t): bool => $t instanceof mtgBuiltinType && $t->isFloat(),
|
|
|
|
));
|
|
|
|
$twig->addTest(new TwigTest(
|
|
|
|
'double',
|
|
|
|
fn(mtgType $t): bool => $t instanceof mtgBuiltinType && $t->isDouble(),
|
|
|
|
));
|
|
|
|
$twig->addTest(new TwigTest(
|
|
|
|
'string',
|
|
|
|
fn(mtgType $t): bool => $t instanceof mtgBuiltinType && $t->isString(),
|
|
|
|
));
|
|
|
|
$twig->addTest(new TwigTest(
|
|
|
|
'blob',
|
|
|
|
fn(mtgType $t): bool => $t instanceof mtgBuiltinType && $t->isBlob(),
|
|
|
|
));
|
|
|
|
|
|
|
|
$twig->addTest(new TwigTest(
|
|
|
|
'instanceof',
|
|
|
|
fn($obj, $class): bool => (new \ReflectionClass($class))->isInstance($obj),
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
function addTwigFilters(\Twig\Environment $twig)
|
|
|
|
{
|
|
|
|
$twig->addFilter(new TwigFilter(
|
|
|
|
'go_type',
|
|
|
|
fn(mtgType $t): string => goType($t),
|
|
|
|
));
|
|
|
|
$twig->addFilter(new TwigFilter(
|
|
|
|
'ucfirst',
|
|
|
|
fn(string $str): string => ucfirst($str),
|
|
|
|
));
|
|
|
|
$twig->addFilter(new TwigFilter(
|
|
|
|
'lcfirst',
|
|
|
|
fn(string $str): string => lcfirst($str),
|
|
|
|
));
|
|
|
|
$twig->addFilter(new TwigFilter(
|
|
|
|
'camel',
|
|
|
|
fn(string $str): string => snake2camel($str),
|
|
|
|
));
|
|
|
|
$twig->addFilter(new TwigFilter(
|
|
|
|
'quote',
|
|
|
|
fn(string $str, string $char = '`'): string => "{$char}{$str}{$char}"
|
|
|
|
));
|
|
|
|
$twig->addFilter(new TwigFilter(
|
|
|
|
'sql_where',
|
|
|
|
function(array $fields): string {
|
|
|
|
$exprs = [];
|
|
|
|
foreach ($fields as $field) {
|
|
|
|
$fieldName = $field->getName();
|
|
|
|
$exprs[] = "`{$fieldName}` = ?";
|
|
|
|
}
|
|
|
|
return implode(' AND ', $exprs);
|
2022-12-08 11:40:55 +03:00
|
|
|
}
|
|
|
|
));
|
2023-06-06 14:37:34 +03:00
|
|
|
$twig->addFilter(new TwigFilter(
|
|
|
|
'alias',
|
|
|
|
function(mtgMetaField $field): string {
|
|
|
|
if ($field->hasToken('alias')) {
|
|
|
|
return $field->getToken('alias');
|
|
|
|
}
|
|
|
|
return $field->getName();
|
2022-12-08 11:40:55 +03:00
|
|
|
}
|
|
|
|
));
|
2023-06-06 14:37:34 +03:00
|
|
|
$twig->addFilter(new TwigFilter(
|
|
|
|
'fname',
|
|
|
|
fn(mtgMetaField $field): string => snake2camel($field->getName())
|
|
|
|
));
|
|
|
|
$twig->addFilter(new TwigFilter(
|
|
|
|
'varname',
|
|
|
|
fn(mtgMetaField $field): string => lcfirst(snake2camel($field->getName()))
|
|
|
|
));
|
|
|
|
$twig->addFilter(new TwigFilter(
|
|
|
|
'builtin_type_suffix',
|
|
|
|
fn (mtgBuiltinType $type): string => builtinTypeMethodSuffix($type),
|
|
|
|
));
|
|
|
|
$twig->addFilter(new TwigFilter(
|
|
|
|
'default_val',
|
|
|
|
fn(mtgMetaField $field) => defaultValue($field)
|
|
|
|
));
|
|
|
|
|
|
|
|
$twig->addFilter(new TwigFilter(
|
|
|
|
'rpc_invert',
|
|
|
|
fn(string $name): string => rpc_invert($name),
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
function addTwigFunctions(\Twig\Environment $twig)
|
|
|
|
{
|
|
|
|
$twig->addFunction(new TwigFunction(
|
|
|
|
'Error',
|
|
|
|
function(string $e) {
|
|
|
|
throw new Exception($e);
|
2022-12-08 14:23:55 +03:00
|
|
|
}
|
|
|
|
));
|
2023-06-06 14:37:34 +03:00
|
|
|
$twig->addFunction(new TwigFunction(
|
|
|
|
'has_token',
|
|
|
|
fn($o, string $token): bool => $o->hasToken($token),
|
|
|
|
));
|
|
|
|
$twig->addFunction(new TwigFunction(
|
|
|
|
'has_token_in_parent',
|
|
|
|
fn(mtgMetaStruct $s, string $token): bool => $s->hasTokenInParent($token),
|
|
|
|
));
|
|
|
|
$twig->addFunction(new TwigFunction(
|
|
|
|
'token',
|
|
|
|
fn($o, string $name) => $o->getToken($name),
|
|
|
|
));
|
|
|
|
$twig->addFunction(new TwigFunction(
|
|
|
|
'token_or',
|
|
|
|
fn($o, string $name, $v) => $o->hasToken($name) ? $o->getToken($name) : $v,
|
|
|
|
));
|
|
|
|
$twig->addFunction(new TwigFunction(
|
|
|
|
'get_all_fields',
|
|
|
|
fn(mtgMetaStruct $s): array => \mtg_get_all_fields($s),
|
|
|
|
));
|
|
|
|
$twig->addFunction(new TwigFunction(
|
|
|
|
'count_optional',
|
|
|
|
function($os) {
|
2022-12-08 14:50:32 +03:00
|
|
|
$opts = 0;
|
2022-12-09 11:22:17 +03:00
|
|
|
foreach($os as $o)
|
|
|
|
if($o->hasToken('optional'))
|
2022-12-08 14:50:32 +03:00
|
|
|
++$opts;
|
|
|
|
return $opts;
|
|
|
|
}
|
2023-06-06 14:37:34 +03:00
|
|
|
));
|
|
|
|
$twig->addFunction(new TwigFunction(
|
|
|
|
'arr_fill',
|
|
|
|
fn($value, int $count): array => array_fill(0, $count, $value)
|
2022-12-08 14:50:32 +03:00
|
|
|
));
|
2023-06-06 14:37:34 +03:00
|
|
|
$twig->addFunction(new TwigFunction(
|
|
|
|
'table_pkey',
|
|
|
|
function(mtgMetaStruct $struct): array {
|
|
|
|
$pkey = explode(',', $struct->getToken('table_pkey'));
|
|
|
|
$fields = [];
|
|
|
|
foreach ($pkey as $fieldName) {
|
|
|
|
$fields[] = $struct->getField($fieldName);
|
|
|
|
}
|
|
|
|
return $fields;
|
|
|
|
}
|
|
|
|
));
|
|
|
|
$twig->addFunction(new TwigFunction(
|
|
|
|
'table_fields',
|
|
|
|
function(mtgMetaStruct $struct): array {
|
|
|
|
$pkey = explode(',', $struct->getToken('table_pkey'));
|
|
|
|
return array_filter(
|
|
|
|
$struct->getFields(),
|
|
|
|
fn(mtgMetaField $field): bool => !in_array($field->getName(), $pkey),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
));
|
|
|
|
$twig->addFunction(new TwigFunction(
|
|
|
|
'meta_field',
|
|
|
|
function (string $str) use ($twig): mtgMetaField {
|
|
|
|
$meta = $twig->getGlobals()['meta'];
|
|
|
|
return parseMetaField($str, $meta);
|
|
|
|
}
|
|
|
|
));
|
|
|
|
|
|
|
|
$twig->addFunction(new TwigFunction('field_reset',
|
2022-12-08 16:21:04 +03:00
|
|
|
function($name, $type, $tokens)
|
|
|
|
{
|
|
|
|
return field_reset($name, $type, $tokens);
|
|
|
|
}
|
|
|
|
));
|
2023-06-06 14:37:34 +03:00
|
|
|
$twig->addFunction(new TwigFunction('buf2var',
|
2022-12-08 15:21:54 +03:00
|
|
|
function($name, $fname, $type, $buf, $tokens, $is_ptr)
|
|
|
|
{
|
|
|
|
return buf2var($name, $fname, $type, $buf, $tokens, $is_ptr);
|
|
|
|
}
|
|
|
|
));
|
2023-06-06 14:37:34 +03:00
|
|
|
$twig->addFunction(new TwigFunction('var2buf',
|
2022-12-08 16:05:26 +03:00
|
|
|
function($name, $fname, $type, $buf, $tokens, $is_ptr)
|
|
|
|
{
|
|
|
|
return var2buf($name, $fname, $type, $buf, $tokens, $is_ptr);
|
|
|
|
}
|
|
|
|
));
|
2023-06-06 14:37:34 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
function snake2camel(string $str): string
|
|
|
|
{
|
|
|
|
return str_replace('_', '', ucwords($str, '_'));
|
|
|
|
}
|
|
|
|
|
|
|
|
function goType(mtgType $type, array $tokens = []): string
|
|
|
|
{
|
|
|
|
if ($type instanceof mtgMetaEnum) {
|
|
|
|
return $type->getName();
|
|
|
|
} else if ($type instanceof mtgMetaStruct) {
|
|
|
|
return $type->getName();
|
|
|
|
} else if ($type instanceof mtgBuiltinType) {
|
|
|
|
if ($type->isFloat()) {
|
|
|
|
return 'float32';
|
|
|
|
} else if ($type->isDouble()) {
|
|
|
|
return 'float64';
|
|
|
|
} else if ($type->isBlob()) {
|
|
|
|
return '[]byte';
|
|
|
|
} else {
|
|
|
|
return $type->getName();
|
2022-12-08 13:29:16 +03:00
|
|
|
}
|
2023-06-06 14:37:34 +03:00
|
|
|
} else if ($type instanceof mtgArrType) {
|
|
|
|
$native = goType($type->getValue());
|
|
|
|
return "[]$native";
|
|
|
|
} else {
|
|
|
|
throw new Exception("Unknown type '$type'");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function builtinTypeMethodSuffix(mtgBuiltinType $type): string
|
|
|
|
{
|
|
|
|
if ($type->isBlob()) {
|
|
|
|
return 'Bytes';
|
|
|
|
}
|
|
|
|
return ucfirst(goType($type));
|
|
|
|
}
|
|
|
|
|
|
|
|
function defaultValue(mtgMetaField $field)
|
|
|
|
{
|
|
|
|
$type = $field->getType();
|
|
|
|
$tokens = $field->getTokens();
|
|
|
|
$default = $field->getToken('default');
|
|
|
|
|
|
|
|
if ($type instanceof mtgBuiltinType) {
|
|
|
|
if ($type->isNumeric()) {
|
|
|
|
return $default ?? 0;
|
|
|
|
} else if ($type->isString()) {
|
|
|
|
return $default ?? '""';
|
|
|
|
} else if($type->isBool()) {
|
|
|
|
return $default ?? 'false';
|
|
|
|
} else if($type->isBlob()) {
|
|
|
|
return $default ?? 'nil';
|
|
|
|
} else {
|
|
|
|
throw new Exception("Unknown type '$type'");
|
2022-12-08 13:29:16 +03:00
|
|
|
}
|
2023-06-06 14:37:34 +03:00
|
|
|
} else if($type instanceof mtgMetaEnum) {
|
|
|
|
return $default ? goType($type, $tokens)."_".trim($tokens['default'], '"') : 0;
|
|
|
|
} else {
|
|
|
|
throw new Exception("Unknown type '$type'");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function parseMetaField(string $str, mtgMetaInfo $meta): mtgMetaField
|
|
|
|
{
|
|
|
|
list($name, $type) = explode('|', $str);
|
|
|
|
return new mtgMetaField($name, new mtgTypeRef(new mtgBuiltinType($type), $meta));
|
2022-12-08 13:29:16 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
function go_type(\mtgType $type, array $tokens = array())
|
|
|
|
{
|
|
|
|
if($type instanceof \mtgArrType)
|
|
|
|
{
|
|
|
|
$vtype = $type->getValue();
|
|
|
|
|
|
|
|
$native = go_type($vtype);
|
|
|
|
|
|
|
|
$str = "[]";
|
|
|
|
if(array_key_exists("virtual", $tokens))
|
|
|
|
$str .= "I";
|
|
|
|
else
|
2022-12-08 15:21:54 +03:00
|
|
|
$str .= $vtype instanceof \mtgMetaStruct ? "*" : "";
|
2022-12-08 13:29:16 +03:00
|
|
|
|
|
|
|
$str .= $native;
|
|
|
|
|
|
|
|
return $str;
|
|
|
|
}
|
|
|
|
else if($type instanceof \mtgBuiltinType)
|
|
|
|
{
|
|
|
|
if($type->isFloat())
|
|
|
|
return "float32";
|
|
|
|
else if($type->isDouble())
|
|
|
|
return "float64";
|
|
|
|
else if($type->isBlob())
|
|
|
|
return "[]byte";
|
|
|
|
else
|
|
|
|
return $type->getName();
|
|
|
|
}
|
|
|
|
else if($type instanceof \mtgMetaEnum)
|
|
|
|
return $type->getName();
|
|
|
|
else if($type instanceof \mtgMetaStruct)
|
|
|
|
{
|
|
|
|
if(array_key_exists("virtual", $tokens))
|
|
|
|
return "I{$type->getName()}";
|
|
|
|
else
|
|
|
|
return $type->getName();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
throw new Exception("Unknown type '$type'");
|
2022-12-08 11:40:55 +03:00
|
|
|
}
|
2022-12-08 13:29:16 +03:00
|
|
|
|
2023-06-06 14:37:34 +03:00
|
|
|
function builtin_type_prefix(mtgBuiltinType $type)
|
2022-12-08 15:21:54 +03:00
|
|
|
{
|
|
|
|
switch($type->getName())
|
|
|
|
{
|
|
|
|
case "string":
|
|
|
|
return "String";
|
|
|
|
case "bool":
|
|
|
|
return "Bool";
|
|
|
|
case "blob":
|
|
|
|
return "Blob";
|
|
|
|
case "float":
|
|
|
|
return "Float";
|
|
|
|
case "double":
|
|
|
|
return "Double";
|
|
|
|
case "uint64":
|
|
|
|
return "U64";
|
|
|
|
case "int64":
|
|
|
|
return "I64";
|
|
|
|
case "uint":
|
|
|
|
case "uint32":
|
|
|
|
return "U32";
|
|
|
|
case "uint16":
|
|
|
|
return "U16";
|
|
|
|
case "uint8":
|
|
|
|
return "U8";
|
|
|
|
case "int":
|
|
|
|
case "int32":
|
|
|
|
return "I32";
|
|
|
|
case "int16":
|
|
|
|
return "I16";
|
|
|
|
case "int8":
|
|
|
|
return "I8";
|
|
|
|
default:
|
|
|
|
throw new Exception("Unknown type '{$type}'");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-06 14:37:34 +03:00
|
|
|
function field_reset($name, mtgType $type, array $tokens)
|
2022-12-08 16:21:04 +03:00
|
|
|
{
|
|
|
|
$str = '';
|
|
|
|
|
2023-06-06 14:37:34 +03:00
|
|
|
if($type instanceof mtgBuiltinType)
|
2022-12-08 16:21:04 +03:00
|
|
|
{
|
|
|
|
if($type->isNumeric())
|
|
|
|
{
|
|
|
|
if(array_key_exists('default', $tokens) && is_numeric($tokens['default']))
|
|
|
|
$str .= "self.$name = ".$tokens['default'];
|
|
|
|
else
|
|
|
|
$str .= " self.$name = 0";
|
|
|
|
}
|
|
|
|
else if($type->isString())
|
|
|
|
{
|
|
|
|
if(array_key_exists('default', $tokens))
|
|
|
|
$str .= "self.$name = ".$tokens['default'];
|
|
|
|
else
|
|
|
|
$str .= "self.$name = \"\"";
|
|
|
|
}
|
|
|
|
else if($type->isBool())
|
|
|
|
{
|
|
|
|
if(array_key_exists('default', $tokens))
|
|
|
|
$str .= "self.$name = ".$tokens['default'];
|
|
|
|
else
|
|
|
|
$str .= "self.$name = false";
|
|
|
|
}
|
|
|
|
else if($type->isBlob())
|
|
|
|
{
|
|
|
|
if(array_key_exists('default', $tokens))
|
|
|
|
$str .= "self.$name = ".$tokens['default'];
|
|
|
|
else
|
|
|
|
$str .= "self.$name = nil";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
throw new Exception("Unknown type '$type'");
|
|
|
|
}
|
2023-06-06 14:37:34 +03:00
|
|
|
else if($type instanceof mtgArrType)
|
2022-12-08 16:21:04 +03:00
|
|
|
{
|
2023-06-06 14:37:34 +03:00
|
|
|
$str = "if self.$name == nil { \nself.$name = make(".goType($type, $tokens).",0) \n}\n ";
|
2022-12-08 16:21:04 +03:00
|
|
|
$str .= "self.$name = self.{$name}[0:0]";
|
|
|
|
}
|
2023-06-06 14:37:34 +03:00
|
|
|
else if($type instanceof mtgMetaEnum)
|
2022-12-08 16:21:04 +03:00
|
|
|
{
|
|
|
|
if(array_key_exists('default', $tokens))
|
2023-06-06 14:37:34 +03:00
|
|
|
$str = "self.$name = ".goType($type, $tokens)."_".trim($tokens['default'], '"');
|
2022-12-08 16:21:04 +03:00
|
|
|
else
|
|
|
|
$str = "self.$name = 0";
|
|
|
|
}
|
2023-06-06 14:37:34 +03:00
|
|
|
else if($type instanceof mtgMetaStruct)
|
2022-12-08 16:21:04 +03:00
|
|
|
{
|
|
|
|
$is_virtual = array_key_exists("virtual", $tokens);
|
|
|
|
if($is_virtual)
|
2023-06-06 14:37:34 +03:00
|
|
|
$str .= "self.$name = New".ltrim(goType($type, $tokens),'I')."() ";
|
2022-12-08 16:21:04 +03:00
|
|
|
else
|
|
|
|
$str .= "self.$name.Reset()";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
throw new Exception("Unknown type '$type'");
|
|
|
|
return $str;
|
|
|
|
}
|
|
|
|
|
2023-06-06 14:37:34 +03:00
|
|
|
function buf2var($name, $fname, mtgType $type, $buf, array $tokens = array(), $is_ptr = false)
|
2022-12-08 15:21:54 +03:00
|
|
|
{
|
|
|
|
$str = '';
|
|
|
|
|
2023-06-06 14:37:34 +03:00
|
|
|
if($type instanceof mtgBuiltinType)
|
2022-12-08 15:21:54 +03:00
|
|
|
{
|
|
|
|
$str .= _read_op($tokens, $buf.'.Read'.builtin_type_prefix($type).'(&'.$fname.', "'.$name.'")');
|
|
|
|
}
|
2023-06-06 14:37:34 +03:00
|
|
|
else if($type instanceof mtgMetaEnum)
|
2022-12-08 15:21:54 +03:00
|
|
|
{
|
|
|
|
$str .= _read_op($tokens, "{$buf}.ReadI32((*int32)(&{$fname}), \"$name\")");
|
|
|
|
$str .= "\n if !{$fname}.IsValid() { return errors.Errorf(\"Bad enum value %d for $name\", $fname) }";
|
|
|
|
}
|
2023-06-06 14:37:34 +03:00
|
|
|
else if($type instanceof mtgMetaStruct)
|
2022-12-08 15:21:54 +03:00
|
|
|
{
|
|
|
|
if(array_key_exists('virtual', $tokens))
|
|
|
|
$str .= "if v, err := meta.ReadStructGeneric($buf, CreateById, \"{$name}\"); err != nil { return err } else { {$fname} = v.(I{$type}) }";
|
|
|
|
else
|
|
|
|
$str .= _read_op($tokens, "meta.ReadStruct($buf, ".($is_ptr?"":"&")."$fname, \"$name\")");
|
|
|
|
}
|
2023-06-06 14:37:34 +03:00
|
|
|
else if($type instanceof mtgArrType)
|
2022-12-08 15:21:54 +03:00
|
|
|
{
|
|
|
|
$is_virtual = array_key_exists("virtual", $tokens);
|
2023-06-06 14:37:34 +03:00
|
|
|
$native_type = goType($type->getValue(), $tokens);
|
2022-12-08 15:21:54 +03:00
|
|
|
$offset = "\n ";
|
|
|
|
$str .= "/*[]{$name}*/";
|
|
|
|
$str .= $offset . _read_op($tokens, "{$buf}.BeginContainer(\"$name\")");
|
|
|
|
//we don't want to propagate 'optionalness' below
|
|
|
|
unset($tokens['optional']);
|
|
|
|
$str .= $offset . "_{$name}_size, err := {$buf}.GetContainerSize()";
|
|
|
|
$str .= $offset . "if err != nil { return err }";
|
|
|
|
|
2023-06-06 14:37:34 +03:00
|
|
|
$need_new = !$is_virtual && $type->getValue() instanceof mtgMetaStruct;
|
2022-12-08 15:21:54 +03:00
|
|
|
|
|
|
|
$str .= $offset . "for ; _{$name}_size > 0; _{$name}_size-- {";
|
|
|
|
$offset = "\n ";
|
|
|
|
$str .= $offset . "var tmp_{$name} {$native_type}";
|
|
|
|
|
|
|
|
$str .= $offset . buf2var("", "tmp_{$name}", $type->getValue(), $buf, $tokens, $is_virtual);
|
2023-06-06 14:37:34 +03:00
|
|
|
$str .= $offset . "{$fname} = append({$fname}, tmp_{$name})";
|
2022-12-08 15:21:54 +03:00
|
|
|
|
|
|
|
$offset = "\n ";
|
|
|
|
$str .= $offset . "}";
|
|
|
|
$str .= $offset . _read_op($tokens, "{$buf}.EndContainer()");
|
|
|
|
$str .= "\n";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
throw new Exception("Unknown type '{$type}'");
|
|
|
|
|
|
|
|
return $str;
|
|
|
|
}
|
|
|
|
|
2023-06-06 14:37:34 +03:00
|
|
|
function var2buf($name, $fname, mtgType $type, $buf, array $tokens = array(), $is_ptr = false)
|
2022-12-08 16:05:26 +03:00
|
|
|
{
|
|
|
|
$str = '';
|
|
|
|
|
2023-06-06 14:37:34 +03:00
|
|
|
if($type instanceof mtgBuiltinType)
|
2022-12-08 16:05:26 +03:00
|
|
|
{
|
|
|
|
$str .= _write_op("{$buf}.Write".builtin_type_prefix($type)."($fname, \"$name\")")."\n";
|
|
|
|
}
|
2023-06-06 14:37:34 +03:00
|
|
|
else if($type instanceof mtgMetaEnum)
|
2022-12-08 16:05:26 +03:00
|
|
|
{
|
|
|
|
$str .= _write_op("{$buf}.WriteI32(int32($fname), \"$name\")");
|
|
|
|
}
|
2023-06-06 14:37:34 +03:00
|
|
|
else if($type instanceof mtgMetaStruct)
|
2022-12-08 16:05:26 +03:00
|
|
|
{
|
|
|
|
if(array_key_exists('virtual', $tokens))
|
|
|
|
$str .= _write_op("meta.WriteStructGeneric($buf, ".($is_ptr?"":"&")."$fname, \"$name\")");
|
|
|
|
else
|
2023-06-06 14:37:34 +03:00
|
|
|
$str .= _write_op("meta.WriteStruct($buf, &$fname, \"$name\")");
|
2022-12-08 16:05:26 +03:00
|
|
|
}
|
2023-06-06 14:37:34 +03:00
|
|
|
else if($type instanceof mtgArrType)
|
2022-12-08 16:05:26 +03:00
|
|
|
{
|
|
|
|
$str .= "{$buf}.BeginContainer(\"{$name}\")\n";
|
|
|
|
$str .= " for _, v := range({$fname}) {\n";
|
|
|
|
$str .= " ".var2buf("", "v", $type->getValue(), $buf, $tokens, true)."\n";
|
|
|
|
$str .= " }\n";
|
|
|
|
$str .= " "._write_op("{$buf}.EndContainer()")."\n";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
throw new Exception("Unknown type '$type'");
|
|
|
|
|
|
|
|
return $str;
|
|
|
|
}
|
|
|
|
|
|
|
|
function _write_op($op)
|
|
|
|
{
|
|
|
|
return "if err := $op; err != nil { return err }";
|
|
|
|
}
|
|
|
|
|
2022-12-08 15:21:54 +03:00
|
|
|
function _read_op(array $tokens, $op)
|
|
|
|
{
|
|
|
|
return "if err := $op; err != nil { return " . (array_key_exists("optional", $tokens) ? "/*optional*/nil" : "err"). " }";
|
|
|
|
}
|
2022-12-08 17:45:28 +03:00
|
|
|
|
|
|
|
function rpc_invert($name)
|
|
|
|
{
|
|
|
|
if(strpos($name, '_RSP_') !== false)
|
|
|
|
return str_replace('_RSP_', '_REQ_', $name);
|
|
|
|
else
|
|
|
|
return str_replace('_REQ_', '_RSP_', $name);
|
|
|
|
}
|
|
|
|
|