Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
go
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
go
Commits
98607d01
Commit
98607d01
authored
Jul 29, 2009
by
Rob Pike
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
handle unsupported types safely.
R=rsc DELTA=154 (71 added, 6 deleted, 77 changed) OCL=32483 CL=32492
parent
312bd7a1
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
140 additions
and
75 deletions
+140
-75
src/pkg/gob/codec_test.go
src/pkg/gob/codec_test.go
+25
-8
src/pkg/gob/encode.go
src/pkg/gob/encode.go
+34
-16
src/pkg/gob/encoder.go
src/pkg/gob/encoder.go
+7
-2
src/pkg/gob/encoder_test.go
src/pkg/gob/encoder_test.go
+3
-3
src/pkg/gob/type.go
src/pkg/gob/type.go
+66
-45
src/pkg/gob/type_test.go
src/pkg/gob/type_test.go
+5
-1
No files found.
src/pkg/gob/codec_test.go
View file @
98607d01
...
@@ -564,7 +564,7 @@ func TestEndToEnd(t *testing.T) {
...
@@ -564,7 +564,7 @@ func TestEndToEnd(t *testing.T) {
b
:=
new
(
bytes
.
Buffer
);
b
:=
new
(
bytes
.
Buffer
);
encode
(
b
,
t1
);
encode
(
b
,
t1
);
var
_t1
T1
;
var
_t1
T1
;
decode
(
b
,
getTypeInfo
(
reflect
.
Typeof
(
_t1
))
.
id
,
&
_t1
);
decode
(
b
,
getTypeInfo
NoError
(
reflect
.
Typeof
(
_t1
))
.
id
,
&
_t1
);
if
!
reflect
.
DeepEqual
(
t1
,
&
_t1
)
{
if
!
reflect
.
DeepEqual
(
t1
,
&
_t1
)
{
t
.
Errorf
(
"encode expected %v got %v"
,
*
t1
,
_t1
);
t
.
Errorf
(
"encode expected %v got %v"
,
*
t1
,
_t1
);
}
}
...
@@ -580,7 +580,7 @@ func TestOverflow(t *testing.T) {
...
@@ -580,7 +580,7 @@ func TestOverflow(t *testing.T) {
}
}
var
it
inputT
;
var
it
inputT
;
var
err
os
.
Error
;
var
err
os
.
Error
;
id
:=
getTypeInfo
(
reflect
.
Typeof
(
it
))
.
id
;
id
:=
getTypeInfo
NoError
(
reflect
.
Typeof
(
it
))
.
id
;
b
:=
new
(
bytes
.
Buffer
);
b
:=
new
(
bytes
.
Buffer
);
// int8
// int8
...
@@ -733,7 +733,7 @@ func TestNesting(t *testing.T) {
...
@@ -733,7 +733,7 @@ func TestNesting(t *testing.T) {
b
:=
new
(
bytes
.
Buffer
);
b
:=
new
(
bytes
.
Buffer
);
encode
(
b
,
rt
);
encode
(
b
,
rt
);
var
drt
RT
;
var
drt
RT
;
decode
(
b
,
getTypeInfo
(
reflect
.
Typeof
(
drt
))
.
id
,
&
drt
);
decode
(
b
,
getTypeInfo
NoError
(
reflect
.
Typeof
(
drt
))
.
id
,
&
drt
);
if
drt
.
a
!=
rt
.
a
{
if
drt
.
a
!=
rt
.
a
{
t
.
Errorf
(
"nesting: encode expected %v got %v"
,
*
rt
,
drt
);
t
.
Errorf
(
"nesting: encode expected %v got %v"
,
*
rt
,
drt
);
}
}
...
@@ -775,7 +775,7 @@ func TestAutoIndirection(t *testing.T) {
...
@@ -775,7 +775,7 @@ func TestAutoIndirection(t *testing.T) {
b
:=
new
(
bytes
.
Buffer
);
b
:=
new
(
bytes
.
Buffer
);
encode
(
b
,
t1
);
encode
(
b
,
t1
);
var
t0
T0
;
var
t0
T0
;
t0Id
:=
getTypeInfo
(
reflect
.
Typeof
(
t0
))
.
id
;
t0Id
:=
getTypeInfo
NoError
(
reflect
.
Typeof
(
t0
))
.
id
;
decode
(
b
,
t0Id
,
&
t0
);
decode
(
b
,
t0Id
,
&
t0
);
if
t0
.
a
!=
17
||
t0
.
b
!=
177
||
t0
.
c
!=
1777
||
t0
.
d
!=
17777
{
if
t0
.
a
!=
17
||
t0
.
b
!=
177
||
t0
.
c
!=
1777
||
t0
.
d
!=
17777
{
t
.
Errorf
(
"t1->t0: expected {17 177 1777 17777}; got %v"
,
t0
);
t
.
Errorf
(
"t1->t0: expected {17 177 1777 17777}; got %v"
,
t0
);
...
@@ -800,7 +800,7 @@ func TestAutoIndirection(t *testing.T) {
...
@@ -800,7 +800,7 @@ func TestAutoIndirection(t *testing.T) {
b
.
Reset
();
b
.
Reset
();
encode
(
b
,
t0
);
encode
(
b
,
t0
);
t1
=
T1
{};
t1
=
T1
{};
t1Id
:=
getTypeInfo
(
reflect
.
Typeof
(
t1
))
.
id
;
t1Id
:=
getTypeInfo
NoError
(
reflect
.
Typeof
(
t1
))
.
id
;
decode
(
b
,
t1Id
,
&
t1
);
decode
(
b
,
t1Id
,
&
t1
);
if
t1
.
a
!=
17
||
*
t1
.
b
!=
177
||
**
t1
.
c
!=
1777
||
***
t1
.
d
!=
17777
{
if
t1
.
a
!=
17
||
*
t1
.
b
!=
177
||
**
t1
.
c
!=
1777
||
***
t1
.
d
!=
17777
{
t
.
Errorf
(
"t0->t1 expected {17 177 1777 17777}; got {%d %d %d %d}"
,
t1
.
a
,
*
t1
.
b
,
**
t1
.
c
,
***
t1
.
d
);
t
.
Errorf
(
"t0->t1 expected {17 177 1777 17777}; got {%d %d %d %d}"
,
t1
.
a
,
*
t1
.
b
,
**
t1
.
c
,
***
t1
.
d
);
...
@@ -810,7 +810,7 @@ func TestAutoIndirection(t *testing.T) {
...
@@ -810,7 +810,7 @@ func TestAutoIndirection(t *testing.T) {
b
.
Reset
();
b
.
Reset
();
encode
(
b
,
t0
);
encode
(
b
,
t0
);
t2
=
T2
{};
t2
=
T2
{};
t2Id
:=
getTypeInfo
(
reflect
.
Typeof
(
t2
))
.
id
;
t2Id
:=
getTypeInfo
NoError
(
reflect
.
Typeof
(
t2
))
.
id
;
decode
(
b
,
t2Id
,
&
t2
);
decode
(
b
,
t2Id
,
&
t2
);
if
***
t2
.
a
!=
17
||
**
t2
.
b
!=
177
||
*
t2
.
c
!=
1777
||
t2
.
d
!=
17777
{
if
***
t2
.
a
!=
17
||
**
t2
.
b
!=
177
||
*
t2
.
c
!=
1777
||
t2
.
d
!=
17777
{
t
.
Errorf
(
"t0->t2 expected {17 177 1777 17777}; got {%d %d %d %d}"
,
***
t2
.
a
,
**
t2
.
b
,
*
t2
.
c
,
t2
.
d
);
t
.
Errorf
(
"t0->t2 expected {17 177 1777 17777}; got {%d %d %d %d}"
,
***
t2
.
a
,
**
t2
.
b
,
*
t2
.
c
,
t2
.
d
);
...
@@ -848,7 +848,7 @@ func TestReorderedFields(t *testing.T) {
...
@@ -848,7 +848,7 @@ func TestReorderedFields(t *testing.T) {
rt0
.
c
=
3.14159
;
rt0
.
c
=
3.14159
;
b
:=
new
(
bytes
.
Buffer
);
b
:=
new
(
bytes
.
Buffer
);
encode
(
b
,
rt0
);
encode
(
b
,
rt0
);
rt0Id
:=
getTypeInfo
(
reflect
.
Typeof
(
rt0
))
.
id
;
rt0Id
:=
getTypeInfo
NoError
(
reflect
.
Typeof
(
rt0
))
.
id
;
var
rt1
RT1
;
var
rt1
RT1
;
// Wire type is RT0, local type is RT1.
// Wire type is RT0, local type is RT1.
decode
(
b
,
rt0Id
,
&
rt1
);
decode
(
b
,
rt0Id
,
&
rt1
);
...
@@ -886,7 +886,7 @@ func TestIgnoredFields(t *testing.T) {
...
@@ -886,7 +886,7 @@ func TestIgnoredFields(t *testing.T) {
b
:=
new
(
bytes
.
Buffer
);
b
:=
new
(
bytes
.
Buffer
);
encode
(
b
,
it0
);
encode
(
b
,
it0
);
rt0Id
:=
getTypeInfo
(
reflect
.
Typeof
(
it0
))
.
id
;
rt0Id
:=
getTypeInfo
NoError
(
reflect
.
Typeof
(
it0
))
.
id
;
var
rt1
RT1
;
var
rt1
RT1
;
// Wire type is IT0, local type is RT1.
// Wire type is IT0, local type is RT1.
err
:=
decode
(
b
,
rt0Id
,
&
rt1
);
err
:=
decode
(
b
,
rt0Id
,
&
rt1
);
...
@@ -897,3 +897,20 @@ func TestIgnoredFields(t *testing.T) {
...
@@ -897,3 +897,20 @@ func TestIgnoredFields(t *testing.T) {
t
.
Errorf
(
"rt1->rt0: expected %v; got %v"
,
it0
,
rt1
);
t
.
Errorf
(
"rt1->rt0: expected %v; got %v"
,
it0
,
rt1
);
}
}
}
}
type
Bad0
struct
{
inter
interface
{};
c
float
;
}
func
TestInvalidField
(
t
*
testing
.
T
)
{
var
bad0
Bad0
;
bad0
.
inter
=
17
;
b
:=
new
(
bytes
.
Buffer
);
err
:=
encode
(
b
,
&
bad0
);
if
err
==
nil
{
t
.
Error
(
"expected error; got none"
)
}
else
if
strings
.
Index
(
err
.
String
(),
"interface"
)
<
0
{
t
.
Error
(
"expected type error; got"
,
err
)
}
}
src/pkg/gob/encode.go
View file @
98607d01
...
@@ -335,11 +335,11 @@ var encOpMap = map[reflect.Type] encOp {
...
@@ -335,11 +335,11 @@ var encOpMap = map[reflect.Type] encOp {
valueKind
(
"x"
)
:
encString
,
valueKind
(
"x"
)
:
encString
,
}
}
func
getEncEngine
(
rt
reflect
.
Type
)
*
encEngine
func
getEncEngine
(
rt
reflect
.
Type
)
(
*
encEngine
,
os
.
Error
)
// Return the encoding op for the base type under rt and
// Return the encoding op for the base type under rt and
// the indirection count to reach it.
// the indirection count to reach it.
func
encOpFor
(
rt
reflect
.
Type
)
(
encOp
,
int
)
{
func
encOpFor
(
rt
reflect
.
Type
)
(
encOp
,
int
,
os
.
Error
)
{
typ
,
indir
:=
indirect
(
rt
);
typ
,
indir
:=
indirect
(
rt
);
op
,
ok
:=
encOpMap
[
reflect
.
Typeof
(
typ
)];
op
,
ok
:=
encOpMap
[
reflect
.
Typeof
(
typ
)];
if
!
ok
{
if
!
ok
{
...
@@ -352,7 +352,10 @@ func encOpFor(rt reflect.Type) (encOp, int) {
...
@@ -352,7 +352,10 @@ func encOpFor(rt reflect.Type) (encOp, int) {
break
;
break
;
}
}
// Slices have a header; we decode it to find the underlying array.
// Slices have a header; we decode it to find the underlying array.
elemOp
,
indir
:=
encOpFor
(
t
.
Elem
());
elemOp
,
indir
,
err
:=
encOpFor
(
t
.
Elem
());
if
err
!=
nil
{
return
nil
,
0
,
err
}
op
=
func
(
i
*
encInstr
,
state
*
encoderState
,
p
unsafe
.
Pointer
)
{
op
=
func
(
i
*
encInstr
,
state
*
encoderState
,
p
unsafe
.
Pointer
)
{
slice
:=
(
*
reflect
.
SliceHeader
)(
p
);
slice
:=
(
*
reflect
.
SliceHeader
)(
p
);
if
slice
.
Len
==
0
{
if
slice
.
Len
==
0
{
...
@@ -363,15 +366,21 @@ func encOpFor(rt reflect.Type) (encOp, int) {
...
@@ -363,15 +366,21 @@ func encOpFor(rt reflect.Type) (encOp, int) {
};
};
case
*
reflect
.
ArrayType
:
case
*
reflect
.
ArrayType
:
// True arrays have size in the type.
// True arrays have size in the type.
elemOp
,
indir
:=
encOpFor
(
t
.
Elem
());
elemOp
,
indir
,
err
:=
encOpFor
(
t
.
Elem
());
if
err
!=
nil
{
return
nil
,
0
,
err
}
op
=
func
(
i
*
encInstr
,
state
*
encoderState
,
p
unsafe
.
Pointer
)
{
op
=
func
(
i
*
encInstr
,
state
*
encoderState
,
p
unsafe
.
Pointer
)
{
state
.
update
(
i
);
state
.
update
(
i
);
state
.
err
=
encodeArray
(
state
.
b
,
uintptr
(
p
),
elemOp
,
t
.
Elem
()
.
Size
(),
t
.
Len
(),
indir
);
state
.
err
=
encodeArray
(
state
.
b
,
uintptr
(
p
),
elemOp
,
t
.
Elem
()
.
Size
(),
t
.
Len
(),
indir
);
};
};
case
*
reflect
.
StructType
:
case
*
reflect
.
StructType
:
// Generate a closure that calls out to the engine for the nested type.
// Generate a closure that calls out to the engine for the nested type.
engine
:=
getEncEngine
(
typ
);
engine
,
err
:=
getEncEngine
(
typ
);
info
:=
getTypeInfo
(
typ
);
if
err
!=
nil
{
return
nil
,
0
,
err
}
info
:=
getTypeInfoNoError
(
typ
);
op
=
func
(
i
*
encInstr
,
state
*
encoderState
,
p
unsafe
.
Pointer
)
{
op
=
func
(
i
*
encInstr
,
state
*
encoderState
,
p
unsafe
.
Pointer
)
{
state
.
update
(
i
);
state
.
update
(
i
);
// indirect through info to delay evaluation for recursive structs
// indirect through info to delay evaluation for recursive structs
...
@@ -380,13 +389,13 @@ func encOpFor(rt reflect.Type) (encOp, int) {
...
@@ -380,13 +389,13 @@ func encOpFor(rt reflect.Type) (encOp, int) {
}
}
}
}
if
op
==
nil
{
if
op
==
nil
{
panicln
(
"can't happen: encode type"
,
rt
.
String
());
return
op
,
indir
,
os
.
ErrorString
(
"gob enc: can't happen: encode type"
+
rt
.
String
());
}
}
return
op
,
indir
return
op
,
indir
,
nil
}
}
// The local Type was compiled from the actual value, so we know it's compatible.
// The local Type was compiled from the actual value, so we know it's compatible.
func
compileEnc
(
rt
reflect
.
Type
)
*
encEngine
{
func
compileEnc
(
rt
reflect
.
Type
)
(
*
encEngine
,
os
.
Error
)
{
srt
,
ok
:=
rt
.
(
*
reflect
.
StructType
);
srt
,
ok
:=
rt
.
(
*
reflect
.
StructType
);
if
!
ok
{
if
!
ok
{
panicln
(
"can't happen: non-struct"
);
panicln
(
"can't happen: non-struct"
);
...
@@ -395,23 +404,29 @@ func compileEnc(rt reflect.Type) *encEngine {
...
@@ -395,23 +404,29 @@ func compileEnc(rt reflect.Type) *encEngine {
engine
.
instr
=
make
([]
encInstr
,
srt
.
NumField
()
+
1
);
// +1 for terminator
engine
.
instr
=
make
([]
encInstr
,
srt
.
NumField
()
+
1
);
// +1 for terminator
for
fieldnum
:=
0
;
fieldnum
<
srt
.
NumField
();
fieldnum
++
{
for
fieldnum
:=
0
;
fieldnum
<
srt
.
NumField
();
fieldnum
++
{
f
:=
srt
.
Field
(
fieldnum
);
f
:=
srt
.
Field
(
fieldnum
);
op
,
indir
:=
encOpFor
(
f
.
Type
);
op
,
indir
,
err
:=
encOpFor
(
f
.
Type
);
if
err
!=
nil
{
return
nil
,
err
}
engine
.
instr
[
fieldnum
]
=
encInstr
{
op
,
fieldnum
,
indir
,
uintptr
(
f
.
Offset
)};
engine
.
instr
[
fieldnum
]
=
encInstr
{
op
,
fieldnum
,
indir
,
uintptr
(
f
.
Offset
)};
}
}
engine
.
instr
[
srt
.
NumField
()]
=
encInstr
{
encStructTerminator
,
0
,
0
,
0
};
engine
.
instr
[
srt
.
NumField
()]
=
encInstr
{
encStructTerminator
,
0
,
0
,
0
};
return
engine
;
return
engine
,
nil
;
}
}
// typeLock must be held (or we're in initialization and guaranteed single-threaded).
// typeLock must be held (or we're in initialization and guaranteed single-threaded).
// The reflection type must have all its indirections processed out.
// The reflection type must have all its indirections processed out.
func
getEncEngine
(
rt
reflect
.
Type
)
*
encEngine
{
func
getEncEngine
(
rt
reflect
.
Type
)
(
*
encEngine
,
os
.
Error
)
{
info
:=
getTypeInfo
(
rt
);
info
,
err
:=
getTypeInfo
(
rt
);
if
err
!=
nil
{
return
nil
,
err
}
if
info
.
encoder
==
nil
{
if
info
.
encoder
==
nil
{
// mark this engine as underway before compiling to handle recursive types.
// mark this engine as underway before compiling to handle recursive types.
info
.
encoder
=
new
(
encEngine
);
info
.
encoder
=
new
(
encEngine
);
info
.
encoder
=
compileEnc
(
rt
);
info
.
encoder
,
err
=
compileEnc
(
rt
);
}
}
return
info
.
encoder
;
return
info
.
encoder
,
err
;
}
}
func
encode
(
b
*
bytes
.
Buffer
,
e
interface
{})
os
.
Error
{
func
encode
(
b
*
bytes
.
Buffer
,
e
interface
{})
os
.
Error
{
...
@@ -425,7 +440,10 @@ func encode(b *bytes.Buffer, e interface{}) os.Error {
...
@@ -425,7 +440,10 @@ func encode(b *bytes.Buffer, e interface{}) os.Error {
return
os
.
ErrorString
(
"gob: encode can't handle "
+
v
.
Type
()
.
String
())
return
os
.
ErrorString
(
"gob: encode can't handle "
+
v
.
Type
()
.
String
())
}
}
typeLock
.
Lock
();
typeLock
.
Lock
();
engine
:=
getEncEngine
(
rt
);
engine
,
err
:=
getEncEngine
(
rt
);
typeLock
.
Unlock
();
typeLock
.
Unlock
();
if
err
!=
nil
{
return
err
}
return
encodeStruct
(
engine
,
b
,
v
.
Addr
());
return
encodeStruct
(
engine
,
b
,
v
.
Addr
());
}
}
src/pkg/gob/encoder.go
View file @
98607d01
...
@@ -73,7 +73,7 @@
...
@@ -73,7 +73,7 @@
Maps are not supported yet, but they will be. Interfaces, functions, and channels
Maps are not supported yet, but they will be. Interfaces, functions, and channels
cannot be sent in a gob. Attempting to encode a value that contains one will
cannot be sent in a gob. Attempting to encode a value that contains one will
fail.
(TODO(r): fix this - it panics now.)
fail.
The rest of this comment documents the encoding, details that are not important
The rest of this comment documents the encoding, details that are not important
for most users. Details are presented bottom-up.
for most users. Details are presented bottom-up.
...
@@ -267,8 +267,12 @@ func (enc *Encoder) sendType(origt reflect.Type) {
...
@@ -267,8 +267,12 @@ func (enc *Encoder) sendType(origt reflect.Type) {
// Need to send it.
// Need to send it.
typeLock
.
Lock
();
typeLock
.
Lock
();
info
:=
getTypeInfo
(
rt
);
info
,
err
:=
getTypeInfo
(
rt
);
typeLock
.
Unlock
();
typeLock
.
Unlock
();
if
err
!=
nil
{
enc
.
state
.
err
=
err
;
return
;
}
// Send the pair (-id, type)
// Send the pair (-id, type)
// Id:
// Id:
encodeInt
(
enc
.
state
,
-
int64
(
info
.
id
));
encodeInt
(
enc
.
state
,
-
int64
(
info
.
id
));
...
@@ -285,6 +289,7 @@ func (enc *Encoder) sendType(origt reflect.Type) {
...
@@ -285,6 +289,7 @@ func (enc *Encoder) sendType(origt reflect.Type) {
for
i
:=
0
;
i
<
st
.
NumField
();
i
++
{
for
i
:=
0
;
i
<
st
.
NumField
();
i
++
{
enc
.
sendType
(
st
.
Field
(
i
)
.
Type
);
enc
.
sendType
(
st
.
Field
(
i
)
.
Type
);
}
}
return
}
}
// Encode transmits the data item represented by the empty interface value,
// Encode transmits the data item represented by the empty interface value,
...
...
src/pkg/gob/encoder_test.go
View file @
98607d01
...
@@ -69,7 +69,7 @@ func TestBasicEncoder(t *testing.T) {
...
@@ -69,7 +69,7 @@ func TestBasicEncoder(t *testing.T) {
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
"error decoding ET1 type:"
,
err
);
t
.
Fatal
(
"error decoding ET1 type:"
,
err
);
}
}
info
:=
getTypeInfo
(
reflect
.
Typeof
(
ET1
{}));
info
:=
getTypeInfo
NoError
(
reflect
.
Typeof
(
ET1
{}));
trueWire1
:=
&
wireType
{
s
:
info
.
id
.
gobType
()
.
(
*
structType
)};
trueWire1
:=
&
wireType
{
s
:
info
.
id
.
gobType
()
.
(
*
structType
)};
if
!
reflect
.
DeepEqual
(
wire1
,
trueWire1
)
{
if
!
reflect
.
DeepEqual
(
wire1
,
trueWire1
)
{
t
.
Fatalf
(
"invalid wireType for ET1: expected %+v; got %+v
\n
"
,
*
trueWire1
,
*
wire1
);
t
.
Fatalf
(
"invalid wireType for ET1: expected %+v; got %+v
\n
"
,
*
trueWire1
,
*
wire1
);
...
@@ -90,7 +90,7 @@ func TestBasicEncoder(t *testing.T) {
...
@@ -90,7 +90,7 @@ func TestBasicEncoder(t *testing.T) {
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
"error decoding ET2 type:"
,
err
);
t
.
Fatal
(
"error decoding ET2 type:"
,
err
);
}
}
info
=
getTypeInfo
(
reflect
.
Typeof
(
ET2
{}));
info
=
getTypeInfo
NoError
(
reflect
.
Typeof
(
ET2
{}));
trueWire2
:=
&
wireType
{
s
:
info
.
id
.
gobType
()
.
(
*
structType
)};
trueWire2
:=
&
wireType
{
s
:
info
.
id
.
gobType
()
.
(
*
structType
)};
if
!
reflect
.
DeepEqual
(
wire2
,
trueWire2
)
{
if
!
reflect
.
DeepEqual
(
wire2
,
trueWire2
)
{
t
.
Fatalf
(
"invalid wireType for ET2: expected %+v; got %+v
\n
"
,
*
trueWire2
,
*
wire2
);
t
.
Fatalf
(
"invalid wireType for ET2: expected %+v; got %+v
\n
"
,
*
trueWire2
,
*
wire2
);
...
@@ -107,7 +107,7 @@ func TestBasicEncoder(t *testing.T) {
...
@@ -107,7 +107,7 @@ func TestBasicEncoder(t *testing.T) {
}
}
// 8) The value of et1
// 8) The value of et1
newEt1
:=
new
(
ET1
);
newEt1
:=
new
(
ET1
);
et1Id
:=
getTypeInfo
(
reflect
.
Typeof
(
*
newEt1
))
.
id
;
et1Id
:=
getTypeInfo
NoError
(
reflect
.
Typeof
(
*
newEt1
))
.
id
;
err
=
decode
(
b
,
et1Id
,
newEt1
);
err
=
decode
(
b
,
et1Id
,
newEt1
);
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
"error decoding ET1 value:"
,
err
);
t
.
Fatal
(
"error decoding ET1 value:"
,
err
);
...
...
src/pkg/gob/type.go
View file @
98607d01
...
@@ -202,7 +202,7 @@ func newStructType(name string) *structType {
...
@@ -202,7 +202,7 @@ func newStructType(name string) *structType {
}
}
// Construction
// Construction
func
newType
(
name
string
,
rt
reflect
.
Type
)
gobType
func
getType
(
name
string
,
rt
reflect
.
Type
)
(
gobType
,
os
.
Error
)
// Step through the indirections on a type to discover the base type.
// Step through the indirections on a type to discover the base type.
// Return the number of indirections.
// Return the number of indirections.
...
@@ -219,55 +219,63 @@ func indirect(t reflect.Type) (rt reflect.Type, count int) {
...
@@ -219,55 +219,63 @@ func indirect(t reflect.Type) (rt reflect.Type, count int) {
return
;
return
;
}
}
func
newTypeObject
(
name
string
,
rt
reflect
.
Type
)
gobType
{
func
newTypeObject
(
name
string
,
rt
reflect
.
Type
)
(
gobType
,
os
.
Error
)
{
switch
t
:=
rt
.
(
type
)
{
switch
t
:=
rt
.
(
type
)
{
// All basic types are easy: they are predefined.
// All basic types are easy: they are predefined.
case
*
reflect
.
BoolType
:
case
*
reflect
.
BoolType
:
return
tBool
.
gobType
()
return
tBool
.
gobType
()
,
nil
case
*
reflect
.
IntType
:
case
*
reflect
.
IntType
:
return
tInt
.
gobType
()
return
tInt
.
gobType
()
,
nil
case
*
reflect
.
Int8Type
:
case
*
reflect
.
Int8Type
:
return
tInt
.
gobType
()
return
tInt
.
gobType
()
,
nil
case
*
reflect
.
Int16Type
:
case
*
reflect
.
Int16Type
:
return
tInt
.
gobType
()
return
tInt
.
gobType
()
,
nil
case
*
reflect
.
Int32Type
:
case
*
reflect
.
Int32Type
:
return
tInt
.
gobType
()
return
tInt
.
gobType
()
,
nil
case
*
reflect
.
Int64Type
:
case
*
reflect
.
Int64Type
:
return
tInt
.
gobType
()
return
tInt
.
gobType
()
,
nil
case
*
reflect
.
UintType
:
case
*
reflect
.
UintType
:
return
tUint
.
gobType
()
return
tUint
.
gobType
()
,
nil
case
*
reflect
.
Uint8Type
:
case
*
reflect
.
Uint8Type
:
return
tUint
.
gobType
()
return
tUint
.
gobType
()
,
nil
case
*
reflect
.
Uint16Type
:
case
*
reflect
.
Uint16Type
:
return
tUint
.
gobType
()
return
tUint
.
gobType
()
,
nil
case
*
reflect
.
Uint32Type
:
case
*
reflect
.
Uint32Type
:
return
tUint
.
gobType
()
return
tUint
.
gobType
()
,
nil
case
*
reflect
.
Uint64Type
:
case
*
reflect
.
Uint64Type
:
return
tUint
.
gobType
()
return
tUint
.
gobType
()
,
nil
case
*
reflect
.
UintptrType
:
case
*
reflect
.
UintptrType
:
return
tUint
.
gobType
()
return
tUint
.
gobType
()
,
nil
case
*
reflect
.
FloatType
:
case
*
reflect
.
FloatType
:
return
tFloat
.
gobType
()
return
tFloat
.
gobType
()
,
nil
case
*
reflect
.
Float32Type
:
case
*
reflect
.
Float32Type
:
return
tFloat
.
gobType
()
return
tFloat
.
gobType
()
,
nil
case
*
reflect
.
Float64Type
:
case
*
reflect
.
Float64Type
:
return
tFloat
.
gobType
()
return
tFloat
.
gobType
()
,
nil
case
*
reflect
.
StringType
:
case
*
reflect
.
StringType
:
return
tString
.
gobType
()
return
tString
.
gobType
()
,
nil
case
*
reflect
.
ArrayType
:
case
*
reflect
.
ArrayType
:
return
newArrayType
(
name
,
newType
(
""
,
t
.
Elem
()),
t
.
Len
());
gt
,
err
:=
getType
(
""
,
t
.
Elem
());
if
err
!=
nil
{
return
nil
,
err
}
return
newArrayType
(
name
,
gt
,
t
.
Len
()),
nil
;
case
*
reflect
.
SliceType
:
case
*
reflect
.
SliceType
:
// []byte == []uint8 is a special case
// []byte == []uint8 is a special case
if
_
,
ok
:=
t
.
Elem
()
.
(
*
reflect
.
Uint8Type
);
ok
{
if
_
,
ok
:=
t
.
Elem
()
.
(
*
reflect
.
Uint8Type
);
ok
{
return
tBytes
.
gobType
()
return
tBytes
.
gobType
(),
nil
}
gt
,
err
:=
getType
(
t
.
Elem
()
.
Name
(),
t
.
Elem
());
if
err
!=
nil
{
return
nil
,
err
}
}
return
newSliceType
(
name
,
newType
(
t
.
Elem
()
.
Name
(),
t
.
Elem
()))
;
return
newSliceType
(
name
,
gt
),
nil
;
case
*
reflect
.
StructType
:
case
*
reflect
.
StructType
:
// Install the struct type itself before the fields so recursive
// Install the struct type itself before the fields so recursive
...
@@ -283,18 +291,24 @@ func newTypeObject(name string, rt reflect.Type) gobType {
...
@@ -283,18 +291,24 @@ func newTypeObject(name string, rt reflect.Type) gobType {
if
tname
==
""
{
if
tname
==
""
{
tname
=
f
.
Type
.
String
();
tname
=
f
.
Type
.
String
();
}
}
field
[
i
]
=
&
fieldType
{
f
.
Name
,
newType
(
tname
,
f
.
Type
)
.
id
()
};
gt
,
err
:=
getType
(
tname
,
f
.
Type
);
if
err
!=
nil
{
return
nil
,
err
}
field
[
i
]
=
&
fieldType
{
f
.
Name
,
gt
.
id
()
};
}
}
strType
.
field
=
field
;
strType
.
field
=
field
;
return
strType
;
return
strType
,
nil
;
default
:
default
:
panicln
(
"gob NewTypeObject can't handle type"
,
rt
.
String
());
// TODO(r): panic?
return
nil
,
os
.
ErrorString
(
"gob NewTypeObject can't handle type: "
+
rt
.
String
());
}
}
return
nil
return
nil
,
nil
}
}
func
newType
(
name
string
,
rt
reflect
.
Type
)
gobType
{
// getType returns the Gob type describing the given reflect.Type.
// typeLock must be held.
func
getType
(
name
string
,
rt
reflect
.
Type
)
(
gobType
,
os
.
Error
)
{
// Flatten the data structure by collapsing out pointers
// Flatten the data structure by collapsing out pointers
for
{
for
{
pt
,
ok
:=
rt
.
(
*
reflect
.
PtrType
);
pt
,
ok
:=
rt
.
(
*
reflect
.
PtrType
);
...
@@ -305,19 +319,13 @@ func newType(name string, rt reflect.Type) gobType {
...
@@ -305,19 +319,13 @@ func newType(name string, rt reflect.Type) gobType {
}
}
typ
,
present
:=
types
[
rt
];
typ
,
present
:=
types
[
rt
];
if
present
{
if
present
{
return
typ
return
typ
,
nil
}
}
typ
=
newTypeObject
(
name
,
rt
);
typ
,
err
:=
newTypeObject
(
name
,
rt
);
types
[
rt
]
=
typ
;
if
err
==
nil
{
return
typ
types
[
rt
]
=
typ
}
}
return
typ
,
err
// getType returns the Gob type describing the given reflect.Type.
// typeLock must be held.
func
getType
(
name
string
,
rt
reflect
.
Type
)
gobType
{
// Set lock; all code running under here is synchronized.
t
:=
newType
(
name
,
rt
);
return
t
;
}
}
func
checkId
(
want
,
got
typeId
)
{
func
checkId
(
want
,
got
typeId
)
{
...
@@ -371,7 +379,7 @@ var typeInfoMap = make(map[reflect.Type] *typeInfo) // protected by typeLock
...
@@ -371,7 +379,7 @@ var typeInfoMap = make(map[reflect.Type] *typeInfo) // protected by typeLock
// The reflection type must have all its indirections processed out.
// The reflection type must have all its indirections processed out.
// typeLock must be held.
// typeLock must be held.
func
getTypeInfo
(
rt
reflect
.
Type
)
*
typeInfo
{
func
getTypeInfo
(
rt
reflect
.
Type
)
(
*
typeInfo
,
os
.
Error
)
{
if
pt
,
ok
:=
rt
.
(
*
reflect
.
PtrType
);
ok
{
if
pt
,
ok
:=
rt
.
(
*
reflect
.
PtrType
);
ok
{
panicln
(
"pointer type in getTypeInfo:"
,
rt
.
String
())
panicln
(
"pointer type in getTypeInfo:"
,
rt
.
String
())
}
}
...
@@ -379,12 +387,25 @@ func getTypeInfo(rt reflect.Type) *typeInfo {
...
@@ -379,12 +387,25 @@ func getTypeInfo(rt reflect.Type) *typeInfo {
if
!
ok
{
if
!
ok
{
info
=
new
(
typeInfo
);
info
=
new
(
typeInfo
);
name
:=
rt
.
Name
();
name
:=
rt
.
Name
();
info
.
id
=
getType
(
name
,
rt
)
.
id
();
gt
,
err
:=
getType
(
name
,
rt
);
if
err
!=
nil
{
return
nil
,
err
}
info
.
id
=
gt
.
id
();
// assume it's a struct type
// assume it's a struct type
info
.
wire
=
&
wireType
{
info
.
id
.
gobType
()
.
(
*
structType
)};
info
.
wire
=
&
wireType
{
info
.
id
.
gobType
()
.
(
*
structType
)};
typeInfoMap
[
rt
]
=
info
;
typeInfoMap
[
rt
]
=
info
;
}
}
return
info
;
return
info
,
nil
;
}
// Called only when a panic is acceptable and unexpected.
func
getTypeInfoNoError
(
rt
reflect
.
Type
)
*
typeInfo
{
t
,
err
:=
getTypeInfo
(
rt
);
if
err
!=
nil
{
panicln
(
"getTypeInfo:"
,
err
.
String
());
}
return
t
}
}
func
init
()
{
func
init
()
{
...
@@ -396,9 +417,9 @@ func init() {
...
@@ -396,9 +417,9 @@ func init() {
// The string for tBytes is "bytes" not "[]byte" to signify its specialness.
// The string for tBytes is "bytes" not "[]byte" to signify its specialness.
tBytes
=
bootstrapType
(
"bytes"
,
make
([]
byte
,
0
),
5
);
tBytes
=
bootstrapType
(
"bytes"
,
make
([]
byte
,
0
),
5
);
tString
=
bootstrapType
(
"string"
,
""
,
6
);
tString
=
bootstrapType
(
"string"
,
""
,
6
);
tWireType
=
getTypeInfo
(
reflect
.
Typeof
(
wireType
{}))
.
id
;
tWireType
=
getTypeInfo
NoError
(
reflect
.
Typeof
(
wireType
{}))
.
id
;
checkId
(
7
,
tWireType
);
checkId
(
7
,
tWireType
);
checkId
(
8
,
getTypeInfo
(
reflect
.
Typeof
(
structType
{}))
.
id
);
checkId
(
8
,
getTypeInfo
NoError
(
reflect
.
Typeof
(
structType
{}))
.
id
);
checkId
(
9
,
getTypeInfo
(
reflect
.
Typeof
(
commonType
{}))
.
id
);
checkId
(
9
,
getTypeInfo
NoError
(
reflect
.
Typeof
(
commonType
{}))
.
id
);
checkId
(
10
,
getTypeInfo
(
reflect
.
Typeof
(
fieldType
{}))
.
id
);
checkId
(
10
,
getTypeInfo
NoError
(
reflect
.
Typeof
(
fieldType
{}))
.
id
);
}
}
src/pkg/gob/type_test.go
View file @
98607d01
...
@@ -27,7 +27,11 @@ var basicTypes = []typeT {
...
@@ -27,7 +27,11 @@ var basicTypes = []typeT {
func
getTypeUnlocked
(
name
string
,
rt
reflect
.
Type
)
gobType
{
func
getTypeUnlocked
(
name
string
,
rt
reflect
.
Type
)
gobType
{
typeLock
.
Lock
();
typeLock
.
Lock
();
defer
typeLock
.
Unlock
();
defer
typeLock
.
Unlock
();
return
getType
(
name
,
rt
);
t
,
err
:=
getType
(
name
,
rt
);
if
err
!=
nil
{
panicln
(
"getTypeUnlocked:"
,
err
.
String
())
}
return
t
;
}
}
// Sanity checks
// Sanity checks
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment