gob: beginning of support for GobEncoder/GobDecoder interfaces.

This allows a data item that can marshal itself to be transmitted by its
own encoding, enabling some types to be handled that cannot be
normally, plus providing a way to use gobs on data with unexported
fields.

In this CL, the necessary methods are protected by leading _, so only
package gob can use the facilities (in its tests, of course); this
code is not ready for real use yet.  I could be talked into enabling
it for experimentation, though.  The main drawback is that the
methods must be implemented by the actual type passed through,
not by an indirection from it.  For instance, if *T implements
GobEncoder, you must send a *T, not a T.  This will be addressed
in due course.

Also there is improved commentary and a couple of unrelated
minor bug fixes.

R=rsc
CC=golang-dev
https://golang.org/cl/4243056
diff --git a/src/pkg/gob/debug.go b/src/pkg/gob/debug.go
index e458390..69c83bd 100644
--- a/src/pkg/gob/debug.go
+++ b/src/pkg/gob/debug.go
@@ -155,6 +155,16 @@
 
 // Debug prints a human-readable representation of the gob data read from r.
 func Debug(r io.Reader) {
+	err := debug(r)
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "gob debug: %s\n", err)
+	}
+}
+
+// debug implements Debug, but catches panics and returns
+// them as errors to be printed by Debug.
+func debug(r io.Reader) (err os.Error) {
+	defer catchError(&err)
 	fmt.Fprintln(os.Stderr, "Start of debugging")
 	deb := &debugger{
 		r:        newPeekReader(r),
@@ -166,6 +176,7 @@
 		deb.remainingKnown = true
 	}
 	deb.gobStream()
+	return
 }
 
 // note that we've consumed some bytes
@@ -386,11 +397,15 @@
 		// Field number 1 is type Id of key
 		deb.delta(1)
 		keyId := deb.typeId()
-		wire.SliceT = &sliceType{com, id}
 		// Field number 2 is type Id of elem
 		deb.delta(1)
 		elemId := deb.typeId()
 		wire.MapT = &mapType{com, keyId, elemId}
+	case 4: // GobEncoder type, one field of {{Common}}
+		// Field number 0 is CommonType
+		deb.delta(1)
+		com := deb.common()
+		wire.GobEncoderT = &gobEncoderType{com}
 	default:
 		errorf("bad field in type %d", fieldNum)
 	}
@@ -507,6 +522,8 @@
 		for i, field := range wire.StructT.Field {
 			fmt.Fprintf(os.Stderr, "%sfield %d:\t%s\tid=%d\n", indent+1, i, field.Name, field.Id)
 		}
+	case wire.GobEncoderT != nil:
+		deb.printCommonType(indent, "GobEncoder", &wire.GobEncoderT.CommonType)
 	}
 	indent--
 	fmt.Fprintf(os.Stderr, "%s}\n", indent)
@@ -538,6 +555,8 @@
 		deb.sliceValue(indent, wire)
 	case wire.StructT != nil:
 		deb.structValue(indent, id)
+	case wire.GobEncoderT != nil:
+		deb.gobEncoderValue(indent, id)
 	default:
 		panic("bad wire type for field")
 	}
@@ -654,3 +673,17 @@
 	fmt.Fprintf(os.Stderr, "%s} // end %s struct\n", indent, id.name())
 	deb.dump(">> End of struct value of type %d %q", id, id.name())
 }
+
+// GobEncoderValue:
+//	uint(n) byte*n
+func (deb *debugger) gobEncoderValue(indent tab, id typeId) {
+	len := deb.uint64()
+	deb.dump("GobEncoder value of %q id=%d, length %d\n", id.name(), id, len)
+	fmt.Fprintf(os.Stderr, "%s%s (implements GobEncoder)\n", indent, id.name())
+	data := make([]byte, len)
+	_, err := deb.r.Read(data)
+	if err != nil {
+		errorf("gobEncoder data read: %s", err)
+	}
+	fmt.Fprintf(os.Stderr, "%s[% .2x]\n", indent+1, data)
+}