Implemented generics properly, updated cpp generator to use operator<< and operator>> for json parsing

This commit is contained in:
2023-10-13 15:43:56 +02:00
parent 613cf68fc3
commit 12392808f7
10 changed files with 165 additions and 252 deletions

View File

@@ -1,6 +1,6 @@
@use crate::data::RPC;
@use crate::generators::cpp_s::*;
@use super::cpp_server_json_cpp;
@use super::cpp_server_json_cxx;
@(header_name: &str, rpc: &RPC)
#include "@header_name"
@@ -8,7 +8,9 @@
#include <corvusoft/restbed/resource.hpp>
#include <corvusoft/restbed/request.hpp>
@:cpp_server_json_cpp(rpc)
using namespace mrpc;
@:cpp_server_json_cxx(rpc)
template<typename T>
void send_msg(const std::shared_ptr<restbed::Session> &c, const T &v) @{
@@ -55,7 +57,7 @@ mrpc::MRPCStreamImpl::MRPCStreamImpl(const std::shared_ptr<restbed::Session> &co
void mrpc::MRPCStreamImpl::close() const noexcept @{ conn->close("data:null\n\n"); @}
bool mrpc::MRPCStreamImpl::is_open() const noexcept @{ return conn->is_open(); @}
@for s in streams_required(rpc) {template<> void MRPCStream<mrpc::@s>::send(const mrpc::@s &v) const noexcept @{ send_sse_msg(conn, v); @}
@for s in streams_required(rpc) {template<> void MRPCStream<@s>::send(const @s &v) const noexcept @{ send_sse_msg(conn, v); @}
}
mrpc::MRPCServer::MRPCServer(std::shared_ptr<restbed::Resource> &r) @{
@@ -75,7 +77,8 @@ void mrpc::MRPCServer::msg_handler(const std::shared_ptr<restbed::Session> __c,
if (__j.HasParseError())
throw std::exception@{@};
std::string __service, __method;
json_get(__j, "service", __service); json_get(__j, "method", __method);
__service << json_get(__j, "service");
__method << json_get(__j, "method");
auto __data_member = __j.FindMember("data");
if (__data_member == __j.MemberEnd() || !__data_member->value.IsObject())
throw std::exception@{@};
@@ -84,7 +87,7 @@ void mrpc::MRPCServer::msg_handler(const std::shared_ptr<restbed::Session> __c,
@for (mi, m) in s.methods.iter().enumerate() {@if mi > 0 { else }else{ }if (__method == "@m.name") @{
@if m.ret_stream {auto __stream = MRPCStream<@ty_to_str(m.ret.as_ref().unwrap())>@{__c@};
}
@for (name, ty) in m.args.iter().map(|a| (&a.name, ty_to_str(&a.ty))) { @ty @name; json_get<@ty>(__data, "@name", @name);
@for (name, ty) in m.args.iter().map(|a| (&a.name, ty_to_str(&a.ty))) { @ty @name; @name << json_get(__data, "@name");
}
@if m.ret_stream || m.ret.is_none() {@(s.name)_@(m.name)(@call_args(m));}
else {send_msg(__c, @(s.name)_@(m.name)(@call_args(m)));}

View File

@@ -31,10 +31,10 @@ enum struct @e.name : std::uint64_t @{
@e.values.iter().map(|(k,v)| format!("{k} = {v}")).join(",\n ")
@};
}
@for s in &rpc.structs {struct @s.name;
@for s in &rpc.structs {@get_struct_generics(s)struct @s.name;
}
@for s in &rpc.structs {
struct @s.name @{
@get_struct_generics(s)struct @s.name @{
@for f in &s.fields { @ty_to_str(&f.ty) @f.name;
}
MRPCJWriter& operator >>(MRPCJWriter&) const;
@@ -58,6 +58,7 @@ struct MRPCStream final : MRPCStreamImpl @{
@for s in streams_required(rpc) {template struct MRPCStream<@(s)>;
}}
struct MRPCServer @{
MRPCServer() = delete;
explicit MRPCServer(std::shared_ptr<restbed::Resource>&);
private:
@for s in &rpc.services {@for m in &s.methods { virtual @method_ret(m) @(s.name)_@(m.name)(@method_args(m)) = 0;

View File

@@ -1,73 +0,0 @@
@use crate::data::RPC;
@use crate::generators::cpp_s::*;
@(rpc: &RPC)
template<typename T>
void json_get(const rapidjson::Value &j, const char *key, T &v);
template<typename T>
void json_get_inner(const rapidjson::Value&, T &v) = delete;
@for (ty, jty) in JSON_INNER_IMPLS {
template<> inline void json_get_inner(const rapidjson::Value &member, @ty &v) @{
if (!member.Is@(jty)())
throw std::exception@{@};
v = member.Get@(jty)();
@}}
template<typename T>
inline void json_get_inner(const rapidjson::Value &member, std::optional<T> &v) @{
if (member.IsNull())
v = std::nullopt;
else @{
T t;
json_get_inner<T>(member, t);
v = std::move(t);
@}
@}
template<typename T>
inline void json_get_inner(const rapidjson::Value &member, std::vector<T> &v) @{
if (!member.IsArray())
throw std::exception@{@};
for (const auto &j : member.GetArray()) @{
T t;
json_get_inner<T>(j, t);
v.push_back(std::move(t));
@}
@}
@for s in &rpc.structs {
template<> inline void json_get_inner(const rapidjson::Value &__j, mrpc::@s.name &v) @{
using namespace mrpc;
@for f in &s.fields { json_get<@ty_to_str(&f.ty)>(__j, "@f.name", v.@f.name);
}@}
}
@for e in &rpc.enums {
template<> inline void json_get_inner(const rapidjson::Value &j, mrpc::@e.name &v) @{
json_get_inner<std::uint64_t>(j, (std::uint64_t&)v);
@}
mrpc::MRPCJWriter& operator >>(const mrpc::@e.name &v, mrpc::MRPCJWriter &w) @{
w.Uint64((std::uint64_t)v);
return w;
@}
}
template<typename T>
inline void json_get(const rapidjson::Value &j, const char *key, T &v) @{
auto member = j.FindMember(key);
if (member == j.MemberEnd())
throw std::exception@{@};
json_get_inner(member->value, v);
@}
namespace mrpc @{
@for s in &rpc.structs {
MRPCJWriter& @(s.name)::operator >>(MRPCJWriter &__w) const @{
__w.StartObject();
@for f in &s.fields { __w.Key("@f.name", @f.name.len());
@json_write(&f)
} __w.EndObject();
return __w;
@}
@(s.name)& @(s.name)::operator <<(const rapidjson::Value &__j) @{ json_get_inner<@(s.name)>(__j, *this); return *this; @}
}

View File

@@ -0,0 +1,95 @@
@use crate::data::RPC;
@use crate::generators::cpp_s::*;
@(rpc: &RPC)
@for (ty, jty) in JSON_INNER_IMPLS {
inline @(ty)& operator<<(@ty &v, const rapidjson::Value &j) @{
if (!j.Is@(jty)())
throw std::exception@{@};
v = j.Get@(jty)();
return v;
@}
inline mrpc::MRPCJWriter& operator>>(const @ty &v, mrpc::MRPCJWriter &w) @{
w.@(jty)(v);
return w;
@}}
@for e in &rpc.enums {
inline mrpc::@e.name& operator<<(mrpc::@e.name &v, const rapidjson::Value &j) @{
((std::uint64_t&)v) << j;
return v;
@}
mrpc::MRPCJWriter& operator>>(const mrpc::@e.name &v, mrpc::MRPCJWriter &w) @{
w.Uint64((std::uint64_t)v);
return w;
@}
}
template<typename T>
inline std::vector<T>& operator<<(std::vector<T> &v, const rapidjson::Value &j);
template<typename T>
inline std::optional<T>& operator<<(std::optional<T> &v, const rapidjson::Value &j) @{
if (j.IsNull())
v = std::nullopt;
else @{
T t;
t << j;
v = std::move(t);
@}
return v;
@}
template<typename T>
inline std::vector<T>& operator<<(std::vector<T> &v, const rapidjson::Value &j) @{
if (!j.IsArray())
throw std::exception@{@};
for (const auto &e : j.GetArray()) @{
T t;
t << e;
v.push_back(std::move(t));
@}
return v;
@}
template<typename T>
inline mrpc::MRPCJWriter& operator>>(const std::vector<T> &v, mrpc::MRPCJWriter &w);
template<typename T>
inline mrpc::MRPCJWriter& operator>>(const std::optional<T> &v, mrpc::MRPCJWriter &w) @{
if (v.has_value())
v.value() >> w;
else
w.Null();
return w;
@}
template<typename T>
inline mrpc::MRPCJWriter& operator>>(const std::vector<T> &v, mrpc::MRPCJWriter &w) @{
w.StartArray();
for (const auto &e : v)
e >> w;
w.EndArray();
return w;
@}
inline const rapidjson::Value& json_get(const rapidjson::Value &j, const char *key) @{
auto member = j.FindMember(key);
if (member == j.MemberEnd())
throw std::exception@{@};
return member->value;
@}
namespace mrpc @{
@for s in &rpc.structs {
@get_struct_generics(s)MRPCJWriter& @(s.name)@(generics_brace(s))::operator>>(MRPCJWriter &__w) const @{
__w.StartObject();
@for f in &s.fields { __w.Key("@f.name", @f.name.len());
@f.name >> __w;
} __w.EndObject();
return __w;
@}
@get_struct_generics(s)@(s.name)@(generics_brace(s))& @(s.name)@(generics_brace(s))::operator<<(const rapidjson::Value &__j) @{
using namespace mrpc;
@for f in &s.fields { @f.name << json_get(__j, "@f.name");
} return *this;
@}
}

View File

@@ -10,7 +10,7 @@ export enum @e.name @{
}@}
}
@for s in &rpc.structs {
export interface @s.name @{
export interface @s.name@get_struct_generics(s) @{
@for f in &s.fields { @f.name: @ty_to_str(&f.ty);
}@}
}