Replaced json in cpp with RapidJson
This commit is contained in:
		@@ -45,6 +45,37 @@ pub fn call_args(method: &crate::data::MethodTy) -> String {
 | 
				
			|||||||
        .join(", ")
 | 
					        .join(", ")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn json_write(ty: &crate::data::FieldTy) -> String {
 | 
				
			||||||
 | 
					    use crate::data::Types;
 | 
				
			||||||
 | 
					    match &ty.ty {
 | 
				
			||||||
 | 
					        Types::String => format!("__w.String({});", ty.name),
 | 
				
			||||||
 | 
					        Types::Bool => format!("__w.Bool({});", ty.name),
 | 
				
			||||||
 | 
					        Types::F32 | Types::F64 => format!("__w.Double({});", ty.name),
 | 
				
			||||||
 | 
					        Types::I8 | Types::I16 | Types::I32 | Types::I64 => format!("__w.Int64({});", ty.name),
 | 
				
			||||||
 | 
					        Types::U8 | Types::U16 | Types::U32 | Types::U64 => format!("__w.Uint64({});", ty.name),
 | 
				
			||||||
 | 
					        Types::Named(_) => format!("{} >> __w;", ty.name),
 | 
				
			||||||
 | 
					        Types::Optional(inner) => {
 | 
				
			||||||
 | 
					            let inner = crate::data::FieldTy { name: format!("({}.value())", ty.name), ty: (**inner).clone() };
 | 
				
			||||||
 | 
					            let inner = json_write(&inner);
 | 
				
			||||||
 | 
					            format!(
 | 
				
			||||||
 | 
					"if ({}.has_value()) {{
 | 
				
			||||||
 | 
					        {}
 | 
				
			||||||
 | 
					    }} else __w.Null();", ty.name, inner)
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        Types::Array(inner) => {
 | 
				
			||||||
 | 
					            let inner_var_name = format!("__{}__entry", ty.name);
 | 
				
			||||||
 | 
					            let inner = crate::data::FieldTy { name: inner_var_name.clone(), ty: (**inner).clone() };
 | 
				
			||||||
 | 
					            let inner = json_write(&inner);
 | 
				
			||||||
 | 
					            format!(
 | 
				
			||||||
 | 
					"__w.StartArray();
 | 
				
			||||||
 | 
					    for (const auto &{} : {}) {{
 | 
				
			||||||
 | 
					        {}
 | 
				
			||||||
 | 
					    }}
 | 
				
			||||||
 | 
					    __w.EndArray();", inner_var_name, ty.name, inner)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn gen(file_base_name: &std::path::PathBuf, rpc: &RPC) {
 | 
					pub fn gen(file_base_name: &std::path::PathBuf, rpc: &RPC) {
 | 
				
			||||||
    let header_name = file_base_name.with_extension("h");
 | 
					    let header_name = file_base_name.with_extension("h");
 | 
				
			||||||
    let header_name = header_name.file_name().unwrap().to_str().unwrap();
 | 
					    let header_name = header_name.file_name().unwrap().to_str().unwrap();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,44 +1,25 @@
 | 
				
			|||||||
@use crate::data::RPC;
 | 
					@use crate::data::RPC;
 | 
				
			||||||
@use crate::generators::cpp_s::*;
 | 
					@use crate::generators::cpp_s::*;
 | 
				
			||||||
 | 
					@use super::cpp_server_json_cpp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@(header_name: &str, rpc: &RPC)
 | 
					@(header_name: &str, rpc: &RPC)
 | 
				
			||||||
#include "@header_name"
 | 
					#include "@header_name"
 | 
				
			||||||
using json = nlohmann::json;
 | 
					@:cpp_server_json_cpp(rpc)
 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace nlohmann @{
 | 
					 | 
				
			||||||
    template <typename T>
 | 
					 | 
				
			||||||
    struct adl_serializer<std::optional<T>> @{
 | 
					 | 
				
			||||||
        static void to_json(json &j, const std::optional<T> &v) @{
 | 
					 | 
				
			||||||
            if (v.has_value())
 | 
					 | 
				
			||||||
                j = v.value();
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
                j = nullptr;
 | 
					 | 
				
			||||||
        @}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        static void from_json(const json &j, std::optional<T> &v) @{
 | 
					 | 
				
			||||||
            if (j.is_null())
 | 
					 | 
				
			||||||
                v.reset();
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
                v = j.get<T>();
 | 
					 | 
				
			||||||
        @}
 | 
					 | 
				
			||||||
    @};
 | 
					 | 
				
			||||||
@}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace mrpc @{
 | 
					 | 
				
			||||||
@for s in &rpc.structs {
 | 
					 | 
				
			||||||
void to_json(nlohmann::json &j, const @s.name &v) @{
 | 
					 | 
				
			||||||
@for f in &s.fields {    j["@f.name"] = v.@f.name;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@}
 | 
					 | 
				
			||||||
void from_json(const nlohmann::json &j, @s.name &v) @{
 | 
					 | 
				
			||||||
@for f in &s.fields {    j.at("@f.name").get_to(v.@f.name);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
template<class T>
 | 
					template<class T>
 | 
				
			||||||
void send_msg(crow::websocket::connection &c, uint64_t id, const T &v) @{
 | 
					void send_msg(crow::websocket::connection &c, std::uint64_t id, const T &v) @{
 | 
				
			||||||
    c.send_text(json@{@{"id", id@},@{"data", v@}@}.dump());
 | 
					    rapidjson::StringBuffer s;
 | 
				
			||||||
 | 
					    mrpc::MRPCJWriter writer@{s@};
 | 
				
			||||||
 | 
					    writer.StartObject();
 | 
				
			||||||
 | 
					    writer.Key("id");
 | 
				
			||||||
 | 
					    writer.Uint64(id);
 | 
				
			||||||
 | 
					    writer.Key("data");
 | 
				
			||||||
 | 
					    if constexpr (std::is_same_v<T, std::nullptr_t>)
 | 
				
			||||||
 | 
					        writer.Null();
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        v >> writer;
 | 
				
			||||||
 | 
					    writer.EndObject();
 | 
				
			||||||
 | 
					    c.send_text(s.GetString());
 | 
				
			||||||
@}
 | 
					@}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void mrpc::MRPCStreamImpl::close() noexcept @{
 | 
					void mrpc::MRPCStreamImpl::close() noexcept @{
 | 
				
			||||||
@@ -65,12 +46,18 @@ void mrpc::MRPCServer::install(crow::SimpleApp &app, std::string &&route) @{
 | 
				
			|||||||
            catch (const std::exception &_) @{@}
 | 
					            catch (const std::exception &_) @{@}
 | 
				
			||||||
        @});
 | 
					        @});
 | 
				
			||||||
@}
 | 
					@}
 | 
				
			||||||
void mrpc::MRPCServer::msg_handler(crow::websocket::connection &__c, const std::string &__msg, bool) @{
 | 
					void mrpc::MRPCServer::msg_handler(crow::websocket::connection &__c, std::string __msg, bool) @{
 | 
				
			||||||
    json __j = json::parse(__msg);
 | 
					    rapidjson::Document __j;
 | 
				
			||||||
    std::uint64_t __id = __j.at("id");
 | 
					    __j.ParseInsitu(__msg.data());
 | 
				
			||||||
    std::string __service = __j.at("service"), __method = __j.at("method");
 | 
					    if (__j.HasParseError())
 | 
				
			||||||
 | 
					        throw std::exception@{@};
 | 
				
			||||||
 | 
					    std::uint64_t __id; std::string __service, __method;
 | 
				
			||||||
 | 
					    json_get(__j, "id", __id); json_get(__j, "service", __service); json_get(__j, "method", __method);
 | 
				
			||||||
    try @{
 | 
					    try @{
 | 
				
			||||||
        json __data = __j.at("data");
 | 
					        auto __data_member = __j.FindMember("data");
 | 
				
			||||||
 | 
					        if (__data_member == __j.MemberEnd() || !__data_member->value.IsObject())
 | 
				
			||||||
 | 
					            throw std::exception@{@};
 | 
				
			||||||
 | 
					        auto &__data = __data_member->value;
 | 
				
			||||||
@for (si, s) in rpc.services.iter().enumerate() {
 | 
					@for (si, s) in rpc.services.iter().enumerate() {
 | 
				
			||||||
        @if si > 0 {else }if (__service == "@s.name") @{
 | 
					        @if si > 0 {else }if (__service == "@s.name") @{
 | 
				
			||||||
@for (mi, m) in s.methods.iter().enumerate() {
 | 
					@for (mi, m) in s.methods.iter().enumerate() {
 | 
				
			||||||
@@ -79,7 +66,7 @@ void mrpc::MRPCServer::msg_handler(crow::websocket::connection &__c, const std::
 | 
				
			|||||||
                auto __stream = std::make_shared<MRPCStream<@ty_to_str(m.ret.as_ref().unwrap())>>(&__c, __id);
 | 
					                auto __stream = std::make_shared<MRPCStream<@ty_to_str(m.ret.as_ref().unwrap())>>(&__c, __id);
 | 
				
			||||||
                @{ std::lock_guard guard@{__streams_mutex@}; __streams.emplace(&__c, __stream); @}
 | 
					                @{ std::lock_guard guard@{__streams_mutex@}; __streams.emplace(&__c, __stream); @}
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@for (name, ty) in m.args.iter().map(|a| (&a.name, ty_to_str(&a.ty))) {                @ty @name = __data.at("@name");
 | 
					@for (name, ty) in m.args.iter().map(|a| (&a.name, ty_to_str(&a.ty))) {                @ty @name; json_get<@ty>(__data, "@name", @name);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                @if m.ret_stream || m.ret.is_none() {@(s.name)_@(m.name)(@call_args(m));}
 | 
					                @if m.ret_stream || m.ret.is_none() {@(s.name)_@(m.name)(@call_args(m));}
 | 
				
			||||||
                else {send_msg(__c, __id, @(s.name)_@(m.name)(@call_args(m)));}
 | 
					                else {send_msg(__c, __id, @(s.name)_@(m.name)(@call_args(m)));}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,9 +14,13 @@
 | 
				
			|||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
#include <cstdint>
 | 
					#include <cstdint>
 | 
				
			||||||
#include <crow.h>
 | 
					#include <crow.h>
 | 
				
			||||||
#include <json.hpp>
 | 
					#define RAPIDJSON_HAS_STDSTRING 1
 | 
				
			||||||
 | 
					#include <rapidjson/stringbuffer.h>
 | 
				
			||||||
 | 
					#include <rapidjson/writer.h>
 | 
				
			||||||
 | 
					#include <rapidjson/document.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace mrpc @{
 | 
					namespace mrpc @{
 | 
				
			||||||
 | 
					    using MRPCJWriter = rapidjson::Writer<rapidjson::StringBuffer>;
 | 
				
			||||||
@for e in &rpc.enums {
 | 
					@for e in &rpc.enums {
 | 
				
			||||||
enum struct @e.name : std::uint64_t @{
 | 
					enum struct @e.name : std::uint64_t @{
 | 
				
			||||||
    @e.values.iter().map(|(k,v)| format!("{k} = {v}")).join(",\n    ")
 | 
					    @e.values.iter().map(|(k,v)| format!("{k} = {v}")).join(",\n    ")
 | 
				
			||||||
@@ -24,13 +28,13 @@ enum struct @e.name : std::uint64_t @{
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
@for s in &rpc.structs {
 | 
					@for s in &rpc.structs {
 | 
				
			||||||
struct @s.name;
 | 
					struct @s.name;
 | 
				
			||||||
void to_json(nlohmann::json&, const @s.name&);
 | 
					 | 
				
			||||||
void from_json(const nlohmann::json&, @s.name&);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@for s in &rpc.structs {
 | 
					@for s in &rpc.structs {
 | 
				
			||||||
struct @s.name @{
 | 
					struct @s.name @{
 | 
				
			||||||
@for f in &s.fields {    @ty_to_str(&f.ty) @f.name;
 | 
					@for f in &s.fields {    @ty_to_str(&f.ty) @f.name;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					    MRPCJWriter& operator >>(MRPCJWriter&) const;
 | 
				
			||||||
 | 
					    @(s.name)& operator <<(const rapidjson::Value&);
 | 
				
			||||||
@};
 | 
					@};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -50,7 +54,15 @@ struct MRPCStream final : MRPCStreamImpl @{
 | 
				
			|||||||
    bool send(const T &v) noexcept @{
 | 
					    bool send(const T &v) noexcept @{
 | 
				
			||||||
        if (!conn) return false;
 | 
					        if (!conn) return false;
 | 
				
			||||||
        try @{
 | 
					        try @{
 | 
				
			||||||
            conn->send_text(nlohmann::json@{@{"id", id@},@{"data", v@}@}.dump());
 | 
					            rapidjson::StringBuffer s;
 | 
				
			||||||
 | 
					            mrpc::MRPCJWriter writer@{s@};
 | 
				
			||||||
 | 
					            writer.StartObject();
 | 
				
			||||||
 | 
					            writer.Key("id");
 | 
				
			||||||
 | 
					            writer.Uint64(id);
 | 
				
			||||||
 | 
					            writer.Key("data");
 | 
				
			||||||
 | 
					            v >> writer;
 | 
				
			||||||
 | 
					            writer.EndObject();
 | 
				
			||||||
 | 
					            conn->send_text(s.GetString());
 | 
				
			||||||
        @} catch (const std::exception &_) @{
 | 
					        @} catch (const std::exception &_) @{
 | 
				
			||||||
            abort();
 | 
					            abort();
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
@@ -64,7 +76,7 @@ struct MRPCServer @{
 | 
				
			|||||||
private:
 | 
					private:
 | 
				
			||||||
@for s in &rpc.services {@for m in &s.methods {    virtual @method_ret(m) @(s.name)_@(m.name)(@method_args(m)) = 0;
 | 
					@for s in &rpc.services {@for m in &s.methods {    virtual @method_ret(m) @(s.name)_@(m.name)(@method_args(m)) = 0;
 | 
				
			||||||
}}
 | 
					}}
 | 
				
			||||||
    virtual void msg_handler(crow::websocket::connection&, const std::string&, bool) final;
 | 
					    virtual void msg_handler(crow::websocket::connection&, std::string, bool) final;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::mutex __streams_mutex;
 | 
					    std::mutex __streams_mutex;
 | 
				
			||||||
    std::unordered_multimap<crow::websocket::connection*, std::shared_ptr<MRPCStreamImpl>> __streams;
 | 
					    std::unordered_multimap<crow::websocket::connection*, std::shared_ptr<MRPCStreamImpl>> __streams;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										121
									
								
								templates/cpp_server_json.rs.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								templates/cpp_server_json.rs.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,121 @@
 | 
				
			|||||||
 | 
					@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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<>
 | 
				
			||||||
 | 
					inline void json_get_inner(const rapidjson::Value &member, std::string &v) @{
 | 
				
			||||||
 | 
					    if (!member.IsString())
 | 
				
			||||||
 | 
					        throw std::exception@{@};
 | 
				
			||||||
 | 
					    v = member.GetString();
 | 
				
			||||||
 | 
					@}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@for i in [8, 16, 32] {
 | 
				
			||||||
 | 
					template<>
 | 
				
			||||||
 | 
					inline void json_get_inner(const rapidjson::Value &member, std::int@(i)_t &v) @{
 | 
				
			||||||
 | 
					    if (!member.IsInt())
 | 
				
			||||||
 | 
					        throw std::exception@{@};
 | 
				
			||||||
 | 
					    v = member.GetInt();
 | 
				
			||||||
 | 
					@}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<>
 | 
				
			||||||
 | 
					inline void json_get_inner(const rapidjson::Value &member, std::uint@(i)_t& v) @{
 | 
				
			||||||
 | 
					    if (!member.IsUint())
 | 
				
			||||||
 | 
					        throw std::exception@{@};
 | 
				
			||||||
 | 
					    v = member.GetUint();
 | 
				
			||||||
 | 
					@}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<>
 | 
				
			||||||
 | 
					inline void json_get_inner(const rapidjson::Value &member, std::int64_t &v) @{
 | 
				
			||||||
 | 
					    if (!member.IsInt64())
 | 
				
			||||||
 | 
					        throw std::exception@{@};
 | 
				
			||||||
 | 
					    v = member.GetInt64();
 | 
				
			||||||
 | 
					@}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<>
 | 
				
			||||||
 | 
					inline void json_get_inner(const rapidjson::Value &member, std::uint64_t& v) @{
 | 
				
			||||||
 | 
					    if (!member.IsUint64())
 | 
				
			||||||
 | 
					        throw std::exception@{@};
 | 
				
			||||||
 | 
					    v = member.GetUint64();
 | 
				
			||||||
 | 
					@}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<>
 | 
				
			||||||
 | 
					inline void json_get_inner(const rapidjson::Value &member, bool &v) @{
 | 
				
			||||||
 | 
					    if (!member.IsBool())
 | 
				
			||||||
 | 
					        throw std::exception@{@};
 | 
				
			||||||
 | 
					    v = member.GetBool();
 | 
				
			||||||
 | 
					@}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<>
 | 
				
			||||||
 | 
					inline void json_get_inner(const rapidjson::Value &member, double &v) @{
 | 
				
			||||||
 | 
					    if (!member.IsDouble())
 | 
				
			||||||
 | 
					        throw std::exception@{@};
 | 
				
			||||||
 | 
					    v = member.GetDouble();
 | 
				
			||||||
 | 
					@}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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");
 | 
				
			||||||
 | 
					    @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; @}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user