рдордХреНрдЦреА рдкрд░ рдЪрд░рд┐рддреНрд░ рдкреНрд░рдХрд╛рд░ рдЙрддреНрдкрдиреНрди рдХрд░рдирд╛ (рдпрд╛ рдЬрдВрдЧ рдХреЗ рд╕рд╛рде рдкрд╛рдЧрд▓)

рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рд╣рдо рд░рд╕реНрдЯ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛, рдФрд░ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ, рд╡рд┐рд╢реЗрд╖рддрд╛ рд╡рд╕реНрддреБрдУрдВ рдХрд╛ рдордЬрд╛рдХ рдЙрдбрд╝рд╛рдПрдВрдЧреЗред


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


рдЪрд▓реЛ рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдЙрджрд╛рд╣рд░рдг рд╕реЗ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ рдЬреЛ рдореЛрдЯреЗ рдмрд┐рдВрджреБрдУрдВ рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИред рдирд┐рдореНрди рдХреЛрдб 64-рдмрд┐рдЯ рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ 8 рдФрд░ 16 рдкрд░ рдЖрдЙрдЯрдкреБрдЯ рдХрд░реЗрдЧрд╛:


fn main () { let v: &String = &"hello".into(); let disp: &std::fmt::Display = v; println!("  : {}", std::mem::size_of_val(&v)); println!("   -: {}", std::mem::size_of_val(&disp)); } 

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


рдореБрдЭреЗ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рдХрд░рдирд╛ рдерд╛:


 Person adapt(Json value) { // ...- , , ,  "value"  //   Person return new PersonJsonAdapter(value); } 

рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЗ рд╕рд╛рде рд╡рд┐рднрд┐рдиреНрди рд╕рдорд╕реНрдпрд╛рдПрдВ рдереАрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рдПрдХ рд╣реА рд╡рд╕реНрддреБ рджреЛ рдмрд╛рд░ "рдПрдбреИрдкреНрдЯ" рд╣реЛрддреА рд╣реИ, рддреЛ рд╣рдореЗрдВ рджреЛ рдЕрд▓рдЧ-рдЕрд▓рдЧ Person рдорд┐рд▓рддреЗ рд╣реИрдВ (рд▓рд┐рдВрдХ рддреБрд▓рдирд╛ рдХреЗ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╕реЗ)ред рдФрд░ рдпрд╣ рддрдереНрдп рдХрд┐ рдЖрдкрдХреЛ рд╣рд░ рдмрд╛рд░ рдирдИ рд╡рд╕реНрддреБрдПрдВ рдмрдирд╛рдиреА рд╣реЛрддреА рд╣реИрдВ, рдХрд┐рд╕реА рддрд░рд╣ рдмрджрд╕реВрд░рдд рд╣реЛрддреА рд╣реИрдВред


рдЬрдм рдореИрдВрдиреЗ Rust рдореЗрдВ рдЯрд╛рдЗрдк рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХреЛ рджреЗрдЦрд╛, рддреЛ рдореБрдЭреЗ рдЕрдВрджрд╛рдЬрд╛ рдерд╛ рдХрд┐ Rust рдореЗрдВ рдпрд╣ рдмрд╣реБрдд рдЕрдзрд┐рдХ рд╕реБрд░реБрдЪрд┐рдкреВрд░реНрдг рдврдВрдЧ рд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ! рдЖрдк рдбреЗрдЯрд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рдФрд░ рд╡рд░реНрдЪреБрдЕрд▓ рдЯреЗрдмрд▓ рднреА рд▓реЗ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдПрдХ рдирдИ рд╡рд┐рд╢реЗрд╖рддрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ! рдФрд░ рдкреНрд░рддреНрдпреЗрдХ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдореЗрдореЛрд░реА рдЖрд╡рдВрдЯрд┐рдд рди рдХрд░реЗрдВред рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ, "рдЙрдзрд╛рд░" рдХрд╛ рдкреВрд░рд╛ рддрд░реНрдХ рдЬрдЧрд╣ рдкрд░ рд░рд╣рддрд╛ рд╣реИ - рд╣рдорд╛рд░рд╛ рдЕрдиреБрдХреВрд▓рди рдХрд╛рд░реНрдп рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦреЗрдЧрд╛ fn adapt<'a>(value: &'a Json) -> &'a Person (рдЕрд░реНрдерд╛рдд, рд╣рдо рдПрдХ рддрд░рд╣ рд╕реЗ рдЙрдзрд╛рд░ рд▓реЗрддреЗ рд╣реИрдВ) рд╕реНрд░реЛрдд рдбреЗрдЯрд╛)ред


рдЗрд╕рд╕реЗ рднреА рдЕрдзрд┐рдХ, рдЖрдк рдПрдХ рд╣реА рдкреНрд░рдХрд╛рд░ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, String ) рдХреЛ рд╡рд┐рднрд┐рдиреНрди рдкреНрд░рдХрд╛рд░ рдХреЗ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЗ рд╕рд╛рде, рдХрдИ рдмрд╛рд░ рд╣рдорд╛рд░реЗ рдкреНрд░рдХрд╛рд░ рдХреА рд╡рд╕реНрддреБ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП "рдмрд╛рдзреНрдп" рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдХреНрдпреЛрдВ? рд▓реЗрдХрд┐рди рдЖрдк рдХрднреА рдирд╣реАрдВ рдЬрд╛рдирддреЗ рдХрд┐ рдЙрджреНрдпрдо рдореЗрдВ рдХреНрдпрд╛ рдЬрд░реВрд░рдд рд╣реЛ рд╕рдХрддреА рд╣реИ! "


