deb.delta(1)
                com := deb.common()
                wire.GobEncoderT = &gobEncoderType{com}
+       case 5: // BinaryMarshaler type, one field of {{Common}}
+               // Field number 0 is CommonType
+               deb.delta(1)
+               com := deb.common()
+               wire.BinaryMarshalerT = &gobEncoderType{com}
+       case 6: // TextMarshaler type, one field of {{Common}}
+               // Field number 0 is CommonType
+               deb.delta(1)
+               com := deb.common()
+               wire.TextMarshalerT = &gobEncoderType{com}
        default:
                errorf("bad field in type %d", fieldNum)
        }
 
 
 import (
        "bytes"
+       "encoding"
        "errors"
        "io"
        "math"
 
 // decodeGobDecoder decodes something implementing the GobDecoder interface.
 // The data is encoded as a byte slice.
-func (dec *Decoder) decodeGobDecoder(state *decoderState, v reflect.Value) {
+func (dec *Decoder) decodeGobDecoder(ut *userTypeInfo, state *decoderState, v reflect.Value) {
        // Read the bytes for the value.
        b := make([]byte, state.decodeUint())
        _, err := state.b.Read(b)
        if err != nil {
                error_(err)
        }
-       // We know it's a GobDecoder, so just call the method directly.
-       err = v.Interface().(GobDecoder).GobDecode(b)
+       // We know it's one of these.
+       switch ut.externalDec {
+       case xGob:
+               err = v.Interface().(GobDecoder).GobDecode(b)
+       case xBinary:
+               err = v.Interface().(encoding.BinaryUnmarshaler).UnmarshalBinary(b)
+       case xText:
+               err = v.Interface().(encoding.TextUnmarshaler).UnmarshalText(b)
+       }
        if err != nil {
                error_(err)
        }
 func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProgress map[reflect.Type]*decOp) (*decOp, int) {
        ut := userType(rt)
        // If the type implements GobEncoder, we handle it without further processing.
-       if ut.isGobDecoder {
+       if ut.externalDec != 0 {
                return dec.gobDecodeOpFor(ut)
        }
+
        // If this type is already in progress, it's a recursive type (e.g. map[string]*T).
        // Return the pointer to the op we're already building.
        if opPtr := inProgress[rt]; opPtr != nil {
                                state.dec.ignoreStruct(*enginePtr)
                        }
 
-               case wire.GobEncoderT != nil:
+               case wire.GobEncoderT != nil, wire.BinaryMarshalerT != nil, wire.TextMarshalerT != nil:
                        op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
                                state.dec.ignoreGobDecoder(state)
                        }
                } else {
                        v = reflect.NewAt(rcvrType, p).Elem()
                }
-               state.dec.decodeGobDecoder(state, v)
+               state.dec.decodeGobDecoder(ut, state, v)
        }
        return &op, int(ut.indir)
 
        inProgress[fr] = fw
        ut := userType(fr)
        wire, ok := dec.wireType[fw]
-       // If fr is a GobDecoder, the wire type must be GobEncoder.
-       // And if fr is not a GobDecoder, the wire type must not be either.
-       if ut.isGobDecoder != (ok && wire.GobEncoderT != nil) { // the parentheses look odd but are correct.
+       // If wire was encoded with an encoding method, fr must have that method.
+       // And if not, it must not.
+       // At most one of the booleans in ut is set.
+       // We could possibly relax this constraint in the future in order to
+       // choose the decoding method using the data in the wireType.
+       // The parentheses look odd but are correct.
+       if (ut.externalDec == xGob) != (ok && wire.GobEncoderT != nil) ||
+               (ut.externalDec == xBinary) != (ok && wire.BinaryMarshalerT != nil) ||
+               (ut.externalDec == xText) != (ok && wire.TextMarshalerT != nil) {
                return false
        }
-       if ut.isGobDecoder { // This test trumps all others.
+       if ut.externalDec != 0 { // This test trumps all others.
                return true
        }
        switch t := ut.base; t.Kind() {
 func (dec *Decoder) compileDec(remoteId typeId, ut *userTypeInfo) (engine *decEngine, err error) {
        rt := ut.base
        srt := rt
-       if srt.Kind() != reflect.Struct ||
-               ut.isGobDecoder {
+       if srt.Kind() != reflect.Struct || ut.externalDec != 0 {
                return dec.compileSingle(remoteId, ut)
        }
        var wireStruct *structType
                return
        }
        engine := *enginePtr
-       if st := base; st.Kind() == reflect.Struct && !ut.isGobDecoder {
+       if st := base; st.Kind() == reflect.Struct && ut.externalDec == 0 {
                if engine.numInstr == 0 && st.NumField() > 0 && len(dec.wireType[wireId].StructT.Field) > 0 {
                        name := base.Name()
                        errorf("type mismatch: no fields matched compiling decoder for %s", name)
 
 the destination variable must be able to represent the value or the decode
 operation will fail.
 
-Structs, arrays and slices are also supported.  Structs encode and
-decode only exported fields. Strings and arrays of bytes are supported
-with a special, efficient representation (see below).  When a slice
-is decoded, if the existing slice has capacity the slice will be
-extended in place; if not, a new array is allocated.  Regardless,
-the length of the resulting slice reports the number of elements
-decoded.
-
-Functions and channels cannot be sent in a gob.  Attempting
-to encode a value that contains one will fail.
-
-The rest of this comment documents the encoding, details that are not important
-for most users.  Details are presented bottom-up.
+Structs, arrays and slices are also supported. Structs encode and decode only
+exported fields. Strings and arrays of bytes are supported with a special,
+efficient representation (see below). When a slice is decoded, if the existing
+slice has capacity the slice will be extended in place; if not, a new array is
+allocated. Regardless, the length of the resulting slice reports the number of
+elements decoded.
+
+Functions and channels cannot be sent in a gob. Attempting to encode a value
+that contains one will fail.
+
+Gob can encode a value of any type implementing the GobEncoder,
+encoding.BinaryMarshaler, or encoding.TextMarshaler interfaces by calling the
+corresponding method, in that order of preference.
+
+Gob can decode a value of any type implementing the GobDecoder,
+encoding.BinaryUnmarshaler, or encoding.TextUnmarshaler interfaces by calling
+the corresponding method, again in that order of preference.
+
+Encoding Details
+
+This section documents the encoding, details that are not important for most
+users. Details are presented bottom-up.
 
 An unsigned integer is sent one of two ways.  If it is less than 128, it is sent
 as a byte with that value.  Otherwise it is sent as a minimal-length big-endian
 
 
 import (
        "bytes"
+       "encoding"
        "math"
        "reflect"
        "unsafe"
 
 // encGobEncoder encodes a value that implements the GobEncoder interface.
 // The data is sent as a byte array.
-func (enc *Encoder) encodeGobEncoder(b *bytes.Buffer, v reflect.Value) {
+func (enc *Encoder) encodeGobEncoder(b *bytes.Buffer, ut *userTypeInfo, v reflect.Value) {
        // TODO: should we catch panics from the called method?
-       // We know it's a GobEncoder, so just call the method directly.
-       data, err := v.Interface().(GobEncoder).GobEncode()
+
+       var data []byte
+       var err error
+       // We know it's one of these.
+       switch ut.externalEnc {
+       case xGob:
+               data, err = v.Interface().(GobEncoder).GobEncode()
+       case xBinary:
+               data, err = v.Interface().(encoding.BinaryMarshaler).MarshalBinary()
+       case xText:
+               data, err = v.Interface().(encoding.TextMarshaler).MarshalText()
+       }
        if err != nil {
                error_(err)
        }
 func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp) (*encOp, int) {
        ut := userType(rt)
        // If the type implements GobEncoder, we handle it without further processing.
-       if ut.isGobEncoder {
+       if ut.externalEnc != 0 {
                return enc.gobEncodeOpFor(ut)
        }
        // If this type is already in progress, it's a recursive type (e.g. map[string]*T).
                        return
                }
                state.update(i)
-               state.enc.encodeGobEncoder(state.b, v)
+               state.enc.encodeGobEncoder(state.b, ut, v)
        }
        return &op, int(ut.encIndir) // encIndir: op will get called with p == address of receiver.
 }
        engine := new(encEngine)
        seen := make(map[reflect.Type]*encOp)
        rt := ut.base
-       if ut.isGobEncoder {
+       if ut.externalEnc != 0 {
                rt = ut.user
        }
-       if !ut.isGobEncoder &&
+       if ut.externalEnc == 0 &&
                srt.Kind() == reflect.Struct {
                for fieldNum, wireFieldNum := 0, 0; fieldNum < srt.NumField(); fieldNum++ {
                        f := srt.Field(fieldNum)
        defer catchError(&enc.err)
        engine := enc.lockAndGetEncEngine(ut)
        indir := ut.indir
-       if ut.isGobEncoder {
+       if ut.externalEnc != 0 {
                indir = int(ut.encIndir)
        }
        for i := 0; i < indir; i++ {
                value = reflect.Indirect(value)
        }
-       if !ut.isGobEncoder && value.Type().Kind() == reflect.Struct {
+       if ut.externalEnc == 0 && value.Type().Kind() == reflect.Struct {
                enc.encodeStruct(b, engine, unsafeAddr(value))
        } else {
                enc.encodeSingle(b, engine, unsafeAddr(value))
 
 // sendType sends the type info to the other side, if necessary.
 func (enc *Encoder) sendType(w io.Writer, state *encoderState, origt reflect.Type) (sent bool) {
        ut := userType(origt)
-       if ut.isGobEncoder {
+       if ut.externalEnc != 0 {
                // The rules are different: regardless of the underlying type's representation,
                // we need to tell the other side that the base type is a GobEncoder.
                return enc.sendActualType(w, state, ut, ut.base)
        // Make sure the type is known to the other side.
        // First, have we already sent this type?
        rt := ut.base
-       if ut.isGobEncoder {
+       if ut.externalEnc != 0 {
                rt = ut.user
        }
        if _, alreadySent := enc.sent[rt]; !alreadySent {
 
 
 type ValueGobber string // encodes with a value, decodes with a pointer.
 
+type BinaryGobber int
+
+type BinaryValueGobber string
+
+type TextGobber int
+
+type TextValueGobber string
+
 // The relevant methods
 
 func (g *ByteStruct) GobEncode() ([]byte, error) {
        return err
 }
 
+func (g *BinaryGobber) MarshalBinary() ([]byte, error) {
+       return []byte(fmt.Sprintf("VALUE=%d", *g)), nil
+}
+
+func (g *BinaryGobber) UnmarshalBinary(data []byte) error {
+       _, err := fmt.Sscanf(string(data), "VALUE=%d", (*int)(g))
+       return err
+}
+
+func (g *TextGobber) MarshalText() ([]byte, error) {
+       return []byte(fmt.Sprintf("VALUE=%d", *g)), nil
+}
+
+func (g *TextGobber) UnmarshalText(data []byte) error {
+       _, err := fmt.Sscanf(string(data), "VALUE=%d", (*int)(g))
+       return err
+}
+
 func (v ValueGobber) GobEncode() ([]byte, error) {
        return []byte(fmt.Sprintf("VALUE=%s", v)), nil
 }
        return err
 }
 
+func (v BinaryValueGobber) MarshalBinary() ([]byte, error) {
+       return []byte(fmt.Sprintf("VALUE=%s", v)), nil
+}
+
+func (v *BinaryValueGobber) UnmarshalBinary(data []byte) error {
+       _, err := fmt.Sscanf(string(data), "VALUE=%s", (*string)(v))
+       return err
+}
+
+func (v TextValueGobber) MarshalText() ([]byte, error) {
+       return []byte(fmt.Sprintf("VALUE=%s", v)), nil
+}
+
+func (v *TextValueGobber) UnmarshalText(data []byte) error {
+       _, err := fmt.Sscanf(string(data), "VALUE=%s", (*string)(v))
+       return err
+}
+
 // Structs that include GobEncodable fields.
 
 type GobTest0 struct {
 type GobTest3 struct {
        X int // guarantee we have  something in common with GobTest*
        G *Gobber
+       B *BinaryGobber
+       T *TextGobber
 }
 
 type GobTest4 struct {
-       X int // guarantee we have  something in common with GobTest*
-       V ValueGobber
+       X  int // guarantee we have  something in common with GobTest*
+       V  ValueGobber
+       BV BinaryValueGobber
+       TV TextValueGobber
 }
 
 type GobTest5 struct {
-       X int // guarantee we have  something in common with GobTest*
-       V *ValueGobber
+       X  int // guarantee we have  something in common with GobTest*
+       V  *ValueGobber
+       BV *BinaryValueGobber
+       TV *TextValueGobber
 }
 
 type GobTest6 struct {
-       X int // guarantee we have  something in common with GobTest*
-       V ValueGobber
-       W *ValueGobber
+       X  int // guarantee we have  something in common with GobTest*
+       V  ValueGobber
+       W  *ValueGobber
+       BV BinaryValueGobber
+       BW *BinaryValueGobber
+       TV TextValueGobber
+       TW *TextValueGobber
 }
 
 type GobTest7 struct {
-       X int // guarantee we have  something in common with GobTest*
-       V *ValueGobber
-       W ValueGobber
+       X  int // guarantee we have  something in common with GobTest*
+       V  *ValueGobber
+       W  ValueGobber
+       BV *BinaryValueGobber
+       BW BinaryValueGobber
+       TV *TextValueGobber
+       TW TextValueGobber
 }
 
 type GobTestIgnoreEncoder struct {
        // Now a field that's not a structure.
        b.Reset()
        gobber := Gobber(23)
-       err = enc.Encode(GobTest3{17, &gobber})
+       bgobber := BinaryGobber(24)
+       tgobber := TextGobber(25)
+       err = enc.Encode(GobTest3{17, &gobber, &bgobber, &tgobber})
        if err != nil {
                t.Fatal("encode error:", err)
        }
        if err != nil {
                t.Fatal("decode error:", err)
        }
-       if *y.G != 23 {
+       if *y.G != 23 || *y.B != 24 || *y.T != 25 {
                t.Errorf("expected '23 got %d", *y.G)
        }
 }
        // first, string in field to byte in field
        b := new(bytes.Buffer)
        enc := NewEncoder(b)
-       err := enc.Encode(GobTest4{17, ValueGobber("hello")})
+       err := enc.Encode(GobTest4{17, ValueGobber("hello"), BinaryValueGobber("Καλημέρα"), TextValueGobber("こんにちは")})
        if err != nil {
                t.Fatal("encode error:", err)
        }
        if err != nil {
                t.Fatal("decode error:", err)
        }
-       if *x.V != "hello" {
+       if *x.V != "hello" || *x.BV != "Καλημέρα" || *x.TV != "こんにちは" {
                t.Errorf("expected `hello` got %s", x.V)
        }
 }
 func TestGobEncoderValueThenPointer(t *testing.T) {
        v := ValueGobber("forty-two")
        w := ValueGobber("six-by-nine")
+       bv := BinaryValueGobber("1nanocentury")
+       bw := BinaryValueGobber("πseconds")
+       tv := TextValueGobber("gravitationalacceleration")
+       tw := TextValueGobber("π²ft/s²")
 
        // this was a bug: encoding a GobEncoder by value before a GobEncoder
        // pointer would cause duplicate type definitions to be sent.
 
        b := new(bytes.Buffer)
        enc := NewEncoder(b)
-       if err := enc.Encode(GobTest6{42, v, &w}); err != nil {
+       if err := enc.Encode(GobTest6{42, v, &w, bv, &bw, tv, &tw}); err != nil {
                t.Fatal("encode error:", err)
        }
        dec := NewDecoder(b)
        if err := dec.Decode(x); err != nil {
                t.Fatal("decode error:", err)
        }
+
        if got, want := x.V, v; got != want {
                t.Errorf("v = %q, want %q", got, want)
        }
        } else if *got != want {
                t.Errorf("w = %q, want %q", *got, want)
        }
+
+       if got, want := x.BV, bv; got != want {
+               t.Errorf("bv = %q, want %q", got, want)
+       }
+       if got, want := x.BW, bw; got == nil {
+               t.Errorf("bw = nil, want %q", want)
+       } else if *got != want {
+               t.Errorf("bw = %q, want %q", *got, want)
+       }
+
+       if got, want := x.TV, tv; got != want {
+               t.Errorf("tv = %q, want %q", got, want)
+       }
+       if got, want := x.TW, tw; got == nil {
+               t.Errorf("tw = nil, want %q", want)
+       } else if *got != want {
+               t.Errorf("tw = %q, want %q", *got, want)
+       }
 }
 
 // Test that we can use a pointer then a value type of a GobEncoder
 func TestGobEncoderPointerThenValue(t *testing.T) {
        v := ValueGobber("forty-two")
        w := ValueGobber("six-by-nine")
+       bv := BinaryValueGobber("1nanocentury")
+       bw := BinaryValueGobber("πseconds")
+       tv := TextValueGobber("gravitationalacceleration")
+       tw := TextValueGobber("π²ft/s²")
 
        b := new(bytes.Buffer)
        enc := NewEncoder(b)
-       if err := enc.Encode(GobTest7{42, &v, w}); err != nil {
+       if err := enc.Encode(GobTest7{42, &v, w, &bv, bw, &tv, tw}); err != nil {
                t.Fatal("encode error:", err)
        }
        dec := NewDecoder(b)
        if err := dec.Decode(x); err != nil {
                t.Fatal("decode error:", err)
        }
+
        if got, want := x.V, v; got == nil {
                t.Errorf("v = nil, want %q", want)
        } else if *got != want {
-               t.Errorf("v = %q, want %q", got, want)
+               t.Errorf("v = %q, want %q", *got, want)
        }
        if got, want := x.W, w; got != want {
                t.Errorf("w = %q, want %q", got, want)
        }
+
+       if got, want := x.BV, bv; got == nil {
+               t.Errorf("bv = nil, want %q", want)
+       } else if *got != want {
+               t.Errorf("bv = %q, want %q", *got, want)
+       }
+       if got, want := x.BW, bw; got != want {
+               t.Errorf("bw = %q, want %q", got, want)
+       }
+
+       if got, want := x.TV, tv; got == nil {
+               t.Errorf("tv = nil, want %q", want)
+       } else if *got != want {
+               t.Errorf("tv = %q, want %q", *got, want)
+       }
+       if got, want := x.TW, tw; got != want {
+               t.Errorf("tw = %q, want %q", got, want)
+       }
 }
 
 func TestGobEncoderFieldTypeError(t *testing.T) {
        // First a field that's a structure.
        enc := NewEncoder(b)
        gobber := Gobber(23)
-       err := enc.Encode(GobTest3{17, &gobber})
+       bgobber := BinaryGobber(24)
+       tgobber := TextGobber(25)
+       err := enc.Encode(GobTest3{17, &gobber, &bgobber, &tgobber})
        if err != nil {
                t.Fatal("encode error:", err)
        }
 
 package gob
 
 import (
+       "encoding"
        "errors"
        "fmt"
        "os"
 // to the package.  It's computed once and stored in a map keyed by reflection
 // type.
 type userTypeInfo struct {
-       user         reflect.Type // the type the user handed us
-       base         reflect.Type // the base type after all indirections
-       indir        int          // number of indirections to reach the base type
-       isGobEncoder bool         // does the type implement GobEncoder?
-       isGobDecoder bool         // does the type implement GobDecoder?
-       encIndir     int8         // number of indirections to reach the receiver type; may be negative
-       decIndir     int8         // number of indirections to reach the receiver type; may be negative
-}
+       user        reflect.Type // the type the user handed us
+       base        reflect.Type // the base type after all indirections
+       indir       int          // number of indirections to reach the base type
+       externalEnc int          // xGob, xBinary, or xText
+       externalDec int          // xGob, xBinary or xText
+       encIndir    int8         // number of indirections to reach the receiver type; may be negative
+       decIndir    int8         // number of indirections to reach the receiver type; may be negative
+}
+
+// externalEncoding bits
+const (
+       xGob    = 1 + iota // GobEncoder or GobDecoder
+       xBinary            // encoding.BinaryMarshaler or encoding.BinaryUnmarshaler
+       xText              // encoding.TextMarshaler or encoding.TextUnmarshaler
+)
 
 var (
        // Protected by an RWMutex because we read it a lot and write
                }
                ut.indir++
        }
-       ut.isGobEncoder, ut.encIndir = implementsInterface(ut.user, gobEncoderInterfaceType)
-       ut.isGobDecoder, ut.decIndir = implementsInterface(ut.user, gobDecoderInterfaceType)
+
+       if ok, indir := implementsInterface(ut.user, gobEncoderInterfaceType); ok {
+               ut.externalEnc, ut.encIndir = xGob, indir
+       } else if ok, indir := implementsInterface(ut.user, binaryMarshalerInterfaceType); ok {
+               ut.externalEnc, ut.encIndir = xBinary, indir
+       } else if ok, indir := implementsInterface(ut.user, textMarshalerInterfaceType); ok {
+               ut.externalEnc, ut.encIndir = xText, indir
+       }
+
+       if ok, indir := implementsInterface(ut.user, gobDecoderInterfaceType); ok {
+               ut.externalDec, ut.decIndir = xGob, indir
+       } else if ok, indir := implementsInterface(ut.user, binaryUnmarshalerInterfaceType); ok {
+               ut.externalDec, ut.decIndir = xBinary, indir
+       } else if ok, indir := implementsInterface(ut.user, textUnmarshalerInterfaceType); ok {
+               ut.externalDec, ut.decIndir = xText, indir
+       }
+
        userTypeCache[rt] = ut
        return
 }
 
 var (
-       gobEncoderInterfaceType = reflect.TypeOf((*GobEncoder)(nil)).Elem()
-       gobDecoderInterfaceType = reflect.TypeOf((*GobDecoder)(nil)).Elem()
+       gobEncoderInterfaceType        = reflect.TypeOf((*GobEncoder)(nil)).Elem()
+       gobDecoderInterfaceType        = reflect.TypeOf((*GobDecoder)(nil)).Elem()
+       binaryMarshalerInterfaceType   = reflect.TypeOf((*encoding.BinaryMarshaler)(nil)).Elem()
+       binaryUnmarshalerInterfaceType = reflect.TypeOf((*encoding.BinaryUnmarshaler)(nil)).Elem()
+       textMarshalerInterfaceType     = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
+       textUnmarshalerInterfaceType   = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
 )
 
 // implementsInterface reports whether the type implements the
 // works through typeIds and userTypeInfos alone.
 func newTypeObject(name string, ut *userTypeInfo, rt reflect.Type) (gobType, error) {
        // Does this type implement GobEncoder?
-       if ut.isGobEncoder {
+       if ut.externalEnc != 0 {
                return newGobEncoderType(name), nil
        }
        var err error
 // To maintain binary compatibility, if you extend this type, always put
 // the new fields last.
 type wireType struct {
-       ArrayT      *arrayType
-       SliceT      *sliceType
-       StructT     *structType
-       MapT        *mapType
-       GobEncoderT *gobEncoderType
+       ArrayT           *arrayType
+       SliceT           *sliceType
+       StructT          *structType
+       MapT             *mapType
+       GobEncoderT      *gobEncoderType
+       BinaryMarshalerT *gobEncoderType
+       TextMarshalerT   *gobEncoderType
 }
 
 func (w *wireType) string() string {
                return w.MapT.Name
        case w.GobEncoderT != nil:
                return w.GobEncoderT.Name
+       case w.BinaryMarshalerT != nil:
+               return w.BinaryMarshalerT.Name
+       case w.TextMarshalerT != nil:
+               return w.TextMarshalerT.Name
        }
        return unknown
 }
 // typeLock must be held.
 func getTypeInfo(ut *userTypeInfo) (*typeInfo, error) {
        rt := ut.base
-       if ut.isGobEncoder {
+       if ut.externalEnc != 0 {
                // We want the user type, not the base type.
                rt = ut.user
        }
        }
        info.id = gt.id()
 
-       if ut.isGobEncoder {
+       if ut.externalEnc != 0 {
                userType, err := getType(rt.Name(), ut, rt)
                if err != nil {
                        return nil, err
                }
-               info.wire = &wireType{GobEncoderT: userType.id().gobType().(*gobEncoderType)}
+               gt := userType.id().gobType().(*gobEncoderType)
+               switch ut.externalEnc {
+               case xGob:
+                       info.wire = &wireType{GobEncoderT: gt}
+               case xBinary:
+                       info.wire = &wireType{BinaryMarshalerT: gt}
+               case xText:
+                       info.wire = &wireType{TextMarshalerT: gt}
+               }
                typeInfoMap[ut.user] = info
                return info, nil
        }