github.com/alexflint/go-memdump@v1.1.0/single.go (about) 1 package memdump 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 "io/ioutil" 8 "reflect" 9 ) 10 11 // Encode writes a memdump of the provided object to output. You must 12 // pass a pointer to the object you wish to encode. 13 func Encode(w io.Writer, obj interface{}) error { 14 t := reflect.TypeOf(obj) 15 if t.Kind() != reflect.Ptr { 16 panic(fmt.Sprintf("expected a pointer but got %T", obj)) 17 } 18 19 // write the object data to a temporary buffer 20 var buf bytes.Buffer 21 mem := newMemEncoder(&buf) 22 ptrs, err := mem.Encode(obj) 23 if err != nil { 24 return fmt.Errorf("error while walking data: %v", err) 25 } 26 27 // write the locations at the top 28 err = encodeLocations(w, &locations{Pointers: ptrs}) 29 if err != nil { 30 return fmt.Errorf("error writing location segment: %v", err) 31 } 32 33 // now write the data segment 34 _, err = buf.WriteTo(w) 35 if err != nil { 36 return fmt.Errorf("error writing data segment: %v", err) 37 } 38 39 return nil 40 } 41 42 // Decode reads an object of the specified type from the input 43 // and stores a pointer to it at the location specified by ptrptr, 44 // which must be a pointer to a pointer. If you originally called 45 // Encode with parameter *T then you should pass **T to Decode. 46 func Decode(r io.Reader, ptrptr interface{}) error { 47 v := reflect.ValueOf(ptrptr) 48 t := v.Type() 49 if t.Kind() != reflect.Ptr || t.Elem().Kind() != reflect.Ptr { 50 panic(fmt.Sprintf("expected a pointer to a pointer but got %v", v.Type())) 51 } 52 53 // read the locations 54 var loc locations 55 err := decodeLocations(r, &loc) 56 if err != nil { 57 return fmt.Errorf("error decoding relocation data: %v", err) 58 } 59 60 buf, err := ioutil.ReadAll(r) 61 if err != nil { 62 return fmt.Errorf("error reading data segment: %v", err) 63 } 64 65 // relocate the data 66 out, err := relocate(buf, loc.Pointers, loc.Main, v.Type().Elem().Elem()) 67 if err != nil { 68 return fmt.Errorf("error relocating data: %v", err) 69 } 70 71 v.Elem().Set(reflect.ValueOf(out)) 72 return nil 73 }