рдбреА рдореЗрдВ рд╕рдВрджреЗрд╢ рдкреНрд░реЗрд╖рдг

рдХрдИ рдЧреЗрдо рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЛ рдХреНрд▓рд╛рдЗрдВрдЯ-рд╕рд░реНрд╡рд░ рд╕рдВрдЪрд╛рд░ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдФрд░ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рдирд╛ рдкрдбрд╝рддрд╛ рд╣реИ, рдЦрд╛рд╕рдХрд░ рдпрджрд┐ рд╡реЗ рд╕реЙрдХреЗрдЯреНрд╕ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдкрдиреА рдмрд╛рдЗрдХ рд▓рд┐рдЦрддреЗ рд╣реИрдВред рдиреАрдЪреЗ рдореИрдВ рдЖрд╡реЗрджрди рдХреЗ рдЙрдкрдпреЛрдЧ рдФрд░ рд╕реНрдХреЗрд▓рд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рд╕рдорд╕реНрдпрд╛ рдХреЛ рдпрдерд╛рд╕рдВрднрд╡ рд╕реБрд░реБрдЪрд┐рдкреВрд░реНрдг рдФрд░ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рддрд░реАрдХреЗ рд╕реЗ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рдЕрдкрдиреЗ рдкреНрд░рдпрд╛рд╕ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░реВрдВрдЧрд╛ред рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдХреЛрдб рдкреАрдврд╝реА рдХреЗ рд╕рд╛рде рдХрдИ рд╕рдВрдХрд▓рди-рдЯрд╛рдЗрдо-рдП рд╣реЛрдВрдЧреЗ, рдзреАрд░реЗ-рдзреАрд░реЗ рд░рди-рдЯрд╛рдЗрдо рдХреЗ рдЪреБрдЯрдХреА рдХреЗ рд╕рд╛рде рдЕрдиреБрднрд╡реАред

рд╕рдорд╕реНрдпрд╛ рдХрд╛ рдмрдпрд╛рди


рдХреНрд▓рд╛рдЗрдВрдЯ рдФрд░ рд╕рд░реНрд╡рд░ рд▓рдЧрд╛рддрд╛рд░ рд╕рдВрджреЗрд╢реЛрдВ рдХрд╛ рдЖрджрд╛рди-рдкреНрд░рджрд╛рди рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЗрди рд╕рдВрджреЗрд╢реЛрдВ рдХреЛ рдкрд╣рд▓реЗ рддреИрдпрд╛рд░ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдЕрдЧреНрд░реЗрд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдФрд░ рдлрд┐рд░ рдкрдардиреАрдп рд░реВрдк рдореЗрдВ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рд╕рдВрдХреНрд╖рд┐рдкреНрдд рдЪрд┐рддреНрд░ рдиреАрдЪреЗ:



рд╕рдВрджреЗрд╢ рдХреЛ рдкрдврд╝рдиреЗ рдФрд░ рдбрд┐рд╕реЗрд░рд┐рдПрд▓рд╛рдЗрдЬрд╝реЗрд╢рди рдХреЗ рдЪрд░рдг рдХреЗ рдмреАрдЪ рдореБрдЦреНрдп рд╕рдорд╕реНрдпрд╛ рдЙрддреНрдкрдиреНрди рд╣реЛрддреА рд╣реИ, рд░рд┐рд╕реАрд╡рд░ рдкрд░ рдмрд╛рдЗрдЯреНрд╕ рдХреА рдПрдХ рдзрд╛рд░рд╛ рдЖрддреА рд╣реИ, рдФрд░ рд╕рд╣реА рдбрд┐рд╕реЗрд░рд┐рдПрд▓рд╛рдЗрдЬрд╝реЗрд╢рди рдХреЗ рд▓рд┐рдП рдЖрдкрдХреЛ рд╕рдВрджреЗрд╢ рдХреА рд╕рдВрд░рдЪрдирд╛, рдпрд╛рдиреА рдкреНрд░рдХрд╛рд░ рдХреЛ рдЬрд╛рдирдирд╛ рд╣реЛрдЧрд╛ред рд╕рднреА рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рдВрдЪрд╛рд▓рди рд╕рдВрдХрд▓рд┐рдд рд╕рдордп рдореЗрдВ рд╕рдорд╛рдкреНрдд рд╣реЛ рдЧрдП рдФрд░ рдЕрдм рд╣рдореЗрдВ рд╕рдВрдХрд▓рдХ рдХреА рдорджрдж рдирд╣реАрдВ рдорд┐рд▓реА рд╣реИред рдмрд╣реБрдд рдкрд╣рд▓реЗ, рд╕рдмрд╕реЗ рдХреНрд░реВрд░ рдирд┐рд░реНрдгрдп рдЬреЛ рдорди рдореЗрдВ рдЖрддрд╛ рд╣реИ рд╡рд╣ рдПрдХ рд╡рд┐рд╢рд╛рд▓ рд╕реНрд╡рд┐рдЪ рд▓рд┐рдЦрдирд╛ рд╣реИ рдЬреЛ рд╕рдВрджреЗрд╢ рдЖрдИрдбреА рдХреЛ рдмрд╛рдВрдзрддрд╛ рд╣реИ рдФрд░ рд╕рдВрджреЗрд╢ рдХреЛ рдЕрдирдкреИрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИред рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рд╕рдордЭрд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рддреЗ рд╕рдордп рдпрд╣ рдирд┐рд░реНрдгрдп рд╕рд┐рд░рджрд░реНрдж рдХреНрдпреЛрдВ рд╣реЛрддрд╛ рд╣реИ рдФрд░ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдбрд╝реА рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдореБрд╢реНрдХрд┐рд▓ рд╣реИред рд╣рдо рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рдорд╛рдзрд╛рди рдХрд░реЗрдВрдЧреЗред

