From bd311a3a4fb276b9415aaa2f2c87c9a7480130fe Mon Sep 17 00:00:00 2001 From: Wizou <11647984+wiz0u@users.noreply.github.com> Date: Mon, 2 Mar 2026 16:25:35 +0100 Subject: [PATCH] TLDef.inheritBefore => inheritAt --- generator/MTProtoGenerator.cs | 7 ++-- src/TL.MTProto.cs | 20 +++++------ src/TL.Schema.cs | 66 +++++++++++++++++------------------ src/TL.Secret.cs | 2 +- src/TL.cs | 23 +++++++++--- 5 files changed, 66 insertions(+), 52 deletions(-) diff --git a/generator/MTProtoGenerator.cs b/generator/MTProtoGenerator.cs index f326c13..44c7c35 100644 --- a/generator/MTProtoGenerator.cs +++ b/generator/MTProtoGenerator.cs @@ -112,11 +112,12 @@ public class MTProtoGenerator : IIncrementalGenerator .AppendLine("\t\t{") .AppendLine($"\t\t\twriter.Write(0x{id:X8});"); var members = symbol.GetMembers().ToList(); + int inheritIndex = 0; for (var parent = symbol.BaseType; parent != object_; parent = parent.BaseType) { - var inheritBefore = (bool?)tldef.NamedArguments.FirstOrDefault(k => k.Key == "inheritBefore").Value.Value ?? false; - if (inheritBefore) members.InsertRange(0, parent.GetMembers()); - else members.AddRange(parent.GetMembers()); + var inheritAt = (int?)tldef.NamedArguments.FirstOrDefault(k => k.Key == "inheritAt").Value.Value ?? -1; + if (inheritAt >= 0) members.InsertRange(inheritIndex += inheritAt, parent.GetMembers()); + else { inheritIndex = members.Count; members.AddRange(parent.GetMembers()); } tldef = parent.GetAttributes().FirstOrDefault(a => a.AttributeClass == tlDefAttribute); } foreach (var member in members.OfType()) diff --git a/src/TL.MTProto.cs b/src/TL.MTProto.cs index 4b6e052..de10b70 100644 --- a/src/TL.MTProto.cs +++ b/src/TL.MTProto.cs @@ -25,17 +25,17 @@ namespace TL public Int128 server_nonce; public Int256 new_nonce; } - [TLDef(0xA9F55F95, inheritBefore = true)] //p_q_inner_data_dc#a9f55f95 pq:bytes p:bytes q:bytes nonce:int128 server_nonce:int128 new_nonce:int256 dc:int = P_Q_inner_data + [TLDef(0xA9F55F95, inheritAt = 0)] //p_q_inner_data_dc#a9f55f95 pq:bytes p:bytes q:bytes nonce:int128 server_nonce:int128 new_nonce:int256 dc:int = P_Q_inner_data public sealed partial class PQInnerDataDc : PQInnerData { public int dc; } - [TLDef(0x3C6A84D4, inheritBefore = true)] //p_q_inner_data_temp#3c6a84d4 pq:bytes p:bytes q:bytes nonce:int128 server_nonce:int128 new_nonce:int256 expires_in:int = P_Q_inner_data + [TLDef(0x3C6A84D4, inheritAt = 0)] //p_q_inner_data_temp#3c6a84d4 pq:bytes p:bytes q:bytes nonce:int128 server_nonce:int128 new_nonce:int256 expires_in:int = P_Q_inner_data public sealed partial class PQInnerDataTemp : PQInnerData { public int expires_in; } - [TLDef(0x56FDDF88, inheritBefore = true)] //p_q_inner_data_temp_dc#56fddf88 pq:bytes p:bytes q:bytes nonce:int128 server_nonce:int128 new_nonce:int256 dc:int expires_in:int = P_Q_inner_data + [TLDef(0x56FDDF88, inheritAt = 0)] //p_q_inner_data_temp_dc#56fddf88 pq:bytes p:bytes q:bytes nonce:int128 server_nonce:int128 new_nonce:int256 dc:int expires_in:int = P_Q_inner_data public sealed partial class PQInnerDataTempDc : PQInnerData { public int dc; @@ -57,12 +57,12 @@ namespace TL public Int128 nonce; public Int128 server_nonce; } - [TLDef(0x79CB045D, inheritBefore = true)] //server_DH_params_fail#79cb045d nonce:int128 server_nonce:int128 new_nonce_hash:int128 = Server_DH_Params + [TLDef(0x79CB045D, inheritAt = 0)] //server_DH_params_fail#79cb045d nonce:int128 server_nonce:int128 new_nonce_hash:int128 = Server_DH_Params public sealed partial class ServerDHParamsFail : ServerDHParams { public Int128 new_nonce_hash; } - [TLDef(0xD0E8075C, inheritBefore = true)] //server_DH_params_ok#d0e8075c nonce:int128 server_nonce:int128 encrypted_answer:bytes = Server_DH_Params + [TLDef(0xD0E8075C, inheritAt = 0)] //server_DH_params_ok#d0e8075c nonce:int128 server_nonce:int128 encrypted_answer:bytes = Server_DH_Params public sealed partial class ServerDHParamsOk : ServerDHParams { public byte[] encrypted_answer; @@ -93,17 +93,17 @@ namespace TL public Int128 nonce; public Int128 server_nonce; } - [TLDef(0x3BCBF734, inheritBefore = true)] //dh_gen_ok#3bcbf734 nonce:int128 server_nonce:int128 new_nonce_hash1:int128 = Set_client_DH_params_answer + [TLDef(0x3BCBF734, inheritAt = 0)] //dh_gen_ok#3bcbf734 nonce:int128 server_nonce:int128 new_nonce_hash1:int128 = Set_client_DH_params_answer public sealed partial class DhGenOk : SetClientDHParamsAnswer { public Int128 new_nonce_hash1; } - [TLDef(0x46DC1FB9, inheritBefore = true)] //dh_gen_retry#46dc1fb9 nonce:int128 server_nonce:int128 new_nonce_hash2:int128 = Set_client_DH_params_answer + [TLDef(0x46DC1FB9, inheritAt = 0)] //dh_gen_retry#46dc1fb9 nonce:int128 server_nonce:int128 new_nonce_hash2:int128 = Set_client_DH_params_answer public sealed partial class DhGenRetry : SetClientDHParamsAnswer { public Int128 new_nonce_hash2; } - [TLDef(0xA69DAE02, inheritBefore = true)] //dh_gen_fail#a69dae02 nonce:int128 server_nonce:int128 new_nonce_hash3:int128 = Set_client_DH_params_answer + [TLDef(0xA69DAE02, inheritAt = 0)] //dh_gen_fail#a69dae02 nonce:int128 server_nonce:int128 new_nonce_hash3:int128 = Set_client_DH_params_answer public sealed partial class DhGenFail : SetClientDHParamsAnswer { public Int128 new_nonce_hash3; @@ -130,7 +130,7 @@ namespace TL public int bad_msg_seqno; public int error_code; } - [TLDef(0xEDAB447B, inheritBefore = true)] //bad_server_salt#edab447b bad_msg_id:long bad_msg_seqno:int error_code:int new_server_salt:long = BadMsgNotification + [TLDef(0xEDAB447B, inheritAt = 0)] //bad_server_salt#edab447b bad_msg_id:long bad_msg_seqno:int error_code:int new_server_salt:long = BadMsgNotification public sealed partial class BadServerSalt : BadMsgNotification { public long new_server_salt; @@ -267,7 +267,7 @@ namespace TL public int ipv4; public int port; } - [TLDef(0x37982646, inheritBefore = true)] //ipPortSecret#37982646 ipv4:int port:int secret:bytes = IpPort + [TLDef(0x37982646, inheritAt = 0)] //ipPortSecret#37982646 ipv4:int port:int secret:bytes = IpPort public sealed partial class IpPortSecret : IpPort { public byte[] secret; diff --git a/src/TL.Schema.cs b/src/TL.Schema.cs index e0f1216..e5d7470 100644 --- a/src/TL.Schema.cs +++ b/src/TL.Schema.cs @@ -2732,7 +2732,7 @@ namespace TL [TLDef(0xEBBCA3CB)] public sealed partial class MessageActionChatJoinedByRequest : MessageAction { } /// Data from an opened reply keyboard bot mini app was relayed to the bot that owns it (bot side service message). See - [TLDef(0x47DD8079, inheritBefore = true)] + [TLDef(0x47DD8079, inheritAt = 0)] public sealed partial class MessageActionWebViewDataSentMe : MessageActionWebViewDataSent { /// Relayed data. @@ -4401,7 +4401,7 @@ namespace TL } /// Affected part of communication history with the user or in a chat. See - [TLDef(0xB45C69D1, inheritBefore = true)] + [TLDef(0xB45C69D1, inheritAt = 0)] public partial class Messages_AffectedHistory : Messages_AffectedMessages { /// If a parameter contains positive value, it is necessary to repeat the method call using the given value; during the proceeding of all the history the value itself shall gradually decrease @@ -4531,7 +4531,7 @@ namespace TL } } /// The user is preparing a message in a group; typing, recording, uploading, etc. This update is valid for 6 seconds. If no further updates of this kind are received after 6 seconds, it should be considered that the user stopped doing whatever they were doing See - [TLDef(0x83487AF0, inheritBefore = true)] + [TLDef(0x83487AF0, inheritAt = 0)] public sealed partial class UpdateChatUserTyping : UpdateChat { /// Peer that started typing (can be the chat itself, in case of anonymous admins). @@ -4547,14 +4547,14 @@ namespace TL public ChatParticipantsBase participants; } /// Contact status update. See - [TLDef(0xE5BDF8DE, inheritBefore = true)] + [TLDef(0xE5BDF8DE, inheritAt = 0)] public sealed partial class UpdateUserStatus : UpdateUser { /// New status public UserStatus status; } /// Changes the user's first name, last name and username. See - [TLDef(0xA7848924, inheritBefore = true)] + [TLDef(0xA7848924, inheritAt = 0)] public sealed partial class UpdateUserName : UpdateUser { /// New first name. Corresponds to the new value of real_first_name field of the . @@ -4625,7 +4625,7 @@ namespace TL public DateTime date; } /// New group member. See - [TLDef(0x3DDA5451, inheritBefore = true)] + [TLDef(0x3DDA5451, inheritAt = 0)] public sealed partial class UpdateChatParticipantAdd : UpdateChat { /// ID of the new member @@ -4638,7 +4638,7 @@ namespace TL public int version; } /// A member has left the group. See - [TLDef(0xE32F3D77, inheritBefore = true)] + [TLDef(0xE32F3D77, inheritAt = 0)] public sealed partial class UpdateChatParticipantDelete : UpdateChat { /// ID of the user @@ -4699,7 +4699,7 @@ namespace TL public PrivacyRule[] rules; } /// A user's phone number was changed See - [TLDef(0x05492A13, inheritBefore = true)] + [TLDef(0x05492A13, inheritAt = 0)] public sealed partial class UpdateUserPhone : UpdateUser { /// New phone number @@ -4861,7 +4861,7 @@ namespace TL public override void SetPTS(int new_pts, int new_pts_count) => (pts, pts_count) = (new_pts, new_pts_count); } /// The view counter of a message in a channel has changed See - [TLDef(0xF226AC08, inheritBefore = true)] + [TLDef(0xF226AC08, inheritAt = 0)] public sealed partial class UpdateChannelMessageViews : UpdateChannel { /// ID of the message @@ -4870,7 +4870,7 @@ namespace TL public int views; } /// Admin permissions of a user in a basic group were changed See - [TLDef(0xD7CA61A2, inheritBefore = true)] + [TLDef(0xD7CA61A2, inheritAt = 0)] public sealed partial class UpdateChatParticipantAdmin : UpdateChat { /// ID of the (de)admined user @@ -5254,7 +5254,7 @@ namespace TL [TLDef(0x7084A7BE)] public sealed partial class UpdateContactsReset : Update { } /// The history of a channel/supergroup was hidden. See - [TLDef(0xB23FC698, inheritBefore = true)] + [TLDef(0xB23FC698, inheritAt = 0)] public sealed partial class UpdateChannelAvailableMessages : UpdateChannel { /// Identifier of a maximum unavailable message in a channel due to hidden history. @@ -5437,7 +5437,7 @@ namespace TL public byte[] data; } /// The forward counter of a message in a channel has changed See - [TLDef(0xD29A27F4, inheritBefore = true)] + [TLDef(0xD29A27F4, inheritAt = 0)] public sealed partial class UpdateChannelMessageForwards : UpdateChannel { /// ID of the message @@ -5836,7 +5836,7 @@ namespace TL [TLDef(0xFB4C496C)] public sealed partial class UpdateReadFeaturedEmojiStickers : Update { } /// The emoji status of a certain user has changed See - [TLDef(0x28373599, inheritBefore = true)] + [TLDef(0x28373599, inheritAt = 0)] public sealed partial class UpdateUserEmojiStatus : UpdateUser { /// New emoji status @@ -5946,7 +5946,7 @@ namespace TL public override void SetPTS(int new_qts, int _) => qts = new_qts; } /// Users may also choose to display messages from all topics as if they were sent to a normal group, using a "View as messages" setting in the local client.
This setting only affects the current account, and is synced to other logged in sessions using the Channels_ToggleViewForumAsMessages method; invoking this method will update the value of the view_forum_as_messages flag of or and emit an . See
- [TLDef(0x07B68920, inheritBefore = true)] + [TLDef(0x07B68920, inheritAt = 0)] public sealed partial class UpdateChannelViewForumAsMessages : UpdateChannel { /// The new value of the toggle. @@ -6080,7 +6080,7 @@ namespace TL public MessageBase message; } /// One or more messages in a quick reply shortcut ยป were deleted. See - [TLDef(0x566FE7CD, inheritBefore = true)] + [TLDef(0x566FE7CD, inheritAt = 0)] public sealed partial class UpdateDeleteQuickReplyMessages : UpdateDeleteQuickReply { /// IDs of the deleted messages. @@ -7272,7 +7272,7 @@ namespace TL public DateTime date; } /// Message with a file enclosure sent to a protected chat See - [TLDef(0x9493FF32, inheritBefore = true)] + [TLDef(0x9493FF32, inheritAt = 0)] public sealed partial class Messages_SentEncryptedFile : Messages_SentEncryptedMessage { /// Attached file @@ -9026,28 +9026,28 @@ namespace TL [TLDef(0x28A20571)] public sealed partial class MessageEntityCode : MessageEntity { } /// Message entity representing a preformatted codeblock, allowing the user to specify a programming language for the codeblock. See - [TLDef(0x73924BE0, inheritBefore = true)] + [TLDef(0x73924BE0, inheritAt = 0)] public sealed partial class MessageEntityPre : MessageEntity { /// Programming language of the code public string language; } /// Message entity representing a text url: for in-text urls like https://google.com use . See - [TLDef(0x76A6D327, inheritBefore = true)] + [TLDef(0x76A6D327, inheritAt = 0)] public sealed partial class MessageEntityTextUrl : MessageEntity { /// The actual URL public string url; } /// Message entity representing a user mention: for creating a mention use . See - [TLDef(0xDC7B1140, inheritBefore = true)] + [TLDef(0xDC7B1140, inheritAt = 0)] public sealed partial class MessageEntityMentionName : MessageEntity { /// Identifier of the user that was mentioned public long user_id; } /// Message entity that can be used to create a user user mention: received mentions use the , instead. See - [TLDef(0x208E68C9, inheritBefore = true)] + [TLDef(0x208E68C9, inheritAt = 0)] public sealed partial class InputMessageEntityMentionName : MessageEntity { /// Identifier of the user that was mentioned @@ -9072,7 +9072,7 @@ namespace TL [TLDef(0x32CA960F)] public sealed partial class MessageEntitySpoiler : MessageEntity { } /// Represents a custom emoji.
Note that this entity must wrap exactly one regular emoji (the one contained in .alt) in the related text, otherwise the server will ignore it. See
- [TLDef(0xC8CF05F8, inheritBefore = true)] + [TLDef(0xC8CF05F8, inheritAt = 0)] public sealed partial class MessageEntityCustomEmoji : MessageEntity { /// Document ID of the custom emoji, use Messages_GetCustomEmojiDocuments to fetch the emoji animation and the actual emoji it represents. @@ -12993,28 +12993,28 @@ namespace TL [TLDef(0x46E1D13D)] public sealed partial class RecentMeUrlUnknown : RecentMeUrl { } /// Recent t.me link to a user See - [TLDef(0xB92C09E2, inheritBefore = true)] + [TLDef(0xB92C09E2, inheritAt = 0)] public sealed partial class RecentMeUrlUser : RecentMeUrl { /// User ID public long user_id; } /// Recent t.me link to a chat See - [TLDef(0xB2DA71D2, inheritBefore = true)] + [TLDef(0xB2DA71D2, inheritAt = 0)] public sealed partial class RecentMeUrlChat : RecentMeUrl { /// Chat ID public long chat_id; } /// Recent t.me invite link to a chat See - [TLDef(0xEB49081D, inheritBefore = true)] + [TLDef(0xEB49081D, inheritAt = 0)] public sealed partial class RecentMeUrlChatInvite : RecentMeUrl { /// Chat invitation public ChatInviteBase chat_invite; } /// Recent t.me stickerset installation URL See - [TLDef(0xBC0A57DC, inheritBefore = true)] + [TLDef(0xBC0A57DC, inheritAt = 0)] public sealed partial class RecentMeUrlStickerSet : RecentMeUrl { /// Stickerset @@ -13881,14 +13881,14 @@ namespace TL public string num; } /// Ordered list of text items See - [TLDef(0x5E068047, inheritBefore = true)] + [TLDef(0x5E068047, inheritAt = 0)] public sealed partial class PageListOrderedItemText : PageListOrderedItem { /// Text public RichText text; } /// Ordered list of IV blocks See - [TLDef(0x98DD8936, inheritBefore = true)] + [TLDef(0x98DD8936, inheritAt = 0)] public sealed partial class PageListOrderedItemBlocks : PageListOrderedItem { /// Item contents @@ -15864,7 +15864,7 @@ namespace TL } /// Messages found and affected by changes See - [TLDef(0xEF8D3E6C, inheritBefore = true)] + [TLDef(0xEF8D3E6C, inheritAt = 0)] public sealed partial class Messages_AffectedFoundMessages : Messages_AffectedHistory { /// Affected message IDs @@ -16077,7 +16077,7 @@ namespace TL [TLDef(0x3FD863D1)] public sealed partial class BotCommandScopePeerAdmins : BotCommandScopePeer { } /// The specified bot commands will be valid only for a specific user in the specified group or supergroup. See - [TLDef(0x0A1321F3, inheritBefore = true)] + [TLDef(0x0A1321F3, inheritAt = 0)] public sealed partial class BotCommandScopePeerUser : BotCommandScopePeer { /// The user @@ -17366,7 +17366,7 @@ namespace TL public string email; } /// The email was verified correctly, and a login code was just sent to it. See - [TLDef(0xE1BB0D61, inheritBefore = true)] + [TLDef(0xE1BB0D61, inheritAt = 0)] public sealed partial class Account_EmailVerifiedLogin : Account_EmailVerified { /// Info about the sent login code @@ -22484,13 +22484,13 @@ namespace TL public DataJSON client_data; } /// See - [TLDef(0x3E63935C, inheritBefore = true)] + [TLDef(0x3E63935C, inheritAt = 0)] public sealed partial class InputPasskeyResponseRegister : InputPasskeyResponse { public byte[] attestation_data; } /// See - [TLDef(0xC31FC14A, inheritBefore = true)] + [TLDef(0xC31FC14A, inheritAt = 0)] public sealed partial class InputPasskeyResponseLogin : InputPasskeyResponse { public byte[] authenticator_data; @@ -22532,7 +22532,7 @@ namespace TL public int duration; } /// See - [TLDef(0x0AA021E5, inheritBefore = true)] + [TLDef(0x0AA021E5, inheritAt = 0)] public sealed partial class StarGiftAuctionRoundExtendable : StarGiftAuctionRound { public int extend_top; diff --git a/src/TL.Secret.cs b/src/TL.Secret.cs index 0bc2a97..4988782 100644 --- a/src/TL.Secret.cs +++ b/src/TL.Secret.cs @@ -571,7 +571,7 @@ namespace TL } /// Message entity representing a user mention: for creating a mention use . See - [TLDef(0x352DCA58, inheritBefore = true)] + [TLDef(0x352DCA58, inheritAt = 0)] public sealed partial class MessageEntityMentionName : MessageEntity { /// Identifier of the user that was mentioned diff --git a/src/TL.cs b/src/TL.cs index 0bb4583..2f12b19 100644 --- a/src/TL.cs +++ b/src/TL.cs @@ -24,7 +24,7 @@ namespace TL public sealed class TLDefAttribute(uint ctorNb) : Attribute { public readonly uint CtorNb = ctorNb; - public bool inheritBefore; + public int inheritAt = -1; } [AttributeUsage(AttributeTargets.Field)] @@ -68,8 +68,7 @@ namespace TL var tlDef = type.GetCustomAttribute(); var ctorNb = tlDef.CtorNb; writer.Write(ctorNb); - IEnumerable fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public); - if (tlDef.inheritBefore) fields = fields.GroupBy(f => f.DeclaringType).Reverse().SelectMany(g => g); + var fields = GetTLFields(type, tlDef); ulong flags = 0; IfFlagAttribute ifFlag; foreach (var field in fields) @@ -98,8 +97,7 @@ namespace TL if (type == null) return null; // nullable ctor (class meaning is associated with null) var tlDef = type.GetCustomAttribute(); var obj = Activator.CreateInstance(type, true); - IEnumerable fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public); - if (tlDef.inheritBefore) fields = fields.GroupBy(f => f.DeclaringType).Reverse().SelectMany(g => g); + var fields = GetTLFields(type, tlDef); ulong flags = 0; IfFlagAttribute ifFlag; foreach (var field in fields) @@ -115,6 +113,16 @@ namespace TL #endif } +#if !MTPG + static IEnumerable GetTLFields(Type type, TLDefAttribute tlDef) + { + if (!(tlDef?.inheritAt >= 0)) return type.GetFields(BindingFlags.Instance | BindingFlags.Public); + var fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly); + if (type.IsAbstract || type.BaseType == typeof(IObject)) return fields; + var subfields = GetTLFields(type.BaseType, type.BaseType.GetCustomAttribute()); + return fields.Take(tlDef.inheritAt).Concat(subfields).Concat(fields.Skip(tlDef.inheritAt)); + } +#else public static IMethod ReadTLMethod(this BinaryReader reader) { uint ctorNb = reader.ReadUInt32(); @@ -125,6 +133,7 @@ namespace TL method = new BoolMethod { query = method }; return (IMethod)method; } +#endif internal static void WriteTLValue(this BinaryWriter writer, object value, Type valueType) { @@ -490,6 +499,10 @@ namespace TL public sealed class BoolMethod : IMethod { public IObject query; +#if MTPG public void WriteTL(BinaryWriter writer) => query.WriteTL(writer); +#else + public void WriteTL(BinaryWriter writer) => writer.WriteTLObject(query); +#endif } }