рдЖрдЗрдП рдЗрд╕реЗ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред


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


рд╣рдо рдХрд╛рд░реНрдп рдХреЛ рдЗрд╕ рддрд░рд╣ рд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВ: annotate рдлрд╝рдВрдХреНрд╢рди рдмрдирд╛рддреЗ рд╣реИрдВ, рдЬреЛ рдирд┐рдпрдорд┐рдд String рдкреНрд░рдХрд╛рд░ рдХреЗ рд▓рд┐рдП рдирд┐рдореНрди рдкреНрд░рдХрд╛рд░ рдХреА рд╡рд╕реНрддреБ "рдЕрд╕рд╛рдЗрди" рдХрд░рддрд╛ рд╣реИ:


 trait Object { fn type_name(&self) -> &str; fn as_string(&self) -> &String; } 

рдФрд░ annotate рд╕реНрд╡рдпрдВ рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИ:


 ///    - `Object`,   , ///   "" -- ,    `type_name`. fn annotate<'a>(input: &'a String, type_name: &str) -> &'a dyn Object { // ... } 

рдЪрд▓рд┐рдП рдЕрднреА рдПрдХ рдЯреЗрд╕реНрдЯ рд▓рд┐рдЦрддреЗ рд╣реИрдВред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ рдХрд┐ "рдЕрд╕рд╛рдЗрди рдХрд┐рдпрд╛ рдЧрдпрд╛" рдкреНрд░рдХрд╛рд░ рдЕрдкреЗрдХреНрд╖рд┐рдд рд╕реЗ рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИред рджреВрд╕рд░реА рдмрд╛рдд, рд╣рдо рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВрдЧреЗ рдХрд┐ рд╣рдо рдореВрд▓ рдкрдВрдХреНрддрд┐ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХреЗрдВ рдФрд░ рдпрд╣ рдПрдХ рд╣реА рдкрдВрдХреНрддрд┐ рд╣реЛрдЧреА (рдмрд┐рдВрджреБрдУрдВ рдХреЗ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╕реЗ):


 #[test] fn test() { let input: String = "hello".into(); let annotated1 = annotate(&input, "Widget"); let annotated2 = annotate(&input, "Gadget"); // -   ,    assert_eq!("Widget", annotated1.type_name()); assert_eq!("Gadget", annotated2.type_name()); let unwrapped1 = annotated1.as_string(); let unwrapped2 = annotated2.as_string(); //       --   assert_eq!(unwrapped1 as *const String, &input as *const String); assert_eq!(unwrapped2 as *const String, &input as *const String); } 

рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╕рдВрдЦреНрдпрд╛ 1: рдФрд░ рд╣рдорд╛рд░реЗ рдмрд╛рдж рдХрдо рд╕реЗ рдХрдо рдмрд╛рдврд╝!


рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдЪрд▓реЛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрдиреБрднрд╡рд╣реАрди рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдмрдирд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддреЗ рд╣реИрдВред рдмрд╕ рд╣рдорд╛рд░реЗ рдбреЗрдЯрд╛ рдХреЛ "рд░реИрдкрд░" рдореЗрдВ рд▓рдкреЗрдЯреЗрдВ, рдЬрд┐рд╕рдореЗрдВ рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛ type_name :


 struct Wrapper<'a> { value: &'a String, type_name: String, } impl<'a> Object for Wrapper<'a> { fn type_name(&self) -> &str { &self.type_name } fn as_string(&self) -> &String { self.value } } 

рдЕрднреА рддрдХ рдХреБрдЫ рдЦрд╛рд╕ рдирд╣реАрдВ рд╣реБрдЖред рдЬрд╛рд╡рд╛ рдореЗрдВ рд╕рдм рдХреБрдЫ рдЬреИрд╕рд╛ рд╣реИред рд▓реЗрдХрд┐рди рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХреВрдбрд╝рд╛ рдЙрдард╛рдиреЗ рд╡рд╛рд▓рд╛ рдирд╣реАрдВ рд╣реИ, рд╣рдо рдЗрд╕ рд░реИрдкрд░ рдХреЛ рдХрд╣рд╛рдВ рд░рдЦреЗрдВрдЧреЗ? рд╣рдореЗрдВ рд▓рд┐рдВрдХ рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рддрд╛рдХрд┐ annotate рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рдпрд╣ рд╡реИрдз рдмрдирд╛ рд░рд╣реЗред рд╣рдо Box рдореЗрдВ рдХреБрдЫ рдбрд░рд╛рд╡рдирд╛ рд░рдЦ рджреЗрдВрдЧреЗ рддрд╛рдХрд┐ Wrapper рдвреЗрд░ рдкрд░ рдкреНрд░рдХрд╛рд╢ рдбрд╛рд▓рд╛ рдЬрд╛рдПред рдФрд░ рдлрд┐рд░ рд╣рдо рдЗрд╕рдХреЗ рд▓рд┐рдВрдХ рдХреЛ рд╡рд╛рдкрд╕ рдХрд░ рджреЗрдВрдЧреЗред рдФрд░ рддрд╛рдХрд┐ рд░реИрдкрд░ annotate рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рднреА рдЬреАрд╡рд┐рдд рд░рд╣реЗ, рд╣рдо рдЗрд╕ рдмреЙрдХреНрд╕ рдХреЛ "рд▓реАрдХ" рдХрд░реЗрдВрдЧреЗ:


 fn annotate<'a>(input: &'a String, type_name: &str) -> &'a dyn Object { let b = Box::new(Wrapper { value: input, type_name: type_name.into(), }); Box::leak(b) } 

