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

Documentation for new code generator tags, august2024 #1727

Merged
merged 6 commits into from
Aug 26, 2024
Merged
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
159 changes: 159 additions & 0 deletions docs/plugin/interfaces/interfaces.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,165 @@ By default, when the `@json` tag is added, all methods in the COM-RPC interface

In older Thunder versions (<R4), JSON-RPC interfaces were defined using separate JSON schema files. These would then need to be manually wired up in the plugin. By using the code-generators, we can eliminate this step, making it much faster and easier to write plugins. It is no longer recommended to create JSON schema files for JSON-RPC interfaces.

#### Overview
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we should also document that fixed size arrays are now supported (e.g. array[10], it is used in the new examples below) in certain cases.
We haven't yet documented although it was already possible but guess we should add it now that you can also use variable lenght arrays (so also for json rpc) : https://github.com/rdkcentral/ThunderInterfaces/blob/a229ea291aa52dc99e9c27839938f4f2af4a6190/interfaces/IDisplayInfo.h#L101


* It is now possible to specify a separate JSON-RPC interface for handling connection issues and correct session management, and this will bring more options when the JSON-RPC interface deviates from the COM-RPC interface.

* The JSON-RPC generator now supports the usage of nested "plain-old data"(POD) types (such as plain C structs) in the C++ interface.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also nested PODs are supported

* The JSON-RPC generator can now parse these structs and their usage in methods and generate a JSON-RPC interface for such cases.

* `Core::hresult` is now supported as a return type from Thunder 5.0 onwards for JSONRPC and is strongly recommended to be used.