рдкрд╣рд▓реЗ рдЖрдкрдХреЛ рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ рдХрд┐ рд╣рдо рдХреНрдпрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ:


рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ


рд╣рдорд╛рд░реА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдзрд╛рд░рд╛рд╡рд╛рд╣рд┐рдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреА рд╣реИ, рдЬреЛ рд╕рдХреНрд░рд┐рдп рд░реВрдк рд╕реЗ рд╕рдВрдХрд▓рди-рд╕рдордп рдХрд╛ рднреА рдЙрдкрдпреЛрдЧ рдХрд░рддреА рд╣реИ (рдпрд╣ рдПрдХ рдЕрд▓рдЧ рдкреЛрд╕реНрдЯ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд┐рд╖рдп рд╣реИ)ред рд╣рдо рд╕рд╣рдордд рд╣реИрдВ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рдмреНрд▓реИрдХ рдмреЙрдХреНрд╕ рд╣реИ рдЬреЛ рдЗрди рдХреЙрд▓ рдХреЗ рд╕рд╛рде рд╡рд░реНрдЧреЛрдВ рдФрд░ рдЙрдирдХреЗ рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЛ рдмрд╛рдЗрдЯреНрд╕ рдореЗрдВ рдЕрдиреБрд╡рд╛рдж рдХрд░ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рдЗрд╕рдХреЗ рд╡рд┐рдкрд░реАрдд:

 auto stream = serialize!(ByteBackend)(SomeObject, "name"); auto object = deserialize!(ByteBackend, SomeClass)(stream, "name"); 


рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдкреНрд░рд╕реНрддреБрддрд┐ рдХреА рд╕рд╛рджрдЧреА рдХреЗ рд▓рд┐рдП, рд╣рдо рднреЛрд▓реЗрдкрди рд╕реЗ рдпрд╣ рдорд╛рдиреЗрдВрдЧреЗ рдХрд┐ рд╕рдВрджреЗрд╢ рдПрдиреНрдХреНрд░рд┐рдкреНрдЯ рдирд╣реАрдВ рдХрд┐рдП рдЧрдП рд╣реИрдВ рдФрд░ рдзрд╛рд░рд╛рд╡рд╛рд╣рд┐рдХ рд╕рднреА рд╕реБрд░рдХреНрд╖рд╛ рд╕рдорд╕реНрдпрд╛рдУрдВ рдХрд╛ рд╣рд▓ рдХрд░рддрд╛ рд╣реИ, рдпрджрд┐ рд╕рдВрджреЗрд╢ рдШреЛрд╖рд┐рдд рд╕рдВрд░рдЪрдирд╛ рд╕реЗ рдореЗрд▓ рдирд╣реАрдВ рдЦрд╛рддрд╛ рд╣реИ, рддреЛ рдПрдХ рдЕрдкрд╡рд╛рдж рдлреЗрдВрдХ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рд╣рдо рд╕рдорд╕реНрдпрд╛ рд╕рдВрджреЗрд╢ рдХреА рдЙрдкреЗрдХреНрд╖рд╛ рдХрд░рддреЗ рд╣реИрдВред

рдЖрдЧреЗ рдЬрд╛рдиреЗ рд╡рд╛рд▓рд╛ рд╕рднреА рдХреЛрдб dmd 2.060 рдкрд░ рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ рдФрд░ рд╕рдВрднрд╡рдд: 2.059 (рдПрдХ рдмрд╣реБрдд рд╣реА рдЕрдкреНрд░рд┐рдп рдмрдЪрдкрди рдХреА рдмреАрдорд╛рд░реА D2) рдкрд░ рд╕рдВрдХрд▓рд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