... рдФрд░ рдкрд░реАрдХреНрд╖рд╛ рдкрд╛рд╕!


рд▓реЗрдХрд┐рди рдпрд╣ рдХреБрдЫ рд╕рдВрджрд┐рдЧреНрдз рдирд┐рд░реНрдгрдп рд╣реИред рди рдХреЗрд╡рд▓ рд╣рдо рдЕрднреА рднреА рдкреНрд░рддреНрдпреЗрдХ "рдПрдиреЛрдЯреЗрд╢рди" рдХреЗ рд╕рд╛рде рдореЗрдореЛрд░реА рдЖрд╡рдВрдЯрд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдореЗрдореЛрд░реА рд▓реАрдХ рд╣реЛ рдЬрд╛рддреА рд╣реИ ( Box::leak рдкрд░ рд╕рдВрдЧреНрд░рд╣реАрдд рдбреЗрдЯрд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рд▓рд┐рдВрдХ рджреЗрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ "рдмреЙрдХреНрд╕" рдХреЛ рднреВрд▓ рдЬрд╛рддрд╛ рд╣реИ, рдЕрд░реНрдерд╛рдд, рд╕реНрд╡рдд: рдбреАрдЯреЛрдХреЗрд╢рди рдирд╣реАрдВ рд╣реЛрдЧрд╛) )ред


рджреГрд╖реНрдЯрд┐рдХреЛрдг 2: рдЕрдЦрд╛рдбрд╝рд╛!


рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдЗрдП рдЗрди рд░реИрдкрд░реЛрдВ рдХреЛ рдХрд╣реАрдВ рдФрд░ рд╕рд╣реЗрдЬрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЗрдВ рддрд╛рдХрд┐ рд╡реЗ рдХрд┐рд╕реА рдмрд┐рдВрджреБ рдкрд░ рдЬрд╛рд░реА рди рд╣реЛрдВред рд▓реЗрдХрд┐рди рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ annotate рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдХреЛ рдмрдирд╛рдП рд░рдЦрдирд╛ рдЬреИрд╕рд╛ рдХрд┐ рдпрд╣ рд╣реИред рдпрд╣реА рд╣реИ, рд╕рдВрджрд░реНрдн рдЧрд┐рдирддреА рдХреЗ рд╕рд╛рде рдПрдХ рд▓рд┐рдВрдХ рд▓реМрдЯрд╛рдирд╛ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, Rc<Wrapper> ) рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред


рд╕рдмрд╕реЗ рд╕рд░рд▓ рд╡рд┐рдХрд▓реНрдк рдПрдХ рд╕рд╣рд╛рдпрдХ рд╕рдВрд░рдЪрдирд╛, рдПрдХ "рдкреНрд░рдХрд╛рд░ рдкреНрд░рдгрд╛рд▓реА" рдмрдирд╛рдирд╛ рд╣реИ, рдЬреЛ рдЗрди рд░реИрдкрд░реЛрдВ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реЛрдЧрд╛ред рдФрд░ рдЬрдм рд╣рдо рд╕рдорд╛рдкреНрдд рдХрд░ рд▓реЗрдВрдЧреЗ, рд╣рдо рдЗрд╕ рд╕рдВрд░рдЪрдирд╛ рдФрд░ рдЗрд╕рдХреЗ рд╕рд╛рде рд╕рднреА рдЖрд╡рд░рдгреЛрдВ рдХреЛ рдЫреЛрдбрд╝ рджреЗрдВрдЧреЗред


