diff --git a/Makefile b/Makefile index 7f9e80c7..81376e89 100644 --- a/Makefile +++ b/Makefile @@ -31,7 +31,6 @@ TL_BYTE_VERSIONS := ch_proxy.,ab. all: build build: - @echo "Building tlgen" @$(GO) build -ldflags "$(COMMON_LDFLAGS)" -buildvcs=false -o target/bin/tlgen ./cmd/tlgen tlo-bootstrap: build @@ -147,3 +146,9 @@ cpp_gen: build cpp: $(MAKE) cpp_gen $(MAKE) cpp_build + +# target should be as close as possible to github actions used to enable merge +.PHONY: check +check: build + @go test $(shell go list ./cmd/... ./internal/... ./pkg/... | grep -v /internal/tlcodegen/test/gen/) + @go run honnef.co/go/tools/cmd/staticcheck@v0.4.7 ./... # update version together with github actions \ No newline at end of file diff --git a/README.md b/README.md index f5131334..7a0747a6 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,16 @@ The TL format is characterized by compactness and high efficiency. TL is schema-driven format. Tool caled `tlgen` is used to generate structs/classes and (de)serialization methods. +## Running without installation + +You can run tool without installation. This is recommended way for most use cases. + +``` +go run github.com/vkcom/tl/cmd/tlgen@latest +``` + +For build scripts, you can pin particular version instead of `latest`. + ## Installation Install `tlgen` with the following command diff --git a/cmd/tlgen/main2.go b/cmd/tlgen/main2.go index 496a965b..750cc971 100644 --- a/cmd/tlgen/main2.go +++ b/cmd/tlgen/main2.go @@ -41,6 +41,8 @@ func parseFlags(opt *tlcodegen.Gen2Options) { "treat all warnings as errors") flag.BoolVar(&opt.Verbose, "v", false, "verbose mode that prints debug info") + flag.BoolVar(&opt.PrintDiff, "print-diff", false, + "prints diff of outdir contents before and after generating") flag.BoolVar(&opt.SplitInternal, "split-internal", false, "generated code will be split into independent packages (in a simple word: speeds up compilation)") @@ -92,17 +94,17 @@ func run(opt tlcodegen.Gen2Options) { log.Println(err.Error()) } if opt.Language == "" { - log.Printf("TL Linter Failed") + log.Printf("TL Linter Failed") // do not check Verbose } else { - log.Printf("TL Generation Failed") + log.Printf("TL Generation Failed") // do not check Verbose } os.Exit(1) return } if opt.Language == "" { - log.Printf("TL Linter Success") + log.Printf("TL Linter Success") // do not check Verbose } else { - log.Printf("TL Generation Success") + log.Printf("TL Generation Success") // do not check Verbose } } @@ -146,7 +148,7 @@ func runMain(opt *tlcodegen.Gen2Options) error { } if opt.TLOPath != "" { if opt.Verbose { - log.Print("generating tlo file") + log.Print("generating TLO file...") } s, err := fullAst.GenerateTLO(uint32(opt.SchemaTimestamp)) if err != nil { @@ -173,7 +175,7 @@ func runMain(opt *tlcodegen.Gen2Options) error { } if opt.CanonicalFormPath != "" { if opt.Verbose { - log.Print("generating file with combinators in canonical form") + log.Print("generating file with combinators in canonical form,,,") } var buf bytes.Buffer fullAst.WriteGenerate2TL(&buf) diff --git a/internal/tlcodegen/combined_tl_legacy.go b/internal/tlcodegen/combined_tl_legacy.go index aef71195..e95f01a6 100644 --- a/internal/tlcodegen/combined_tl_legacy.go +++ b/internal/tlcodegen/combined_tl_legacy.go @@ -6,9 +6,40 @@ package tlcodegen +import ( + "fmt" + "sort" +) + // All compatibility code that will be removed after some fixes to TL itself -func EnableWarningsUnionNamespaceSkipLegacy(conNamespace string, typeNamespace string) bool { +type legacyPair struct { + conName string + fieldName string +} + +var legacyExceptions []legacyPair // use it to populate this file with content of combined tl + +func LegacyPrintGlobalMap() { + sort.Slice(legacyExceptions, func(i, j int) bool { + if legacyExceptions[i].conName != legacyExceptions[j].conName { + return legacyExceptions[i].conName < legacyExceptions[j].conName + } + return legacyExceptions[i].fieldName < legacyExceptions[j].fieldName + }) + + for _, v := range legacyExceptions { + fmt.Printf(` if conFullName == %q && fieldName == %q { + return true + } +`, v.conName, v.fieldName) + } + if len(legacyExceptions) != 0 { + fmt.Printf("--- Total %d exceptions\n", len(legacyExceptions)) + } +} + +func LegacyEnableWarningsUnionNamespaceSkip(conNamespace string, typeNamespace string) bool { if conNamespace == "messagesLong" && typeNamespace == "messages" { return true } @@ -34,7 +65,7 @@ func EnableWarningsUnionNamespaceSkipLegacy(conNamespace string, typeNamespace s return false } -func EnableWarningsSimpleTypeNameSkipLegacy(conFullName string) bool { +func LegacyEnableWarningsSimpleTypeNameSkip(conFullName string) bool { if conFullName == "healthLoyalty.tmpGetCatalogResultOk" { return true } @@ -125,11 +156,12 @@ func EnableWarningsSimpleTypeNameSkipLegacy(conFullName string) bool { return false } -func EnableWarningsUnionNamePrefixSkipLegacy(conName string, typePrefix string, typeSuffix string) bool { +// too many of them, impractical +func LegacyEnableWarningsUnionNamePrefixSkip(conName string, typePrefix string, typeSuffix string) bool { return true // skip all warnings for now } -func EnableWarningsUnionNameExactSkipLegacy(conFullName string) bool { +func LegacyEnableWarningsUnionNameExactSkip(conFullName string) bool { if conFullName == "engine.queryResult" { return true } @@ -158,6 +190,230 @@ func EnableWarningsUnionNameExactSkipLegacy(conFullName string) bool { return false } -func GenerateUnusedNatTemplates(conFullName string) bool { +func LegacyGenerateUnusedNatTemplates(conFullName string) bool { return conFullName == "rpcInvokeReqExtra" || conFullName == "rpcReqResultExtra" } + +func LegacyAllowTrueBoxed(conFullName string, fieldName string) bool { + if conFullName == "genericModel.predict" && fieldName == "need_results_float" { + return true + } + if conFullName == "gopusher2.apnsPush" && fieldName == "is_voip" { + return true + } + if conFullName == "storage2.namespacePolicyBlocksCreation" && fieldName == "enable_blocks_creation" { + return true + } + if conFullName == "urlBoss.impParams" && fieldName == "keepAspectRatio" { + return true + } + if conFullName == "urlBoss.impParams" && fieldName == "proxy" { + return true + } + if conFullName == "urlBoss2.impParams" && fieldName == "keepAspectRatio" { + return true + } + if conFullName == "urlBoss2.impParams" && fieldName == "proxy" { + return true + } + if conFullName == "urlBoss2.routingParams" && fieldName == "randomSeed" { + return true + } + // below is goldmaster, we keep it to test generated code for this case + if conFullName == "useTrue" && fieldName == "b" { + return true + } + if conFullName == "useTrue" && fieldName == "d" { + return true + } + return false +} + +func LegacyAllowBoolFieldsmask(conFullName string, fieldName string) bool { + if conFullName == "adsLalProcessing.processing" && fieldName == "is_deleted" { + return true + } + if conFullName == "adsLalProcessing.startProcessing" && fieldName == "use_apps" { + return true + } + if conFullName == "adsLalProcessing.startProcessing" && fieldName == "use_keywords" { + return true + } + if conFullName == "audiofpgen.genToPMCEx" && fieldName == "allow_short" { + return true + } + if conFullName == "audiofpgen.genToPMCEx" && fieldName == "delete_after_gen" { + return true + } + if conFullName == "blockchainNftCli.getNftDataRequestItem" && fieldName == "img_update" { + return true + } + if conFullName == "ch_proxy.params" && fieldName == "as_post" { + return true + } + if conFullName == "donutLevels.getResponse" && fieldName == "can_add" { + return true + } + if conFullName == "messages.keyboard" && fieldName == "inline" { + return true + } + if conFullName == "messages.keyboard" && fieldName == "one_time" { + return true + } + if conFullName == "messages.setPeerNotificationsSettings" && fieldName == "muted" { + return true + } + if conFullName == "messagesChat.setNotificationsStatus" && fieldName == "is_push_muted" { + return true + } + if conFullName == "messagesChatLong.changeChatMembers" && fieldName == "response_idlong" { + return true + } + if conFullName == "messagesChatLong.setNotificationsStatus" && fieldName == "is_push_muted" { + return true + } + if conFullName == "messagesLong.setFolderNotificationsSettings" && fieldName == "muted" { + return true + } + if conFullName == "messagesLong.setPeerNotificationsSettings" && fieldName == "muted" { + return true + } + if conFullName == "news2.joinedNews" && fieldName == "hidden_by_privacy" { + return true + } + if conFullName == "news2.modifiedNewsEntry" && fieldName == "hidden_by_privacy" { + return true + } + if conFullName == "news2.typeSettings" && fieldName == "deleted" { + return true + } + if conFullName == "news2.typeSettings" && fieldName == "non_std_lengths" { + return true + } + if conFullName == "news2.typeSettings" && fieldName == "normalize_id_lengths" { + return true + } + if conFullName == "online.setFriendOnlineExtraTyped" && fieldName == "invisible_mode" { + return true + } + if conFullName == "sandbox.attachProcessSettings" && fieldName == "store_stats" { + return true + } + if conFullName == "sandbox.createProcessSettings" && fieldName == "store_stats" { + return true + } + if conFullName == "sandbox.storeResultSettings" && fieldName == "store_stderr" { + return true + } + if conFullName == "sandbox.storeResultSettings" && fieldName == "store_stdout" { + return true + } + if conFullName == "searchService.searchMarket" && fieldName == "has_video" { + return true + } + if conFullName == "service.adsTargAdEngineInfo" && fieldName == "user_ad_has_click" { + return true + } + if conFullName == "socket.operateResponse" && fieldName == "closed" { + return true + } + if conFullName == "storage2Impl.engineState" && fieldName == "too_many_uploads" { + return true + } + if conFullName == "targ.ad" && fieldName == "enabled" { + return true + } + if conFullName == "targ.ad" && fieldName == "result_active" { + return true + } + if conFullName == "targ.ad" && fieldName == "schedule_active" { + return true + } + if conFullName == "targ.ad" && fieldName == "suspended" { + return true + } + if conFullName == "targ.adCampaign" && fieldName == "enabled" { + return true + } + if conFullName == "targ.banner" && fieldName == "enabled" { + return true + } + if conFullName == "targ.lal" && fieldName == "is_user_scores_fill_finished" { + return true + } + if conFullName == "targ.searchAdsFilter" && fieldName == "enabled_status" { + return true + } + if conFullName == "targ.searchAdsFilter" && fieldName == "suspended_status" { + return true + } + if conFullName == "targ.user" && fieldName == "has_photo" { + return true + } + if conFullName == "targ.user" && fieldName == "hidden" { + return true + } + if conFullName == "targ.user" && fieldName == "is_online" { + return true + } + if conFullName == "targ.user" && fieldName == "online_invisible" { + return true + } + if conFullName == "targ.user" && fieldName == "pays_money" { + return true + } + if conFullName == "targ.user" && fieldName == "uses_apps" { + return true + } + if conFullName == "targ.userAdApplyViewOptions" && fieldName == "use_for_predictions" { + return true + } + if conFullName == "targLong.user" && fieldName == "has_photo" { + return true + } + if conFullName == "targLong.user" && fieldName == "hidden" { + return true + } + if conFullName == "targLong.user" && fieldName == "is_online" { + return true + } + if conFullName == "targLong.user" && fieldName == "online_invisible" { + return true + } + if conFullName == "targLong.user" && fieldName == "pays_money" { + return true + } + if conFullName == "targLong.user" && fieldName == "uses_apps" { + return true + } + if conFullName == "targUser.adDetails" && fieldName == "is_fake" { + return true + } + if conFullName == "targUser.campaignDetails" && fieldName == "is_fake" { + return true + } + if conFullName == "tasks.queueTypeSettings" && fieldName == "is_blocking" { + return true + } + if conFullName == "tasks.queueTypeSettings" && fieldName == "is_enabled" { + return true + } + if conFullName == "tasks.queueTypeSettings" && fieldName == "is_persistent" { + return true + } + if conFullName == "tasks.queueTypeSettings" && fieldName == "is_staging" { + return true + } + if conFullName == "tasks.queueTypeSettings" && fieldName == "move_to_queue_begin_on_retry" { + return true + } + if conFullName == "wall.searchV2" && fieldName == "reverse" { + return true + } + // below is goldmaster, we keep it to test generated code for this case + if conFullName == "useTrue" && fieldName == "e" { + return true + } + // legacyExceptions = append(legacyExceptions, legacyPair{conName: conFullName, fieldName: fieldName}) + return false +} diff --git a/internal/tlcodegen/test/gen/goldmaster.tlo.json b/internal/tlcodegen/test/gen/goldmaster.tlo.json index 4778bf6e..445984bd 100644 --- a/internal/tlcodegen/test/gen/goldmaster.tlo.json +++ b/internal/tlcodegen/test/gen/goldmaster.tlo.json @@ -1827,7 +1827,7 @@ "left": { "type": "tls.combinatorLeft", "value": { - "args_num": 5, + "args_num": 6, "args": [ { "id": "fm", @@ -1883,6 +1883,18 @@ "name": 1072550713 } } + }, + { + "id": "e", + "flags": 4, + "exist_var_num": 0, + "exist_var_bit": 2, + "type": { + "type": "tls.typeExpr", + "value": { + "name": 621535874 + } + } } ] } diff --git a/internal/tlcodegen/test/gen/goldmaster/factory_bytes/factory_bytes.go b/internal/tlcodegen/test/gen/goldmaster/factory_bytes/factory_bytes.go index 0c19baf4..7fceb6e7 100644 --- a/internal/tlcodegen/test/gen/goldmaster/factory_bytes/factory_bytes.go +++ b/internal/tlcodegen/test/gen/goldmaster/factory_bytes/factory_bytes.go @@ -64,6 +64,7 @@ import ( "github.com/vkcom/tl/internal/tlcodegen/test/gen/goldmaster/internal/tl/tlUseDictUgly" "github.com/vkcom/tl/internal/tlcodegen/test/gen/goldmaster/internal/tl/tlUseResponse" "github.com/vkcom/tl/internal/tlcodegen/test/gen/goldmaster/internal/tl/tlUseStr" + "github.com/vkcom/tl/internal/tlcodegen/test/gen/goldmaster/internal/tl/tlUseTrue" "github.com/vkcom/tl/internal/tlcodegen/test/gen/goldmaster/internal/tla/tlATop2" "github.com/vkcom/tl/internal/tlcodegen/test/gen/goldmaster/internal/tlab/tlAbCall1" "github.com/vkcom/tl/internal/tlcodegen/test/gen/goldmaster/internal/tlab/tlAbCall2" @@ -229,5 +230,6 @@ func init() { meta.SetGlobalFactoryCreateForObjectBytes(0xfb9ce817, func() meta.Object { var ret tlUseDictUgly.UseDictUgly; return &ret }) meta.SetGlobalFactoryCreateForObjectBytes(0x0a63ec5f, func() meta.Object { var ret tlUseResponse.UseResponse; return &ret }) meta.SetGlobalFactoryCreateForObjectBytes(0x9aa3dee5, func() meta.Object { var ret tlUseStr.UseStrBytes; return &ret }) + meta.SetGlobalFactoryCreateForObjectBytes(0xdfdd4180, func() meta.Object { var ret tlUseTrue.UseTrue; return &ret }) meta.SetGlobalFactoryCreateForFunctionBytes(0x3c857e52, func() meta.Object { var ret tlUsefulServiceGetUserEntity.UsefulServiceGetUserEntity; return &ret }, func() meta.Function { var ret tlUsefulServiceGetUserEntity.UsefulServiceGetUserEntity; return &ret }, nil) } diff --git a/internal/tlcodegen/test/gen/goldmaster/internal/tl/tlUseTrue/useTrue.go b/internal/tlcodegen/test/gen/goldmaster/internal/tl/tlUseTrue/useTrue.go index 06f0694f..c58b69a6 100644 --- a/internal/tlcodegen/test/gen/goldmaster/internal/tl/tlUseTrue/useTrue.go +++ b/internal/tlcodegen/test/gen/goldmaster/internal/tl/tlUseTrue/useTrue.go @@ -9,6 +9,7 @@ package tlUseTrue import ( "github.com/vkcom/tl/internal/tlcodegen/test/gen/goldmaster/internal" + "github.com/vkcom/tl/internal/tlcodegen/test/gen/goldmaster/internal/tl/tlBool" "github.com/vkcom/tl/internal/tlcodegen/test/gen/goldmaster/internal/tl/tlTrue" "github.com/vkcom/tl/pkg/basictl" ) @@ -22,6 +23,7 @@ type UseTrue struct { // B (TrueType) // Conditional: item.Fm.1 // C (TrueType) // D (TrueType) + E bool // Conditional: item.Fm.2 } func (UseTrue) TLName() string { return "useTrue" } @@ -45,8 +47,19 @@ func (item *UseTrue) SetB(v bool) { } func (item UseTrue) IsSetB() bool { return item.Fm&(1<<1) != 0 } +func (item *UseTrue) SetE(v bool) { + item.E = v + item.Fm |= 1 << 2 +} +func (item *UseTrue) ClearE() { + item.E = false + item.Fm &^= 1 << 2 +} +func (item UseTrue) IsSetE() bool { return item.Fm&(1<<2) != 0 } + func (item *UseTrue) Reset() { item.Fm = 0 + item.E = false } func (item *UseTrue) FillRandom(rg *basictl.RandGenerator) { @@ -59,6 +72,14 @@ func (item *UseTrue) FillRandom(rg *basictl.RandGenerator) { if maskFm&(1<<1) != 0 { item.Fm |= (1 << 1) } + if maskFm&(1<<2) != 0 { + item.Fm |= (1 << 2) + } + if item.Fm&(1<<2) != 0 { + item.E = basictl.RandomUint(rg)&1 == 1 + } else { + item.E = false + } } func (item *UseTrue) Read(w []byte) (_ []byte, err error) { @@ -70,7 +91,17 @@ func (item *UseTrue) Read(w []byte) (_ []byte, err error) { return w, err } } - return basictl.NatReadExactTag(w, 0x3fedd339) + if w, err = basictl.NatReadExactTag(w, 0x3fedd339); err != nil { + return w, err + } + if item.Fm&(1<<2) != 0 { + if w, err = tlBool.BoolReadBoxed(w, &item.E); err != nil { + return w, err + } + } else { + item.E = false + } + return w, nil } // This method is general version of Write, use it instead! @@ -84,6 +115,9 @@ func (item *UseTrue) Write(w []byte) []byte { w = basictl.NatWrite(w, 0x3fedd339) } w = basictl.NatWrite(w, 0x3fedd339) + if item.Fm&(1<<2) != 0 { + w = tlBool.BoolWriteBoxed(w, item.E) + } return w } @@ -114,6 +148,7 @@ func (item *UseTrue) ReadJSON(legacyTypeNames bool, in *basictl.JsonLexer) error var trueTypeAValue bool var trueTypeBPresented bool var trueTypeBValue bool + var propEPresented bool if in != nil { in.Delim('{') @@ -158,6 +193,14 @@ func (item *UseTrue) ReadJSON(legacyTypeNames bool, in *basictl.JsonLexer) error if err := tmpD.ReadJSON(legacyTypeNames, in); err != nil { return err } + case "e": + if propEPresented { + return internal.ErrorInvalidJSONWithDuplicatingKeys("useTrue", "e") + } + if err := internal.Json2ReadBool(in, &item.E); err != nil { + return err + } + propEPresented = true default: return internal.ErrorInvalidJSONExcessElement("useTrue", key) } @@ -171,6 +214,9 @@ func (item *UseTrue) ReadJSON(legacyTypeNames bool, in *basictl.JsonLexer) error if !propFmPresented { item.Fm = 0 } + if !propEPresented { + item.E = false + } if trueTypeAPresented { if trueTypeAValue { item.Fm |= 1 << 0 @@ -181,6 +227,9 @@ func (item *UseTrue) ReadJSON(legacyTypeNames bool, in *basictl.JsonLexer) error item.Fm |= 1 << 1 } } + if propEPresented { + item.Fm |= 1 << 2 + } // tries to set bit to zero if it is 1 if trueTypeAPresented && !trueTypeAValue && (item.Fm&(1<<0) != 0) { return internal.ErrorInvalidJSON("useTrue", "fieldmask bit fm.0 is indefinite because of the contradictions in values") @@ -217,6 +266,11 @@ func (item *UseTrue) WriteJSONOpt(newTypeNames bool, short bool, w []byte) []byt w = basictl.JSONAddCommaIfNeeded(w) w = append(w, `"b":true`...) } + if item.Fm&(1<<2) != 0 { + w = basictl.JSONAddCommaIfNeeded(w) + w = append(w, `"e":`...) + w = basictl.JSONWriteBool(w, item.E) + } return append(w, '}') } diff --git a/internal/tlcodegen/test/gen/goldmaster/tljson.html b/internal/tlcodegen/test/gen/goldmaster/tljson.html index b74eec19..4947b156 100644 --- a/internal/tlcodegen/test/gen/goldmaster/tljson.html +++ b/internal/tlcodegen/test/gen/goldmaster/tljson.html @@ -4980,17 +4980,26 @@

