From d25cc22266457f8519982e08a1e9d23ee006a41e Mon Sep 17 00:00:00 2001 From: Grigory Buteyko Date: Thu, 13 Jun 2024 14:18:27 +0300 Subject: [PATCH] exception-neutral cpp code --- internal/tlcodegen/helpers_cpp.go | 409 +++++++------------- internal/tlcodegen/type_rw.go | 4 +- internal/tlcodegen/type_rw_bool_cpp.go | 16 +- internal/tlcodegen/type_rw_maybe_cpp.go | 26 +- internal/tlcodegen/type_rw_primitive_cpp.go | 4 +- internal/tlcodegen/type_rw_struct_cpp.go | 60 +-- internal/tlcodegen/type_rw_tuple_cpp.go | 40 +- internal/tlcodegen/type_rw_union_cpp.go | 30 +- 8 files changed, 238 insertions(+), 351 deletions(-) diff --git a/internal/tlcodegen/helpers_cpp.go b/internal/tlcodegen/helpers_cpp.go index 73ff5f2b..da17c120 100644 --- a/internal/tlcodegen/helpers_cpp.go +++ b/internal/tlcodegen/helpers_cpp.go @@ -17,15 +17,11 @@ const basicCPPTLCodeHeader = `%s #include #include #include - -#if __cplusplus >= 201703L #include #include -#endif -#define TLGEN2_EXOTIC_LAYOUT 0 // when your architecture int32_t, int64_t, float and double types are not the same as in x86 #define TLGEN2_UNLIKELY(x) (x) // __builtin_expect((x), 0) // could improve performance on your platform -#define TLGEN2_NOINLINE //__attribute__ ((noinline)) // could improve performance on your platform +#define TLGEN2_NOINLINE // __attribute__ ((noinline)) // could improve performance on your platform namespace %s { @@ -37,377 +33,248 @@ const basicCPPTLCodeFooter = ` #undef TLGEN2_NOINLINE #undef TLGEN2_UNLIKELY -#undef TLGEN2_EXOTIC_LAYOUT ` const basicCPPTLCodeBody = ` -#if __cplusplus >= 201703L -using std::optional; -using std::variant; -using std::string_view; -#else -#error "TODO - if compiling to C++14 standard, define our toy optional and toy variant here." -#endif - - enum { TL_MAX_TINY_STRING_LEN = 253, TL_BIG_STRING_LEN = 0xffffff, TL_BIG_STRING_MARKER = 0xfe, }; -class parse_exception : public std::runtime_error { -public: - explicit parse_exception() : std::runtime_error("TL parse exception") {} -}; - -class string_too_long : public std::runtime_error { -public: - explicit string_too_long() : std::runtime_error("TL string too long") {} -}; - -class string_padding_wrong : public std::runtime_error { -public: - explicit string_padding_wrong() : std::runtime_error("TL string padding non zero") {} -}; - -class tag_wrong : public std::runtime_error { -public: - explicit tag_wrong() : std::runtime_error("TL tag wrong") {} -}; - -class sequence_length_wrong : public std::runtime_error { -public: - explicit sequence_length_wrong() : std::runtime_error("TL sequence length wrong") {} -}; - -class bool_tag_wrong : public std::runtime_error { -public: - explicit bool_tag_wrong() : std::runtime_error("TL bool tag wrong") {} -}; - -class union_tag_wrong : public std::runtime_error { -public: - explicit union_tag_wrong() : std::runtime_error("TL union/enum tag wrong") {} -}; - -inline TLGEN2_NOINLINE void throwEOF() { - throw parse_exception{}; -} - -inline TLGEN2_NOINLINE void throwStringTooLong() { - throw string_too_long{}; -} - -inline TLGEN2_NOINLINE void throwStringPaddingWrong() { - throw string_padding_wrong{}; -} - -inline TLGEN2_NOINLINE void throwTagWrong() { - throw tag_wrong{}; -} - -inline TLGEN2_NOINLINE void throwSequenceLengthWrong() { - throw sequence_length_wrong{}; -} - -inline TLGEN2_NOINLINE void throwBoolTagWrong() { - throw bool_tag_wrong{}; -} - -inline TLGEN2_NOINLINE void throwUnionTagWrong() { - throw union_tag_wrong{}; -} - -inline void tl_pack32(char *buf, uint32_t val) { -#if TLGEN2_EXOTIC_LAYOUT - buf[0] = char(val); - buf[1] = char(val >> 8); - buf[2] = char(val >> 16); - buf[3] = char(val >> 24); -#else - std::memcpy(buf, &val, 4); -#endif -} - -inline uint32_t tl_unpack32(const char * buf) { -#if TLGEN2_EXOTIC_LAYOUT - return uint32_t(buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24)); -#else - uint32_t value = 0; - std::memcpy(&value, buf, 4); - return value; -#endif -} - class tl_istream { // TODO - prohibit copy/move public: virtual ~tl_istream() = default; - void nat_read(uint32_t & value) { - value = nat_read(); + bool nat_read(uint32_t & value) { + return fetch_data(&value, 4); } - uint32_t nat_read() { - auto p = advance(4); - return tl_unpack32(p); + bool nat_read_exact_tag(uint32_t tag) { + uint32_t actual_tag = 0; + if (TLGEN2_UNLIKELY(!nat_read(actual_tag))) { return false; } + if (TLGEN2_UNLIKELY(tag != actual_tag)) { return set_error_expected_tag(); } + return true; } - void nat_read_exact_tag(uint32_t tag) { - if (TLGEN2_UNLIKELY(tag != nat_read())) { - throwTagWrong(); - } + bool int_read(int32_t & value) { + return fetch_data(&value, 4); } - void int_read(int32_t & value) { - value = int_read(); + bool long_read(int64_t & value) { + return fetch_data(&value, 8); } - int32_t int_read() { - auto p = advance(4); - return static_cast(tl_unpack32(p)); + bool float_read(float & value) { + return fetch_data(&value, 4); } - void long_read(int64_t & value) { - value = long_read(); + bool double_read(double & value) { + return fetch_data(&value, 8); } - int64_t long_read() { - auto p = advance(8); - int64_t value = 0; -#if TLGEN2_EXOTIC_LAYOUT - value = int64_t((long long)(p[0]) | ((long long)p[1] << 8) | ((long long)p[2] << 16) | ((long long)p[3] << 24) | ((long long)p[4] << 32) | ((long long)p[5] << 40) | ((long long)p[6] << 48) | ((long long)p[7] << 56)); -#else - std::memcpy(&value, p, 8); -#endif - return value; + bool bool_read(bool & value, uint32_t f, uint32_t t) { + uint32_t tag = 0; + if (TLGEN2_UNLIKELY(!nat_read(tag))) { return false; } + if (tag == t) { value = true; return true; } + if (TLGEN2_UNLIKELY(tag != f)) { set_error_bool_tag(); } + value = false; + return true; } - void float_read(float & value) { - value = float_read(); - } - float float_read() { - auto p = advance(4); - float value = 0; -#if TLGEN2_EXOTIC_LAYOUT - static_assert(false, "Please define conversion from x86 float layout to your architecture"); -#else - std::memcpy(&value, p, 4); -#endif - return value; - } - void double_read(double & value) { - value = double_read(); - } - double double_read() { - auto p = advance(8); - double value = 0; -#if TLGEN2_EXOTIC_LAYOUT - static_assert(false, "Please define conversion from x86 double layout to your architecture"); -#else - std::memcpy(&value, p, 8); -#endif - return value; - } - std::string string_read() { - std::string value; - string_read(value); - return value; - } - bool bool_read(uint32_t f, uint32_t t) { - auto tag = nat_read(); - if (tag == t) { return true; } - if (tag != f) { throwBoolTagWrong(); } - return false; - } - void string_read(std::string & value) { - ensure(4); + bool string_read(std::string & value) { + if (TLGEN2_UNLIKELY(!ensure_byte())) { return false; } auto len = size_t(static_cast(*ptr)); if (TLGEN2_UNLIKELY(len >= TL_BIG_STRING_MARKER)) { if (TLGEN2_UNLIKELY(len > TL_BIG_STRING_MARKER)) { - throwStringTooLong(); + return set_error("TODO - huge string"); } - len = tl_unpack32(ptr) >> 8U; - ptr += 4; + uint32_t len32 = 0; + if (TLGEN2_UNLIKELY(!nat_read(len32))) { return false; } + len = len32 >> 8U; value.clear(); - fetch_data_append(value, len); - fetch_pad((-len) & 3); - return; + if (TLGEN2_UNLIKELY(!fetch_data_append(value, len))) { return false; } + if (TLGEN2_UNLIKELY(!fetch_pad((-len) & 3))) { return false; } + return true; } auto pad = ((-(len+1)) & 3); auto fullLen = 1 + len + pad; if (TLGEN2_UNLIKELY(ptr + fullLen > end)) { ptr += 1; value.clear(); - fetch_data_append(value, len); - fetch_pad(pad); - return; + if (TLGEN2_UNLIKELY(!fetch_data_append(value, len))) { return false; } + if (TLGEN2_UNLIKELY(!fetch_pad(pad))) { return false; } + return true; } // fast path for short strings that fully fit in buffer - auto x = tl_unpack32(ptr + fullLen - 4); + uint32_t x = 0; + std::memcpy(&x, ptr + fullLen - 4, 4); if (TLGEN2_UNLIKELY((x & ~(0xFFFFFFFFU >> (8*pad))) != 0)) { - throwStringPaddingWrong(); + return set_error_string_padding(); } value.assign(ptr + 1, len); ptr += fullLen; - } + return true; + } + bool set_error(const char * e) { return false; } // TODO - set error field + bool set_error_eof() { return set_error("EOF"); } + bool set_error_sequence_length() { return set_error("sequence_length"); } + bool set_error_string_padding() { return set_error("string_padding"); } + bool set_error_bool_tag() { return set_error("bool_tag"); } + bool set_error_expected_tag() { return set_error("expected_tag"); } + bool set_error_union_tag() { return set_error("union_tag"); } protected: const char * ptr{}; const char * end{}; - virtual void grow_buffer(size_t size) = 0; // after call buffer must contain at least 8 bytes + virtual void grow_buffer(size_t size_hint) = 0; // after call buffer must contain at least single byte, otherwise error private: - void fetch_data(char * data, size_t size) { + bool ensure_byte() { + if (TLGEN2_UNLIKELY(ptr >= end)) { + // assert(ptr <= end) + grow_buffer(1); + // assert(ptr <= end) + if (TLGEN2_UNLIKELY(ptr == end)) { + return set_error_eof(); + } + } + return true; + } + bool fetch_data(void * vdata, size_t size) { + char * data = reinterpret_cast(vdata); + if (TLGEN2_UNLIKELY(ptr + size > end)) { + return fetch_data2(vdata, size); + } + std::memcpy(data, ptr, size); + ptr += size; + return true; + } + bool fetch_data2(void * vdata, size_t size) { + char * data = reinterpret_cast(vdata); for (;TLGEN2_UNLIKELY(ptr + size > end);) { + // assert(ptr <= end) std::memcpy(data, ptr, end - ptr); data += end - ptr; size -= end - ptr; ptr = end; grow_buffer(size); + // assert(ptr <= end) if (TLGEN2_UNLIKELY(ptr == end)) { - throwEOF(); + return set_error_eof(); } } - std::memcpy(data, ptr, size); + std::memcpy(data, ptr, size); ptr += size; + return true; } - void fetch_data_append(std::string & value, size_t size) { + bool fetch_data_append(std::string & value, size_t size) { for (;TLGEN2_UNLIKELY(ptr + size > end);) { + // assert(ptr <= end) value.append(ptr, end - ptr); size -= end - ptr; ptr = end; grow_buffer(size); + // assert(ptr <= end) if (TLGEN2_UNLIKELY(ptr == end)) { - throwEOF(); + return set_error_eof(); } } value.append(ptr, size); ptr += size; + return true; } - void fetch_pad(size_t len) { - auto p = advance(len); + bool fetch_pad(size_t len) { uint32_t x = 0; - std::memcpy(&x, p, len); - if (TLGEN2_UNLIKELY(x != 0)) { - throwStringPaddingWrong(); - } - } - const char * advance(size_t size) { - ensure(size); - auto p = ptr; - ptr += size; - return p; - } - void ensure(size_t size) { - if (TLGEN2_UNLIKELY(ptr + size > end)) { - grow_buffer(size); - if (TLGEN2_UNLIKELY(ptr + size > end)) { - throwEOF(); - } - } + if (TLGEN2_UNLIKELY(!fetch_data(&x, len))) { return false; } + if (TLGEN2_UNLIKELY(x != 0)) { return set_error_string_padding(); } + return true; } }; class tl_ostream { // TODO - prohibit copy/move public: virtual ~tl_ostream() = default; - void nat_write(uint32_t value) { - auto p = advance(4); - tl_pack32(p, value); + bool nat_write(uint32_t value) { + return store_data(&value, 4); } - void int_write(int32_t value) { - auto p = advance(4); - tl_pack32(p, static_cast(value)); + bool int_write(int32_t value) { + return store_data(&value, 4); } - void long_write(int64_t value) { - auto p = advance(8); -#if TLGEN2_EXOTIC_LAYOUT - ptr[0] = char(value); - ptr[1] = char(value >> 8); - ptr[2] = char(value >> 16); - ptr[3] = char(value >> 24); - ptr[4] = char(value >> 32); - ptr[5] = char(value >> 40); - ptr[6] = char(value >> 48); - ptr[7] = char(value >> 56); -#else - std::memcpy(p, &value, 8); -#endif + bool long_write(int64_t value) { + return store_data(&value, 8); } - void float_write(float value) { - auto p = advance(4); -#if TLGEN2_EXOTIC_LAYOUT - static_assert(false, "Please define conversion to x86 float layout from your architecture"); -#else - std::memcpy(p, &value, 4); -#endif + bool float_write(float value) { + return store_data(&value, 4); } - void double_write(double value) { - auto p = advance(8); -#if TLGEN2_EXOTIC_LAYOUT - static_assert(false, "Please define conversion from x86 double layout to your architecture"); -#else - std::memcpy(p, &value, 8); -#endif + bool double_write(double value) { + return store_data(&value, 8); } - void string_write(const std::string & value) { + bool string_write(const std::string & value) { auto len = value.size(); if (TLGEN2_UNLIKELY(len > TL_MAX_TINY_STRING_LEN)) { if (TLGEN2_UNLIKELY(len > TL_BIG_STRING_LEN)) { - throwStringTooLong(); + return set_error("TODO - huge string"); } - auto p = advance(4); - tl_pack32(p, (len << 8U) | TL_BIG_STRING_MARKER); - store_data(value.data(), value.size()); - store_pad((-len) & 3); - return; + uint32_t p = (len << 8U) | TL_BIG_STRING_MARKER; + if (TLGEN2_UNLIKELY(!store_data(&p, 4))) { return false; } + if (TLGEN2_UNLIKELY(!store_data(value.data(), value.size()))) { return false; } + if (TLGEN2_UNLIKELY(!store_pad((-len) & 3))) { return false; } + return true; } auto pad = ((-(len+1)) & 3); auto fullLen = 1 + len + pad; if (TLGEN2_UNLIKELY(ptr + fullLen > end)) { - auto p = advance(1); - *p = static_cast(len); - store_data(value.data(), value.size()); - store_pad(pad); - return; + auto p = static_cast(len); + if (TLGEN2_UNLIKELY(!store_data(&p,1))) { return false; } + if (TLGEN2_UNLIKELY(!store_data(value.data(), value.size()))) { return false; } + if (TLGEN2_UNLIKELY(!store_pad(pad))) { return false; } + return true; } - tl_pack32(ptr + fullLen - 4, 0); // padding first - tl_pack32(ptr, len); + // fast path for short strings that fully fit in buffer + uint32_t x = 0; + std::memcpy(ptr + fullLen - 4, &x, 4); // padding first + *ptr = static_cast(len); std::memcpy(ptr + 1, value.data(), len); ptr += fullLen; + return true; } + bool set_error(const char * e) { return false; } // TODO - set error field + bool set_error_eof() { return set_error("EOF"); } + bool set_error_sequence_length() { return set_error("sequence_length"); } protected: char * ptr{}; char * end{}; - virtual void grow_buffer(size_t size) = 0; // after call buffer must contain at least 8 bytes + virtual void grow_buffer(size_t size) = 0; // after call buffer must contain at least single bytes, otherwise error private: - void store_data(const char * data, size_t size) { + bool store_data(const void * vdata, size_t size) { + const char * data = reinterpret_cast(vdata); for (;TLGEN2_UNLIKELY(ptr + size > end);) { + // assert(ptr <= end) std::memcpy(ptr, data, end - ptr); data += end - ptr; size -= end - ptr; ptr = end; grow_buffer(size); + // assert(ptr <= end) if (TLGEN2_UNLIKELY(ptr == end)) { - throwEOF(); + return set_error_eof(); } } std::memcpy(ptr, data, size); ptr += size; + return true; } - void store_pad(size_t len) { - auto p = advance(len); - if (len != 0) { - p[0] = 0; - p[len-1] = 0; - p[len/2] = 0; - } - } - char * advance(size_t size) { - ensure(size); - auto p = ptr; - ptr += size; - return p; - } - void ensure(size_t size) { - if (TLGEN2_UNLIKELY(ptr + size > end)) { + bool store_pad(size_t size) { + for (;TLGEN2_UNLIKELY(ptr + size > end);) { + // assert(ptr <= end) + std::memset(ptr, 0, end - ptr); + size -= end - ptr; + ptr = end; grow_buffer(size); - if (TLGEN2_UNLIKELY(ptr + size > end)) { - throwEOF(); + // assert(ptr <= end) + if (TLGEN2_UNLIKELY(ptr == end)) { + return set_error_eof(); } } + if (size != 0) { + ptr[0] = 0; + ptr[size-1] = 0; + ptr[size/2] = 0; + ptr += size; + } + return true; } }; @@ -418,7 +285,7 @@ public: end = ptr + buf.size(); } protected: - void grow_buffer(size_t size) override { throwEOF(); } + void grow_buffer(size_t size) override {} }; class tl_ostream_string : public tl_ostream { // TODO - custom copy/move diff --git a/internal/tlcodegen/type_rw.go b/internal/tlcodegen/type_rw.go index 2fb0811a..660a0d5f 100644 --- a/internal/tlcodegen/type_rw.go +++ b/internal/tlcodegen/type_rw.go @@ -427,7 +427,7 @@ func (w *TypeRWWrapper) cppTypeStringInNamespace(bytesVersion bool, hppInc *Dire } else { bArgs.WriteString(", ") } - if halfResolve { + if halfResolve && i < len(halfResolved.Args) { half := halfResolved.Args[i] if half.Name != "" { bArgs.WriteString(half.Name) @@ -442,7 +442,7 @@ func (w *TypeRWWrapper) cppTypeStringInNamespace(bytesVersion bool, hppInc *Dire } else { bArgs.WriteString(", ") } - if halfResolve { + if halfResolve && i < len(halfResolved.Args) { half := halfResolved.Args[i] if half.Name != "" { bArgs.WriteString(half.Name) diff --git a/internal/tlcodegen/type_rw_bool_cpp.go b/internal/tlcodegen/type_rw_bool_cpp.go index d6a8b293..bf75fdb5 100644 --- a/internal/tlcodegen/type_rw_bool_cpp.go +++ b/internal/tlcodegen/type_rw_bool_cpp.go @@ -38,12 +38,12 @@ func (trw *TypeRWBool) CPPTypeResettingCode(bytesVersion bool, val string) strin func (trw *TypeRWBool) CPPTypeWritingCode(bytesVersion bool, val string, bare bool, natArgs []string, last bool) string { goGlobalName := addBytes(trw.wr.goGlobalName, bytesVersion) - return fmt.Sprintf("\t::%s::%sWrite%s(s, %s%s);", trw.wr.gen.DetailsCPPNamespace, goGlobalName, addBare(bare), val, joinWithCommas(natArgs)) + return fmt.Sprintf("\tif (!::%s::%sWrite%s(s, %s%s)) { return false; }", trw.wr.gen.DetailsCPPNamespace, goGlobalName, addBare(bare), val, joinWithCommas(natArgs)) } func (trw *TypeRWBool) CPPTypeReadingCode(bytesVersion bool, val string, bare bool, natArgs []string, last bool) string { goGlobalName := addBytes(trw.wr.goGlobalName, bytesVersion) - return fmt.Sprintf("\t::%s::%sRead%s(s, %s%s);", trw.wr.gen.DetailsCPPNamespace, goGlobalName, addBare(bare), val, joinWithCommas(natArgs)) + return fmt.Sprintf("\tif (!::%s::%sRead%s(s, %s%s) { return false; }", trw.wr.gen.DetailsCPPNamespace, goGlobalName, addBare(bare), val, joinWithCommas(natArgs)) } func (trw *TypeRWBool) CPPGenerateCode(hpp *strings.Builder, hppInc *DirectIncludesCPP, hppIncFwd *DirectIncludesCPP, hppDet *strings.Builder, hppDetInc *DirectIncludesCPP, cppDet *strings.Builder, cppDetInc *DirectIncludesCPP, bytesVersion bool, forwardDeclaration bool) { @@ -61,17 +61,17 @@ func (trw *TypeRWBool) CPPGenerateCode(hpp *strings.Builder, hppInc *DirectInclu cppStartNamespace(hppDet, trw.wr.gen.DetailsCPPNamespaceElements) hppDet.WriteString(fmt.Sprintf(` -void %[1]sReadBoxed(::basictl::tl_istream & s, bool& item); -void %[1]sWriteBoxed(::basictl::tl_ostream & s, bool item); +bool %[1]sReadBoxed(::basictl::tl_istream & s, bool& item); +bool %[1]sWriteBoxed(::basictl::tl_ostream & s, bool item); `, addBytes(trw.wr.goGlobalName, bytesVersion))) cppDet.WriteString(fmt.Sprintf(` -void %[6]s::%[1]sReadBoxed(::basictl::tl_istream & s, bool& item) { - item = s.bool_read(0x%[2]x, 0x%[3]x); +bool %[6]s::%[1]sReadBoxed(::basictl::tl_istream & s, bool& item) { + return s.bool_read(item, 0x%[2]x, 0x%[3]x); } -void %[6]s::%[1]sWriteBoxed(::basictl::tl_ostream & s, bool item) { - s.nat_write(item ? 0x%[3]x : 0x%[2]x); +bool %[6]s::%[1]sWriteBoxed(::basictl::tl_ostream & s, bool item) { + return s.nat_write(item ? 0x%[3]x : 0x%[2]x); } `, addBytes(trw.wr.goGlobalName, bytesVersion), trw.falseTag, trw.trueTag, trw.falseGoName, trw.trueGoName, trw.wr.gen.DetailsCPPNamespace)) diff --git a/internal/tlcodegen/type_rw_maybe_cpp.go b/internal/tlcodegen/type_rw_maybe_cpp.go index 945998dc..a2282f91 100644 --- a/internal/tlcodegen/type_rw_maybe_cpp.go +++ b/internal/tlcodegen/type_rw_maybe_cpp.go @@ -17,12 +17,12 @@ func (trw *TypeRWMaybe) CPPFillRecursiveChildren(visitedNodes map[*TypeRWWrapper func (trw *TypeRWMaybe) cppTypeStringInNamespace(bytesVersion bool, hppInc *DirectIncludesCPP) string { hppInc.ns[trw.wr.fileName] = struct{}{} - return "::basictl::optional<" + trw.element.t.CPPTypeStringInNamespace(bytesVersion, hppInc) + ">" + return "std::optional<" + trw.element.t.CPPTypeStringInNamespace(bytesVersion, hppInc) + ">" } func (trw *TypeRWMaybe) cppTypeStringInNamespaceHalfResolved(bytesVersion bool, hppInc *DirectIncludesCPP, halfResolved HalfResolvedArgument) string { hppInc.ns[trw.wr.fileName] = struct{}{} - return "::basictl::optional<" + trw.element.t.CPPTypeStringInNamespaceHalfResolved(bytesVersion, hppInc, halfResolved.Args[0]) + ">" + return "std::optional<" + trw.element.t.CPPTypeStringInNamespaceHalfResolved(bytesVersion, hppInc, halfResolved.Args[0]) + ">" } func (trw *TypeRWMaybe) cppDefaultInitializer(halfResolved HalfResolvedArgument, halfResolve bool) string { @@ -39,13 +39,13 @@ func (trw *TypeRWMaybe) CPPTypeResettingCode(bytesVersion bool, val string) stri func (trw *TypeRWMaybe) CPPTypeWritingCode(bytesVersion bool, val string, bare bool, natArgs []string, last bool) string { goGlobalName := addBytes(trw.wr.goGlobalName, bytesVersion) - return fmt.Sprintf("\t::%s::%sWrite%s(s, %s%s);", trw.wr.gen.DetailsCPPNamespace, goGlobalName, addBare(bare), val, joinWithCommas(natArgs)) + return fmt.Sprintf("\tif (!::%s::%sWrite%s(s, %s%s)) { return false; }", trw.wr.gen.DetailsCPPNamespace, goGlobalName, addBare(bare), val, joinWithCommas(natArgs)) //return wrapLast(last, fmt.Sprintf("\t%s.Write%s( w %s)", val, addBare(bare), formatNatArgsCallCPP(natArgs))) } func (trw *TypeRWMaybe) CPPTypeReadingCode(bytesVersion bool, val string, bare bool, natArgs []string, last bool) string { goGlobalName := addBytes(trw.wr.goGlobalName, bytesVersion) - return fmt.Sprintf("\t::%s::%sRead%s(s, %s%s);", trw.wr.gen.DetailsCPPNamespace, goGlobalName, addBare(bare), val, joinWithCommas(natArgs)) + return fmt.Sprintf("\tif (!::%s::%sRead%s(s, %s%s)) { return false; }", trw.wr.gen.DetailsCPPNamespace, goGlobalName, addBare(bare), val, joinWithCommas(natArgs)) //return wrapLast(last, fmt.Sprintf("\t%s.Read%s( r %s)", val, addBare(bare), formatNatArgsCallCPP(natArgs))) } @@ -56,8 +56,8 @@ func (trw *TypeRWMaybe) CPPGenerateCode(hpp *strings.Builder, hppInc *DirectIncl cppStartNamespace(hppDet, trw.wr.gen.DetailsCPPNamespaceElements) hppDet.WriteString(fmt.Sprintf(` -void %[1]sReadBoxed(::basictl::tl_istream & s, %[2]s& item%[3]s); -void %[1]sWriteBoxed(::basictl::tl_ostream & s, const %[2]s& item%[3]s); +bool %[1]sReadBoxed(::basictl::tl_istream & s, %[2]s& item%[3]s); +bool %[1]sWriteBoxed(::basictl::tl_ostream & s, const %[2]s& item%[3]s); `, goGlobalName, myFullType, @@ -66,22 +66,26 @@ void %[1]sWriteBoxed(::basictl::tl_ostream & s, const %[2]s& item%[3]s); trw.wr.tlTag)) cppDet.WriteString(fmt.Sprintf(` -void %[6]s::%[1]sReadBoxed(::basictl::tl_istream & s, %[2]s& item%[3]s) { - if (s.bool_read(0x%[4]x, 0x%[5]x)) { +bool %[6]s::%[1]sReadBoxed(::basictl::tl_istream & s, %[2]s& item%[3]s) { + bool has_item = false; + if (!s.bool_read(has_item, 0x%[4]x, 0x%[5]x)) { return false; } + if (has_item) { if (!item) { item.emplace(); } %[7]s - return; + return true; } item.reset(); + return true; } -void %[6]s::%[1]sWriteBoxed(::basictl::tl_ostream & s, const %[2]s& item%[3]s) { - s.nat_write(item ? 0x%[5]x : 0x%[4]x); +bool %[6]s::%[1]sWriteBoxed(::basictl::tl_ostream & s, const %[2]s& item%[3]s) { + if (!s.nat_write(item ? 0x%[5]x : 0x%[4]x)) { return false; } if (item) { %[8]s } + return true; } `, goGlobalName, diff --git a/internal/tlcodegen/type_rw_primitive_cpp.go b/internal/tlcodegen/type_rw_primitive_cpp.go index a5b7ace5..bdba8e72 100644 --- a/internal/tlcodegen/type_rw_primitive_cpp.go +++ b/internal/tlcodegen/type_rw_primitive_cpp.go @@ -35,11 +35,11 @@ func (trw *TypeRWPrimitive) CPPTypeResettingCode(bytesVersion bool, val string) } func (trw *TypeRWPrimitive) CPPTypeWritingCode(bytesVersion bool, val string, bare bool, natArgs []string, last bool) string { - return fmt.Sprintf("\ts.%s_write(%s);", trw.cppFunctionSuffix, val) + return fmt.Sprintf("\tif (!s.%s_write(%s)) { return false;}", trw.cppFunctionSuffix, val) } func (trw *TypeRWPrimitive) CPPTypeReadingCode(bytesVersion bool, val string, bare bool, natArgs []string, last bool) string { - return fmt.Sprintf("\ts.%s_read(%s);", trw.cppFunctionSuffix, val) + return fmt.Sprintf("\tif (!s.%s_read(%s)) { return false; }", trw.cppFunctionSuffix, val) } func (trw *TypeRWPrimitive) CPPGenerateCode(hpp *strings.Builder, hppInc *DirectIncludesCPP, hppIncFwd *DirectIncludesCPP, hppDet *strings.Builder, hppDetInc *DirectIncludesCPP, cppDet *strings.Builder, cppDetInc *DirectIncludesCPP, bytesVersion bool, forwardDeclaration bool) { diff --git a/internal/tlcodegen/type_rw_struct_cpp.go b/internal/tlcodegen/type_rw_struct_cpp.go index 9d51627d..bcc44408 100644 --- a/internal/tlcodegen/type_rw_struct_cpp.go +++ b/internal/tlcodegen/type_rw_struct_cpp.go @@ -60,11 +60,11 @@ func (trw *TypeRWStruct) CPPTypeWritingCode(bytesVersion bool, val string, bare if trw.isUnwrapType() { prefix := "" if !bare { - prefix = fmt.Sprintf("\ts.nat_write(0x%x);\n", trw.wr.tlTag) + prefix = fmt.Sprintf("\tif (!s.nat_write(0x%x)) { return false; }\n", trw.wr.tlTag) } return prefix + trw.Fields[0].t.trw.CPPTypeWritingCode(bytesVersion, val, trw.Fields[0].Bare(), trw.replaceUnwrapArgs(natArgs), last) } - return fmt.Sprintf("\t::%s::%sWrite%s(s, %s%s);", trw.wr.gen.DetailsCPPNamespace, goGlobalName, addBare(bare), val, joinWithCommas(natArgs)) + return fmt.Sprintf("\tif (!::%s::%sWrite%s(s, %s%s)) { return false; }", trw.wr.gen.DetailsCPPNamespace, goGlobalName, addBare(bare), val, joinWithCommas(natArgs)) } func (trw *TypeRWStruct) CPPTypeReadingCode(bytesVersion bool, val string, bare bool, natArgs []string, last bool) string { @@ -72,11 +72,11 @@ func (trw *TypeRWStruct) CPPTypeReadingCode(bytesVersion bool, val string, bare if trw.isUnwrapType() { prefix := "" if !bare { - prefix = fmt.Sprintf("\ts.nat_read_exact_tag(0x%x);\n", trw.wr.tlTag) + prefix = fmt.Sprintf("\tif (!s.nat_read_exact_tag(0x%x)) { return false;}\n", trw.wr.tlTag) } return prefix + trw.Fields[0].t.trw.CPPTypeReadingCode(bytesVersion, val, trw.Fields[0].Bare(), trw.replaceUnwrapArgs(natArgs), last) } - return fmt.Sprintf("\t::%s::%sRead%s(s, %s%s);", trw.wr.gen.DetailsCPPNamespace, goGlobalName, addBare(bare), val, joinWithCommas(natArgs)) + return fmt.Sprintf("\tif (!::%s::%sRead%s(s, %s%s)) { return false; }", trw.wr.gen.DetailsCPPNamespace, goGlobalName, addBare(bare), val, joinWithCommas(natArgs)) } func (trw *TypeRWStruct) CPPGenerateCode(hpp *strings.Builder, hppInc *DirectIncludesCPP, hppIncFwd *DirectIncludesCPP, hppDet *strings.Builder, hppDetInc *DirectIncludesCPP, cppDet *strings.Builder, cppDetInc *DirectIncludesCPP, bytesVersion bool, forwardDeclaration bool) { @@ -132,27 +132,29 @@ func (trw *TypeRWStruct) CPPGenerateCode(hpp *strings.Builder, hppInc *DirectInc } if trw.wr.tlTag != 0 { // anonymous square brackets citizens or other exotic type hpp.WriteString(fmt.Sprintf(` - ::basictl::string_view tl_name() const { return "%s"; } + std::string_view tl_name() const { return "%s"; } uint32_t tl_tag() const { return 0x%08x; } `, trw.wr.tlName, trw.wr.tlTag)) } if len(myArgsDecl) == 0 { // cppStartNamespace(cppDet, trw.wr.gen.RootCPPNamespaceElements) hpp.WriteString(fmt.Sprintf(` - void read(::basictl::tl_istream & s%[1]s); - void write(::basictl::tl_ostream & s%[1]s)const; + bool read(::basictl::tl_istream & s%[1]s); + bool write(::basictl::tl_ostream & s%[1]s)const; `, formatNatArgsDeclCPP(trw.wr.NatParams), trw.CPPTypeResettingCode(bytesVersion, "*this"), trw.CPPTypeReadingCode(bytesVersion, "*this", true, formatNatArgsAddNat(trw.wr.NatParams), true), trw.CPPTypeWritingCode(bytesVersion, "*this", true, formatNatArgsAddNat(trw.wr.NatParams), true))) cppDet.WriteString(fmt.Sprintf(` -void %[5]s::read(::basictl::tl_istream & s%[1]s) { +bool %[5]s::read(::basictl::tl_istream & s%[1]s) { %[3]s + return true; } -void %[5]s::write(::basictl::tl_ostream & s%[1]s)const { +bool %[5]s::write(::basictl::tl_ostream & s%[1]s)const { %[4]s + return true; } `, formatNatArgsDeclCPP(trw.wr.NatParams), @@ -162,20 +164,22 @@ void %[5]s::write(::basictl::tl_ostream & s%[1]s)const { myFullTypeNoPrefix)) if trw.wr.tlTag != 0 { // anonymous square brackets citizens or other exotic type hpp.WriteString(fmt.Sprintf(` - void read_boxed(::basictl::tl_istream & s%[1]s); - void write_boxed(::basictl::tl_ostream & s%[1]s)const; + bool read_boxed(::basictl::tl_istream & s%[1]s); + bool write_boxed(::basictl::tl_ostream & s%[1]s)const; `, formatNatArgsDeclCPP(trw.wr.NatParams), trw.CPPTypeResettingCode(bytesVersion, "*this"), trw.CPPTypeReadingCode(bytesVersion, "*this", false, formatNatArgsAddNat(trw.wr.NatParams), true), trw.CPPTypeWritingCode(bytesVersion, "*this", false, formatNatArgsAddNat(trw.wr.NatParams), true))) cppDet.WriteString(fmt.Sprintf(` -void %[5]s::read_boxed(::basictl::tl_istream & s%[1]s) { +bool %[5]s::read_boxed(::basictl::tl_istream & s%[1]s) { %[3]s + return true; } -void %[5]s::write_boxed(::basictl::tl_ostream & s%[1]s)const { +bool %[5]s::write_boxed(::basictl::tl_ostream & s%[1]s)const { %[4]s + return true; } `, formatNatArgsDeclCPP(trw.wr.NatParams), @@ -194,11 +198,13 @@ void %[5]s::write_boxed(::basictl::tl_ostream & s%[1]s)const { void %[7]s::%[1]sReset(%[2]s& item) { %[4]s} -void %[7]s::%[1]sRead(::basictl::tl_istream & s, %[2]s& item%[3]s) { -%[5]s} +bool %[7]s::%[1]sRead(::basictl::tl_istream & s, %[2]s& item%[3]s) { +%[5]s return true; +} -void %[7]s::%[1]sWrite(::basictl::tl_ostream & s, const %[2]s& item%[3]s) { -%[6]s} +bool %[7]s::%[1]sWrite(::basictl::tl_ostream & s, const %[2]s& item%[3]s) { +%[6]s return true; +} `, goGlobalName, myFullType, @@ -212,27 +218,27 @@ void %[7]s::%[1]sWrite(::basictl::tl_ostream & s, const %[2]s& item%[3]s) { cppStartNamespace(hppDet, trw.wr.gen.DetailsCPPNamespaceElements) hppDet.WriteString(fmt.Sprintf(` void %[1]sReset(%[2]s& item); -void %[1]sRead(::basictl::tl_istream & s, %[2]s& item%[3]s); -void %[1]sWrite(::basictl::tl_ostream & s, const %[2]s& item%[3]s); +bool %[1]sRead(::basictl::tl_istream & s, %[2]s& item%[3]s); +bool %[1]sWrite(::basictl::tl_ostream & s, const %[2]s& item%[3]s); `, goGlobalName, myFullType, formatNatArgsDeclCPP(trw.wr.NatParams))) if trw.wr.tlTag != 0 { // anonymous square brackets citizens or other exotic type - hppDet.WriteString(fmt.Sprintf(`void %[1]sReadBoxed(::basictl::tl_istream & s, %[2]s& item%[3]s); -void %[1]sWriteBoxed(::basictl::tl_ostream & s, const %[2]s& item%[3]s); + hppDet.WriteString(fmt.Sprintf(`bool %[1]sReadBoxed(::basictl::tl_istream & s, %[2]s& item%[3]s); +bool %[1]sWriteBoxed(::basictl::tl_ostream & s, const %[2]s& item%[3]s); `, goGlobalName, myFullType, formatNatArgsDeclCPP(trw.wr.NatParams))) cppDet.WriteString(fmt.Sprintf(` -void %[7]s::%[1]sReadBoxed(::basictl::tl_istream & s, %[2]s& item%[3]s) { - s.nat_read_exact_tag(0x%08[9]x); - %[1]sRead(s, item%[8]s); +bool %[7]s::%[1]sReadBoxed(::basictl::tl_istream & s, %[2]s& item%[3]s) { + if (!s.nat_read_exact_tag(0x%08[9]x)) { return false; } + return %[1]sRead(s, item%[8]s); } -void %[7]s::%[1]sWriteBoxed(::basictl::tl_ostream & s, const %[2]s& item%[3]s) { - s.nat_write(0x%08[9]x); - %[1]sWrite(s, item%[8]s); +bool %[7]s::%[1]sWriteBoxed(::basictl::tl_ostream & s, const %[2]s& item%[3]s) { + if (!s.nat_write(0x%08[9]x)) { return false; } + return %[1]sWrite(s, item%[8]s); } `, goGlobalName, diff --git a/internal/tlcodegen/type_rw_tuple_cpp.go b/internal/tlcodegen/type_rw_tuple_cpp.go index be3c008b..0cf87298 100644 --- a/internal/tlcodegen/type_rw_tuple_cpp.go +++ b/internal/tlcodegen/type_rw_tuple_cpp.go @@ -75,12 +75,12 @@ func (trw *TypeRWBrackets) CPPTypeResettingCode(bytesVersion bool, val string) s func (trw *TypeRWBrackets) CPPTypeWritingCode(bytesVersion bool, val string, bare bool, natArgs []string, last bool) string { goGlobalName := addBytes(trw.wr.goGlobalName, bytesVersion) - return fmt.Sprintf("\t::%s::%sWrite%s(s, %s%s);", trw.wr.gen.DetailsCPPNamespace, goGlobalName, addBare(bare), val, joinWithCommas(natArgs)) + return fmt.Sprintf("\tif (!::%s::%sWrite%s(s, %s%s)) { return false; }", trw.wr.gen.DetailsCPPNamespace, goGlobalName, addBare(bare), val, joinWithCommas(natArgs)) } func (trw *TypeRWBrackets) CPPTypeReadingCode(bytesVersion bool, val string, bare bool, natArgs []string, last bool) string { goGlobalName := addBytes(trw.wr.goGlobalName, bytesVersion) - return fmt.Sprintf("\t::%s::%sRead%s(s, %s%s);", trw.wr.gen.DetailsCPPNamespace, goGlobalName, addBare(bare), val, joinWithCommas(natArgs)) + return fmt.Sprintf("\tif (!::%s::%sRead%s(s, %s%s)) { return false; }", trw.wr.gen.DetailsCPPNamespace, goGlobalName, addBare(bare), val, joinWithCommas(natArgs)) } func (trw *TypeRWBrackets) CPPGenerateCode(hpp *strings.Builder, hppInc *DirectIncludesCPP, hppIncFwd *DirectIncludesCPP, hppDet *strings.Builder, hppDetInc *DirectIncludesCPP, cppDet *strings.Builder, cppDetInc *DirectIncludesCPP, bytesVersion bool, forwardDeclaration bool) { @@ -88,8 +88,8 @@ func (trw *TypeRWBrackets) CPPGenerateCode(hpp *strings.Builder, hppInc *DirectI hppDetCode := ` void %[1]sReset(std::array<%[2]s, %[3]d>& item); -void %[1]sRead(::basictl::tl_istream & s, std::array<%[2]s, %[3]d>& item%[4]s); -void %[1]sWrite(::basictl::tl_ostream & s, const std::array<%[2]s, %[3]d>& item%[4]s); +bool %[1]sRead(::basictl::tl_istream & s, std::array<%[2]s, %[3]d>& item%[4]s); +bool %[1]sWrite(::basictl::tl_ostream & s, const std::array<%[2]s, %[3]d>& item%[4]s); ` cppCode := ` void %[8]s::%[1]sReset(std::array<%[2]s, %[3]d>& item) { @@ -98,16 +98,18 @@ void %[8]s::%[1]sReset(std::array<%[2]s, %[3]d>& item) { } } -void %[8]s::%[1]sRead(::basictl::tl_istream & s, std::array<%[2]s, %[3]d>& item%[4]s) { +bool %[8]s::%[1]sRead(::basictl::tl_istream & s, std::array<%[2]s, %[3]d>& item%[4]s) { for(auto && el : item) { %[5]s } + return true; } -void %[8]s::%[1]sWrite(::basictl::tl_ostream & s, const std::array<%[2]s, %[3]d>& item%[4]s) { +bool %[8]s::%[1]sWrite(::basictl::tl_ostream & s, const std::array<%[2]s, %[3]d>& item%[4]s) { for(const auto & el : item) { %[6]s } + return true; } ` // keyTypeString := "" @@ -166,42 +168,45 @@ void %[8]s::%[1]sWrite(::basictl::tl_ostream & s, const std::array<%[2]s, %[3]d> case trw.vectorLike: hppDetCode = ` void %[1]sReset(std::vector<%[2]s>& item); -void %[1]sRead(::basictl::tl_istream & s, std::vector<%[2]s>& item%[4]s); -void %[1]sWrite(::basictl::tl_ostream & s, const std::vector<%[2]s>& item%[4]s); +bool %[1]sRead(::basictl::tl_istream & s, std::vector<%[2]s>& item%[4]s); +bool %[1]sWrite(::basictl::tl_ostream & s, const std::vector<%[2]s>& item%[4]s); ` cppCode = ` void %[8]s::%[1]sReset(std::vector<%[2]s>& item) { item.resize(0); // TODO - unwrap } -void %[8]s::%[1]sRead(::basictl::tl_istream & s, std::vector<%[2]s>& item%[4]s) { - auto len = s.nat_read(); +bool %[8]s::%[1]sRead(::basictl::tl_istream & s, std::vector<%[2]s>& item%[4]s) { + uint32_t len = 0; + if (!s.nat_read(len)) { return false; } // TODO - check length sanity item.resize(len); for(auto && el : item) { %[5]s } + return true; } -void %[8]s::%[1]sWrite(::basictl::tl_ostream & s, const std::vector<%[2]s>& item%[4]s) { - s.nat_write(item.size()); +bool %[8]s::%[1]sWrite(::basictl::tl_ostream & s, const std::vector<%[2]s>& item%[4]s) { + if (!s.nat_write(item.size())) { return false; } for(const auto & el : item) { %[6]s } + return true; } ` case trw.dynamicSize: hppDetCode = ` void %[1]sReset(std::vector<%[2]s>& item); -void %[1]sRead(::basictl::tl_istream & s, std::vector<%[2]s>& item%[4]s); -void %[1]sWrite(::basictl::tl_ostream & s, const std::vector<%[2]s>& item%[4]s); +bool %[1]sRead(::basictl::tl_istream & s, std::vector<%[2]s>& item%[4]s); +bool %[1]sWrite(::basictl::tl_ostream & s, const std::vector<%[2]s>& item%[4]s); ` cppCode = ` void %[8]s::%[1]sReset(std::vector<%[2]s>& item) { item.resize(0); } -void %[8]s::%[1]sRead(::basictl::tl_istream & s, std::vector<%[2]s>& item%[4]s) { +bool %[8]s::%[1]sRead(::basictl::tl_istream & s, std::vector<%[2]s>& item%[4]s) { // TODO - check length sanity item.resize(nat_n); for(auto && el : item) { @@ -209,12 +214,13 @@ void %[8]s::%[1]sRead(::basictl::tl_istream & s, std::vector<%[2]s>& item%[4]s) } } -void %[8]s::%[1]sWrite(::basictl::tl_ostream & s, const std::vector<%[2]s>& item%[4]s) { +bool %[8]s::%[1]sWrite(::basictl::tl_ostream & s, const std::vector<%[2]s>& item%[4]s) { if (item.size() != nat_n) - ::basictl::throwSequenceLengthWrong(); + return s.set_error_sequence_length(); for(const auto & el : item) { %[6]s } + return true; } ` } diff --git a/internal/tlcodegen/type_rw_union_cpp.go b/internal/tlcodegen/type_rw_union_cpp.go index 3796d944..ecedea1a 100644 --- a/internal/tlcodegen/type_rw_union_cpp.go +++ b/internal/tlcodegen/type_rw_union_cpp.go @@ -44,12 +44,12 @@ func (trw *TypeRWUnion) CPPTypeResettingCode(bytesVersion bool, val string) stri func (trw *TypeRWUnion) CPPTypeWritingCode(bytesVersion bool, val string, bare bool, natArgs []string, last bool) string { goGlobalName := addBytes(trw.wr.goGlobalName, bytesVersion) - return fmt.Sprintf("\t::%s::%sWrite%s(s, %s%s);", trw.wr.gen.DetailsCPPNamespace, goGlobalName, addBare(bare), val, joinWithCommas(natArgs)) + return fmt.Sprintf("\tif (!::%s::%sWrite%s(s, %s%s)) { return false; }", trw.wr.gen.DetailsCPPNamespace, goGlobalName, addBare(bare), val, joinWithCommas(natArgs)) } func (trw *TypeRWUnion) CPPTypeReadingCode(bytesVersion bool, val string, bare bool, natArgs []string, last bool) string { goGlobalName := addBytes(trw.wr.goGlobalName, bytesVersion) - return fmt.Sprintf("\t::%s::%sRead%s(s, %s%s);", trw.wr.gen.DetailsCPPNamespace, goGlobalName, addBare(bare), val, joinWithCommas(natArgs)) + return fmt.Sprintf("\tif (!::%s::%sRead%s(s, %s%s) { return false; }", trw.wr.gen.DetailsCPPNamespace, goGlobalName, addBare(bare), val, joinWithCommas(natArgs)) } func (trw *TypeRWUnion) CPPGenerateCode(hpp *strings.Builder, hppInc *DirectIncludesCPP, hppIncFwd *DirectIncludesCPP, hppDet *strings.Builder, hppDetInc *DirectIncludesCPP, cppDet *strings.Builder, cppDetInc *DirectIncludesCPP, bytesVersion bool, forwardDeclaration bool) { @@ -65,8 +65,8 @@ func (trw *TypeRWUnion) CPPGenerateCode(hpp *strings.Builder, hppInc *DirectIncl cppStartNamespace(hppDet, trw.wr.gen.DetailsCPPNamespaceElements) hppDet.WriteString(fmt.Sprintf(` void %[1]sReset(%[2]s& item); -void %[1]sReadBoxed(::basictl::tl_istream & s, %[2]s& item%[3]s); -void %[1]sWriteBoxed(::basictl::tl_ostream & s, const %[2]s& item%[3]s); +bool %[1]sReadBoxed(::basictl::tl_istream & s, %[2]s& item%[3]s); +bool %[1]sWriteBoxed(::basictl::tl_ostream & s, const %[2]s& item%[3]s); `, goGlobalName, myFullType, formatNatArgsDeclCPP(trw.wr.NatParams))) cppFinishNamespace(hppDet, trw.wr.gen.DetailsCPPNamespaceElements) @@ -105,7 +105,7 @@ void %[1]sWriteBoxed(::basictl::tl_ostream & s, const %[2]s& item%[3]s); hpp.WriteString(trw.CPPSetters(bytesVersion)) hpp.WriteString(` - ::basictl::string_view tl_name() const; + std::string_view tl_name() const; uint32_t tl_tag() const; `) @@ -120,21 +120,23 @@ static const uint32_t %[1]s_tbl_tl_tag[]{%[3]s}; if len(myArgsDecl) == 0 { // cppStartNamespace(cppDet, trw.wr.gen.RootCPPNamespaceElements) hpp.WriteString(fmt.Sprintf(` - void read_boxed(::basictl::tl_istream & s%[1]s); - void write_boxed(::basictl::tl_ostream & s%[1]s)const; + bool read_boxed(::basictl::tl_istream & s%[1]s); + bool write_boxed(::basictl::tl_ostream & s%[1]s)const; `, formatNatArgsDeclCPP(trw.wr.NatParams), trw.CPPTypeResettingCode(bytesVersion, "*this"), trw.CPPTypeReadingCode(bytesVersion, "*this", false, trw.wr.NatParams, true), trw.CPPTypeWritingCode(bytesVersion, "*this", false, trw.wr.NatParams, true))) cppDet.WriteString(fmt.Sprintf(` -void %[5]s::read_boxed(::basictl::tl_istream & s%[1]s) { +bool %[5]s::read_boxed(::basictl::tl_istream & s%[1]s) { %[3]s + return true; } -void %[5]s::write_boxed(::basictl::tl_ostream & s%[1]s)const { +bool %[5]s::write_boxed(::basictl::tl_ostream & s%[1]s)const { %[4]s + return true; } -::basictl::string_view %[5]s::tl_name() const { +std::string_view %[5]s::tl_name() const { return %[6]s_tbl_tl_name[value.index()]; } uint32_t %[5]s::tl_tag() const { @@ -157,17 +159,19 @@ void %[7]s::%[1]sReset(%[2]s& item) { item.value.emplace<0>(); // TODO - optimize, if already 0, call Reset function } -void %[7]s::%[1]sReadBoxed(::basictl::tl_istream & s, %[2]s& item%[3]s) { +bool %[7]s::%[1]sReadBoxed(::basictl::tl_istream & s, %[2]s& item%[3]s) { switch (s.nat_read()) { %[5]s default: - ::basictl::throwUnionTagWrong(); + return s.set_error_union_tag(); } + return true; } -void %[7]s::%[1]sWriteBoxed(::basictl::tl_ostream & s, const %[2]s& item%[3]s) { +bool %[7]s::%[1]sWriteBoxed(::basictl::tl_ostream & s, const %[2]s& item%[3]s) { s.nat_write(%[1]s_tbl_tl_tag[item.value.index()]); switch (item.value.index()) { %[6]s } + return true; } `, goGlobalName,