рдХреБрдЫ рдЗрд╕ рддрд░рд╣ред typed-arena рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рд░реИрдкрд░реЛрдВ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЖрдк Vec<Box<Wrapper>> рд╕рд╛рде рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдореБрдЦреНрдп рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ Wrapper рдХрд╣реАрдВ рднреА рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ (рд░рд╛рдд рдореЗрдВ рдЬрдВрдЧ рдЖрдк рдкрд┐рди рдПрдкреАрдЖрдИ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ):


 struct TypeSystem { wrappers: typed_arena::Arena<Wrapper>, } impl TypeSystem { pub fn new() -> Self { Self { wrappers: typed_arena::Arena::new(), } } ///     `input`,      , ///    (  ,    , ///        )! pub fn annotate<'a: 'b, 'b>( &'a self, input: &'b String, type_name: &str ) -> &'b dyn Object { self.wrappers.alloc(Wrapper { value: input, type_name: type_name.into(), }) } } 

рд▓реЗрдХрд┐рди Wrapper рдкреНрд░рдХрд╛рд░ рдХреЗ рд▓рд┐рдВрдХ рдХреЗ рдЬреАрд╡рдирдХрд╛рд▓ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рдкреИрд░рд╛рдореАрдЯрд░ рдХрд╣рд╛рдВ рдЧрдпрд╛? рд╣рдореЗрдВ рдЗрд╕рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛рдирд╛ рдерд╛, рдХреНрдпреЛрдВрдХрд┐ рд╣рдо рдЯрд╛рдЗрдк рдХрд┐рдП typed_arena::Arena<Wrapper<'?>> рдореЗрдВ рдХреБрдЫ рдирд┐рд╢реНрдЪрд┐рдд рдЬреАрд╡рдирдХрд╛рд▓ рдХрд╛ рдЧреБрдг рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗред рдкреНрд░рддреНрдпреЗрдХ рд░реИрдкрд░ рдореЗрдВ input рдЖрдзрд╛рд░ рдкрд░ рдПрдХ рдЕрджреНрд╡рд┐рддреАрдп рдкреИрд░рд╛рдореАрдЯрд░ input !


рдЗрд╕рдХреЗ рдмрдЬрд╛рдп, рд╣рдо рдЖрдЬреАрд╡рди рд╕рдордп рдХреЗ рдкреИрд░рд╛рдореАрдЯрд░ рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдереЛрдбрд╝рд╛ рдЕрд╕реБрд░рдХреНрд╖рд┐рдд рдЬрдВрдЧ рдЫрд┐рдбрд╝рдХрддреЗ рд╣реИрдВ:


 struct Wrapper { value: *const String, type_name: String, } impl Object for Wrapper { fn type_name(&self) -> &str { &self.type_name } ///   -- ,     (  /// `annotate`),     (    - /// `&Object`)  ,      (`String`). fn as_string(&self) -> &String { unsafe { &*self.value } } } 

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


рд▓реЗрдХрд┐рди рдлрд┐рд░ рднреА, рд╡рд╛рджрд╛ рдХрд┐рдП рдЧрдП рд╡рд┐рдХрд▓реНрдк рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреНрдпрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рд░реИрдкрд░ рдХреЗ рд▓рд┐рдП рдЕрддрд┐рд░рд┐рдХреНрдд рдореЗрдореЛрд░реА рдЖрд╡рдВрдЯрди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ?


рджреГрд╖реНрдЯрд┐рдХреЛрдг # 3: рдирд░рдХ рдХреЗ рджреНрд╡рд╛рд░ рдЦреЛрд▓реЗрдВ


рдЖрдЗрдбрд┐рдпрд╛ред рдкреНрд░рддреНрдпреЗрдХ рдЕрджреНрд╡рд┐рддреАрдп "рдкреНрд░рдХрд╛рд░" ("рд╡рд┐рдЬреЗрдЯ", "рдЧреИрдЬреЗрдЯ") рдХреЗ рд▓рд┐рдП, рд╣рдо рдПрдХ рд╡рд░реНрдЪреБрдЕрд▓ рдЯреЗрдмрд▓ рдмрдирд╛рдПрдВрдЧреЗред рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЗ рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рджреМрд░рд╛рди рд╣рд╛рдеред рдФрд░ рд╣рдо рдЗрд╕реЗ рдбреЗрдЯрд╛ рджреНрд╡рд╛рд░рд╛ рд╣рдореЗрдВ рджрд┐рдП рдЧрдП рд▓рд┐рдВрдХ рдкрд░ рд╣реА рдЕрд╕рд╛рдЗрди рдХрд░рддреЗ рд╣реИрдВ (рдЬреЛ, рдЬреИрд╕рд╛ рдХрд┐ рд╣рдо рдпрд╛рдж рдХрд░рддреЗ рд╣реИрдВ, рдмрд╕ String )ред


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


 #[repr(C)] struct TraitObject { pub data: *const (), pub vtable: *const (), } 

( #[repr(C)] рд╣рдореЗрдВ рдореЗрдореЛрд░реА рдореЗрдВ рд╕рд╣реА рд╕реНрдерд╛рди рдХреА рдЧрд╛рд░рдВрдЯреА рджреЗрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ)ред


рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╕рдм рдХреБрдЫ рд╕рд░рд▓ рд╣реИ, рд╣рдо рджрд┐рдП рдЧрдП рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рдирдИ рддрд╛рд▓рд┐рдХрд╛ рддреИрдпрд╛рд░ рдХрд░реЗрдВрдЧреЗ рдФрд░ рдЯрд╛рдЗрдк рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд▓рд┐рдП "рдЗрдХрдЯреНрдард╛" рдХрд░реЗрдВрдЧреЗ! рд▓реЗрдХрд┐рди рдЗрд╕ рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рдХреНрдпрд╛ рд╣реИ?


рдЗрд╕ рдкреНрд░рд╢реНрди рдХрд╛ рд╕рд╣реА рдЙрддреНрддрд░ рд╣реЛрдЧрд╛ "рдпрд╣ рдПрдХ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╡рд┐рд╡рд░рдг рд╣реИред" рд▓реЗрдХрд┐рди рд╣рдо рдРрд╕рд╛ рдХрд░реЗрдВрдЧреЗ; рд╣рдорд╛рд░реА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреА рдЬрдбрд╝ рдореЗрдВ рдПрдХ rust-toolchain рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдПрдВ рдФрд░ рдЗрд╕реЗ рд╡рд╣рд╛рдВ рд▓рд┐рдЦреЗрдВ: nightly-2018-12-01 ред рдЖрдЦрд┐рд░рдХрд╛рд░, рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рд╡рд┐рдзрд╛рдирд╕рднрд╛ рдХреЛ рд╕реНрдерд┐рд░ рдорд╛рдирд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рд╣реИ рдирд╛?


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


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


рддреЛ рд╣рдо рд▓рд┐рдЦрддреЗ рд╣реИрдВ:


 #[repr(C)] #[derive(Clone, Copy)] struct VirtualTableHeader { destructor_fn: fn(*mut ()), size: usize, align: usize, } #[repr(C)] struct ObjectVirtualTable { header: VirtualTableHeader, type_name_fn: fn(*const String) -> *const str, as_string_fn: fn(*const String) -> *const String, } 

рдЗрд╕реА рддрд░рд╣, рд╕реНрдореГрддрд┐ рдореЗрдВ рд╕рд╣реА рд╕реНрдерд╛рди рдХреА рдЧрд╛рд░рдВрдЯреА рдХреЗ рд▓рд┐рдП #[repr(C)] рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдореИрдВ рджреЛ рд╕рдВрд░рдЪрдирд╛рдУрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рд╣реБрдЖ, рдереЛрдбрд╝реА рджреЗрд░ рдмрд╛рдж рдпрд╣ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧрд╛ред


рдЕрдм рдЖрдЗрдП рд╣рдорд╛рд░реЗ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рд┐рд╕реНрдЯрдо рдХреЛ рд▓рд┐рдЦрдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВ, рдЬреЛ annotate рдлрд╝рдВрдХреНрд╢рди рдкреНрд░рджрд╛рди рдХрд░реЗрдЧрд╛ред рд╣рдореЗрдВ рдЙрддреНрдкрдиреНрди рддрд╛рд▓рд┐рдХрд╛рдУрдВ рдХреЛ рдХреИрд╢ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА, рддреЛ рдЖрдЗрдП рдХреИрд╢ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ:


 struct TypeInfo { vtable: ObjectVirtualTable, } #[derive(Default)] struct TypeSystem { infos: RefCell<HashMap<String, TypeInfo>>, } 

рд╣рдо RefCell рдХреА рдЖрдВрддрд░рд┐рдХ рд╕реНрдерд┐рддрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ рддрд╛рдХрд┐ рд╣рдорд╛рд░реЗ TypeSystem::annotate рдлрд╝рдВрдХреНрд╢рди рдПрдХ рд╕рд╛рдЭрд╛ рд▓рд┐рдВрдХ рдХреЗ рд░реВрдк рдореЗрдВ рдкреНрд░рд╛рдкреНрдд &self рдХрд░ рд╕рдХреЗрдВред рдпрд╣ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рд╣рдо TypeSystem рд╕реЗ "рдЙрдзрд╛рд░ рд▓реЗрддреЗ рд╣реИрдВ" рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рд╣рдордиреЗ рдЬреЛ рд╡рд░реНрдЪреБрдЕрд▓ рдЯреЗрдмрд▓ рдЙрддреНрдкрдиреНрди рдХреА рд╣реИ, рд╡рд╣ рдЙрд╕ рдкреНрд░рдХрд╛рд░ рдХреА рд╡рд╕реНрддреБ рдХреЗ рд╕рдВрджрд░реНрдн рд╕реЗ рдЕрдзрд┐рдХ рд╕рдордп рддрдХ рд░рд╣рддреА рд╣реИ, рдЬрд┐рд╕реЗ рд╣рдо annotate рд╕реЗ рд▓реМрдЯрд╛рддреЗ рд╣реИрдВред


рдЪреВрдВрдХрд┐ рд╣рдо рдХрдИ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЛ рдПрдиреЛрдЯреЗрдЯ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдПрдХ рдкрд░рд╕реНрдкрд░ рд▓рд┐рдВрдХ рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдзрд╛рд░ рдирд╣реАрдВ рд▓реЗ рд╕рдХрддреЗ рд╣реИрдВред


рдФрд░ рд╣рдо рдЗрд╕ рдХреЛрдб рдХреЛ рд╕реНрдХреЗрдЪ рдХрд░реЗрдВрдЧреЗ:


 impl TypeSystem { pub fn annotate<'a: 'b, 'b>( &'a self, input: &'b String, type_name: &str ) -> &'b dyn Object { let type_name = type_name.to_string(); let mut infos = self.infos.borrow_mut(); let imp = infos.entry(type_name).or_insert_with(|| unsafe { //    ,  ? let vtable = unimplemented!(); TypeInfo { vtable } }); let object_obj = TraitObject { data: input as *const String as *const (), vtable: &imp.vtable as *const ObjectVirtualTable as *const (), }; //       - unsafe { std::mem::transmute::<TraitObject, &dyn Object>(object_obj) } } } 

рд╣рдореЗрдВ рдпрд╣ рддрд╛рд▓рд┐рдХрд╛ рдХрд╣рд╛рдВ рд╕реЗ рдорд┐рд▓реА? рдЗрд╕рдореЗрдВ рдкрд╣рд▓реЗ рддреАрди рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐рдпрд╛рдБ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдкреНрд░рдХрд╛рд░ рдХреЗ рд▓рд┐рдП рдХрд┐рд╕реА рдЕрдиреНрдп рдЖрднрд╛рд╕реА рддрд╛рд▓рд┐рдХрд╛ рдХреЗ рд▓рд┐рдП рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐рдпреЛрдВ рд╕реЗ рдореЗрд▓ рдЦрд╛рдПрдБрдЧреАред рдЗрд╕рд▓рд┐рдП, рдмрд╕ рдЙрдиреНрд╣реЗрдВ рдХреЙрдкреА рдФрд░ рдХреЙрдкреА рдХрд░реЗрдВред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдЖрдЗрдП рдЗрд╕реЗ рдЯрд╛рдЗрдк рдХрд░реЗрдВ:


 trait Whatever {} impl<T> Whatever for T {} 

рдпрд╣ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдмрд╣реБрдд рд╣реА рдЙрдкрдпреЛрдЧреА рд╣реИ "рдХрд┐рд╕реА рднреА рдЕрдиреНрдп рдЖрднрд╛рд╕реА рддрд╛рд▓рд┐рдХрд╛ред" рдФрд░ рдлрд┐рд░, рд╣рдо рдЙрд╕рд╕реЗ рдпреЗ рддреАрди рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐рдпрд╛рдБ рдХреЙрдкреА рдХрд░рддреЗ рд╣реИрдВ:


 let whatever = input as &dyn Whatever; let whatever_obj = std::mem::transmute::<&dyn Whatever, TraitObject>(whatever); let whatever_vtable_header = whatever_obj.vtable as *const VirtualTableHeader; let vtable = ObjectVirtualTable { //  ! header: *whatever_vtable_header, type_name_fn: unimplemented!(), as_string_fn: unimplemented!(), }; TypeInfo { vtable } 

рдЕрд╕рд▓ рдореЗрдВ, рд╣рдо std::mem::size_of::<String>() рдорд╛рдзреНрдпрдо рд╕реЗ рдЖрдХрд╛рд░ рдФрд░ рд╕рдВрд░реЗрдЦрдг рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ std::mem::size_of::<String>() рдФрд░ std::mem::align_of::<String>() ред рд▓реЗрдХрд┐рди рдФрд░ рдХрд╣рд╛рдБ рд╕реЗ рд╡рд┐рдирд╛рд╢рдХрд╛рд░реА "рдЪреЛрд░реА" рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рдореБрдЭреЗ рдирд╣реАрдВ рдкрддрд╛ред


рдареАрдХ рд╣реИ, рд▓реЗрдХрд┐рди рд╣рдореЗрдВ рдЗрди рдлрд╝рдВрдХреНрд╢рдВрд╕ рдХреЗ рдкрддреЗ type_name_fn , type_name_fn рдФрд░ as_string_fn ? рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ as_string_fn рдХреА рдЖрдорддреМрд░ рдкрд░ рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реЛрддреА рд╣реИ, рдбреЗрдЯрд╛ рдкреЙрдЗрдВрдЯрд░ рд╣рдореЗрд╢рд╛ рдЯрд╛рдЗрдк рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдореЗрдВ рдкрд╣рд▓реЗ рд░рд┐рдХреЙрд░реНрдб рдХреЗ рд░реВрдк рдореЗрдВ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣реА рд╣реИ, рдпрд╣ рдлрд╝рдВрдХреНрд╢рди рд╣рдореЗрд╢рд╛ рд╕рдорд╛рди рд╣реЛрддрд╛ рд╣реИ:


 impl Object for String { // ... fn as_string(&self) -> String { self } } 

рд▓реЗрдХрд┐рди рджреВрд╕рд░реЗ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд╕рд╛рде рдпрд╣ рдЗрддрдирд╛ рдЖрд╕рд╛рди рдирд╣реАрдВ рд╣реИ! рдпрд╣ рд╣рдорд╛рд░реЗ рдирд╛рдо "рдкреНрд░рдХрд╛рд░", type_name рдкрд░ рднреА рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИред


рдЗрд╕рд╕реЗ рдХреЛрдИ рдлрд░реНрдХ рдирд╣реАрдВ рдкрдбрд╝рддрд╛, рд╣рдо рдХреЗрд╡рд▓ рд░рдирдЯрд╛рдЗрдо рдореЗрдВ рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдЙрддреНрдкрдиреНрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЖрдЗрдП рдЗрд╕ рдХреЗ рд▓рд┐рдП dynasm рдкреБрд╕реНрддрдХрд╛рд▓рдп рд▓реЗрдВ (рдлрд┐рд▓рд╣рд╛рд▓, рдЗрд╕реЗ рд░рд╛рд╕реНрдЯ рдмрд┐рд▓реНрдб рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ)ред рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкрдврд╝реЗрдВ
рд╕рдорд╛рд░реЛрд╣ рдХреЙрд▓ рд╕рдореНрдореЗрд▓рдиреЛрдВ ред


рд╕рд╛рджрдЧреА рдХреЗ рд▓рд┐рдП, рдорд╛рди рд▓реЗрдВ рдХрд┐ рд╣рдо рдХреЗрд╡рд▓ рдореИрдХ рдУрдПрд╕ рдФрд░ рд▓рд┐рдирдХреНрд╕ рдореЗрдВ рд░реБрдЪрд┐ рд░рдЦрддреЗ рд╣реИрдВ (рдЗрди рд╕рднреА рдордЬрд╝реЗрджрд╛рд░ рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЗ рдмрд╛рдж, рд╕рдВрдЧрддрддрд╛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЕрдм рдФрд░ рдирд╣реАрдВ рдкрд░реЗрд╢рд╛рди рдХрд░рддреА рд╣реИ?)ред рдФрд░, рд╣рд╛рдБ, рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ x86-64, рдмрд┐рд▓реНрдХреБрд▓ред


рджреВрд╕рд░рд╛ рдлрд╝рдВрдХреНрд╢рди, as_string рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рдЖрд╕рд╛рди рд╣реИред рд╣рдореЗрдВ рд╡рд╛рджрд╛ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рдкрд╣рд▓рд╛ рдкреИрд░рд╛рдореАрдЯрд░ RDI рд░рдЬрд┐рд╕реНрдЯрд░ рдореЗрдВ рд╣реЛрдЧрд╛ред рдФрд░ RAX рдХреЛ рдорд╛рди рд▓реМрдЯрд╛рдПрдВред рдЕрд░реНрдерд╛рддреН, рдлрд╝рдВрдХреНрд╢рди рдХреЛрдб рдХреБрдЫ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реЛрдЧрд╛:


 dynasm!(ops ; mov rax, rdi ; ret ); 

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


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


рд▓реЗрдХрд┐рди рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЗрд╕ рдкрдВрдХреНрддрд┐ рдХреА рдПрдХ рдкреНрд░рддрд┐ рд╣реИ, рдЬрд┐рд╕реЗ рд╣рдо рд╣реИрд╢ рдЯреЗрдмрд▓ рдореЗрдВ рд░рдЦрддреЗ рд╣реИрдВред рдЕрдкрдиреА рдЙрдВрдЧрд▓рд┐рдпреЛрдВ рдХреЛ рдкрд╛рд░ рдХрд░рддреЗ рд╣реБрдП, рд╣рдо рдпрд╣ рдзрд╛рд░рдгрд╛ String::as_str рдХрд┐ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╕реНрд▓рд╛рдЗрд╕ рдХрд╛ рд╕реНрдерд╛рди рдЬреЛ String::as_str рдирд╣реАрдВ String::as_str рд╡рд╣ String рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рд╕реЗ рдирд╣реАрдВ рдмрджрд▓рддрд╛ String (рдФрд░ String рдХреЛ String::as_str рдХреЗ рдЖрдХрд╛рд░ рдХреЛ рдмрджрд▓рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ рдЬрд╣рд╛рдВ рдпрд╣ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреБрдВрдЬреА рджреНрд╡рд╛рд░рд╛ рд╕рдВрдЧреНрд░рд╣реАрдд рд╣реИ)ред рдореБрдЭреЗ рдирд╣реАрдВ рдкрддрд╛ рдХрд┐ рдорд╛рдирдХ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдЗрд╕ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреА рдЧрд╛рд░рдВрдЯреА рджреЗрддреА рд╣реИ, рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рд╣рдо рдЗрд╕реЗ рдЖрд╕рд╛рдиреА рд╕реЗ рдирд┐рднрд╛ рд░рд╣реЗ рд╣реИрдВ?


рд╣рдореЗрдВ рдЖрд╡рд╢реНрдпрдХ рдШрдЯрдХ рдорд┐рд▓рддреЗ рд╣реИрдВ:


 let type_name_ptr = type_name.as_str().as_ptr(); let type_name_len = type_name.as_str().len(); 

рдФрд░ рдпрд╣ рдлрд╝рдВрдХреНрд╢рди рд▓рд┐рдЦреЗрдВ:


 dynasm!(ops ; mov rax, QWORD type_name_ptr as i64 ; mov rdx, QWORD type_name_len as i64 ; ret ); 

рдФрд░ рдЕрдВрдд рдореЗрдВ, рдЕрдВрддрд┐рдо annotate рдХреЛрдб:


 pub fn annotate<'a: 'b, 'b>(&'a self, input: &'b String, type_name: &str) -> &'b Object { let type_name = type_name.to_string(); //       let type_name_ptr = type_name.as_str().as_ptr(); let type_name_len = type_name.as_str().len(); let mut infos = self.infos.borrow_mut(); let imp = infos.entry(type_name).or_insert_with(|| unsafe { let mut ops = dynasmrt::x64::Assembler::new().unwrap(); //     `type_name` let type_name_offset = ops.offset(); dynasm!(ops ; mov rax, QWORD type_name_ptr as i64 ; mov rdx, QWORD type_name_len as i64 ; ret ); //     `as_string` let as_string_offset = ops.offset(); dynasm!(ops ; mov rax, rdi ; ret ); let buffer = ops.finalize().unwrap(); //      let whatever = input as &dyn Whatever; let whatever_obj = std::mem::transmute::<&dyn Whatever, TraitObject>(whatever); let whatever_vtable_header = whatever_obj.vtable as *const VirtualTableHeader; let vtable = ObjectVirtualTable { header: *whatever_vtable_header, type_name_fn: std::mem::transmute(buffer.ptr(type_name_offset)), as_string_fn: std::mem::transmute(buffer.ptr(as_string_offset)), }; TypeInfo { vtable, buffer } }); assert_eq!(imp.vtable.header.size, std::mem::size_of::<String>()); assert_eq!(imp.vtable.header.align, std::mem::align_of::<String>()); let object_obj = TraitObject { data: input as *const String as *const (), vtable: &imp.vtable as *const ObjectVirtualTable as *const (), }; unsafe { std::mem::transmute::<TraitObject, &dyn Object>(object_obj) } } 

dynasm рдЙрджреНрджреЗрд╢реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП dynasm рд╣рдореЗрдВ buffer рдлрд╝реАрд▓реНрдб рдХреЛ рдЕрдкрдиреЗ TypeInfo рд╕рдВрд░рдЪрдирд╛ рдореЗрдВ TypeInfo ред рдпрд╣ рдлрд╝реАрд▓реНрдб рдЙрд╕ рдореЗрдореЛрд░реА рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рддреА рд╣реИ рдЬреЛ рд╣рдорд╛рд░реЗ рдЙрддреНрдкрдиреНрди рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдХреЛрдб рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддреА рд╣реИ:


 #[allow(unused)] buffer: dynasmrt::ExecutableBuffer, 

рдФрд░ рд╕рднреА рдЯреЗрд╕реНрдЯ рдкрд╛рд╕ рдХрд░ рд▓реЗрддреЗ рд╣реИрдВ!


рд╣реЛ рдЧрдпрд╛, рдорд╛рд▓рд┐рдХ!


рдЗрддрдиреА рдЖрд╕рд╛рдиреА рд╕реЗ рдФрд░ рд╕реНрд╡рд╛рднрд╛рд╡рд┐рдХ рд░реВрдк рд╕реЗ рдЖрдк рд░рд╕реНрдЯ рдХреЛрдб рдореЗрдВ рдЯрд╛рдЗрдк рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХрд╛ рдЕрдкрдирд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдЙрддреНрдкрдиреНрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ!


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


рд╣рд╛рд▓рд╛рдБрдХрд┐, рдПрдХ (рдЕрдзрд┐рдХ) рдПрдХ рд╡рд┐рд╢реЗрд╖рддрд╛ рд╣реИ рдЬреЛ рдореИрдВ рдпрд╣рд╛рдБ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реВрдБред рдЕрд░реНрдерд╛рддреН, рдпрд╣ рддрд╛рд▓рд┐рдХрд╛ рджреНрд╡рд╛рд░рд╛ рд╡рд╕реНрддреБрддрдГ рдХрдмреНрдЬрд╛ рдХреА рдЧрдИ рд╕реНрдореГрддрд┐ рдХреЛ рдореБрдХреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реБрд░рдХреНрд╖рд┐рдд рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕рдХреЗ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдкреНрд░рдХрд╛рд░ рдХреЗ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд▓рд┐рдП рдХреЛрдИ рд╕рдВрджрд░реНрдн рдирд╣реАрдВ рд╣реИред рдПрдХ рддрд░рдл, рдпрд╣ рддрд░реНрдХрд╕рдВрдЧрдд рд╣реИ рдХрд┐ рдЖрдк рдХреЗрд╡рд▓ рдЯрд╛рдЗрдк рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХреЗ рд╕рдВрджрд░реНрднреЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╡рд░реНрдЪреБрдЕрд▓ рдЯреЗрдмрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рджреВрд╕рд░реА рдУрд░, рд░рд╕реНрдЯ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рджрд╛рди рдХреА рдЧрдИ рддрд╛рд▓рд┐рдХрд╛рдУрдВ рдореЗрдВ рдПрдХ 'static рдЬреАрд╡рдирдХрд╛рд▓ рд╣реЛрддрд╛ рд╣реИред рдХреБрдЫ рдХреЛрдб рдХреЛ рдорд╛рди рд▓реЗрдирд╛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕рдВрднрд╡ рд╣реИ рдЬреЛ рддрд╛рд▓рд┐рдХрд╛ рдХреЛ рдЗрд╕рдХреЗ рдХреБрдЫ рдЙрджреНрджреЗрд╢реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рд▓рд┐рдВрдХ рд╕реЗ рдЕрд▓рдЧ рдХрд░реЗрдЧрд╛ (рдЖрдк рдХрднреА рдирд╣реАрдВ рдЬрд╛рдирддреЗ рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЗрд╕рдХреА рдХреБрдЫ рдЧрдВрджреА рдЪрд╛рд▓ рдХреЗ рд▓рд┐рдП )ред


рд╕реНрд░реЛрдд рдХреЛрдб рдпрд╣рд╛рдВ рдкрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ ред

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


All Articles