Kenneth Bruen
3 years ago
1 changed files with 0 additions and 425 deletions
@ -1,425 +0,0 @@
|
||||
import 'dart:io'; |
||||
|
||||
import 'tl_scheme.dart'; |
||||
|
||||
import 'package:recase/recase.dart'; |
||||
import 'package:path/path.dart' as path; |
||||
|
||||
Future<void> main(List<String> arguments) async { |
||||
if (arguments.length != 2) { |
||||
print('The program must be run with 2 arguments:'); |
||||
print(' path to .tl schema'); |
||||
print(' path to Dart project source folder'); |
||||
exit(1); |
||||
} |
||||
|
||||
final schemeFileStr = arguments[0]; |
||||
final srcFolderStr = arguments[1]; |
||||
|
||||
if (! await File.fromUri(Uri.file(schemeFileStr)).exists()) { |
||||
print("Schema file $schemeFileStr doesn't exist"); |
||||
exit(1); |
||||
} |
||||
if (! await Directory.fromUri(Uri.directory(srcFolderStr)).exists()) { |
||||
print("Dart project source folder $srcFolderStr doesn't exist"); |
||||
exit(1); |
||||
} |
||||
|
||||
print('.tl schema folder: $schemeFileStr'); |
||||
print('Dart project source folder: $srcFolderStr'); |
||||
print(''); |
||||
|
||||
print('Reading .tl schema file...'); |
||||
final schemeFileContents = await File.fromUri(Uri.file(schemeFileStr)).readAsString(); |
||||
print('Parsing .tl schema file...'); |
||||
final scheme = TlSchema.parse(schemeFileContents); |
||||
|
||||
print('Generating...'); |
||||
|
||||
final baseFile = File.fromUri(Uri.file(path.join(srcFolderStr, 'base.dart'))); |
||||
final abstractFile = File.fromUri(Uri.file(path.join(srcFolderStr, 'abstract.dart'))); |
||||
final objFile = File.fromUri(Uri.file(path.join(srcFolderStr, 'obj.dart'))); |
||||
final fnFile = File.fromUri(Uri.file(path.join(srcFolderStr, 'fn.dart'))); |
||||
await baseFile.writeAsString(makeBaseFile(scheme)); |
||||
await abstractFile.writeAsString(makeAbstractFile(scheme)); |
||||
await objFile.writeAsString(makeObjFile(scheme)); |
||||
await fnFile.writeAsString(makeFnFile(scheme)); |
||||
|
||||
print('Done!'); |
||||
} |
||||
|
||||
String findDartType( |
||||
String type, |
||||
TlSchema scheme, |
||||
{String abstractPrefix = 'a.', |
||||
String objectPrefix = 'o.', |
||||
String functionPrefix = 'f.'} |
||||
) { |
||||
if (type.startsWith('vector<')) { |
||||
final tmp1 = type.replaceFirst('vector<', ''); |
||||
final tmp2 = tmp1.substring(0, tmp1.length - 1); |
||||
final innerType = findDartType( |
||||
tmp2, |
||||
scheme, |
||||
abstractPrefix: abstractPrefix, |
||||
functionPrefix: functionPrefix, |
||||
objectPrefix: objectPrefix, |
||||
); |
||||
return 'List<$innerType>'; |
||||
} |
||||
|
||||
final predefined = { |
||||
'double': 'double', |
||||
'string': 'String', |
||||
'int32': 'int', |
||||
'int53': 'int', |
||||
'int64': 'int', |
||||
'bytes': 'Uint8List', |
||||
'Bool': 'bool', |
||||
}; |
||||
|
||||
if (predefined.containsKey(type)) { |
||||
return predefined[type]!; |
||||
} |
||||
|
||||
final result = scheme.findType(type); |
||||
if (result == null) { |
||||
throw Exception("Couldn't find type: $type"); |
||||
} |
||||
|
||||
if (result is TlSchemeAbstractClass) { |
||||
return abstractPrefix + result.name.pascalCase; |
||||
} |
||||
else if (result is TlSchemeObject) { |
||||
return objectPrefix + result.name.pascalCase; |
||||
} |
||||
else if (result is TlSchemeFunction) { |
||||
return functionPrefix + result.name.pascalCase; |
||||
} |
||||
else { |
||||
throw Exception('Unknown tl object: $result'); |
||||
} |
||||
} |
||||
|
||||
String findToJsonHandling( |
||||
String type, |
||||
String varName, |
||||
TlSchema scheme, |
||||
) { |
||||
if (type.startsWith('vector<')) { |
||||
final tmp1 = type.replaceFirst('vector<', ''); |
||||
final tmp2 = tmp1.substring(0, tmp1.length - 1); |
||||
late String newVarName; |
||||
if (varName.startsWith('_e')) { |
||||
final num = int.parse(varName.substring(2)); |
||||
newVarName = '_e${num + 1}'; |
||||
} |
||||
else { |
||||
newVarName = '_e1'; |
||||
} |
||||
final innerHandling = findToJsonHandling( |
||||
tmp2, |
||||
newVarName, |
||||
scheme, |
||||
); |
||||
return '$varName.map(($newVarName) => $innerHandling).toList(growable: false)'; |
||||
} |
||||
|
||||
final predefined = { |
||||
'double': 'double', |
||||
'string': 'String', |
||||
'int32': 'int', |
||||
'int53': 'int', |
||||
'Bool': 'bool', |
||||
}; |
||||
if (predefined.containsKey(type)) { |
||||
return varName; |
||||
} |
||||
else if (type == 'int64') { |
||||
return '$varName.toString()'; |
||||
} |
||||
else if (type == 'bytes') { |
||||
return 'base64.encode($varName)'; |
||||
} |
||||
else { |
||||
return '$varName.toJson()'; |
||||
} |
||||
} |
||||
|
||||
String findFromJsonHandling( |
||||
String type, |
||||
String keyName, |
||||
TlSchema scheme, |
||||
{String abstractPrefix = 'a.', |
||||
String objectPrefix = 'o.', |
||||
String functionPrefix = 'f.'} |
||||
) { |
||||
if (type.startsWith('vector<')) { |
||||
final tmp1 = type.replaceFirst('vector<', ''); |
||||
final tmp2 = tmp1.substring(0, tmp1.length - 1); |
||||
final innerType = findDartType(tmp2, scheme, abstractPrefix: abstractPrefix, functionPrefix: functionPrefix, objectPrefix: objectPrefix); |
||||
return "(json['$keyName'] as List<dynamic>).map((e) => b.TdBase.fromJson(e) as $innerType).toList(growable: false)"; |
||||
} |
||||
|
||||
final predefined = { |
||||
'double': 'double', |
||||
'string': 'String', |
||||
'int32': 'int', |
||||
'int53': 'int', |
||||
'Bool': 'bool', |
||||
}; |
||||
if (predefined.containsKey(type)) { |
||||
return "json['$keyName']"; |
||||
} |
||||
else if (type == 'int64') { |
||||
return "int.parse(json['$keyName'])"; |
||||
} |
||||
else if (type == 'bytes') { |
||||
return "base64.decode(json['$keyName'])"; |
||||
} |
||||
else { |
||||
return "b.TdBase.fromJson(json['$keyName']) as ${findDartType(type, scheme, abstractPrefix: abstractPrefix, functionPrefix: functionPrefix, objectPrefix: objectPrefix)}"; |
||||
} |
||||
} |
||||
|
||||
String makeBaseFile(TlSchema scheme) { |
||||
var result = r""" |
||||
import 'dart:convert'; |
||||
import 'dart:typed_data'; |
||||
|
||||
import 'abstract.dart' as a; |
||||
import 'obj.dart' as o; |
||||
import 'fn.dart' as f; |
||||
|
||||
abstract class TdBase { |
||||
Map<String, dynamic> toJson(); |
||||
|
||||
static TdBase fromJson(Map<String, dynamic> json) { |
||||
final type = json['@type'] as String; |
||||
if (false) {} |
||||
"""; |
||||
for (final o in scheme.objects) { |
||||
final normName = o.name.pascalCase; |
||||
result += ''' |
||||
else if (type == '${o.name}') { |
||||
return o.$normName.fromJson(json); |
||||
} |
||||
'''; |
||||
} |
||||
|
||||
result += ''' |
||||
else { |
||||
throw Exception('Unknown type: \$type'); |
||||
} |
||||
} |
||||
} |
||||
'''; |
||||
return result; |
||||
} |
||||
|
||||
String makeAbstractFile(TlSchema scheme) { |
||||
var result = r""" |
||||
import 'base.dart' as b; |
||||
|
||||
"""; |
||||
|
||||
for (final ac in scheme.abstractClasses) { |
||||
final normName = ac.name.pascalCase; |
||||
result += ''' |
||||
/// ${ac.doc} |
||||
abstract class $normName extends b.TdBase {} |
||||
|
||||
'''; |
||||
} |
||||
|
||||
return result; |
||||
} |
||||
|
||||
String makeObjFile(TlSchema scheme) { |
||||
var result = r""" |
||||
import 'dart:convert'; |
||||
import 'dart:typed_data'; |
||||
|
||||
import 'base.dart' as b; |
||||
import 'abstract.dart' as a; |
||||
|
||||
"""; |
||||
|
||||
for (final o in scheme.objects) { |
||||
final normName = o.name.pascalCase; |
||||
final baseName = findDartType(o.baseType, scheme, objectPrefix: ''); |
||||
result += ''' |
||||
/// ${o.doc} |
||||
class $normName extends $baseName { |
||||
'''; |
||||
|
||||
for (final param in o.parameters) { |
||||
final normParamName = param.name.camelCase; |
||||
final paramType = findDartType(param.type, scheme, objectPrefix: ''); |
||||
result += ''' |
||||
/// ${param.doc} |
||||
final $paramType $normParamName; |
||||
'''; |
||||
} |
||||
|
||||
// Constructor |
||||
if (o.parameters.isNotEmpty) { |
||||
result += ''' |
||||
|
||||
$normName({ |
||||
'''; |
||||
for (final param in o.parameters) { |
||||
final normParamName = param.name.camelCase; |
||||
result += ''' |
||||
required this.$normParamName, |
||||
'''; |
||||
} |
||||
result += ''' |
||||
}); |
||||
|
||||
'''; |
||||
} |
||||
else { |
||||
result += ''' |
||||
$normName(); |
||||
|
||||
'''; |
||||
} |
||||
|
||||
// toJson |
||||
result += ''' |
||||
@override |
||||
Map<String, dynamic> toJson() => { |
||||
'@type': '${o.name}', |
||||
'''; |
||||
for (final param in o.parameters) { |
||||
final normParamName = param.name.camelCase; |
||||
result += ''' |
||||
'${param.name}': $normParamName, |
||||
'''; |
||||
} |
||||
result += ''' |
||||
}; |
||||
|
||||
'''; |
||||
|
||||
// fromJson |
||||
result += ''' |
||||
factory $normName.fromJson(Map<String, dynamic> json) => $normName( |
||||
'''; |
||||
for (final param in o.parameters) { |
||||
final normParamName = param.name.camelCase; |
||||
final handle = findFromJsonHandling(param.type, param.name, scheme, objectPrefix: ''); |
||||
result += ''' |
||||
$normParamName: $handle, |
||||
'''; |
||||
} |
||||
result += ''' |
||||
); |
||||
'''; |
||||
|
||||
result += ''' |
||||
} |
||||
|
||||
'''; |
||||
} |
||||
|
||||
return result; |
||||
} |
||||
|
||||
String makeFnFile(TlSchema scheme) { |
||||
var result = r""" |
||||
import 'dart:convert'; |
||||
import 'dart:typed_data'; |
||||
|
||||
import 'base.dart' as b; |
||||
import 'abstract.dart' as a; |
||||
import 'obj.dart' as o; |
||||
|
||||
abstract class TdFunction extends b.TdBase {} |
||||
|
||||
"""; |
||||
|
||||
for (final f in scheme.functions) { |
||||
final normName = f.name.pascalCase; |
||||
result += ''' |
||||
/// ${f.doc} |
||||
class $normName extends TdFunction { |
||||
'''; |
||||
|
||||
// Parameters |
||||
for (final param in f.parameters) { |
||||
final pNormName = param.name.camelCase; |
||||
final pType = findDartType(param.type, scheme, functionPrefix: ''); |
||||
result += ''' |
||||
/// ${param.doc} |
||||
final $pType $pNormName; |
||||
'''; |
||||
} |
||||
|
||||
// Constructor |
||||
if (f.parameters.isEmpty) { |
||||
result += ''' |
||||
$normName(); |
||||
|
||||
'''; |
||||
} |
||||
else { |
||||
result += ''' |
||||
|
||||
$normName({ |
||||
'''; |
||||
for (final param in f.parameters) { |
||||
final pNormName = param.name.camelCase; |
||||
result += ''' |
||||
required this.$pNormName, |
||||
'''; |
||||
} |
||||
result += ''' |
||||
}); |
||||
|
||||
'''; |
||||
} |
||||
|
||||
// toJson |
||||
result += ''' |
||||
@override |
||||
Map<String, dynamic> toJson() => { |
||||
'@type': '${f.name}', |
||||
'''; |
||||
for (final param in f.parameters) { |
||||
final pNormName = param.name.camelCase; |
||||
final jsonHandling = findToJsonHandling(param.type, pNormName, scheme); |
||||
result += ''' |
||||
'${param.name}': $jsonHandling, |
||||
'''; |
||||
} |
||||
result += ''' |
||||
}; |
||||
|
||||
'''; |
||||
|
||||
// fromJson |
||||
result += ''' |
||||
factory $normName.fromJson(Map<String, dynamic> json) => $normName( |
||||
'''; |
||||
for (final param in f.parameters) { |
||||
final normParamName = param.name.camelCase; |
||||
final handle = findFromJsonHandling(param.type, param.name, scheme); |
||||
result += ''' |
||||
$normParamName: $handle, |
||||
'''; |
||||
} |
||||
result += ''' |
||||
); |
||||
'''; |
||||
|
||||
result += ''' |
||||
} |
||||
|
||||
'''; |
||||
} |
||||
|
||||
return result; |
||||
} |
||||
|
Loading…
Reference in new issue