* `@text` metatag has been extended to have more options to influence the names used in generated code.
* For more details click [here](../tags/#text).

* Float type is now supported in the IDL header files.

* Fixed size arrays are now supported, for example:`array[10]`
* See an example in [ICryptography](https://github.com/rdkcentral/ThunderInterfaces/blob/master/interfaces/ICryptography.h#L140)

* `Core::instance_id` is now supported in the IDL header files.
* It is presented as a 32/64 bit hexadecimal value in JSON-RPC.

* `Core::Time` is now supported in the IDL header files.
* It is presented as an [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) formatted string in JSON-RPC.

* `Core::OptionalType<T>` allows a member to be optional (this superseded @optional), and must be used if an attribute is expected to be optional on JSON-RPC. In COM-RPC the OptionalType can be used to see if a value was set, and in JSON-RPC it is then allowed to omit this parameter.
* A @default tag can be used to provide a value, in the case T is not set. See more [here](../tags/#default).
* Note: Currently, OptionalType does not work with C-Style arrays.

* JSON-RPC supports the usage of bitmask enums (a combination of enum values can be set in the same enum parameter at the same time).
* This is mapped as an array of values in the JSON-RPC interface.
* See more information about `/* @encode:bitmask */` [here](../tags/#encode).

<hr/>

#### Preventing Memory leaks

A resource allocated by a remote client must still be freed in case the channel is disconnected before the client is able to do it on its own.

To deal with this, a method can receive a ```Core::JSONRPC::Context``` as a parameter.

Amongst other things, the context includes the channel ID, which enables the association of the JSON-RPC call with the client.

Note: Context must be defined as the first parameter and will not be visible in the JSON-RPC messages.
```cpp
virtual Core::hresult Join(const Core::JSONRPC::Context& context,...) = 0;
```
Note: ```IConnection::INotification``` can be used to be notified of the dropped channels.

Examples:

View [Messenger.h](https://github.com/WebPlatformForEmbedded/ThunderNanoServicesRDK/blob/master/Messenger/Messenger.h#L254-L255) to see how ```Core::JSONRPC::Context``` is used.

<hr/>

#### Notification Registration

Notification registration is a way of tracking updates on a notification.

Tagging a notification with @statuslistener will emit additional code that will allow you to be notified when a JSON-RPC client has registered (or unregistered) from this notification. As a result, an additional IHandler interface is generated, providing the callbacks.

Examples:

In [IMessenger.H](https://github.com/rdkcentral/ThunderInterfaces/blob/master/interfaces/IMessenger.h#L95-L111), @statuslistener is used on two methods.

<hr/>
This example will demonstrate the ability to be notified when a user performs a certain action.

Suppose an interface "INotification" that contains a method "RoomUpdate", which tracks the availability of a room. The method is tagged with @statuslistener, which will allow for the creation of an "IHandler" interface. The "IHandler" interface will contain the required declaration of methods to allow for notification registration tracking.

```cpp
// @json 1.0.0
struct EXTERNAL IMessenger {
virtual ~IMessenger() = default;

/* @event */
struct EXTERNAL INotification {
virtual ~INotification() = default;

// @statuslistener
virtual void RoomUpdate(...) = 0;
}
}
```
An example of a generated IHandler interface providing the callbacks from the RoomUpdate() function.

```cpp
struct IHandler {
virtual ~IHandler() = default;

virtual void OnRoomUpdateEventRegistration(const string& client, const
PluginHost::JSONRPCSupportsEventStatus::Status status) = 0;
}
```

Using the "IHandler" interface, its methods should be implemented to track the availability of the room.
``` cpp

class Messenger : public PluginHost::IPlugin
, public JSONRPC::IMessenger
, public JSONRPC::JMessenger::IHandler {

// JSONRPC::JMessenger::IHandler override
void OnRoomUpdateEventRegistration(const string& client, const
PluginHost::JSONRPCSupportsEventStatus::Status status) {

if(status == Status::registered) {

for (const string& room: _rooms) {
JMessenger::Event::RoomUpdate(...)
}
}
}
}
```
For a more detailed view, visit [Messenger.h](https://github.com/WebPlatformForEmbedded/ThunderNanoServicesRDK/blob/master/Messenger/Messenger.h).

<hr/>

#### Object lookup

Object lookup defines the ability to create a JSON-RPC interface to access dynamically created objects (or sessions).
This object interface is brought into JSON-RPC scope with a prefix.

The format for this ability is to use the tag '@lookup:[prefix]' on a method.

Note: If 'prefix' is not set, then the name of the object interface is used instead.

##### Example

The signature of a lookup function must be:

```cpp
virtual <Interface>* Method(const uint32_t id) = 0;
```

An example of an IPlayer interface containing a playback session. Using tag @lookup, you are able to have multiple sessions, which can be differentiated by using JSON-RPC.

```cpp
struct IPlayer {
struct IPlaybackSession {
virtual Core::hresult Play() = 0;
virtual Core::hresult Stop() = 0;
};

// @lookup:session
virtual IPlaySession* Session(const uint32_t id) = 0;

virtual Core::hresult Create(uint32_t& id /* @out */) = 0;
virtual Core::hresult Configure(const string& config) = 0;
}
```
An example of possible calls to the interface: the lookup method is used to convert the id to the object.

```
Player.1.configure
Player.1.create
Player.1.session#1::play
Player.1.session#1::stop
```

### Code Generation

The code generation tooling for Thunder lives in the [ThunderTools](https://github.com/rdkcentral/ThunderTools) repository. These tools are responsible for the generation of ProxyStub implementations for COM-RPC, JSON-RPC interfaces, JSON data types, and documentation.
Expand Down
130 changes: 128 additions & 2 deletions docs/plugin/interfaces/tags.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ Ddefines a literal as a known identifier (equivalent of `#define` in C++ code)
|[@interface](#interface)| Specifies a parameter holding interface ID value for void* interface passing | | Yes | No |Method paramter|
|[@length](#length)|Specifies the expression to evaluate length of an array parameter (can be other parameter name, or constant, or math expression)| | No | Yes | Method Parameter|
|[@maxlength](#maxlength)|Specifies a maximum buffer length value | | No | Yes |Method parameter|
|[@default](#default)|Provides a default value for an unset optional type | | Yes | Yes |Method parameter|

#### @in
This tag will mark a parameter in a function as an input parameter. By default, all parameters in a function are treated as input paramter.
Expand Down Expand Up @@ -208,6 +209,36 @@ When used with `@inout` it will use different buffer for output depending upon t
##### Example
In [IPerformance.h](https://github.com/rdkcentral/ThunderInterfaces/blob/5fa166bd17c6b910696c6113c5520141bcdea07b/interfaces/IPerformance.h#L32) it specifies, the maximum length for the buffer.

<hr/>

#### @default
This tag should be associated with optional types. It provides a default value for JSON-RPC, even if no explicit value was set.

Note: Unless a parameter is optional, it must be set.

Note: Currently, OptionalType does not work with C-Style arrays.

##### Example

In this example class, the OptionalType members have a default value that would be transmitted incase their values have not been set.

```cpp
struct Store {
enum sizetype: uint8_t {
S, M, L
};

Core::OptionalType<string> Brand /* @default:"unknown" */;
Core::OptionalType<sizetype> Size /* @default: M */;
};

virtual Core::hresult Shirt(const Core::OptionalType<Store>& London) = 0;
```
<hr/>

In [IController.h](https://github.com/rdkcentral/Thunder/blob/master/Source/plugins/IController.h#L78) it specifies, the default value assigned incase the parameter is not set.

<hr/>

### JSON-RPC Related Tags

Expand All @@ -221,11 +252,15 @@ In [IPerformance.h](https://github.com/rdkcentral/ThunderInterfaces/blob/5fa166b
|[@event](#event)|Marks a class as JSON notification | | No| Yes|Class|
|[@property](#property)|Marks a method as a property ||No|Yes| Method|
|[@iterator](#iterator)|Marks a class as an iterator | | Yes| Yes|Class|
|[@bitmask](#bitmask)| Indicates that enumerator lists should be packed into into a bit mask | | No | Yes |Method parameter|
|[@bitmask](#bitmask)| Indicates that enumerator lists should be packed into into a bit mask | Yes| No | Yes |Method parameter|
|[@index](#index)|Marks an index parameter to a property or notification | | No| Yes|Method paramter|
|[@opaque](#opaque)| Indicates that a string parameter is an opaque JSON object | | No | Yes |Method parameter|
|[@alt](#alt)| Provides an alternative name a method can by called by | | No | Yes |Method|
|[@text](#text)| Renames identifier Method, Parameter, PoD Member, Enum, Interface | | No | Yes |Enum, Method parameter, Method name, PoD member, Interface |
|[@prefix](#prefix)| Prepends identifier for all JSON-RPC methods and properties in a class | | No | Yes | Class |
|[@statuslistener](#statuslistener)| Notifies when a JSON-RPC client registers/unregisters from an notification | | No | Yes | Method |
|[@lookup](#lookup)| Creates a JSON-RPC interface to access dynamically created sessions | | No | Yes | Method |
|[@encode](#encode)|Encodes data into a different format | | Yes | Yes |Method parameter|

#### @json
This tag helps to generate JSON-RPC files for the given Class/Struct/enum.
Expand Down Expand Up @@ -397,8 +432,19 @@ Indicates the string parameter contains a JSON document that should not be deser
#### @alt
Provide an alternative name for the method. JSON-RPC methods will be generated for both the actual function name and the alternative name

Note: @text, @alt, @deprecated can be used together.

##### Example
[IController](https://github.com/rdkcentral/Thunder/blob/R4.3/Source/plugins/IController.h#L38) uses @alt for the `Reboot()` method to generate an alternatively named method called `Harakiri` (for legacy reasons)

Methods, properties and notifications can be marked by using:
```cpp
// @alt <alternative_name>
// @alt:deprecated <alternative_deprecated_name>
// @alt:obsolete <alternative_obsolete_name>
```
<hr/>

[IController.h](https://github.com/rdkcentral/Thunder/blob/R4.3/Source/plugins/IController.h#L38) uses @alt for the `Reboot()` method to generate an alternatively named method called `Harakiri` (for legacy reasons)

<hr/>

Expand Down Expand Up @@ -442,10 +488,88 @@ In this example now for all enums, method names, method parameters and PoD membe
/* @json 1.0.0 @text:keep */
struct EXTERNAL IExample : virtual public Core::IUnknown {
```
</hr>
<hr>

#### @prefix
Use this tag on a class to prepend all JSON-RPC methods with a prefix identifier. This is an alternative to using multiple @text tags.

In this example, all registered methods would contain the prefix `source::`
This is particularly useful for avoiding clashes, especially if several interfaces are implemented by the same plugin.

```cpp
// @json 1.0.0
// @prefix source
struct EXTERNAL ISource: virtual public Core::IUnknown {
```
</hr>
<hr>

#### @statuslistener

Use this tag, to receive notifications when a JSON-RPC client has registered (or unregistered) from a notification.

For more details, click [here](../interfaces/#notification-registration)

</hr>
<hr>

#### @lookup

This tag is used on methods, to create a JSON-RPC interface that is dynamically accessing created objects (or sessions).

For more details, click [here](../interfaces/#object-lookup)

<hr/>

#### @encode

This tag encodes data into an alternate format.

* `@encode:base64` encodes arrays as base64 JSON-RPC arrays, on the condition that the array base is type `uint8_t`.

##### Example

In this example, C-Style `uint8_t` arrays are encoded as base64.

```cpp
struct Fixated {
struct BlueToothInfo {
uint8_t Addr[6] /* encode:base64 */;
uint32_t UUIDs[8];
string Descriptions[8];
};

Bluetooth BtAddr[5];
uint8_t Edid[128] /*encode:base64 */;
};

```

In [IDisplayInfo.h](https://github.com/rdkcentral/ThunderInterfaces/blob/a229ea291aa52dc99e9c27839938f4f2af4a6190/interfaces/IDisplayInfo.h#L101), the EDID data parameter is encoded.

<hr/>

* `@encode:bitmask` encodes enumerator lists into into a bit mask.

##### Example

In this example, a tagged enum is treated as a bitmasked list.

```cpp
enum soundmode : uint8_t {
MONO = 1,
STEREO = 2,
SURROUND = 4
};

virtual Core::hresult SupportedSoundModes(soundmode &sm /* @out @encode:bitmask */) = 0;
```

Example list:
`["mono", "stereo"]`

<hr>

### JSON-RPC Documentation Related Tags

Expand Down Expand Up @@ -545,3 +669,5 @@ This tag adds description about each return codes specified in the generated mar

##### Example
In [IVolumeControl.h](https://github.com/rdkcentral/ThunderInterfaces/blob/5fa166bd17c6b910696c6113c5520141bcdea07b/interfaces/IVolumeControl.h#L54), it uses this tag to add description about the returned error code.

<hr/>
Loading