fn 
() {
    let x = 5u8;
    let y = "Cold".to_string();

    call_method(x);
    call_method(y);

    // dynamit dispatch
    let x1: u8 = 1;
    let y1: String = "Cool".to_string();

    let x1obj = TraitObj {
        data: &x1,
        vtable: &F1_for_u8_vtable
    };
    let y1obj = TraitObj {
        data: &y1,
        vtable: &F1_for_String_vtable
    };
    (x1obj.vtable.method)(x1.data);
    (y1obj.vtable.method)(y1.data);
}

trait F1 {
    fn method(&self) -> String;
}

impl F1 for u8 {
    fn method(&self) -> String { format!("u8 : {}", *self) }
    // * 什么意思
}

impl F1 for String {
    fn method(&self) -> String { format!("string : {}", *self) }
}


fn call_method<T:F1>(x: T) {
    println!("{}", x.method());
}

// dynamic dispatch

pub struct TraitObj {
    // two pointer
    pub data: *mut (),  // addresses the data of type T
    pub vtable: *mut (),  // vtable(virtual method table) Foo 在 T 上的实现
    // a struct of function pointers, pointing to the concrete piece of machine code for each method in the implementation
}

struct F1Vtable {
    destructor: fn(*mut ()),
    size: usize,
    align: usize,
    mtehod: fn(*const ()) -> String,
}

fn call_method_on_u8(x: *const ()) -> String {
    let byte: &u8 = unsafe { &*(x as *const u8) };
    byte.method()
}

static F1_for_u8_vtable: F1Vtable = F1Vtable {
    destructor: /* */,
    size: 1,
    align: 1,

    method: call_method_on_u8 as fn(*const ()) -> String,
}

fn call_method_on_String(x: *const ()) -> String {
    let string: &String = unsafe { &*(x as *const String) };
    string.method()
}

static F1_for_String_vtable: F1Vtable = F1Vtable {
    destructor: /* */,
    size: 24,
    align: 8,
    method: call_method_on_String as fn(*const ()) -> String,
}

main