Scenarios
- Json Parsing + Stringify [SerDes]
- Command Line Args Parsing [SerDes]
- Persistent Object Storage +CRUD [Database]
- Object Mirroring and Delta updates [Transactions]
- Web Services [Interfaces]
- Python Bindings [Interfaces]
Build : Supported Platforms : Linux, Android, Win32, UWP
- Build Integration (CMake + Submodule)
- Build Integration (CMake + Vcpkg)
- Use your own templates, Language and types
(Future Work - Contribute)
- MySQL ORM [Database]
- Bluetooth (BLE Gatt) Services [Interfaces]
- MQTT Services [Interfaces]
- Encrypted Storage [Database]
A code generation tool that is inspired by Model-Template-View architectural patterns that involve Data-Binding. The tool in its bare-bones form can take as input:
- An IDL representation of interfaces and structs (Model)
- Native Type and container mappings (Type Declarations)
- Templates for binding the Data-Structs and API-Interfaces (Template)
And generate code (View) thats based on replication and substitution of bindable expression in the templates (data-binding)
Includes (optional) built-in templates for some real-world usage scenarios, like json-parsing, tabular-data-storage, command-line-args etc.
THe built-in templates generate compile time reflection of structs and interface that along with a header-only runtime make possible the following core usage scenarios
- Serialization / Deserialization
- Data Storage CRUD
- SQLITE (TODO: Broken currently)
- PageDB (Custom Paged Tabular Records) (FixedSize, Blobs)
- RPC
- REST Web-Service : C++ based REST HTTP Web-service (JSON) based on IDL interface definition. (using cpp-httplib)
- [TODO] Bluetooth BLE Services
- Object Modelling
- Transactions : Record and Replay of Delta changes into runtime objects
- Property change event notifications and listeners
The built-in functionalities follow the design principles:
- Pay for what you use. No runtime compute/memory impact from unused features
- Dont care about compile-times
- Header only to allow for easier build integration and portability
- The templates generate highly reusable compile-time reflection metadata that the header-only runtime uses for providing the requested functionality by integration with the popular corresponding framework (JSON -> nlohmann-json, Web-Service -> cpp-httplib)
- One liner integrations for most common scenarios.
- C++20 . Dont care about older compilers or platforms where C++20 isnt available
- Cross platform Runtime header generation: Tested for Windows, Linux, RaspberryPi's, Android, with Clang, GCC, MSVC
- No compiler warnings with Wall, WEverything, Wextra pedantic pedantic-errors etc on either 32 bit or 64 bit platforms.
The following code usage examples demonstrate how to use the builtin templates for each use-case
- JSON Input and Output
- Command Line Arg parsing and help generation
Consider a simple IDL (foo.pidl)
struct Foo
{
string s (Description = "Some String"),
list<string> l (Description = "List of strings"),
i32 i = 3443 (Description = "Some integer value"),
bool b = false (Description = "A switch")
}
C++ Code
#include <foo.pidl.h> // Generated : Auto includes the header only runtime
#include <iostream>
int main(int arg, char* argv[])
{
// Command line: foo -s "some-string" -l val1,val2, -i 3444
// Command Line args parsing
std::unique_ptr<Foo> obj = CommandLineArgsReader::Parse<Foo>(argc, argv);
// Struct object foocliobj now has the following data
assert(obj.s == "some-string")
assert(obj.l[0] == "val1")
assert(obj.i == 3444)
assert(obj.b == false)
// Json representation of the data
// {"s": "some-string", "l": ["val1", "val2"], "i": 3444 }
// JSON Serialization
std::string foojsonstr = Json::Stringify(foo);
// JSON Deserialization
auto foojsonobj = Json::Parse<Foo>(foojsonstr);
return 0;
}
IDL example
struct UserData
{
//databaseref<wstring> name;
timestamp modified;
timestamp creation;
}
struct Identity
{
db_encrypted_unique_wstring username;
db_encrypted_unique_wstring password;
db_encrypted_unique_wstring privatekey;
db_encrypted_unique_wstring clientcert;
db_encrypted_unique_wstring secretcode;
}
struct RemoteHost
{
db_encrypted_unique_wstring name;
db_encrypted_unique_wstring uri;
uuidref<Identity> identity;
}
attribute database owner = UserData : object = RemoteHost, Identity
attribute uuidbasedobject object = RemoteHost, Identity
attribute encryptedobject object = Identity
attribute timestamped object = RemoteHost, Identity, UserData
C++ Code
#include <UserData.pidl.h>
int main(int argc, char *argv[])
{
// TODO
}
IDL example (Service.pidl)
struct Data
{
i32 result;
}
interface TestInterface
{
Data AddNumber(i32 num1, i32 num2);
}
C++ Code
#include <Service.pidl.h>
#include <WebService.h>
class TestInterfaceImpl : public TestInterface
{
public:
// Inherited via TestInterface
virtual Data AddNumber(int32_t num1, int32_tnum2) override { return Data{ num1 + num2}; }
};
template <> struct ReflectionBase::InterfaceActivator<TestInterface>
{
std::unique_ptr<TestInterface> Activate()
{
return new TestInterfaceImpl();
}
};
int main(int argc, char* argv[])
{
WebService<TestInterface> svc;
svc.StartOnPort(8080);
svc.WaitForStop();
}
To either support a new code generation langauage or to support additional scenarios, certain custom templates may be written.
The code generation tool in its bare-form tries to stick to the follow design principles
- Language independent codegen, to allow for potentially generating other languages
- Currently C++ support only (Builtin)
- Modular parsing of input formats into their in-memory representation to allow extensible and varied input format for
each input category
- Currently supported formats and parsers
- IDL : Custom Thrift-like IDL
- Templates : C++ code (Intellisense available) with HTML-Markup in line-comments and distinct variables naming schema for binding declarations. XML as the parsing engine
- Type-Mappings : YAML
- Currently supported formats and parsers
- Model-Template-View
- Model : IDL
- Template : Code-Template + Type-Mapping
- View : Generated Code
- Declarative (Binding-only) templates, no loops or algorithmic generation codification in templates
- Allow for complete bypass of all Built-in layers (Templates and Type-mapping) with full-barebone usage of the core
engine
- Templates and Mappings can be loaded from user specified directories at runtime
- No loadings of builtin templates and mappings
- Provide Built-in template + mapping support for most common scenarios for easier out-of-box experience
- Cross platform C++
- Easy build system integration. (CMake included)