рд╕рдВрджреЗрд╢реЛрдВ


рдкреНрд░рддреНрдпреЗрдХ рд╕рдВрджреЗрд╢ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рд╡рд░реНрдЧ рд╣реЛрддрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдПрдХ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рдСрдкрд░реЗрдЯрд░ рд╣реЛрддрд╛ рд╣реИ рдЬреЛ рдЕрдзрд┐рднрд╛рд░рд┐рдд рд╣реЛрддрд╛ рд╣реИ рдФрд░ рдЬрд┐рд╕рдореЗрдВ рдмрд┐рдирд╛ рдкреИрд░рд╛рдореАрдЯрд░ (рдбрд┐рд╕рд┐рдПрд░рд▓рд╛рдЗрдЬреЗрд╢рди рдХреЗ рд▓рд┐рдП рдПрдХ рдЖрд╡рд╢реНрдпрдХрддрд╛) рдХреЗ рд╕рд╛рде рдПрдХ рдирд┐рд░реНрдорд╛рдг рд╣реЛрддрд╛ рд╣реИред рдкрд╣рд▓реА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреЛ рдФрдкрдЪрд╛рд░рд┐рдХ рдмрдирд╛рдирд╛ рдЖрд╕рд╛рди рд╣реИ, рдХрд┐рд╕реА рднреА рд╕рдВрджреЗрд╢ рдХреЛ рдЗрд╕ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП:

рдХреЛрдб
 interface Message { void opCall(); } 

рд╕рдВрджреЗрд╢ рдЙрджрд╛рд╣рд░рдг:
  class AMsg : Message { int a; string b; this() {} this(int pa, string pb) { a = pa; b = pb; } void opCall() { writeln("AMsg call with ", a, " ", b); } } 



рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдПрдХ рд╕рдВрджреЗрд╢ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдФрд░ рдиреАрдЪреЗ рдХреЗ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рдмрд┐рдирд╛ рдПрдХ рдирд┐рд░реНрдорд╛рдгрдХрд░реНрддрд╛ рдХреА рдЙрдкрд╕реНрдерд┐рддрд┐ рдХреЗ рд▓рд┐рдП рдЬрд╛рдБрдЪ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рджреВрд╕рд░реЗ рдирд┐рд░реНрдорд╛рддрд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред

рдЬрд╛рджреВ рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░реЛ


C ++ рдореЗрдВ, рдореИрдВ рдЯреЗрдореНрдкреНрд▓реЗрдЯреЗрдб рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд╕рд╛рде рдХрдИ, рдХрдИ рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ, рд▓реЗрдХрд┐рди рдбреА рдореЗрдВ рд╕рдВрдХрд▓рди-рд╕рдордп рдореЗрдВ рдХреЛрдб рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреЗ рдЕрдиреНрдп рддрд░реАрдХреЗ рд╣реИрдВред рдореИрдВ рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдФрд░ рдорд┐рдХреНрд╕рд┐рдВрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реВрдВрдЧрд╛ рддрд╛рдХрд┐ рдЬрд┐рддрдирд╛ рд╕рдВрднрд╡ рд╣реЛ рд╕рдХреЗ рдХрдо-рд╕рдордп рдХреЛрдб рдирд┐рд╖реНрдкрд╛рджрди рдпреЛрдЧреНрдп рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд╡реНрдпрд╡рд╕реНрдерд┐рдд рд╣реЛ рдЬрд╛рдПред рдХреБрд▓ рдорд┐рд▓рд╛рдХрд░, рд╕рднреА рдХреЛрдб рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдорд┐рд╢реНрд░рдг рдореЗрдВ рд╣реЛрдВрдЧреЗ, рдЗрд╕реЗ рдЖрд╕рд╛рдиреА рд╕реЗ рдХрд┐рд╕реА рдЕрдиреНрдп рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ рдпрд╛ рдЙрд╕реА рдХреЗ рдХрд┐рд╕реА рдЕрдиреНрдп рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

 mixin template ProtocolPool(IndexType, SerializerBackend, pairs...) { } 


IndexType рдЗрдВрдбреЗрдХреНрд╕ рдХрд╛ рдкреНрд░рдХрд╛рд░ рд╣реИ рдЬрд┐рд╕рдХрд╛ рд╣рдо рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред SerializerBackend рдзрд╛рд░рд╛рд╡рд╛рд╣рд┐рдХ рдХреЗ рд▓рд┐рдП рдмреИрдХрдПрдВрдб рд╣реИ, рдпрд╣ рдХрд╛рдлреА рд╕рдВрднрд╡ рд╣реИ рдХрд┐ рдХрд┐рд╕реА рдЕрдиреНрдп рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдХреЗ рд▓рд┐рдП рдмрд╛рдЗрдЯреНрд╕ рдореЗрдВ рдХреНрд░рдорд╛рдВрдХрди рдХрд╛ рдПрдХ рдЕрдиреНрдп рддрдВрддреНрд░ рдпрд╛ рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдмрд╛рдЗрдЯреНрд╕ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди xml / json рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