useTrue

-   "d": true +   "d": true, + + +   "e": <bool> + // fm bit #2 + + + + }
TL
- useTrue#dfdd4180 fm:# a:fm.0?true b:fm.1?True c:true d:True = UseTrue; + useTrue#dfdd4180 fm:# a:fm.0?true b:fm.1?True c:true d:True e:fm.2?Bool = UseTrue; + // we give warnings for many fields of this kind
diff --git a/internal/tlcodegen/test/gen/goldmaster_nosplit/factory_bytes/factory_bytes.go b/internal/tlcodegen/test/gen/goldmaster_nosplit/factory_bytes/factory_bytes.go index ea07336b..d90875ac 100644 --- a/internal/tlcodegen/test/gen/goldmaster_nosplit/factory_bytes/factory_bytes.go +++ b/internal/tlcodegen/test/gen/goldmaster_nosplit/factory_bytes/factory_bytes.go @@ -132,5 +132,6 @@ func init() { meta.SetGlobalFactoryCreateForObjectBytes(0xfb9ce817, func() meta.Object { var ret internal.UseDictUgly; return &ret }) meta.SetGlobalFactoryCreateForObjectBytes(0x0a63ec5f, func() meta.Object { var ret internal.UseResponse; return &ret }) meta.SetGlobalFactoryCreateForObjectBytes(0x9aa3dee5, func() meta.Object { var ret internal.UseStrBytes; return &ret }) + meta.SetGlobalFactoryCreateForObjectBytes(0xdfdd4180, func() meta.Object { var ret internal.UseTrue; return &ret }) meta.SetGlobalFactoryCreateForFunctionBytes(0x3c857e52, func() meta.Object { var ret internal.UsefulServiceGetUserEntity; return &ret }, func() meta.Function { var ret internal.UsefulServiceGetUserEntity; return &ret }, nil) } diff --git a/internal/tlcodegen/test/gen/goldmaster_nosplit/internal/useTrue.go b/internal/tlcodegen/test/gen/goldmaster_nosplit/internal/useTrue.go index 9785ec94..8e3d9af9 100644 --- a/internal/tlcodegen/test/gen/goldmaster_nosplit/internal/useTrue.go +++ b/internal/tlcodegen/test/gen/goldmaster_nosplit/internal/useTrue.go @@ -19,6 +19,7 @@ type UseTrue struct { // B (TrueType) // Conditional: item.Fm.1 // C (TrueType) // D (TrueType) + E bool // Conditional: item.Fm.2 } func (UseTrue) TLName() string { return "useTrue" } @@ -42,8 +43,19 @@ func (item *UseTrue) SetB(v bool) { } func (item UseTrue) IsSetB() bool { return item.Fm&(1<<1) != 0 } +func (item *UseTrue) SetE(v bool) { + item.E = v + item.Fm |= 1 << 2 +} +func (item *UseTrue) ClearE() { + item.E = false + item.Fm &^= 1 << 2 +} +func (item UseTrue) IsSetE() bool { return item.Fm&(1<<2) != 0 } + func (item *UseTrue) Reset() { item.Fm = 0 + item.E = false } func (item *UseTrue) FillRandom(rg *basictl.RandGenerator) { @@ -56,6 +68,14 @@ func (item *UseTrue) FillRandom(rg *basictl.RandGenerator) { if maskFm&(1<<1) != 0 { item.Fm |= (1 << 1) } + if maskFm&(1<<2) != 0 { + item.Fm |= (1 << 2) + } + if item.Fm&(1<<2) != 0 { + item.E = basictl.RandomUint(rg)&1 == 1 + } else { + item.E = false + } } func (item *UseTrue) Read(w []byte) (_ []byte, err error) { @@ -67,7 +87,17 @@ func (item *UseTrue) Read(w []byte) (_ []byte, err error) { return w, err } } - return basictl.NatReadExactTag(w, 0x3fedd339) + if w, err = basictl.NatReadExactTag(w, 0x3fedd339); err != nil { + return w, err + } + if item.Fm&(1<<2) != 0 { + if w, err = BoolReadBoxed(w, &item.E); err != nil { + return w, err + } + } else { + item.E = false + } + return w, nil } // This method is general version of Write, use it instead! @@ -81,6 +111,9 @@ func (item *UseTrue) Write(w []byte) []byte { w = basictl.NatWrite(w, 0x3fedd339) } w = basictl.NatWrite(w, 0x3fedd339) + if item.Fm&(1<<2) != 0 { + w = BoolWriteBoxed(w, item.E) + } return w } @@ -111,6 +144,7 @@ func (item *UseTrue) ReadJSON(legacyTypeNames bool, in *basictl.JsonLexer) error var trueTypeAValue bool var trueTypeBPresented bool var trueTypeBValue bool + var propEPresented bool if in != nil { in.Delim('{') @@ -155,6 +189,14 @@ func (item *UseTrue) ReadJSON(legacyTypeNames bool, in *basictl.JsonLexer) error if err := tmpD.ReadJSON(legacyTypeNames, in); err != nil { return err } + case "e": + if propEPresented { + return ErrorInvalidJSONWithDuplicatingKeys("useTrue", "e") + } + if err := Json2ReadBool(in, &item.E); err != nil { + return err + } + propEPresented = true default: return ErrorInvalidJSONExcessElement("useTrue", key) } @@ -168,6 +210,9 @@ func (item *UseTrue) ReadJSON(legacyTypeNames bool, in *basictl.JsonLexer) error if !propFmPresented { item.Fm = 0 } + if !propEPresented { + item.E = false + } if trueTypeAPresented { if trueTypeAValue { item.Fm |= 1 << 0 @@ -178,6 +223,9 @@ func (item *UseTrue) ReadJSON(legacyTypeNames bool, in *basictl.JsonLexer) error item.Fm |= 1 << 1 } } + if propEPresented { + item.Fm |= 1 << 2 + } // tries to set bit to zero if it is 1 if trueTypeAPresented && !trueTypeAValue && (item.Fm&(1<<0) != 0) { return ErrorInvalidJSON("useTrue", "fieldmask bit fm.0 is indefinite because of the contradictions in values") @@ -214,6 +262,11 @@ func (item *UseTrue) WriteJSONOpt(newTypeNames bool, short bool, w []byte) []byt w = basictl.JSONAddCommaIfNeeded(w) w = append(w, `"b":true`...) } + if item.Fm&(1<<2) != 0 { + w = basictl.JSONAddCommaIfNeeded(w) + w = append(w, `"e":`...) + w = basictl.JSONWriteBool(w, item.E) + } return append(w, '}') } diff --git a/internal/tlcodegen/test/gen/goldmaster_nosplit/tljson.html b/internal/tlcodegen/test/gen/goldmaster_nosplit/tljson.html index b74eec19..4947b156 100644 --- a/internal/tlcodegen/test/gen/goldmaster_nosplit/tljson.html +++ b/internal/tlcodegen/test/gen/goldmaster_nosplit/tljson.html @@ -4980,17 +4980,26 @@

useTrue

-   "d": true +   "d": true, + + +   "e": <bool> + // fm bit #2 + + + + }
TL
- useTrue#dfdd4180 fm:# a:fm.0?true b:fm.1?True c:true d:True = UseTrue; + useTrue#dfdd4180 fm:# a:fm.0?true b:fm.1?True c:true d:True e:fm.2?Bool = UseTrue; + // we give warnings for many fields of this kind
diff --git a/internal/tlcodegen/test/gen/schema/internal/cycle_6ca945392bbf8b14f24e5653edc8b214/service1.Value.go b/internal/tlcodegen/test/gen/schema/internal/cycle_6ca945392bbf8b14f24e5653edc8b214/service1.Value.go index 4ed427d2..72b60dba 100644 --- a/internal/tlcodegen/test/gen/schema/internal/cycle_6ca945392bbf8b14f24e5653edc8b214/service1.Value.go +++ b/internal/tlcodegen/test/gen/schema/internal/cycle_6ca945392bbf8b14f24e5653edc8b214/service1.Value.go @@ -27,7 +27,7 @@ type Service1Longvalue struct { } func (Service1Longvalue) TLName() string { return "service1.longvalue" } -func (Service1Longvalue) TLTag() uint32 { return 0x82e0945 } +func (Service1Longvalue) TLTag() uint32 { return 0x082e0945 } func (item *Service1Longvalue) Reset() { item.Value = 0 @@ -53,7 +53,7 @@ func (item *Service1Longvalue) Write(w []byte) []byte { } func (item *Service1Longvalue) ReadBoxed(w []byte) (_ []byte, err error) { - if w, err = basictl.NatReadExactTag(w, 0x82e0945); err != nil { + if w, err = basictl.NatReadExactTag(w, 0x082e0945); err != nil { return w, err } return item.Read(w) @@ -65,7 +65,7 @@ func (item *Service1Longvalue) WriteBoxedGeneral(w []byte) (_ []byte, err error) } func (item *Service1Longvalue) WriteBoxed(w []byte) []byte { - w = basictl.NatWrite(w, 0x82e0945) + w = basictl.NatWrite(w, 0x082e0945) return item.Write(w) } @@ -731,7 +731,7 @@ func (item *Service1StrvalueWithTime) UnmarshalJSON(b []byte) error { var _Service1Value = [5]internal.UnionElement{ {TLTag: 0x1d670b96, TLName: "service1.not_found", TLString: "service1.not_found#1d670b96"}, {TLTag: 0x5faa0c52, TLName: "service1.strvalue", TLString: "service1.strvalue#5faa0c52"}, - {TLTag: 0x82e0945, TLName: "service1.longvalue", TLString: "service1.longvalue#082e0945"}, + {TLTag: 0x082e0945, TLName: "service1.longvalue", TLString: "service1.longvalue#082e0945"}, {TLTag: 0x98b1a484, TLName: "service1.strvalueWithTime", TLString: "service1.strvalueWithTime#98b1a484"}, {TLTag: 0xa04606ec, TLName: "service1.longvalueWithTime", TLString: "service1.longvalueWithTime#a04606ec"}, } @@ -842,7 +842,7 @@ func (item *Service1Value) ReadBoxed(w []byte) (_ []byte, err error) { case 0x5faa0c52: item.index = 1 return item.valueStrvalue.Read(w) - case 0x82e0945: + case 0x082e0945: item.index = 2 return item.valueLongvalue.Read(w) case 0x98b1a484: diff --git a/internal/tlcodegen/test/gen/schema/internal/cycle_e0e20d17984738a60e3bf741bd7db2e9/Either.go b/internal/tlcodegen/test/gen/schema/internal/cycle_e0e20d17984738a60e3bf741bd7db2e9/Either.go index f150c43a..c2e08e8d 100644 --- a/internal/tlcodegen/test/gen/schema/internal/cycle_e0e20d17984738a60e3bf741bd7db2e9/Either.go +++ b/internal/tlcodegen/test/gen/schema/internal/cycle_e0e20d17984738a60e3bf741bd7db2e9/Either.go @@ -19,7 +19,7 @@ var _ = basictl.NatWrite var _ = internal.ErrorInvalidEnumTag var _EitherService6ErrorVectorService6FindResultRow = [2]internal.UnionElement{ - {TLTag: 0xa29cd5d, TLName: "left", TLString: "left#0a29cd5d"}, + {TLTag: 0x0a29cd5d, TLName: "left", TLString: "left#0a29cd5d"}, {TLTag: 0xdf3ecb3b, TLName: "right", TLString: "right#df3ecb3b"}, } @@ -80,7 +80,7 @@ func (item *EitherService6ErrorVectorService6FindResultRow) ReadBoxed(w []byte) return w, err } switch tag { - case 0xa29cd5d: + case 0x0a29cd5d: item.index = 0 return item.valueLeft.Read(w) case 0xdf3ecb3b: @@ -204,7 +204,7 @@ type LeftService6ErrorVectorService6FindResultRow struct { } func (LeftService6ErrorVectorService6FindResultRow) TLName() string { return "left" } -func (LeftService6ErrorVectorService6FindResultRow) TLTag() uint32 { return 0xa29cd5d } +func (LeftService6ErrorVectorService6FindResultRow) TLTag() uint32 { return 0x0a29cd5d } func (item *LeftService6ErrorVectorService6FindResultRow) Reset() { item.Value.Reset() @@ -225,7 +225,7 @@ func (item *LeftService6ErrorVectorService6FindResultRow) Write(w []byte) []byte } func (item *LeftService6ErrorVectorService6FindResultRow) ReadBoxed(w []byte) (_ []byte, err error) { - if w, err = basictl.NatReadExactTag(w, 0xa29cd5d); err != nil { + if w, err = basictl.NatReadExactTag(w, 0x0a29cd5d); err != nil { return w, err } return item.Read(w) @@ -237,7 +237,7 @@ func (item *LeftService6ErrorVectorService6FindResultRow) WriteBoxedGeneral(w [] } func (item *LeftService6ErrorVectorService6FindResultRow) WriteBoxed(w []byte) []byte { - w = basictl.NatWrite(w, 0xa29cd5d) + w = basictl.NatWrite(w, 0x0a29cd5d) return item.Write(w) } diff --git a/internal/tlcodegen/test/gen/schema/internal/cycle_ea8339e8d6257cc96a27be3f42a07a87/Either.go b/internal/tlcodegen/test/gen/schema/internal/cycle_ea8339e8d6257cc96a27be3f42a07a87/Either.go index aa0df114..9e033cc8 100644 --- a/internal/tlcodegen/test/gen/schema/internal/cycle_ea8339e8d6257cc96a27be3f42a07a87/Either.go +++ b/internal/tlcodegen/test/gen/schema/internal/cycle_ea8339e8d6257cc96a27be3f42a07a87/Either.go @@ -18,7 +18,7 @@ var _ = basictl.NatWrite var _ = internal.ErrorInvalidEnumTag var _EitherIntVectorService6FindWithBoundsResult = [2]internal.UnionElement{ - {TLTag: 0xa29cd5d, TLName: "left", TLString: "left#0a29cd5d"}, + {TLTag: 0x0a29cd5d, TLName: "left", TLString: "left#0a29cd5d"}, {TLTag: 0xdf3ecb3b, TLName: "right", TLString: "right#df3ecb3b"}, } @@ -79,7 +79,7 @@ func (item *EitherIntVectorService6FindWithBoundsResult) ReadBoxed(w []byte) (_ return w, err } switch tag { - case 0xa29cd5d: + case 0x0a29cd5d: item.index = 0 return item.valueLeft.Read(w) case 0xdf3ecb3b: @@ -203,7 +203,7 @@ type LeftIntVectorService6FindWithBoundsResult struct { } func (LeftIntVectorService6FindWithBoundsResult) TLName() string { return "left" } -func (LeftIntVectorService6FindWithBoundsResult) TLTag() uint32 { return 0xa29cd5d } +func (LeftIntVectorService6FindWithBoundsResult) TLTag() uint32 { return 0x0a29cd5d } func (item *LeftIntVectorService6FindWithBoundsResult) Reset() { item.Value = 0 @@ -224,7 +224,7 @@ func (item *LeftIntVectorService6FindWithBoundsResult) Write(w []byte) []byte { } func (item *LeftIntVectorService6FindWithBoundsResult) ReadBoxed(w []byte) (_ []byte, err error) { - if w, err = basictl.NatReadExactTag(w, 0xa29cd5d); err != nil { + if w, err = basictl.NatReadExactTag(w, 0x0a29cd5d); err != nil { return w, err } return item.Read(w) @@ -236,7 +236,7 @@ func (item *LeftIntVectorService6FindWithBoundsResult) WriteBoxedGeneral(w []byt } func (item *LeftIntVectorService6FindWithBoundsResult) WriteBoxed(w []byte) []byte { - w = basictl.NatWrite(w, 0xa29cd5d) + w = basictl.NatWrite(w, 0x0a29cd5d) return item.Write(w) } diff --git a/internal/tlcodegen/test/gen/schema/internal/tl/tlWithFloat/withFloat.go b/internal/tlcodegen/test/gen/schema/internal/tl/tlWithFloat/withFloat.go index dcb40369..5a88bd15 100644 --- a/internal/tlcodegen/test/gen/schema/internal/tl/tlWithFloat/withFloat.go +++ b/internal/tlcodegen/test/gen/schema/internal/tl/tlWithFloat/withFloat.go @@ -22,7 +22,7 @@ type WithFloat struct { } func (WithFloat) TLName() string { return "withFloat" } -func (WithFloat) TLTag() uint32 { return 0x71b8685 } +func (WithFloat) TLTag() uint32 { return 0x071b8685 } func (item *WithFloat) Reset() { item.X = 0 @@ -57,7 +57,7 @@ func (item *WithFloat) Write(w []byte) []byte { } func (item *WithFloat) ReadBoxed(w []byte) (_ []byte, err error) { - if w, err = basictl.NatReadExactTag(w, 0x71b8685); err != nil { + if w, err = basictl.NatReadExactTag(w, 0x071b8685); err != nil { return w, err } return item.Read(w) @@ -69,7 +69,7 @@ func (item *WithFloat) WriteBoxedGeneral(w []byte) (_ []byte, err error) { } func (item *WithFloat) WriteBoxed(w []byte) []byte { - w = basictl.NatWrite(w, 0x71b8685) + w = basictl.NatWrite(w, 0x071b8685) return item.Write(w) } diff --git a/internal/tlcodegen/test/gen/schema/internal/tlservice1/tlService1Append/service1.append.go b/internal/tlcodegen/test/gen/schema/internal/tlservice1/tlService1Append/service1.append.go index 49f435bf..15a4e621 100644 --- a/internal/tlcodegen/test/gen/schema/internal/tlservice1/tlService1Append/service1.append.go +++ b/internal/tlcodegen/test/gen/schema/internal/tlservice1/tlService1Append/service1.append.go @@ -24,7 +24,7 @@ type Service1Append struct { } func (Service1Append) TLName() string { return "service1.append" } -func (Service1Append) TLTag() uint32 { return 0x4dec671 } +func (Service1Append) TLTag() uint32 { return 0x04dec671 } func (item *Service1Append) Reset() { item.Key = "" @@ -60,7 +60,7 @@ func (item *Service1Append) Write(w []byte) []byte { } func (item *Service1Append) ReadBoxed(w []byte) (_ []byte, err error) { - if w, err = basictl.NatReadExactTag(w, 0x4dec671); err != nil { + if w, err = basictl.NatReadExactTag(w, 0x04dec671); err != nil { return w, err } return item.Read(w) @@ -72,7 +72,7 @@ func (item *Service1Append) WriteBoxedGeneral(w []byte) (_ []byte, err error) { } func (item *Service1Append) WriteBoxed(w []byte) []byte { - w = basictl.NatWrite(w, 0x4dec671) + w = basictl.NatWrite(w, 0x04dec671) return item.Write(w) } diff --git a/internal/tlcodegen/test/gen/schema/internal/tlservice1/tlService1GetKeysStat/service1.getKeysStat.go b/internal/tlcodegen/test/gen/schema/internal/tlservice1/tlService1GetKeysStat/service1.getKeysStat.go index d5669b3f..02d55f0f 100644 --- a/internal/tlcodegen/test/gen/schema/internal/tlservice1/tlService1GetKeysStat/service1.getKeysStat.go +++ b/internal/tlcodegen/test/gen/schema/internal/tlservice1/tlService1GetKeysStat/service1.getKeysStat.go @@ -21,7 +21,7 @@ type Service1GetKeysStat struct { } func (Service1GetKeysStat) TLName() string { return "service1.getKeysStat" } -func (Service1GetKeysStat) TLTag() uint32 { return 0x6cecd58 } +func (Service1GetKeysStat) TLTag() uint32 { return 0x06cecd58 } func (item *Service1GetKeysStat) Reset() { item.Period = 0 @@ -42,7 +42,7 @@ func (item *Service1GetKeysStat) Write(w []byte) []byte { } func (item *Service1GetKeysStat) ReadBoxed(w []byte) (_ []byte, err error) { - if w, err = basictl.NatReadExactTag(w, 0x6cecd58); err != nil { + if w, err = basictl.NatReadExactTag(w, 0x06cecd58); err != nil { return w, err } return item.Read(w) @@ -54,7 +54,7 @@ func (item *Service1GetKeysStat) WriteBoxedGeneral(w []byte) (_ []byte, err erro } func (item *Service1GetKeysStat) WriteBoxed(w []byte) []byte { - w = basictl.NatWrite(w, 0x6cecd58) + w = basictl.NatWrite(w, 0x06cecd58) return item.Write(w) } diff --git a/internal/tlcodegen/test/gen/schema/internal/tlservice1/tlService1Incr/service1.incr.go b/internal/tlcodegen/test/gen/schema/internal/tlservice1/tlService1Incr/service1.incr.go index c79d19f4..031fe1b7 100644 --- a/internal/tlcodegen/test/gen/schema/internal/tlservice1/tlService1Incr/service1.incr.go +++ b/internal/tlcodegen/test/gen/schema/internal/tlservice1/tlService1Incr/service1.incr.go @@ -22,7 +22,7 @@ type Service1Incr struct { } func (Service1Incr) TLName() string { return "service1.incr" } -func (Service1Incr) TLTag() uint32 { return 0xf96b56e } +func (Service1Incr) TLTag() uint32 { return 0x0f96b56e } func (item *Service1Incr) Reset() { item.Key = "" @@ -48,7 +48,7 @@ func (item *Service1Incr) Write(w []byte) []byte { } func (item *Service1Incr) ReadBoxed(w []byte) (_ []byte, err error) { - if w, err = basictl.NatReadExactTag(w, 0xf96b56e); err != nil { + if w, err = basictl.NatReadExactTag(w, 0x0f96b56e); err != nil { return w, err } return item.Read(w) @@ -60,7 +60,7 @@ func (item *Service1Incr) WriteBoxedGeneral(w []byte) (_ []byte, err error) { } func (item *Service1Incr) WriteBoxed(w []byte) []byte { - w = basictl.NatWrite(w, 0xf96b56e) + w = basictl.NatWrite(w, 0x0f96b56e) return item.Write(w) } diff --git a/internal/tlcodegen/test/gen/schema/internal/tlservice1/tlService1Set/service1.set.go b/internal/tlcodegen/test/gen/schema/internal/tlservice1/tlService1Set/service1.set.go index 98793d0e..39744edc 100644 --- a/internal/tlcodegen/test/gen/schema/internal/tlservice1/tlService1Set/service1.set.go +++ b/internal/tlcodegen/test/gen/schema/internal/tlservice1/tlService1Set/service1.set.go @@ -24,7 +24,7 @@ type Service1Set struct { } func (Service1Set) TLName() string { return "service1.set" } -func (Service1Set) TLTag() uint32 { return 0x5ae5f66 } +func (Service1Set) TLTag() uint32 { return 0x05ae5f66 } func (item *Service1Set) Reset() { item.Key = "" @@ -60,7 +60,7 @@ func (item *Service1Set) Write(w []byte) []byte { } func (item *Service1Set) ReadBoxed(w []byte) (_ []byte, err error) { - if w, err = basictl.NatReadExactTag(w, 0x5ae5f66); err != nil { + if w, err = basictl.NatReadExactTag(w, 0x05ae5f66); err != nil { return w, err } return item.Read(w) @@ -72,7 +72,7 @@ func (item *Service1Set) WriteBoxedGeneral(w []byte) (_ []byte, err error) { } func (item *Service1Set) WriteBoxed(w []byte) []byte { - w = basictl.NatWrite(w, 0x5ae5f66) + w = basictl.NatWrite(w, 0x05ae5f66) return item.Write(w) } diff --git a/internal/tlcodegen/test/gen/schema/internal/tlservice2/tlService2Set/service2.set.go b/internal/tlcodegen/test/gen/schema/internal/tlservice2/tlService2Set/service2.set.go index 7737fb47..9717db6a 100644 --- a/internal/tlcodegen/test/gen/schema/internal/tlservice2/tlService2Set/service2.set.go +++ b/internal/tlcodegen/test/gen/schema/internal/tlservice2/tlService2Set/service2.set.go @@ -28,7 +28,7 @@ type Service2Set struct { } func (Service2Set) TLName() string { return "service2.set" } -func (Service2Set) TLTag() uint32 { return 0xd31f63d } +func (Service2Set) TLTag() uint32 { return 0x0d31f63d } func (item *Service2Set) Reset() { item.ObjectIdLength = 0 @@ -80,7 +80,7 @@ func (item *Service2Set) Write(w []byte) (_ []byte, err error) { } func (item *Service2Set) ReadBoxed(w []byte) (_ []byte, err error) { - if w, err = basictl.NatReadExactTag(w, 0xd31f63d); err != nil { + if w, err = basictl.NatReadExactTag(w, 0x0d31f63d); err != nil { return w, err } return item.Read(w) @@ -92,7 +92,7 @@ func (item *Service2Set) WriteBoxedGeneral(w []byte) (_ []byte, err error) { } func (item *Service2Set) WriteBoxed(w []byte) (_ []byte, err error) { - w = basictl.NatWrite(w, 0xd31f63d) + w = basictl.NatWrite(w, 0x0d31f63d) return item.Write(w) } diff --git a/internal/tlcodegen/test/gen/schema/internal/tlservice5/tlService5PerformQuery/service5.performQuery.go b/internal/tlcodegen/test/gen/schema/internal/tlservice5/tlService5PerformQuery/service5.performQuery.go index b8f54c29..f3abadaf 100644 --- a/internal/tlcodegen/test/gen/schema/internal/tlservice5/tlService5PerformQuery/service5.performQuery.go +++ b/internal/tlcodegen/test/gen/schema/internal/tlservice5/tlService5PerformQuery/service5.performQuery.go @@ -21,7 +21,7 @@ type Service5PerformQuery struct { } func (Service5PerformQuery) TLName() string { return "service5.performQuery" } -func (Service5PerformQuery) TLTag() uint32 { return 0x19d80a5 } +func (Service5PerformQuery) TLTag() uint32 { return 0x019d80a5 } func (item *Service5PerformQuery) Reset() { item.Query = "" @@ -42,7 +42,7 @@ func (item *Service5PerformQuery) Write(w []byte) []byte { } func (item *Service5PerformQuery) ReadBoxed(w []byte) (_ []byte, err error) { - if w, err = basictl.NatReadExactTag(w, 0x19d80a5); err != nil { + if w, err = basictl.NatReadExactTag(w, 0x019d80a5); err != nil { return w, err } return item.Read(w) @@ -54,7 +54,7 @@ func (item *Service5PerformQuery) WriteBoxedGeneral(w []byte) (_ []byte, err err } func (item *Service5PerformQuery) WriteBoxed(w []byte) []byte { - w = basictl.NatWrite(w, 0x19d80a5) + w = basictl.NatWrite(w, 0x019d80a5) return item.Write(w) } diff --git a/internal/tlcodegen/test/gen/schema/internal/tltasks/tlTasksTaskInfo/tasks.taskInfo.go b/internal/tlcodegen/test/gen/schema/internal/tltasks/tlTasksTaskInfo/tasks.taskInfo.go index 4e1a8ed3..b498bd1f 100644 --- a/internal/tlcodegen/test/gen/schema/internal/tltasks/tlTasksTaskInfo/tasks.taskInfo.go +++ b/internal/tlcodegen/test/gen/schema/internal/tltasks/tlTasksTaskInfo/tasks.taskInfo.go @@ -24,7 +24,7 @@ type TasksTaskInfo struct { } func (TasksTaskInfo) TLName() string { return "tasks.taskInfo" } -func (TasksTaskInfo) TLTag() uint32 { return 0x6f0c6a6 } +func (TasksTaskInfo) TLTag() uint32 { return 0x06f0c6a6 } func (item *TasksTaskInfo) Reset() { item.TypeName = "" @@ -55,7 +55,7 @@ func (item *TasksTaskInfo) Write(w []byte) []byte { } func (item *TasksTaskInfo) ReadBoxed(w []byte) (_ []byte, err error) { - if w, err = basictl.NatReadExactTag(w, 0x6f0c6a6); err != nil { + if w, err = basictl.NatReadExactTag(w, 0x06f0c6a6); err != nil { return w, err } return item.Read(w) @@ -67,7 +67,7 @@ func (item *TasksTaskInfo) WriteBoxedGeneral(w []byte) (_ []byte, err error) { } func (item *TasksTaskInfo) WriteBoxed(w []byte) []byte { - w = basictl.NatWrite(w, 0x6f0c6a6) + w = basictl.NatWrite(w, 0x06f0c6a6) return item.Write(w) } diff --git a/internal/tlcodegen/test/gen/schema/internal/tltasks/tlTasksTaskStatus/tasks.TaskStatus.go b/internal/tlcodegen/test/gen/schema/internal/tltasks/tlTasksTaskStatus/tasks.TaskStatus.go index df53cbeb..dd427c00 100644 --- a/internal/tlcodegen/test/gen/schema/internal/tltasks/tlTasksTaskStatus/tasks.TaskStatus.go +++ b/internal/tlcodegen/test/gen/schema/internal/tltasks/tlTasksTaskStatus/tasks.TaskStatus.go @@ -17,9 +17,9 @@ var _ = internal.ErrorInvalidEnumTag var _TasksTaskStatus = [4]internal.UnionElement{ {TLTag: 0xb207caaa, TLName: "tasks.taskStatusNotCurrentlyInEngine", TLString: "tasks.taskStatusNotCurrentlyInEngine#b207caaa"}, - {TLTag: 0xaca80a9, TLName: "tasks.taskStatusScheduled", TLString: "tasks.taskStatusScheduled#0aca80a9"}, + {TLTag: 0x0aca80a9, TLName: "tasks.taskStatusScheduled", TLString: "tasks.taskStatusScheduled#0aca80a9"}, {TLTag: 0x16739c2c, TLName: "tasks.taskStatusWaiting", TLString: "tasks.taskStatusWaiting#16739c2c"}, - {TLTag: 0x6ef70e7, TLName: "tasks.taskStatusInProgress", TLString: "tasks.taskStatusInProgress#06ef70e7"}, + {TLTag: 0x06ef70e7, TLName: "tasks.taskStatusInProgress", TLString: "tasks.taskStatusInProgress#06ef70e7"}, } func TasksTaskStatus__MakeEnum(i int) TasksTaskStatus { return TasksTaskStatus{index: i} } @@ -54,13 +54,13 @@ func (item *TasksTaskStatus) ReadBoxed(w []byte) (_ []byte, err error) { case 0xb207caaa: item.index = 0 return w, nil - case 0xaca80a9: + case 0x0aca80a9: item.index = 1 return w, nil case 0x16739c2c: item.index = 2 return w, nil - case 0x6ef70e7: + case 0x06ef70e7: item.index = 3 return w, nil default: diff --git a/internal/tlcodegen/test/gen/schema/internal/tlunique/tlUniqueStringToInt/unique.stringToInt.go b/internal/tlcodegen/test/gen/schema/internal/tlunique/tlUniqueStringToInt/unique.stringToInt.go index abb060fc..ae23afb6 100644 --- a/internal/tlcodegen/test/gen/schema/internal/tlunique/tlUniqueStringToInt/unique.stringToInt.go +++ b/internal/tlcodegen/test/gen/schema/internal/tlunique/tlUniqueStringToInt/unique.stringToInt.go @@ -20,7 +20,7 @@ type UniqueStringToInt struct { } func (UniqueStringToInt) TLName() string { return "unique.stringToInt" } -func (UniqueStringToInt) TLTag() uint32 { return 0xf766c35 } +func (UniqueStringToInt) TLTag() uint32 { return 0x0f766c35 } func (item *UniqueStringToInt) Reset() { item.Key = "" @@ -41,7 +41,7 @@ func (item *UniqueStringToInt) Write(w []byte) []byte { } func (item *UniqueStringToInt) ReadBoxed(w []byte) (_ []byte, err error) { - if w, err = basictl.NatReadExactTag(w, 0xf766c35); err != nil { + if w, err = basictl.NatReadExactTag(w, 0x0f766c35); err != nil { return w, err } return item.Read(w) @@ -53,7 +53,7 @@ func (item *UniqueStringToInt) WriteBoxedGeneral(w []byte) (_ []byte, err error) } func (item *UniqueStringToInt) WriteBoxed(w []byte) []byte { - w = basictl.NatWrite(w, 0xf766c35) + w = basictl.NatWrite(w, 0x0f766c35) return item.Write(w) } diff --git a/internal/tlcodegen/test/gen/schema/meta/meta.go b/internal/tlcodegen/test/gen/schema/meta/meta.go index 39f0b86a..6c68fb63 100644 --- a/internal/tlcodegen/test/gen/schema/meta/meta.go +++ b/internal/tlcodegen/test/gen/schema/meta/meta.go @@ -90,13 +90,46 @@ func CreateObjectFromName(name string) Object { return nil } +func CreateFunctionBytes(tag uint32) Function { + if item := FactoryItemByTLTagBytes(tag); item != nil && item.createFunctionBytes != nil { + return item.createFunctionBytes() + } + return nil +} + +func CreateObjectBytes(tag uint32) Object { + if item := FactoryItemByTLTagBytes(tag); item != nil && item.createObjectBytes != nil { + return item.createObjectBytes() + } + return nil +} + +// name can be in any of 3 forms "ch_proxy.insert#7cf362ba", "ch_proxy.insert" or "#7cf362ba" +func CreateFunctionFromNameBytes(name string) Function { + if item := FactoryItemByTLNameBytes(name); item != nil && item.createFunctionBytes != nil { + return item.createFunctionBytes() + } + return nil +} + +// name can be in any of 3 forms "ch_proxy.insert#7cf362ba", "ch_proxy.insert" or "#7cf362ba" +func CreateObjectFromNameBytes(name string) Object { + if item := FactoryItemByTLNameBytes(name); item != nil && item.createObjectBytes != nil { + return item.createObjectBytes() + } + return nil +} + type TLItem struct { - tag uint32 - annotations uint32 - tlName string - createFunction func() Function - createFunctionLong func() Function - createObject func() Object + tag uint32 + annotations uint32 + tlName string + createFunction func() Function + createFunctionLong func() Function + createObject func() Object + createFunctionBytes func() Function + createFunctionLongBytes func() Function + createObjectBytes func() Object } func (item TLItem) TLTag() uint32 { return item.tag } @@ -166,10 +199,22 @@ func FactoryItemByTLName(name string) *TLItem { return itemsByName[name] } +func FactoryItemByTLTagBytes(tag uint32) *TLItem { + return itemsBytesByTag[tag] +} + +func FactoryItemByTLNameBytes(name string) *TLItem { + return itemsBytesByName[name] +} + var itemsByTag = map[uint32]*TLItem{} var itemsByName = map[string]*TLItem{} +var itemsBytesByTag = map[uint32]*TLItem{} + +var itemsBytesByName = map[string]*TLItem{} + func SetGlobalFactoryCreateForFunction(itemTag uint32, createObject func() Object, createFunction func() Function, createFunctionLong func() Function) { item := itemsByTag[itemTag] if item == nil { @@ -196,6 +241,40 @@ func SetGlobalFactoryCreateForEnumElement(itemTag uint32) { item.createObject = func() Object { return item } } +func SetGlobalFactoryCreateForFunctionBytes(itemTag uint32, createObject func() Object, createFunction func() Function, createFunctionLong func() Function) { + item := itemsBytesByTag[itemTag] + if item == nil { + panic(fmt.Sprintf("factory cannot find function tag #%08x to set", itemTag)) + } + item.createObjectBytes = createObject + item.createFunctionBytes = createFunction + item.createFunctionLongBytes = createFunctionLong +} + +func SetGlobalFactoryCreateForObjectBytes(itemTag uint32, createObject func() Object) { + item := itemsBytesByTag[itemTag] + if item == nil { + panic(fmt.Sprintf("factory cannot find item tag #%08x to set", itemTag)) + } + item.createObjectBytes = createObject +} + +func SetGlobalFactoryCreateForEnumElementBytes(itemTag uint32) { + item := itemsBytesByTag[itemTag] + if item == nil { + panic(fmt.Sprintf("factory cannot find enum tag #%08x to set", itemTag)) + } + item.createObjectBytes = func() Object { return item } +} + +func pleaseImportFactoryBytesObject() Object { + panic("factory functions are not linked to reduce code bloat, please import 'gen/factory_bytes' instead of 'gen/meta'.") +} + +func pleaseImportFactoryBytesFunction() Function { + panic("factory functions are not linked to reduce code bloat, please import 'gen/factory_bytes' instead of 'gen/meta'.") +} + func pleaseImportFactoryObject() Object { panic("factory functions are not linked to reduce code bloat, please import 'gen/factory' instead of 'gen/meta'.") } @@ -209,7 +288,12 @@ func fillObject(n1 string, n2 string, item *TLItem) { itemsByName[item.tlName] = item itemsByName[n1] = item itemsByName[n2] = item + itemsBytesByTag[item.tag] = item + itemsBytesByName[item.tlName] = item + itemsBytesByName[n1] = item + itemsBytesByName[n2] = item item.createObject = pleaseImportFactoryObject + item.createObjectBytes = pleaseImportFactoryBytesObject // code below is as fast, but allocates some extra strings which are already in binary const segment due to JSON code // itemsByName[fmt.Sprintf("%s#%08x", item.tlName, item.tag)] = item // itemsByName[fmt.Sprintf("#%08x", item.tag)] = item @@ -218,6 +302,7 @@ func fillObject(n1 string, n2 string, item *TLItem) { func fillFunction(n1 string, n2 string, item *TLItem) { fillObject(n1, n2, item) item.createFunction = pleaseImportFactoryFunction + item.createFunctionBytes = pleaseImportFactoryBytesFunction } func init() { @@ -277,7 +362,7 @@ func init() { fillFunction("service1.add#481df8be", "#481df8be", &TLItem{tag: 0x481df8be, annotations: 0x1, tlName: "service1.add"}) fillFunction("service1.addOrGet#6a42faad", "#6a42faad", &TLItem{tag: 0x6a42faad, annotations: 0x1, tlName: "service1.addOrGet"}) fillFunction("service1.addOrIncr#90c4b402", "#90c4b402", &TLItem{tag: 0x90c4b402, annotations: 0x1, tlName: "service1.addOrIncr"}) - fillFunction("service1.append#04dec671", "#04dec671", &TLItem{tag: 0x4dec671, annotations: 0x1, tlName: "service1.append"}) + fillFunction("service1.append#04dec671", "#04dec671", &TLItem{tag: 0x04dec671, annotations: 0x1, tlName: "service1.append"}) fillFunction("service1.cas#51851964", "#51851964", &TLItem{tag: 0x51851964, annotations: 0x1, tlName: "service1.cas"}) fillFunction("service1.decr#eb179ce7", "#eb179ce7", &TLItem{tag: 0xeb179ce7, annotations: 0x1, tlName: "service1.decr"}) fillFunction("service1.delete#83277767", "#83277767", &TLItem{tag: 0x83277767, annotations: 0x1, tlName: "service1.delete"}) @@ -288,26 +373,26 @@ func init() { fillFunction("service1.exists#e0284c9e", "#e0284c9e", &TLItem{tag: 0xe0284c9e, annotations: 0x1, tlName: "service1.exists"}) fillFunction("service1.get#29099b19", "#29099b19", &TLItem{tag: 0x29099b19, annotations: 0x1, tlName: "service1.get"}) fillFunction("service1.getExpireTime#5a731070", "#5a731070", &TLItem{tag: 0x5a731070, annotations: 0x1, tlName: "service1.getExpireTime"}) - fillFunction("service1.getKeysStat#06cecd58", "#06cecd58", &TLItem{tag: 0x6cecd58, annotations: 0x1, tlName: "service1.getKeysStat"}) + fillFunction("service1.getKeysStat#06cecd58", "#06cecd58", &TLItem{tag: 0x06cecd58, annotations: 0x1, tlName: "service1.getKeysStat"}) fillFunction("service1.getKeysStatPeriods#8cdf39e3", "#8cdf39e3", &TLItem{tag: 0x8cdf39e3, annotations: 0x1, tlName: "service1.getKeysStatPeriods"}) fillFunction("service1.getWildcard#2f2abf13", "#2f2abf13", &TLItem{tag: 0x2f2abf13, annotations: 0x1, tlName: "service1.getWildcard"}) fillFunction("service1.getWildcardDict#72bbc81b", "#72bbc81b", &TLItem{tag: 0x72bbc81b, annotations: 0x1, tlName: "service1.getWildcardDict"}) fillFunction("service1.getWildcardList#56b6ead4", "#56b6ead4", &TLItem{tag: 0x56b6ead4, annotations: 0x1, tlName: "service1.getWildcardList"}) fillFunction("service1.getWildcardWithFlags#5f6a1f78", "#5f6a1f78", &TLItem{tag: 0x5f6a1f78, annotations: 0x1, tlName: "service1.getWildcardWithFlags"}) - fillFunction("service1.incr#0f96b56e", "#0f96b56e", &TLItem{tag: 0xf96b56e, annotations: 0x1, tlName: "service1.incr"}) + fillFunction("service1.incr#0f96b56e", "#0f96b56e", &TLItem{tag: 0x0f96b56e, annotations: 0x1, tlName: "service1.incr"}) fillObject("service1.keysStat#f0f6bc68", "#f0f6bc68", &TLItem{tag: 0xf0f6bc68, annotations: 0x0, tlName: "service1.keysStat"}) - fillObject("service1.longvalue#082e0945", "#082e0945", &TLItem{tag: 0x82e0945, annotations: 0x0, tlName: "service1.longvalue"}) + fillObject("service1.longvalue#082e0945", "#082e0945", &TLItem{tag: 0x082e0945, annotations: 0x0, tlName: "service1.longvalue"}) fillObject("service1.longvalueWithTime#a04606ec", "#a04606ec", &TLItem{tag: 0xa04606ec, annotations: 0x0, tlName: "service1.longvalueWithTime"}) fillObject("service1.not_found#1d670b96", "#1d670b96", &TLItem{tag: 0x1d670b96, annotations: 0x0, tlName: "service1.not_found"}) fillFunction("service1.replace#7f2c447d", "#7f2c447d", &TLItem{tag: 0x7f2c447d, annotations: 0x1, tlName: "service1.replace"}) fillFunction("service1.replaceOrIncr#9d1bdcfd", "#9d1bdcfd", &TLItem{tag: 0x9d1bdcfd, annotations: 0x1, tlName: "service1.replaceOrIncr"}) - fillFunction("service1.set#05ae5f66", "#05ae5f66", &TLItem{tag: 0x5ae5f66, annotations: 0x1, tlName: "service1.set"}) + fillFunction("service1.set#05ae5f66", "#05ae5f66", &TLItem{tag: 0x05ae5f66, annotations: 0x1, tlName: "service1.set"}) fillFunction("service1.setOrIncr#772e390d", "#772e390d", &TLItem{tag: 0x772e390d, annotations: 0x1, tlName: "service1.setOrIncr"}) fillObject("service1.strvalue#5faa0c52", "#5faa0c52", &TLItem{tag: 0x5faa0c52, annotations: 0x0, tlName: "service1.strvalue"}) fillObject("service1.strvalueWithTime#98b1a484", "#98b1a484", &TLItem{tag: 0x98b1a484, annotations: 0x0, tlName: "service1.strvalueWithTime"}) fillFunction("service1.touch#b737aa03", "#b737aa03", &TLItem{tag: 0xb737aa03, annotations: 0x1, tlName: "service1.touch"}) fillFunction("service2.addOrIncrMany#5aa52489", "#5aa52489", &TLItem{tag: 0x5aa52489, annotations: 0x2, tlName: "service2.addOrIncrMany"}) - fillFunction("service2.set#0d31f63d", "#0d31f63d", &TLItem{tag: 0xd31f63d, annotations: 0x4, tlName: "service2.set"}) + fillFunction("service2.set#0d31f63d", "#0d31f63d", &TLItem{tag: 0x0d31f63d, annotations: 0x4, tlName: "service2.set"}) fillFunction("service2.setObjectTtl#6f98f025", "#6f98f025", &TLItem{tag: 0x6f98f025, annotations: 0x4, tlName: "service2.setObjectTtl"}) fillFunction("service3.createProduct#b7d92bd9", "#b7d92bd9", &TLItem{tag: 0xb7d92bd9, annotations: 0x1, tlName: "service3.createProduct"}) fillFunction("service3.deleteAllProducts#4494acc2", "#4494acc2", &TLItem{tag: 0x4494acc2, annotations: 0x1, tlName: "service3.deleteAllProducts"}) @@ -332,7 +417,7 @@ func init() { fillObject("service5.emptyOutput#11e46879", "#11e46879", &TLItem{tag: 0x11e46879, annotations: 0x0, tlName: "service5.emptyOutput"}) fillFunction("service5.insert#c911ee2c", "#c911ee2c", &TLItem{tag: 0xc911ee2c, annotations: 0x1, tlName: "service5.insert"}) fillObject("service5.params#12ae5cb5", "#12ae5cb5", &TLItem{tag: 0x12ae5cb5, annotations: 0x0, tlName: "service5.params"}) - fillFunction("service5.performQuery#019d80a5", "#019d80a5", &TLItem{tag: 0x19d80a5, annotations: 0x1, tlName: "service5.performQuery"}) + fillFunction("service5.performQuery#019d80a5", "#019d80a5", &TLItem{tag: 0x019d80a5, annotations: 0x1, tlName: "service5.performQuery"}) fillFunction("service5.query#b3b62513", "#b3b62513", &TLItem{tag: 0xb3b62513, annotations: 0x1, tlName: "service5.query"}) fillObject("service5.stringOutput#179e9863", "#179e9863", &TLItem{tag: 0x179e9863, annotations: 0x0, tlName: "service5.stringOutput"}) fillObject("service6.error#738553ef", "#738553ef", &TLItem{tag: 0x738553ef, annotations: 0x0, tlName: "service6.error"}) @@ -354,15 +439,15 @@ func init() { fillObject("tasks.queueTypeSettings#561fbc09", "#561fbc09", &TLItem{tag: 0x561fbc09, annotations: 0x0, tlName: "tasks.queueTypeSettings"}) fillObject("tasks.queueTypeStats#e1b785f2", "#e1b785f2", &TLItem{tag: 0xe1b785f2, annotations: 0x0, tlName: "tasks.queueTypeStats"}) fillObject("tasks.task#7c23bc2c", "#7c23bc2c", &TLItem{tag: 0x7c23bc2c, annotations: 0x0, tlName: "tasks.task"}) - fillObject("tasks.taskInfo#06f0c6a6", "#06f0c6a6", &TLItem{tag: 0x6f0c6a6, annotations: 0x0, tlName: "tasks.taskInfo"}) - fillObject("tasks.taskStatusInProgress#06ef70e7", "#06ef70e7", &TLItem{tag: 0x6ef70e7, annotations: 0x0, tlName: "tasks.taskStatusInProgress"}) + fillObject("tasks.taskInfo#06f0c6a6", "#06f0c6a6", &TLItem{tag: 0x06f0c6a6, annotations: 0x0, tlName: "tasks.taskInfo"}) + fillObject("tasks.taskStatusInProgress#06ef70e7", "#06ef70e7", &TLItem{tag: 0x06ef70e7, annotations: 0x0, tlName: "tasks.taskStatusInProgress"}) fillObject("tasks.taskStatusNotCurrentlyInEngine#b207caaa", "#b207caaa", &TLItem{tag: 0xb207caaa, annotations: 0x0, tlName: "tasks.taskStatusNotCurrentlyInEngine"}) - fillObject("tasks.taskStatusScheduled#0aca80a9", "#0aca80a9", &TLItem{tag: 0xaca80a9, annotations: 0x0, tlName: "tasks.taskStatusScheduled"}) + fillObject("tasks.taskStatusScheduled#0aca80a9", "#0aca80a9", &TLItem{tag: 0x0aca80a9, annotations: 0x0, tlName: "tasks.taskStatusScheduled"}) fillObject("tasks.taskStatusWaiting#16739c2c", "#16739c2c", &TLItem{tag: 0x16739c2c, annotations: 0x0, tlName: "tasks.taskStatusWaiting"}) fillObject("tree_stats.objectLimitValueDouble#5dfb8816", "#5dfb8816", &TLItem{tag: 0x5dfb8816, annotations: 0x0, tlName: "tree_stats.objectLimitValueDouble"}) fillObject("tree_stats.objectLimitValueLong#73111993", "#73111993", &TLItem{tag: 0x73111993, annotations: 0x0, tlName: "tree_stats.objectLimitValueLong"}) fillObject("true#3fedd339", "#3fedd339", &TLItem{tag: 0x3fedd339, annotations: 0x0, tlName: "true"}) fillFunction("unique.get#ce89bbf2", "#ce89bbf2", &TLItem{tag: 0xce89bbf2, annotations: 0x1, tlName: "unique.get"}) - fillFunction("unique.stringToInt#0f766c35", "#0f766c35", &TLItem{tag: 0xf766c35, annotations: 0x1, tlName: "unique.stringToInt"}) - fillObject("withFloat#071b8685", "#071b8685", &TLItem{tag: 0x71b8685, annotations: 0x0, tlName: "withFloat"}) + fillFunction("unique.stringToInt#0f766c35", "#0f766c35", &TLItem{tag: 0x0f766c35, annotations: 0x1, tlName: "unique.stringToInt"}) + fillObject("withFloat#071b8685", "#071b8685", &TLItem{tag: 0x071b8685, annotations: 0x0, tlName: "withFloat"}) } diff --git a/internal/tlcodegen/test/gen/schema/tlgen2_version.txt b/internal/tlcodegen/test/gen/schema/tlgen2_version.txt index 849df800..e431bfc0 100644 --- a/internal/tlcodegen/test/gen/schema/tlgen2_version.txt +++ b/internal/tlcodegen/test/gen/schema/tlgen2_version.txt @@ -1 +1,4 @@ -tlgen2 version (devel) +tlgen version: (devel) +schema url: +schema commit: +schema version: 0 (1970-01-01 00:00:00 +0000 UTC) diff --git a/internal/tlcodegen/test/tls/goldmaster.tl b/internal/tlcodegen/test/tls/goldmaster.tl index 15d3bcad..ceaf29bc 100644 --- a/internal/tlcodegen/test/tls/goldmaster.tl +++ b/internal/tlcodegen/test/tls/goldmaster.tl @@ -48,7 +48,7 @@ dictionaryFieldAny {k:Type} {v:Type} key:k value:v = DictionaryFieldAny k v; dictionaryAny#1f4c6190 {k:Type} {v:Type} # [(dictionaryFieldAny k v)] = DictionaryAny k v; true = True; // this can be used as void type and serialized to empty array in PHP -useTrue fm:# a:fm.0?true b:fm.1?True c:true d:True = UseTrue; +useTrue#dfdd4180 fm:# a:fm.0?true b:fm.1?True c:true d:True e:fm.2?Bool = UseTrue; // we give warnings for many fields of this kind //---- test bytes version propagation noStr x:int = NoStr; diff --git a/internal/tlcodegen/test/tls/goldmaster_canonical.tl b/internal/tlcodegen/test/tls/goldmaster_canonical.tl index c4560619..3a9b415e 100644 --- a/internal/tlcodegen/test/tls/goldmaster_canonical.tl +++ b/internal/tlcodegen/test/tls/goldmaster_canonical.tl @@ -23,7 +23,7 @@ dictionary#1f4c618f t:Type %Vector %DictionaryField t = Dictionary t // ./inter dictionaryFieldAny#2c43a65b k:Type v:Type key:k value:v = DictionaryFieldAny k v // ./internal/tlcodegen/test/tls/goldmaster.tl dictionaryAny#1f4c6190 k:Type v:Type # [ (dictionaryFieldAny k v) ] = DictionaryAny k v // ./internal/tlcodegen/test/tls/goldmaster.tl true#3fedd339 = True // ./internal/tlcodegen/test/tls/goldmaster.tl -useTrue#dfdd4180 fm:# a:fm.0?true b:fm.1?True c:true d:True = UseTrue // ./internal/tlcodegen/test/tls/goldmaster.tl +useTrue#dfdd4180 fm:# a:fm.0?true b:fm.1?True c:true d:True e:fm.2?Bool = UseTrue // ./internal/tlcodegen/test/tls/goldmaster.tl noStr#3a728324 x:int = NoStr // ./internal/tlcodegen/test/tls/goldmaster.tl useStr#9aa3dee5 x:string = UseStr // ./internal/tlcodegen/test/tls/goldmaster.tl halfStr#647ddaf5 x:noStr y:useStr = HalfStr // ./internal/tlcodegen/test/tls/goldmaster.tl diff --git a/internal/tlcodegen/tlgen.go b/internal/tlcodegen/tlgen.go index 31e7e0cf..fac0c177 100644 --- a/internal/tlcodegen/tlgen.go +++ b/internal/tlcodegen/tlgen.go @@ -8,7 +8,6 @@ package tlcodegen import ( "fmt" - "github.com/google/go-cmp/cmp" "io" "log" "os" @@ -20,11 +19,11 @@ import ( "sync/atomic" "time" - "golang.org/x/exp/slices" - "github.com/TwiN/go-color" - + "github.com/google/go-cmp/cmp" "github.com/vkcom/tl/internal/tlast" + + "golang.org/x/exp/slices" ) const BuiltinTupleName = "__tuple" @@ -310,6 +309,7 @@ type Gen2Options struct { CopyrightFilePath string WarningsAreErrors bool Verbose bool + PrintDiff bool ErrorWriter io.Writer // all Errors and warnings should be redirected to this io.Writer, by default it is os.Stderr SplitInternal bool @@ -526,7 +526,7 @@ func (gen *Gen2) buildMapDescriptors(tl tlast.TL) error { } // We temporarily allow relaxed case match. To use strict match, remove strings.ToLower() calls below if EnableWarningsSimpleTypeName && strings.ToLower(cName.Name) != typePrefix && - !EnableWarningsSimpleTypeNameSkipLegacy(cName.String()) { + !LegacyEnableWarningsSimpleTypeNameSkip(cName.String()) { e1 := typ[0].Construct.NamePR.BeautifulError(fmt.Errorf("simple type constructor name should differ from type name by case only")) e2 := typ[0].TypeDecl.NamePR.BeautifulError(errSeeHere) if gen.options.WarningsAreErrors { @@ -564,7 +564,7 @@ func checkUnionElementsCompatibility(types []*tlast.Combinator, options *Gen2Opt for _, typ := range types { conName := strings.ToLower(typ.Construct.Name.Name) if EnableWarningsUnionNamespace && typ.Construct.Name.Namespace != typ.TypeDecl.Name.Namespace && - !EnableWarningsUnionNamespaceSkipLegacy(typ.Construct.Name.Namespace, typ.TypeDecl.Name.Namespace) { + !LegacyEnableWarningsUnionNamespaceSkip(typ.Construct.Name.Namespace, typ.TypeDecl.Name.Namespace) { e1 := typ.Construct.NamePR.BeautifulError(fmt.Errorf("union constructor namespace %q should match type namespace %q", typ.Construct.Name.Namespace, typ.TypeDecl.Name.Namespace)) e2 := typ.TypeDecl.NamePR.BeautifulError(errSeeHere) if options.WarningsAreErrors { @@ -575,7 +575,7 @@ func checkUnionElementsCompatibility(types []*tlast.Combinator, options *Gen2Opt if EnableWarningsUnionNamePrefix && !strings.HasPrefix(conName, typePrefix) && !strings.HasSuffix(conName, typeSuffix) && - !EnableWarningsUnionNamePrefixSkipLegacy(typ.Construct.Name.Name, typePrefix, typeSuffix) { // same check as in generateType + !LegacyEnableWarningsUnionNamePrefixSkip(typ.Construct.Name.Name, typePrefix, typeSuffix) { // same check as in generateType e1 := typ.Construct.NamePR.BeautifulError(fmt.Errorf("union constructor should have type name prefix or suffix %q", typePrefix)) e2 := typ.TypeDecl.NamePR.BeautifulError(errSeeHere) if options.WarningsAreErrors { @@ -585,7 +585,7 @@ func checkUnionElementsCompatibility(types []*tlast.Combinator, options *Gen2Opt continue } if EnableWarningsUnionNameExact && conName == typePrefix && - !EnableWarningsUnionNameExactSkipLegacy(typ.Construct.Name.String()) { + !LegacyEnableWarningsUnionNameExactSkip(typ.Construct.Name.String()) { e1 := typ.Construct.NamePR.BeautifulError(fmt.Errorf("union constructor name should not exactly match type name %q", typePrefix)) e2 := typ.TypeDecl.PR.BeautifulError(errSeeHere) if options.WarningsAreErrors { @@ -699,7 +699,7 @@ func (gen *Gen2) WriteToDir(outdir string) error { notTouched++ continue } else { - if gen.options.Verbose { + if gen.options.PrintDiff { fmt.Printf("File \"%s\":\n", f) fmt.Println(cmp.Diff(string(was), code)) } @@ -724,6 +724,7 @@ func (gen *Gen2) WriteToDir(outdir string) error { f := filepath.Join(outdir, relativeDirs[i]) _ = os.Remove(f) // non-empty dirs simply will not remove. This is good enough for us } + // do not check Verbose fmt.Printf("%d target files did not change so were not touched, %d written, %d deleted\n", notTouched, written, deleted) return nil } @@ -1056,7 +1057,7 @@ func GenerateCode(tl tlast.TL, options Gen2Options) (*Gen2, error) { gen.typesInfo = processCombinators(gen.allConstructors) for _, typ := range tl { - if GenerateUnusedNatTemplates(typ.Construct.Name.String()) && len(typ.TemplateArguments) == 1 && typ.TemplateArguments[0].IsNat { + if LegacyGenerateUnusedNatTemplates(typ.Construct.Name.String()) && len(typ.TemplateArguments) == 1 && typ.TemplateArguments[0].IsNat { t := tlast.TypeRef{Type: typ.TypeDecl.Name, PR: typ.TypeDecl.PR} argT := tlast.TypeRef{Type: tlast.Name{ Namespace: "", @@ -1105,6 +1106,8 @@ func GenerateCode(tl tlast.TL, options Gen2Options) (*Gen2, error) { } } } + LegacyPrintGlobalMap() + bytesChildren := map[*TypeRWWrapper]bool{} typesCounterMarkBytes := 0 // This loop can be before or after loops below, it is convenient to fill sortedTypes inside, so this loop is here diff --git a/internal/tlcodegen/tlgen_go.go b/internal/tlcodegen/tlgen_go.go index 4bb4ab28..61f1fc83 100644 --- a/internal/tlcodegen/tlgen_go.go +++ b/internal/tlcodegen/tlgen_go.go @@ -167,7 +167,7 @@ var _ = basictl.NatWrite if gen.options.Verbose { log.Printf("generation of serialization code finished, %d constructors processed, %d types generated", len(gen.allConstructors), typesCounter) if len(generateByteVersions) != 0 { - log.Printf(" also generated byte-optimized versions of %d types by the following filter: %s", typesCounterBytes, strings.Join(generateByteVersions, ", ")) + log.Printf(" also generated byte-optimized versions of %d types", typesCounterBytes) } } for name, namespace := range gen.Namespaces { diff --git a/internal/tlcodegen/tlgen_kernel.go b/internal/tlcodegen/tlgen_kernel.go index 7aa6cd9d..476dbf5e 100644 --- a/internal/tlcodegen/tlgen_kernel.go +++ b/internal/tlcodegen/tlgen_kernel.go @@ -519,6 +519,30 @@ func (gen *Gen2) generateTypeStruct(lrc LocalResolveContext, myWrapper *TypeRWWr if err := lrc.checkArgsCollision(field.FieldName, field.PRName, errFieldNameCollision); err != nil { return err } + if newField.t.IsTrueType() && !newField.Bare() && + newField.t.origTL[0].TypeDecl.Name.String() == "True" && + newField.t.origTL[0].Construct.Name.String() == "true" && + !LegacyAllowTrueBoxed(myWrapper.origTL[0].Construct.Name.String(), field.FieldName) { + // We compare type by name, because there is examples of other true types which are to be extended + // to unions or have added fields in the future + e1 := field.FieldType.PR.BeautifulError(fmt.Errorf("true type fields should be bare, use 'true' or '%%True' instead")) + if gen.options.WarningsAreErrors { + return e1 + } + e1.PrintWarning(gen.options.ErrorWriter, nil) + } + if _, ok := newField.t.trw.(*TypeRWBool); ok { + if newField.t.origTL[0].TypeDecl.Name.String() == "Bool" && + newField.fieldMask != nil && !newField.fieldMask.isArith && newField.fieldMask.isField && + !LegacyAllowBoolFieldsmask(myWrapper.origTL[0].Construct.Name.String(), field.FieldName) { + // We compare type by name to make warning more narrow at first. + e1 := field.FieldType.PR.BeautifulError(fmt.Errorf("using Bool type under fields mask produces 3rd state, you probably want to use 'true' instead of 'Bool'")) + if gen.options.WarningsAreErrors { + return e1 + } + e1.PrintWarning(gen.options.ErrorWriter, nil) + } + } lrc.localNatArgs[field.FieldName] = arg } if tlType.IsFunction {