Skip to content

Commit 1058776

Browse files
committed
[#13] Implement services (without reflectable parts)
1 parent 3f22428 commit 1058776

20 files changed

+1269
-2
lines changed

cmake/compiler_utils.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ function(compiler_get_warnings_as_errors_setup VARNAME)
112112
)
113113
string(REPLACE ";" " " WARNINGS_SETUP "${WARNINGS_SETUP} ${WARNINGS_SETUP_LIST}")
114114
endif ()
115-
if (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL "14.0.0")
115+
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "14.0.0")
116116
set(WARNINGS_SETUP_LIST
117117
"-Wno-error=reserved-identifier" # identifier is reserved because it starts with '_' ...
118118
"-Wno-error=deprecated-copy-with-dtor" # definition of implicit copy constructor is deprecated

extension/freemarker/Service.cpp.ftl

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
<#include "FileHeader.inc.ftl">
2+
<#include "Service.inc.ftl">
3+
<@file_header generatorDescription/>
4+
5+
#include <zserio/SerializeUtil.h>
6+
<@type_includes types.bitBuffer/>
7+
<@system_includes cppSystemIncludes/>
8+
9+
<@user_include package.path, "${name}.h"/>
10+
<@user_includes cppUserIncludes, false/>
11+
<@namespace_begin package.path/>
12+
<@namespace_begin [name]/>
13+
14+
Service::Service(const AllocatorType& allocator) :
15+
::zserio::AllocatorHolder<${types.allocator.default}>(allocator)
16+
{}
17+
18+
${types.serviceDataPtr.name} Service::callMethod(
19+
::std::string_view methodName, ::zserio::Span<const uint8_t> requestData, void* context)
20+
{
21+
<#list methodList as method>
22+
if (methodName == methodNames()[${method?index}])
23+
{
24+
return ${method.name}Method(requestData, context);
25+
}
26+
</#list>
27+
throw ::zserio::ServiceException("${serviceFullName}: Method '") << methodName << "' does not exist!";
28+
}
29+
30+
::std::string_view Service::serviceFullName() noexcept
31+
{
32+
static const ::std::string_view serviceFullName = "${serviceFullName}";
33+
return serviceFullName;
34+
}
35+
36+
const ::std::array<::std::string_view, ${methodList?size}>& Service::methodNames() noexcept
37+
{
38+
static constexpr ::std::array<::std::string_view, ${methodList?size}> names =
39+
{
40+
<#list methodList as method>
41+
"${method.name}"<#if method?has_next>,</#if>
42+
</#list>
43+
};
44+
45+
return names;
46+
}
47+
<#list methodList as method>
48+
49+
${types.serviceDataPtr.name} Service::${method.name}Method(
50+
::zserio::Span<const uint8_t> requestData, void* context)
51+
{
52+
<#if !method.requestTypeInfo.isBytes>
53+
${method.requestTypeInfo.typeFullName} request(get_allocator_ref());
54+
zserio::deserializeFromBytes(requestData, request);
55+
56+
</#if>
57+
<#if method.responseTypeInfo.isBytes>
58+
return ::std::allocate_shared<${types.rawServiceDataHolder.name}>(get_allocator_ref(),
59+
${method.name}Impl(request<#if method.requestTypeInfo.isBytes>Data</#if>, context));
60+
<#else>
61+
class ResponseData : public ${types.serviceDataPtr.name}::element_type
62+
{
63+
public:
64+
ResponseData(${method.responseTypeInfo.typeFullName}&& response, const AllocatorType& allocator) :
65+
m_serviceData(response, allocator)
66+
{}
67+
68+
::zserio::Span<const uint8_t> getData() const override
69+
{
70+
return m_serviceData.getData();
71+
}
72+
73+
private:
74+
${types.objectServiceData.name} m_serviceData;
75+
};
76+
77+
return ::std::allocate_shared<ResponseData>(get_allocator_ref(),
78+
${method.name}Impl(request<#if method.requestTypeInfo.isBytes>Data</#if>, context), <#rt>
79+
<#lt>get_allocator_ref());
80+
</#if>
81+
}
82+
</#list>
83+
84+
Client::Client(${types.serviceClient.name}& service, const AllocatorType& allocator) :
85+
::zserio::AllocatorHolder<${types.allocator.default}>(allocator),
86+
m_service(service)
87+
{
88+
}
89+
<#list methodList as method>
90+
91+
${method.responseTypeInfo.typeFullName} Client::${method.name}Method(<#rt>
92+
<#lt><@service_arg_type_name method.requestTypeInfo/> request, void* context)
93+
{
94+
<#if method.requestTypeInfo.isBytes>
95+
const ${types.rawServiceDataView.name} requestData(request);
96+
<#else>
97+
const ${types.objectServiceData.name} requestData(request, get_allocator_ref());
98+
</#if>
99+
100+
auto responseData = m_service.callMethod("${method.name}", requestData, context);
101+
<#if method.responseTypeInfo.isBytes>
102+
return responseData;
103+
<#else>
104+
105+
${method.responseTypeInfo.typeFullName} response(get_allocator_ref());
106+
zserio::deserializeFromBytes(responseData, response);
107+
return response;
108+
</#if>
109+
}
110+
</#list>
111+
<@namespace_end [name]/>
112+
<@namespace_end package.path/>

extension/freemarker/Service.h.ftl

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
<#include "FileHeader.inc.ftl">
2+
<#include "DocComment.inc.ftl">
3+
<#include "Service.inc.ftl">
4+
<@file_header generatorDescription/>
5+
6+
<@include_guard_begin package.path, name/>
7+
8+
<@runtime_version_check generatorVersion/>
9+
10+
#include <array>
11+
#include <zserio/Types.h>
12+
<@type_includes types.service/>
13+
#include <zserio/AllocatorHolder.h>
14+
#include <zserio/ServiceException.h>
15+
<@system_includes headerSystemIncludes/>
16+
<@user_includes headerUserIncludes/>
17+
<@namespace_begin package.path/>
18+
<@namespace_begin [name]/>
19+
20+
/**
21+
* Service part of the service ${name}.
22+
*
23+
<#if docComments??>
24+
* \b Description
25+
*
26+
<@doc_comments_inner docComments/>
27+
</#if>
28+
*/
29+
class Service :
30+
public ${types.service.name},
31+
public ::zserio::AllocatorHolder<${types.allocator.default}>
32+
{
33+
public:
34+
/**
35+
* Default constructor.
36+
*
37+
* \param allocator Allocator to construct from.
38+
*/
39+
explicit Service(const AllocatorType& allocator = AllocatorType());
40+
41+
/** Default destructor. */
42+
~Service() override = default;
43+
44+
/** Disables copy constructor. */
45+
Service(const Service&) = delete;
46+
/** Disables assignment operator. */
47+
Service& operator=(const Service&) = delete;
48+
49+
/** Default move constructor. */
50+
Service(Service&&) = default;
51+
/** Disables move assignment operator. */
52+
Service& operator=(Service&&) = delete;
53+
54+
/**
55+
* Calls method with the given name synchronously.
56+
*
57+
* \param methodName Name of the service method to call.
58+
* \param requestData Request data to be passed to the method.
59+
* \param context Context specific for particular service.
60+
*
61+
* \return Created response data.
62+
*
63+
* \throw ServiceException if the call fails.
64+
*/
65+
${types.serviceDataPtr.name} callMethod(
66+
::std::string_view methodName, ::zserio::Span<const uint8_t> requestData,
67+
void* context) override;
68+
69+
/**
70+
* Gets the service full qualified name.
71+
*
72+
* \return Service name together with its package name.
73+
*/
74+
static ::std::string_view serviceFullName() noexcept;
75+
76+
/**
77+
* Gets all method names of the service.
78+
*
79+
* \return Array of all method names of the service.
80+
*/
81+
static const ::std::array<::std::string_view, ${methodList?size}>& methodNames() noexcept;
82+
83+
private:
84+
<#if methodList?has_content>
85+
<#list methodList as method>
86+
virtual ${method.responseTypeInfo.typeFullName} ${method.name}Impl(<#rt>
87+
<#lt><@service_arg_type_name method.requestTypeInfo/> request, void* context) = 0;
88+
</#list>
89+
90+
<#list methodList as method>
91+
${types.serviceDataPtr.name} ${method.name}Method(
92+
::zserio::Span<const uint8_t> requestData, void* context);
93+
</#list>
94+
</#if>
95+
};
96+
97+
/**
98+
* Client part of the service ${name}.
99+
*
100+
<#if docComments??>
101+
* \b Description
102+
*
103+
<@doc_comments_inner docComments/>
104+
</#if>
105+
*/
106+
class Client : public ::zserio::AllocatorHolder<${types.allocator.default}>
107+
{
108+
public:
109+
/**
110+
* Constructor from the service client backend.
111+
*
112+
* \param service Interface for service client backend.
113+
* \param allocator Allocator to construct from.
114+
*/
115+
explicit Client(${types.serviceClient.name}& service, const AllocatorType& allocator = AllocatorType());
116+
117+
/** Default destructor. */
118+
~Client() = default;
119+
120+
/** Disables copy constructor. */
121+
Client(const Client&) = delete;
122+
/** Disables assignment operator. */
123+
Client& operator=(const Client&) = delete;
124+
125+
/** Default move constructor. */
126+
Client(Client&&) = default;
127+
/** Disables move assignment operator. */
128+
Client& operator=(Client&&) = delete;
129+
<#list methodList as method>
130+
131+
/**
132+
* Calls method ${method.name}.
133+
*
134+
<#if method.docComments??>
135+
* \b Description
136+
*
137+
<@doc_comments_inner method.docComments, 1/>
138+
*
139+
</#if>
140+
* \param request Request to be passed to the method.
141+
* \param context Context specific for particular service.
142+
*
143+
* \return Response returned from the method.
144+
*/
145+
${method.responseTypeInfo.typeFullName} ${method.name}Method(<#rt>
146+
<#lt><@service_arg_type_name method.requestTypeInfo/> request, void* context = nullptr);
147+
</#list>
148+
149+
private:
150+
${types.serviceClient.name}& m_service;
151+
};
152+
<@namespace_end [name]/>
153+
<@namespace_end package.path/>
154+
155+
<@include_guard_end package.path, name/>

extension/freemarker/Service.inc.ftl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<#macro service_arg_type_name typeInfo>
2+
<#if typeInfo.isBytes>
3+
::zserio::BytesView<#t>
4+
<#else>
5+
const ${typeInfo.typeFullName}&<#t>
6+
</#if>
7+
</#macro>

extension/src/zserio/extension/cpp17/Cpp17Extension.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ public void process(Root rootNode, ExtensionParameters parameters) throws Zserio
8888
emitters.add(new ConstEmitter(outputFileManager, cppParameters, context));
8989
emitters.add(new BitmaskEmitter(outputFileManager, cppParameters, context));
9090
emitters.add(new EnumerationEmitter(outputFileManager, cppParameters, context));
91+
emitters.add(new ServiceEmitter(outputFileManager, cppParameters, context));
9192
emitters.add(new StructureEmitter(outputFileManager, cppParameters, context));
9293
emitters.add(new ChoiceEmitter(outputFileManager, cppParameters, context));
9394
emitters.add(new UnionEmitter(outputFileManager, cppParameters, context));

extension/src/zserio/extension/cpp17/CppNativeMapper.java

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,18 @@ public CppNativeMapper(TypesContext typesContext)
6060
bytesType = new NativeAllocType(typesContext.getBytes(), allocatorDefinition);
6161
stringType = new NativeAllocType(typesContext.getString(), allocatorDefinition, "char");
6262
vectorType = new NativeAllocType(typesContext.getVector(), allocatorDefinition);
63+
64+
serviceType = new NativeAllocType(typesContext.getService(), allocatorDefinition, "uint8_t");
65+
serviceClientType =
66+
new NativeAllocType(typesContext.getServiceClient(), allocatorDefinition, "uint8_t");
67+
serviceDataPtrType =
68+
new NativeAllocType(typesContext.getServiceDataPtr(), allocatorDefinition, "uint8_t");
69+
objectServiceDataType =
70+
new NativeAllocType(typesContext.getObjectServiceData(), allocatorDefinition, "uint8_t");
71+
rawServiceDataHolderType =
72+
new NativeAllocType(typesContext.getRawServiceDataHolder(), allocatorDefinition, "uint8_t");
73+
rawServiceDataViewType =
74+
new NativeAllocType(typesContext.getRawServiceDataView(), allocatorDefinition, "uint8_t");
6375
}
6476

6577
public CppNativeSymbol getCppSymbol(AstNode symbol) throws ZserioExtensionException
@@ -164,6 +176,36 @@ public NativeAllocType getVectorType()
164176
return vectorType;
165177
}
166178

179+
public NativeAllocType getServiceType()
180+
{
181+
return serviceType;
182+
}
183+
184+
public NativeAllocType getServiceClientType()
185+
{
186+
return serviceClientType;
187+
}
188+
189+
public NativeAllocType getServiceDataPtrType()
190+
{
191+
return serviceDataPtrType;
192+
}
193+
194+
public NativeAllocType getObjectServiceDataType()
195+
{
196+
return objectServiceDataType;
197+
}
198+
199+
public NativeAllocType getRawServiceDataHolderType()
200+
{
201+
return rawServiceDataHolderType;
202+
}
203+
204+
public NativeAllocType getRawServiceDataViewType()
205+
{
206+
return rawServiceDataViewType;
207+
}
208+
167209
private CppNativeType mapArray(ArrayInstantiation instantiation) throws ZserioExtensionException
168210
{
169211
final TypeInstantiation elementInstantiation = instantiation.getElementTypeInstantiation();
@@ -615,7 +657,10 @@ public void visitExternType(ExternType type)
615657
@Override
616658
public void visitServiceType(ServiceType type)
617659
{
618-
thrownException = new ZserioExtensionException("TODO Unhandled type '" + type.getClass().getName());
660+
final PackageName packageName = type.getPackage().getPackageName();
661+
final String name = type.getName();
662+
final String includeFileName = getIncludePath(packageName, name);
663+
cppType = new NativeUserType(packageName, name, includeFileName);
619664
}
620665

621666
@Override
@@ -709,6 +754,13 @@ private void mapAliasType(ZserioType aliasType, TypeReference referencedType)
709754
private final NativeAllocType stringType;
710755
private final NativeAllocType vectorType;
711756

757+
private final NativeAllocType serviceType;
758+
private final NativeAllocType serviceClientType;
759+
private final NativeAllocType serviceDataPtrType;
760+
private final NativeAllocType objectServiceDataType;
761+
private final NativeAllocType rawServiceDataHolderType;
762+
private final NativeAllocType rawServiceDataViewType;
763+
712764
private final static NativeNumericWrapperType booleanType = new NativeNumericWrapperType("Bool", "bool");
713765
private final static NativeNumericWrapperType float16Type =
714766
new NativeNumericWrapperType("Float16", "float");

0 commit comments

Comments
 (0)