рдЬреЛрдбрд╝реЗ ... - рд╕рдмрд╕реЗ рджрд┐рд▓рдЪрд╕реНрдк рдкреИрд░рд╛рдореАрдЯрд░, рдЬреЛрдбрд╝реЗ рдпрд╣рд╛рдВ рд▓рд┐рдЦреЗ рдЬрд╛рдПрдВрдЧреЗ: рдЖрдИрдбреА рдФрд░ рд╕рдВрджреЗрд╢ рдкреНрд░рдХрд╛рд░ред рдиреАрдЪреЗ рдЙрджрд╛рд╣рд░рдг:

  mixin ProtocolPool!(int, BinaryBackend, 0, AMsg, 1, BMsg, 2, CMsg ); 


рд╣реИрдВрдбрд▓рд┐рдВрдЧ рдореЗрдВ рддреНрд░реБрдЯрд┐

рд▓реЗрдХрд┐рди рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЬреЛрдбрд╝реЗ рдореЗрдВ рдХреБрдЫ рднреА рд░рдЯрдирд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЗрд╕ рдирд╛рдЬреБрдХ рд╕рдордЭреМрддреЗ рдХрд╛ рдЙрд▓реНрд▓рдВрдШрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдлрд┐рд░ рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рд▓рдВрдмрд╛ рдирд╣реАрдВ рд▓рдЧреЗрдЧрд╛ред рд╢реБрджреНрдзрддрд╛ рдХреА рдЬрд╛рдВрдЪ рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИред рдЗрд╕рд▓рд┐рдП, рд╣рдо рдЙрд╕ рдЯреЗрдореНрдкрд▓реЗрдЯ рдореЗрдВ рдПрдХ рдФрд░ рдЯреЗрдореНрдкрд▓реЗрдЯ рд╕рдореНрдорд┐рд▓рд┐рдд рдХрд░реЗрдВрдЧреЗ рдЬреЛ рдЬреЛрдбрд╝реЗ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЪрд▓реЗрдЧрд╛ рдФрд░ рдПрдХ рдЕрдЪреНрдЫрд╛ рдФрд░ рд╕реНрдкрд╖реНрдЯ рддреНрд░реБрдЯрд┐ рд╕рдВрджреЗрд╢ рдХреЗ рд╕рд╛рде рд╕рдВрдХрд▓рди рдХреЛ рд░реЛрдХ рджреЗрдЧрд╛ред

рдХреЛрдб
  template CheckPairs(tpairs...) { static if(tpairs.length > 1) { static assert(__traits(compiles, typeof(tpairs) ), "ProtocolPool expected index first, but got some type"); static assert(is(typeof(tpairs[0]) == IndexType), "ProtocolPool expected index first of type "~ IndexType.stringof~ " not a "~typeof(tpairs[0]).stringof); static assert(is(tpairs[1] : Message), "ProtocolPool expected class implementing Message"~ " interface following index not a "~tpairs[1].stringof); static assert(CountValInList!(tpairs[0], pairs) == 1, "ProtocolPool indexes must be unique! One message,"~ "one index."); enum CheckPairs = CheckPairs!(tpairs[2..$]); } else { static assert(tpairs.length == 0, "ProtocolPool expected even number of parameters. Index and message type."); enum CheckPairs = 0; } } 



__Traits (рд╕рдВрдХрд▓рд┐рдд, рдХреБрдЫ рд╕рдордп) рдкрд░ рдХреЙрд▓ рдпрд╣рд╛рдВ рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рд╣реЛ рд╕рдХрддреА рд╣реИрдВ , рдпрд╣ рд╕рдВрдХрд▓рдХ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реНрдкрд╖реНрдЯ рдЕрдиреБрд░реЛрдз рд╣реИ рдХрд┐ рдпрд╣ рдЬрд╛рдВрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рдХреЛрдИ рдкрд╛рда рд╕рднреА рдХреЛ рд╕рдВрдХрд▓рд┐рдд рдХрд░рддрд╛ рд╣реИ рдпрд╛ рдирд╣реАрдВред рдЖрдк рдпрд╣рд╛рдВ рдирд┐рд░реНрдорд┐рдд рдЕрдВрддрд░реНрдЧреНрд░рд╣рдг рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВред рдФрд░ рдЯреЗрдореНрдкрд▓реЗрдЯ рдШреЛрд╖рдгрд╛ рдХреЗ рдареАрдХ рдмрд╛рдж, рд╣рдо рдЗрд╕реЗ рд╕реНрдерд┐рд░ рдореБрдЦрд░ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХрд╣рддреЗ рд╣реИрдВ ред рдЖрдк рдмрд╕ рдЗрд╕ рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЛ рдХреЙрд▓ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╕рдВрдХрд▓рдХ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдЕрд░реНрдерд╣реАрди рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐рдпреЛрдВ рдкрд░ рд╢рдкрде рд▓реЗрддрд╛ рд╣реИ, рдЬреЛ рдХрднреА-рдХрднреА рдереЛрдбрд╝рд╛ рд╕рд╛ рд░рд╛рд╕реНрддреЗ рдореЗрдВ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред

рдХреЛрдб
 mixin template ProtocolPool(IndexType, SerializerBackend, pairs...) { template CheckPairs(tpairs...) { // ,    } static assert(CheckPairs!pairs == 0, "Parameters check failed! If code works well, you never will see this message!"); } 



рдПрдХ рдЪреМрдХрд╕ рдкрд╛рдардХ (рдпрджрд┐ рдХреЛрдИ рднреА рдЗрд╕ рд░реЗрдЦрд╛ рддрдХ рдкрд╣реБрдБрдЪ рдЧрдпрд╛ рд╣реИ) рдиреЗ рджреЗрдЦрд╛ рд╣реЛрдЧрд╛ рдХрд┐ рдореИрдВрдиреЗ рдХрд╛рдЙрдВрдЯрд╡реЗрд▓рдЗрдирд▓рд┐рд╕реНрдЯ рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рд╣реИ, рдЬреЛ рдХрд┐рд╕реА рд╕реВрдЪреА рдореЗрдВ рдПрдХ рдореВрд▓реНрдп рдХреА рдШрдЯрдирд╛рдУрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЛ рдЧрд┐рдирддрд╛ рд╣реИред

рдХреЛрдб
  // returns count of val occurenes in list template CountValInList(IndexType val, list...) { static if(list.length > 1) { static if(list[0] == val) enum CountValInList = 1 + CountValInList!(val, list[2..$]); else enum CountValInList = CountValInList!(val, list[2..$]); } else enum CountValInList = 0; } 



рдХреЛрдб рдЬрдирд░реЗрд╢рди

рдорд╣рд╛рди, рд╕рднреА рджреБрд░реБрдкрдпреЛрдЧ рдХреЛ рдХрд╛рдЯ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдареАрдХ рд╕реЗ рд╕рдВрднрд╛рд▓рд╛ рдЬрд╛рддрд╛ рд╣реИред рдРрд╕реЗ рддреНрд░реБрдЯрд┐ рд╕рдВрджреЗрд╢реЛрдВ рд╕реЗ, рд╡реИрдЬреНрдЮрд╛рдирд┐рдХ рдкреНрд░рд╣рд╛рд░ рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рд╕рд╣реА рддрд░реАрдХрд╛ рдвреВрдВрдврдирд╛ рдХрд╛рдлреА рд╕рдВрднрд╡ рд╣реИ (рдпрд╣ рдЖрдкрдХреЛ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝реЛрдВ рдХреЛ рд╕рд╣реЗрдЬрдиреЗ рд╕реЗ рдирд╣реАрдВ рдмрдЪрд╛рдПрдЧрд╛!)ред рдЕрдм рдЖрдкрдХреЛ рдХрд╛рд░реНрдп рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реНрд╡рдпрдВ рд╕реЛрдЪрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд╣рдореЗрдВ рдЙрдкрдпреЛрдЧ рдФрд░ рдЧрддрд┐ рдореЗрдВ рдЖрд╕рд╛рдиреА рдХреЗ рдмреАрдЪ рдПрдХ рд╕рдордЭреМрддрд╛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдмрдВрдж рдХрд░реЛ, рд╣рдо рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ рдпрд╣ рдФрд░ рд╡рд╣ рджреЛрдиреЛрдВ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ! рд╣рдо рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдХреА рднрд╛рдЧреАрджрд╛рд░реА рдХреЗ рдмрд┐рдирд╛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдПрдХ рд╡рд┐рд╢рд╛рд▓ рд╕реНрд╡рд┐рдЪ рдЙрддреНрдкрдиреНрди рдХрд░реЗрдВрдЧреЗ:

рдХреЛрдб
  // generating switch template GenerateSwitch() { template GenerateSwitchBody(tpairs...) { static if(tpairs.length > 0) { enum GenerateSwitchBody = "case("~to!string(tpairs[0])~ "): return cast(Message)(func!(SerializerBackend, "~ tpairs[1].stringof~")(args)); break; \n" ~ GenerateSwitchBody!(tpairs[2..$]); } else enum GenerateSwitchBody = ""; } enum GenerateSwitch = "switch(id)\n{\n"~ GenerateSwitchBody!(pairs) ~ "default: " ~ " break;\n}"; } 



рдпрд╣ рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдЗрд╕рдХреЗ рд╕рдорд╛рди рдПрдХ рд░реЗрдЦрд╛ рдЙрддреНрдкрдиреНрди рдХрд░реЗрдЧрд╛:

рдХреЛрдб
 switch(id) { case(0): return cast(Message)(func!(SerializerBackend, AMsg)(args)); break; case(1): return cast(Message)(func!(SerializerBackend, BMsg)(args)); break; case(2): return cast(Message)(func!(SerializerBackend, CMsg)(args)); break; default: break; } 



рдЕрдм рдпрд╣ рдбрд┐рд╕реНрдкреИрдЪ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░рд┐рдгрд╛рдореА рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рдПрдХ рдлрдВрдХреНрд╢рди рдореЗрдВ рдорд┐рдХреНрд╕ рдХрд░рддрд╛ рд╣реИ:

рдХреЛрдб
  //        ,      nested class   ,      private class dummyClass {} // func -  ,         args    Message dispatchMessage(alias func, T...)(IndexType id, T args) { static assert(__traits(compiles, func!(SerializerBackend, dummyClass)(args)), "ChooseMessage func must be callable with got args " ~T.stringof); //  ,      //pragma(msg, GenerateSwitch!()); mixin(GenerateSwitch!()); throw new Exception( "Cannot find corresponding message for id "~to!string(id)~"!"); } 



рдХреЛрдб рдореЗрдВ рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдХреЙрд▓ рдХреИрд╕рд╛ рджрд┐рдЦреЗрдЧрд╛:

рдХреЛрдб
  void readMsg(Stream stream) { int id; stream.read(id); writeln("Got message id is ",id); auto message = dispatchMessage!(deserialize)(id, stream, "MSG"); writeln("Calling message"); message(); } 



рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╕рдмрд╕реЗ рдХрдард┐рди рд╣рд┐рд╕реНрд╕рд╛ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИ, рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╕рдВрджреЗрд╢ рдбрд┐рдЬрд╛рдЗрди рдХреЗ рд▓рд┐рдП рд╕рднреА рдкреНрд░рдХрд╛рд░ рдХреЗ рдЙрдкрд╣рд╛рд░ рд╣реИрдВред рдХреЛрдИ рднреА рдЗрд╕реЗ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реИ? рдЗрд╕реЗ рдЗрд╕ рддрд░рд╣ рдХрд░рдирд╛ рдЕрдзрд┐рдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ:

 auto stream = constructMessage!AMsg(10, "Hello World!"); 


рдХреЛрдИ рдЖрдИрдбреА, рдХреЛрдИ рдЕрдиреНрдп рдЕрддрд┐рд░рд┐рдХреНрдд рд╕рд╛рдорд╛рди рдирд╣реАрдВред рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рддреБрд░рдВрдд рд╕рдВрджреЗрд╢ рдбрд┐рдЬрд╛рдЗрдирд░ рдХреЛ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рд╕рдВрджреЗрд╢ рдХреЛ рдмрд╛рдЗрдЯреНрд╕ рдХреА рдзрд╛рд░рд╛ рдореЗрдВ рдХреНрд░рдордмрджреНрдз рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕реЗ рд▓рд┐рдЦрдирд╛ рдмрд╛рдХреА рд╣реИ ... рдЖрдкрдХреЛ рдЯрд╛рдЗрдк рдХрд░рдХреЗ рд╕рдВрджреЗрд╢ рдЖрдИрдбреА рдХреА рдЦреЛрдЬ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рдЗрд╕рдХреЗ рд▓рд┐рдП рдЖрдкрдХреЛ рдПрдХ рдФрд░ рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:

рдХреЛрдб
  template FindMessageId(Msg, tpairs...) { static if(tpairs.length > 0) { static if(is(tpairs[1] == Msg)) enum FindMessageId = tpairs[0]; else enum FindMessageId = FindMessageId!(Msg, tpairs[2..$]); } else static assert(false, "Cannot find id for message "~ Msg.stringof~". Check protocol list."); } 



рдЗрд╕ рдмрд┐рдВрджреБ рдкрд░, рдореЗрд░реА рдЫреЛрдЯреА рдЬрдирддрд╛ рдХреЛ рдпрд╣ рд╡рд┐рдЪрд╛рд░ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рдореИрдВ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдирдХ рд╕реЗ рдЧреНрд░рд╕реНрдд рд╣реВрдВред рдореИрдВ рд╕рднреА рдкреНрд░рддрд┐рдорд╛рдиреЛрдВ рдХрд╛ рд╕рдореНрдорд╛рди рдХрд░рддрд╛ рд╣реВрдВ, рд▓реЗрдХрд┐рди рд╕рдВрдХрд▓рди-рд╕рдордп рдХреЗ рдЯреЗрдореНрдкрд▓реЗрдЯреНрд╕ рдореЗрдВ рдХреЛрдИ рднреА рдкрд░рд┐рд╡рд░реНрддрдирд╢реАрд▓ рд╕реНрдерд┐рддрд┐ рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрд╣рд╛рдВ рдПрдХ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рд╢реИрд▓реА рд╕реНрд╡рд╛рднрд╛рд╡рд┐рдХ рд░реВрдк рд╕реЗ рдЙрддреНрдкрдиреНрди рд╣реЛрддреА рд╣реИред рдЕрдм рдПрдХ рд╕рдВрджреЗрд╢ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░рдирд╛ рдореБрд╢реНрдХрд┐рд▓ рдирд╣реАрдВ рд╣реЛрдЧрд╛, рдХреЗрд╡рд▓ рдЗрд╕рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЛ рдЬрд╛рдирддреЗ рд╣реБрдП:

рдХреЛрдб
  Stream constructMessage(Msg, T...)(T args) { static assert(is(Msg : Message), Msg.stringof~ " must implement Message interface!"); static assert(__traits(compiles, new Msg(args)), Msg.stringof~ " should implement constructor with formal parameters "~ T.stringof); auto msg = new Msg(args); IndexType sendId = FindMessageId!(Msg, pairs); auto stream = serialize!SerializerBackend(msg, "MSG"); auto fullStream = new MemoryStream; fullStream.write(sendId); fullStream.copyFrom(stream); fullStream.position = 0; return fullStream; } 



рдХреЗ рдЙрдкрдпреЛрдЧ


рдЕрдм рдЬрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдпрд╣ рдкрд░рд┐рд╖реНрдХреГрдд рдкреНрд░рдгрд╛рд▓реА рд╣реИ, рддреЛ рд╣рдореЗрдВ рдЗрд╕реЗ рдЕрднреНрдпрд╛рд╕ рдореЗрдВ рдкрд░рдЦрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЗрд╕рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рд▓рд┐рдЦрд╛ рдерд╛:

рдХреЛрдб
 version(unittest) { class AMsg : Message { int a; string b; this() {} this(int pa, string pb) { a = pa; b = pb; } void opCall() { writeln("AMsg call with ", a, " ", b); } } class BMsg : Message { double a; double b; this() {} this(double pa, double pb) { a = pa; b = pb; } void opCall() { writeln("BMsg call with ", a, " ", b); } } class CMsg : Message { double a; string s; this() {} this(double pa, string ps) { a = pa; s = ps; } void opCall() { writeln("CMsg call ", a, " ", s); } } mixin ProtocolPool!(int, GendocArchive, 0, AMsg, 1, BMsg, 2, CMsg ); } unittest { void readMsg(Stream stream) { int id; stream.read(id); writeln("Got message id is ",id); auto message = dispatchMessage!(deserialize)(id, stream, "MSG"); writeln("Calling message"); message(); } // serializing auto stream = constructMessage!BMsg(4.0,8.0); // sending... // got at other side readMsg(stream); stream = constructMessage!AMsg(10, "Hello World!"); readMsg(stream); stream = constructMessage!CMsg(5., "Some usefull string"); readMsg(stream); } 



рдкреВрд░реНрдг рд╕реНрд░реЛрдд рдХреЛрдб


рдиреАрдЪреЗ рджреА рдЧрдИ рддрд╕реНрд╡реАрд░ рдХреА рдЕрдЦрдВрдбрддрд╛ рдХреЗ рд▓рд┐рдП рдмреВрд╕реНрдЯ рд▓рд╛рдЗрд╕реЗрдВрд╕ рдХреЗ рддрд╣рдд рдкреВрд░реНрдг рд╕реНрд░реЛрдд рд╣реИред рд╕рд╛рдорд╛рдиреНрдп рдСрдкрд░реЗрд╢рди рдХреЗ рд▓рд┐рдП, рдореЙрдбреНрдпреВрд▓ рдХреЛ рдПрдХ рдзрд╛рд░рд╛рд╡рд╛рд╣рд┐рдХ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдЖрдк рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдкреЗрдВрдЪ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдпрд╛ рдСрд░реЗрдВрдЬ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рдХреЛрдб
 // Copyright Gushcha Anton 2012. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) module protocol; import std.stdio; import std.conv; import std.stream; //  ,      import util.serialization.serializer; interface Message { void opCall(); } mixin template ProtocolPool(IndexType, SerializerBackend, pairs...) { // returns count of val occurenes in list template CountValInList(IndexType val, list...) { static if(list.length > 1) { static if(list[0] == val) enum CountValInList = 1 + CountValInList!(val, list[2..$]); else enum CountValInList = CountValInList!(val, list[2..$]); } else enum CountValInList = 0; } // check pairs to be correct template CheckPairs(tpairs...) { static if(tpairs.length > 1) { static assert(__traits(compiles, typeof(tpairs) ), "ProtocolPool expected index first, but got some type"); static assert(is(typeof(tpairs[0]) == IndexType), "ProtocolPool expected index first of type "~IndexType.stringof~" not a "~typeof(tpairs[0]).stringof); static assert(is(tpairs[1] : Message), "ProtocolPool expected class implementing Message interface following index not a "~tpairs[1].stringof); static assert(CountValInList!(tpairs[0], pairs) == 1, "ProtocolPool indexes must be unique! One message, one index."); enum CheckPairs = CheckPairs!(tpairs[2..$]); } else { static assert(tpairs.length == 0, "ProtocolPool expected even number of parameters. Index and message type."); enum CheckPairs = 0; } } // generating switch template GenerateSwitch() { template GenerateSwitchBody(tpairs...) { static if(tpairs.length > 0) { enum GenerateSwitchBody = "case("~to!string(tpairs[0])~"): return cast(Message)(func!(SerializerBackend, "~tpairs[1].stringof~")(args)); break; \n" ~ GenerateSwitchBody!(tpairs[2..$]); } else enum GenerateSwitchBody = ""; } enum GenerateSwitch = "switch(id)\n{\n"~GenerateSwitchBody!(pairs) ~ `default: ` ~ " break;\n}"; } template FindMessageId(Msg, tpairs...) { static if(tpairs.length > 0) { static if(is(tpairs[1] == Msg)) enum FindMessageId = tpairs[0]; else enum FindMessageId = FindMessageId!(Msg, tpairs[2..$]); } else static assert(false, "Cannot find id for message "~Msg.stringof~". Check protocol list."); } // actual check static assert(CheckPairs!pairs == 0, "Parameters check failed! If code works well, you never will see this message!"); private class dummyClass {} Message dispatchMessage(alias func, T...)(IndexType id, T args) { static assert(__traits(compiles, func!(SerializerBackend, dummyClass)(args)), "ChooseMessage func must be callable with got args "~T.stringof); //pragma(msg, GenerateSwitch!()); mixin(GenerateSwitch!()); throw new Exception("Cannot find corresponding message for id "~to!string(id)~"!"); } Stream constructMessage(Msg, T...)(T args) { static assert(is(Msg : Message), Msg.stringof~" must implement Message interface!"); static assert(__traits(compiles, new Msg(args)), Msg.stringof~" should implement constructor with formal parameters "~T.stringof); auto msg = new Msg(args); IndexType sendId = FindMessageId!(Msg, pairs); auto stream = serialize!SerializerBackend(msg, "MSG"); auto fullStream = new MemoryStream; fullStream.write(sendId); fullStream.copyFrom(stream); fullStream.position = 0; return fullStream; } } version(unittest) { class AMsg : Message { int a; string b; this() {} this(int pa, string pb) { a = pa; b = pb; } void opCall() { writeln("AMsg call with ", a, " ", b); } } class BMsg : Message { double a; double b; this() {} this(double pa, double pb) { a = pa; b = pb; } void opCall() { writeln("BMsg call with ", a, " ", b); } } class CMsg : Message { double a; string s; this() {} this(double pa, string ps) { a = pa; s = ps; } void opCall() { writeln("CMsg call ", a, " ", s); } } mixin ProtocolPool!(int, BinaryBackend, 0, AMsg, 1, BMsg, 2, CMsg ); } unittest { void readMsg(Stream stream) { int id; stream.read(id); writeln("Got message id is ",id); auto message = dispatchMessage!(deserialize)(id, stream, "MSG"); writeln("Calling message"); message(); } // serializing auto stream = constructMessage!BMsg(4.0,8.0); // sending... // Got at other side readMsg(stream); stream = constructMessage!AMsg(10, "Hello World!"); readMsg(stream); stream = constructMessage!CMsg(5., "Some usefull string"); readMsg(stream); } 

Source: https://habr.com/ru/post/In149809/


All Articles