Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
G
golang
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
golang
Commits
c701af8c
Commit
c701af8c
authored
Jul 02, 2009
by
Rob Pike
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Encode and decode engines for gobs.
R=rsc DELTA=468 (292 added, 18 deleted, 158 changed) OCL=31008 CL=31012
parent
a439f662
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
339 additions
and
65 deletions
+339
-65
codec_test.go
src/pkg/gob/codec_test.go
+93
-51
decode.go
src/pkg/gob/decode.go
+114
-0
encode.go
src/pkg/gob/encode.go
+132
-14
No files found.
src/pkg/gob/codec_test.go
View file @
c701af8c
...
...
@@ -8,6 +8,7 @@ import (
"bytes"
;
"gob"
;
"os"
;
"reflect"
;
"testing"
;
"unsafe"
;
)
...
...
@@ -106,35 +107,42 @@ func TestIntCodec(t *testing.T) {
verifyInt
(
-
1
<<
63
,
t
);
// a tricky case
}
// The result of encoding three true booleans with field numbers 0, 1, 2
var
boolResult
=
[]
byte
{
0x8
0
,
0x81
,
0x81
,
0x81
,
0x82
,
0x81
}
var
boolResult
=
[]
byte
{
0x8
1
,
0x81
,
0x81
,
0x81
,
0x81
,
0x81
}
// The result of encoding three numbers = 17 with field numbers 0, 1, 2
var
signedResult
=
[]
byte
{
0x80
,
0xa2
,
0x81
,
0xa2
,
0x82
,
0xa2
}
var
unsignedResult
=
[]
byte
{
0x80
,
0x91
,
0x81
,
0x91
,
0x82
,
0x91
}
var
floatResult
=
[]
byte
{
0x80
,
0x40
,
0xe2
,
0x81
,
0x40
,
0xe2
,
0x82
,
0x40
,
0xe2
}
var
signedResult
=
[]
byte
{
0x81
,
0xa2
,
0x81
,
0xa2
,
0x81
,
0xa2
}
var
unsignedResult
=
[]
byte
{
0x81
,
0x91
,
0x81
,
0x91
,
0x81
,
0x91
}
var
floatResult
=
[]
byte
{
0x81
,
0x40
,
0xe2
,
0x81
,
0x40
,
0xe2
,
0x81
,
0x40
,
0xe2
}
func
newEncState
(
b
*
bytes
.
Buffer
)
*
EncState
{
b
.
Reset
();
state
:=
new
(
EncState
);
state
.
w
=
b
;
state
.
fieldnum
=
-
1
;
return
state
;
}
// Test instruction execution for encoding.
// Do not run the machine yet; instead do individual instructions crafted by hand.
func
TestScalarEncInstructions
(
t
*
testing
.
T
)
{
var
b
=
new
(
bytes
.
Buffer
);
state
:=
new
(
EncState
);
// bool
{
b
.
Reset
();
v
:=
true
;
pv
:=
&
v
;
ppv
:=
&
pv
;
data
:=
(
struct
{
a
bool
;
b
*
bool
;
c
**
bool
}){
v
,
pv
,
ppv
};
instr
:=
&
encInstr
{
encBool
,
0
,
0
,
0
};
state
.
w
=
b
;
state
:=
newEncState
(
b
)
;
state
.
base
=
uintptr
(
unsafe
.
Pointer
(
&
data
));
instr
.
op
(
instr
,
state
);
state
.
fieldnum
=
0
;
instr
.
field
=
1
;
instr
.
indir
=
1
;
instr
.
offset
=
uintptr
(
unsafe
.
Offsetof
(
data
.
b
));
instr
.
op
(
instr
,
state
);
state
.
fieldnum
=
1
;
instr
.
field
=
2
;
instr
.
indir
=
2
;
instr
.
offset
=
uintptr
(
unsafe
.
Offsetof
(
data
.
c
));
...
...
@@ -152,13 +160,15 @@ func TestScalarEncInstructions(t *testing.T) {
ppv
:=
&
pv
;
data
:=
(
struct
{
a
int
;
b
*
int
;
c
**
int
}){
v
,
pv
,
ppv
};
instr
:=
&
encInstr
{
encInt
,
0
,
0
,
0
};
state
.
w
=
b
;
state
:=
newEncState
(
b
)
;
state
.
base
=
uintptr
(
unsafe
.
Pointer
(
&
data
));
instr
.
op
(
instr
,
state
);
state
.
fieldnum
=
0
;
instr
.
field
=
1
;
instr
.
indir
=
1
;
instr
.
offset
=
uintptr
(
unsafe
.
Offsetof
(
data
.
b
));
instr
.
op
(
instr
,
state
);
state
.
fieldnum
=
1
;
instr
.
field
=
2
;
instr
.
indir
=
2
;
instr
.
offset
=
uintptr
(
unsafe
.
Offsetof
(
data
.
c
));
...
...
@@ -176,13 +186,15 @@ func TestScalarEncInstructions(t *testing.T) {
ppv
:=
&
pv
;
data
:=
(
struct
{
a
uint
;
b
*
uint
;
c
**
uint
}){
v
,
pv
,
ppv
};
instr
:=
&
encInstr
{
encUint
,
0
,
0
,
0
};
state
.
w
=
b
;
state
:=
newEncState
(
b
)
;
state
.
base
=
uintptr
(
unsafe
.
Pointer
(
&
data
));
instr
.
op
(
instr
,
state
);
state
.
fieldnum
=
0
;
instr
.
field
=
1
;
instr
.
indir
=
1
;
instr
.
offset
=
uintptr
(
unsafe
.
Offsetof
(
data
.
b
));
instr
.
op
(
instr
,
state
);
state
.
fieldnum
=
1
;
instr
.
field
=
2
;
instr
.
indir
=
2
;
instr
.
offset
=
uintptr
(
unsafe
.
Offsetof
(
data
.
c
));
...
...
@@ -200,13 +212,15 @@ func TestScalarEncInstructions(t *testing.T) {
ppv
:=
&
pv
;
data
:=
(
struct
{
a
int8
;
b
*
int8
;
c
**
int8
}){
v
,
pv
,
ppv
};
instr
:=
&
encInstr
{
encInt
,
0
,
0
,
0
};
state
.
w
=
b
;
state
:=
newEncState
(
b
)
;
state
.
base
=
uintptr
(
unsafe
.
Pointer
(
&
data
));
instr
.
op
(
instr
,
state
);
state
.
fieldnum
=
0
;
instr
.
field
=
1
;
instr
.
indir
=
1
;
instr
.
offset
=
uintptr
(
unsafe
.
Offsetof
(
data
.
b
));
instr
.
op
(
instr
,
state
);
state
.
fieldnum
=
1
;
instr
.
field
=
2
;
instr
.
indir
=
2
;
instr
.
offset
=
uintptr
(
unsafe
.
Offsetof
(
data
.
c
));
...
...
@@ -224,13 +238,15 @@ func TestScalarEncInstructions(t *testing.T) {
ppv
:=
&
pv
;
data
:=
(
struct
{
a
uint8
;
b
*
uint8
;
c
**
uint8
}){
v
,
pv
,
ppv
};
instr
:=
&
encInstr
{
encUint
,
0
,
0
,
0
};
state
.
w
=
b
;
state
:=
newEncState
(
b
)
;
state
.
base
=
uintptr
(
unsafe
.
Pointer
(
&
data
));
instr
.
op
(
instr
,
state
);
state
.
fieldnum
=
0
;
instr
.
field
=
1
;
instr
.
indir
=
1
;
instr
.
offset
=
uintptr
(
unsafe
.
Offsetof
(
data
.
b
));
instr
.
op
(
instr
,
state
);
state
.
fieldnum
=
1
;
instr
.
field
=
2
;
instr
.
indir
=
2
;
instr
.
offset
=
uintptr
(
unsafe
.
Offsetof
(
data
.
c
));
...
...
@@ -248,13 +264,15 @@ func TestScalarEncInstructions(t *testing.T) {
ppv
:=
&
pv
;
data
:=
(
struct
{
a
int16
;
b
*
int16
;
c
**
int16
}){
v
,
pv
,
ppv
};
instr
:=
&
encInstr
{
encInt16
,
0
,
0
,
0
};
state
.
w
=
b
;
state
:=
newEncState
(
b
)
;
state
.
base
=
uintptr
(
unsafe
.
Pointer
(
&
data
));
instr
.
op
(
instr
,
state
);
state
.
fieldnum
=
0
;
instr
.
field
=
1
;
instr
.
indir
=
1
;
instr
.
offset
=
uintptr
(
unsafe
.
Offsetof
(
data
.
b
));
instr
.
op
(
instr
,
state
);
state
.
fieldnum
=
1
;
instr
.
field
=
2
;
instr
.
indir
=
2
;
instr
.
offset
=
uintptr
(
unsafe
.
Offsetof
(
data
.
c
));
...
...
@@ -272,13 +290,15 @@ func TestScalarEncInstructions(t *testing.T) {
ppv
:=
&
pv
;
data
:=
(
struct
{
a
uint16
;
b
*
uint16
;
c
**
uint16
}){
v
,
pv
,
ppv
};
instr
:=
&
encInstr
{
encUint16
,
0
,
0
,
0
};
state
.
w
=
b
;
state
:=
newEncState
(
b
)
;
state
.
base
=
uintptr
(
unsafe
.
Pointer
(
&
data
));
instr
.
op
(
instr
,
state
);
state
.
fieldnum
=
0
;
instr
.
field
=
1
;
instr
.
indir
=
1
;
instr
.
offset
=
uintptr
(
unsafe
.
Offsetof
(
data
.
b
));
instr
.
op
(
instr
,
state
);
state
.
fieldnum
=
1
;
instr
.
field
=
2
;
instr
.
indir
=
2
;
instr
.
offset
=
uintptr
(
unsafe
.
Offsetof
(
data
.
c
));
...
...
@@ -296,13 +316,15 @@ func TestScalarEncInstructions(t *testing.T) {
ppv
:=
&
pv
;
data
:=
(
struct
{
a
int32
;
b
*
int32
;
c
**
int32
}){
v
,
pv
,
ppv
};
instr
:=
&
encInstr
{
encInt32
,
0
,
0
,
0
};
state
.
w
=
b
;
state
:=
newEncState
(
b
)
;
state
.
base
=
uintptr
(
unsafe
.
Pointer
(
&
data
));
instr
.
op
(
instr
,
state
);
state
.
fieldnum
=
0
;
instr
.
field
=
1
;
instr
.
indir
=
1
;
instr
.
offset
=
uintptr
(
unsafe
.
Offsetof
(
data
.
b
));
instr
.
op
(
instr
,
state
);
state
.
fieldnum
=
1
;
instr
.
field
=
2
;
instr
.
indir
=
2
;
instr
.
offset
=
uintptr
(
unsafe
.
Offsetof
(
data
.
c
));
...
...
@@ -320,13 +342,15 @@ func TestScalarEncInstructions(t *testing.T) {
ppv
:=
&
pv
;
data
:=
(
struct
{
a
uint32
;
b
*
uint32
;
c
**
uint32
}){
v
,
pv
,
ppv
};
instr
:=
&
encInstr
{
encUint32
,
0
,
0
,
0
};
state
.
w
=
b
;
state
:=
newEncState
(
b
)
;
state
.
base
=
uintptr
(
unsafe
.
Pointer
(
&
data
));
instr
.
op
(
instr
,
state
);
state
.
fieldnum
=
0
;
instr
.
field
=
1
;
instr
.
indir
=
1
;
instr
.
offset
=
uintptr
(
unsafe
.
Offsetof
(
data
.
b
));
instr
.
op
(
instr
,
state
);
state
.
fieldnum
=
1
;
instr
.
field
=
2
;
instr
.
indir
=
2
;
instr
.
offset
=
uintptr
(
unsafe
.
Offsetof
(
data
.
c
));
...
...
@@ -344,13 +368,15 @@ func TestScalarEncInstructions(t *testing.T) {
ppv
:=
&
pv
;
data
:=
(
struct
{
a
int64
;
b
*
int64
;
c
**
int64
}){
v
,
pv
,
ppv
};
instr
:=
&
encInstr
{
encInt64
,
0
,
0
,
0
};
state
.
w
=
b
;
state
:=
newEncState
(
b
)
;
state
.
base
=
uintptr
(
unsafe
.
Pointer
(
&
data
));
instr
.
op
(
instr
,
state
);
state
.
fieldnum
=
0
;
instr
.
field
=
1
;
instr
.
indir
=
1
;
instr
.
offset
=
uintptr
(
unsafe
.
Offsetof
(
data
.
b
));
instr
.
op
(
instr
,
state
);
state
.
fieldnum
=
1
;
instr
.
field
=
2
;
instr
.
indir
=
2
;
instr
.
offset
=
uintptr
(
unsafe
.
Offsetof
(
data
.
c
));
...
...
@@ -368,13 +394,15 @@ func TestScalarEncInstructions(t *testing.T) {
ppv
:=
&
pv
;
data
:=
(
struct
{
a
uint64
;
b
*
uint64
;
c
**
uint64
}){
v
,
pv
,
ppv
};
instr
:=
&
encInstr
{
encUint
,
0
,
0
,
0
};
state
.
w
=
b
;
state
:=
newEncState
(
b
)
;
state
.
base
=
uintptr
(
unsafe
.
Pointer
(
&
data
));
instr
.
op
(
instr
,
state
);
state
.
fieldnum
=
0
;
instr
.
field
=
1
;
instr
.
indir
=
1
;
instr
.
offset
=
uintptr
(
unsafe
.
Offsetof
(
data
.
b
));
instr
.
op
(
instr
,
state
);
state
.
fieldnum
=
1
;
instr
.
field
=
2
;
instr
.
indir
=
2
;
instr
.
offset
=
uintptr
(
unsafe
.
Offsetof
(
data
.
c
));
...
...
@@ -392,13 +420,15 @@ func TestScalarEncInstructions(t *testing.T) {
ppv
:=
&
pv
;
data
:=
(
struct
{
a
float
;
b
*
float
;
c
**
float
}){
v
,
pv
,
ppv
};
instr
:=
&
encInstr
{
encFloat
,
0
,
0
,
0
};
state
.
w
=
b
;
state
:=
newEncState
(
b
)
;
state
.
base
=
uintptr
(
unsafe
.
Pointer
(
&
data
));
instr
.
op
(
instr
,
state
);
state
.
fieldnum
=
0
;
instr
.
field
=
1
;
instr
.
indir
=
1
;
instr
.
offset
=
uintptr
(
unsafe
.
Offsetof
(
data
.
b
));
instr
.
op
(
instr
,
state
);
state
.
fieldnum
=
1
;
instr
.
field
=
2
;
instr
.
indir
=
2
;
instr
.
offset
=
uintptr
(
unsafe
.
Offsetof
(
data
.
c
));
...
...
@@ -416,13 +446,15 @@ func TestScalarEncInstructions(t *testing.T) {
ppv
:=
&
pv
;
data
:=
(
struct
{
a
float32
;
b
*
float32
;
c
**
float32
}){
v
,
pv
,
ppv
};
instr
:=
&
encInstr
{
encFloat32
,
0
,
0
,
0
};
state
.
w
=
b
;
state
:=
newEncState
(
b
)
;
state
.
base
=
uintptr
(
unsafe
.
Pointer
(
&
data
));
instr
.
op
(
instr
,
state
);
state
.
fieldnum
=
0
;
instr
.
field
=
1
;
instr
.
indir
=
1
;
instr
.
offset
=
uintptr
(
unsafe
.
Offsetof
(
data
.
b
));
instr
.
op
(
instr
,
state
);
state
.
fieldnum
=
1
;
instr
.
field
=
2
;
instr
.
indir
=
2
;
instr
.
offset
=
uintptr
(
unsafe
.
Offsetof
(
data
.
c
));
...
...
@@ -440,13 +472,15 @@ func TestScalarEncInstructions(t *testing.T) {
ppv
:=
&
pv
;
data
:=
(
struct
{
a
float64
;
b
*
float64
;
c
**
float64
}){
v
,
pv
,
ppv
};
instr
:=
&
encInstr
{
encFloat64
,
0
,
0
,
0
};
state
.
w
=
b
;
state
:=
newEncState
(
b
)
;
state
.
base
=
uintptr
(
unsafe
.
Pointer
(
&
data
));
instr
.
op
(
instr
,
state
);
state
.
fieldnum
=
0
;
instr
.
field
=
1
;
instr
.
indir
=
1
;
instr
.
offset
=
uintptr
(
unsafe
.
Offsetof
(
data
.
b
));
instr
.
op
(
instr
,
state
);
state
.
fieldnum
=
1
;
instr
.
field
=
2
;
instr
.
indir
=
2
;
instr
.
offset
=
uintptr
(
unsafe
.
Offsetof
(
data
.
c
));
...
...
@@ -462,22 +496,28 @@ func expectField(n int, state *DecState, t *testing.T) {
if
state
.
err
!=
nil
{
t
.
Fatalf
(
"decoding field number %d: %v"
,
n
,
state
.
err
);
}
if
v
!=
n
{
if
v
+
state
.
fieldnum
!=
n
{
t
.
Fatalf
(
"decoding field number %d, got %d"
,
n
,
v
);
}
state
.
fieldnum
=
n
;
}
func
newDecState
(
data
[]
byte
)
*
DecState
{
state
:=
new
(
DecState
);
state
.
r
=
bytes
.
NewBuffer
(
data
);
state
.
fieldnum
=
-
1
;
return
state
;
}
// Test instruction execution for decoding.
// Do not run the machine yet; instead do individual instructions crafted by hand.
func
TestScalarDecInstructions
(
t
*
testing
.
T
)
{
state
:=
new
(
DecState
);
// bool
{
b
:=
bytes
.
NewBuffer
(
boolResult
);
var
data
struct
{
a
bool
;
b
*
bool
;
c
**
bool
};
instr
:=
&
decInstr
{
decBool
,
0
,
0
,
0
};
state
.
r
=
b
;
state
:=
newDecState
(
boolResult
)
;
state
.
base
=
uintptr
(
unsafe
.
Pointer
(
&
data
));
expectField
(
0
,
state
,
t
);
instr
.
op
(
instr
,
state
);
...
...
@@ -504,10 +544,9 @@ func TestScalarDecInstructions(t *testing.T) {
// int
{
b
:=
bytes
.
NewBuffer
(
signedResult
);
var
data
struct
{
a
int
;
b
*
int
;
c
**
int
};
instr
:=
&
decInstr
{
decInt
,
0
,
0
,
0
};
state
.
r
=
b
;
state
:=
newDecState
(
signedResult
)
;
state
.
base
=
uintptr
(
unsafe
.
Pointer
(
&
data
));
expectField
(
0
,
state
,
t
);
instr
.
op
(
instr
,
state
);
...
...
@@ -534,10 +573,9 @@ func TestScalarDecInstructions(t *testing.T) {
// uint
{
b
:=
bytes
.
NewBuffer
(
unsignedResult
);
var
data
struct
{
a
uint
;
b
*
uint
;
c
**
uint
};
instr
:=
&
decInstr
{
decUint
,
0
,
0
,
0
};
state
.
r
=
b
;
state
:=
newDecState
(
unsignedResult
)
;
state
.
base
=
uintptr
(
unsafe
.
Pointer
(
&
data
));
expectField
(
0
,
state
,
t
);
instr
.
op
(
instr
,
state
);
...
...
@@ -564,10 +602,9 @@ func TestScalarDecInstructions(t *testing.T) {
// int8
{
b
:=
bytes
.
NewBuffer
(
signedResult
);
var
data
struct
{
a
int8
;
b
*
int8
;
c
**
int8
};
instr
:=
&
decInstr
{
decInt8
,
0
,
0
,
0
};
state
.
r
=
b
;
state
:=
newDecState
(
signedResult
)
;
state
.
base
=
uintptr
(
unsafe
.
Pointer
(
&
data
));
expectField
(
0
,
state
,
t
);
instr
.
op
(
instr
,
state
);
...
...
@@ -594,10 +631,9 @@ func TestScalarDecInstructions(t *testing.T) {
// uint8
{
b
:=
bytes
.
NewBuffer
(
unsignedResult
);
var
data
struct
{
a
uint8
;
b
*
uint8
;
c
**
uint8
};
instr
:=
&
decInstr
{
decUint8
,
0
,
0
,
0
};
state
.
r
=
b
;
state
:=
newDecState
(
unsignedResult
)
;
state
.
base
=
uintptr
(
unsafe
.
Pointer
(
&
data
));
expectField
(
0
,
state
,
t
);
instr
.
op
(
instr
,
state
);
...
...
@@ -624,10 +660,9 @@ func TestScalarDecInstructions(t *testing.T) {
// int16
{
b
:=
bytes
.
NewBuffer
(
signedResult
);
var
data
struct
{
a
int16
;
b
*
int16
;
c
**
int16
};
instr
:=
&
decInstr
{
decInt16
,
0
,
0
,
0
};
state
.
r
=
b
;
state
:=
newDecState
(
signedResult
)
;
state
.
base
=
uintptr
(
unsafe
.
Pointer
(
&
data
));
expectField
(
0
,
state
,
t
);
instr
.
op
(
instr
,
state
);
...
...
@@ -654,10 +689,9 @@ func TestScalarDecInstructions(t *testing.T) {
// uint16
{
b
:=
bytes
.
NewBuffer
(
unsignedResult
);
var
data
struct
{
a
uint16
;
b
*
uint16
;
c
**
uint16
};
instr
:=
&
decInstr
{
decUint16
,
0
,
0
,
0
};
state
.
r
=
b
;
state
:=
newDecState
(
unsignedResult
)
;
state
.
base
=
uintptr
(
unsafe
.
Pointer
(
&
data
));
expectField
(
0
,
state
,
t
);
instr
.
op
(
instr
,
state
);
...
...
@@ -684,10 +718,9 @@ func TestScalarDecInstructions(t *testing.T) {
// int32
{
b
:=
bytes
.
NewBuffer
(
signedResult
);
var
data
struct
{
a
int32
;
b
*
int32
;
c
**
int32
};
instr
:=
&
decInstr
{
decInt32
,
0
,
0
,
0
};
state
.
r
=
b
;
state
:=
newDecState
(
signedResult
)
;
state
.
base
=
uintptr
(
unsafe
.
Pointer
(
&
data
));
expectField
(
0
,
state
,
t
);
instr
.
op
(
instr
,
state
);
...
...
@@ -714,10 +747,9 @@ func TestScalarDecInstructions(t *testing.T) {
// uint32
{
b
:=
bytes
.
NewBuffer
(
unsignedResult
);
var
data
struct
{
a
uint32
;
b
*
uint32
;
c
**
uint32
};
instr
:=
&
decInstr
{
decUint32
,
0
,
0
,
0
};
state
.
r
=
b
;
state
:=
newDecState
(
unsignedResult
)
;
state
.
base
=
uintptr
(
unsafe
.
Pointer
(
&
data
));
expectField
(
0
,
state
,
t
);
instr
.
op
(
instr
,
state
);
...
...
@@ -744,10 +776,9 @@ func TestScalarDecInstructions(t *testing.T) {
// int64
{
b
:=
bytes
.
NewBuffer
(
signedResult
);
var
data
struct
{
a
int64
;
b
*
int64
;
c
**
int64
};
instr
:=
&
decInstr
{
decInt64
,
0
,
0
,
0
};
state
.
r
=
b
;
state
:=
newDecState
(
signedResult
)
;
state
.
base
=
uintptr
(
unsafe
.
Pointer
(
&
data
));
expectField
(
0
,
state
,
t
);
instr
.
op
(
instr
,
state
);
...
...
@@ -774,10 +805,9 @@ func TestScalarDecInstructions(t *testing.T) {
// uint64
{
b
:=
bytes
.
NewBuffer
(
unsignedResult
);
var
data
struct
{
a
uint64
;
b
*
uint64
;
c
**
uint64
};
instr
:=
&
decInstr
{
decUint64
,
0
,
0
,
0
};
state
.
r
=
b
;
state
:=
newDecState
(
unsignedResult
)
;
state
.
base
=
uintptr
(
unsafe
.
Pointer
(
&
data
));
expectField
(
0
,
state
,
t
);
instr
.
op
(
instr
,
state
);
...
...
@@ -804,10 +834,9 @@ func TestScalarDecInstructions(t *testing.T) {
// float
{
b
:=
bytes
.
NewBuffer
(
floatResult
);
var
data
struct
{
a
float
;
b
*
float
;
c
**
float
};
instr
:=
&
decInstr
{
decFloat
,
0
,
0
,
0
};
state
.
r
=
b
;
state
:=
newDecState
(
floatResult
)
;
state
.
base
=
uintptr
(
unsafe
.
Pointer
(
&
data
));
expectField
(
0
,
state
,
t
);
instr
.
op
(
instr
,
state
);
...
...
@@ -834,10 +863,9 @@ func TestScalarDecInstructions(t *testing.T) {
// float32
{
b
:=
bytes
.
NewBuffer
(
floatResult
);
var
data
struct
{
a
float32
;
b
*
float32
;
c
**
float32
};
instr
:=
&
decInstr
{
decFloat32
,
0
,
0
,
0
};
state
.
r
=
b
;
state
:=
newDecState
(
floatResult
)
;
state
.
base
=
uintptr
(
unsafe
.
Pointer
(
&
data
));
expectField
(
0
,
state
,
t
);
instr
.
op
(
instr
,
state
);
...
...
@@ -864,10 +892,9 @@ func TestScalarDecInstructions(t *testing.T) {
// float64
{
b
:=
bytes
.
NewBuffer
(
floatResult
);
var
data
struct
{
a
float64
;
b
*
float64
;
c
**
float64
};
instr
:=
&
decInstr
{
decFloat64
,
0
,
0
,
0
};
state
.
r
=
b
;
state
:=
newDecState
(
floatResult
)
;
state
.
base
=
uintptr
(
unsafe
.
Pointer
(
&
data
));
expectField
(
0
,
state
,
t
);
instr
.
op
(
instr
,
state
);
...
...
@@ -892,3 +919,18 @@ func TestScalarDecInstructions(t *testing.T) {
}
}
}
type
T1
struct
{
a
,
b
,
c
int
}
func
TestEncode
(
t
*
testing
.
T
)
{
t1
:=
&
T1
{
17
,
18
,
-
5
};
b
:=
new
(
bytes
.
Buffer
);
Encode
(
b
,
t1
);
var
_t1
T1
;
Decode
(
b
,
&
_t1
);
if
!
reflect
.
DeepEqual
(
t1
,
&
_t1
)
{
t
.
Errorf
(
"encode expected %v got %v"
,
*
t1
,
_t1
);
}
}
src/pkg/gob/decode.go
View file @
c701af8c
...
...
@@ -5,9 +5,11 @@
package
gob
import
(
"gob"
;
"io"
;
"math"
;
"os"
;
"reflect"
;
"unsafe"
;
)
...
...
@@ -16,6 +18,7 @@ type DecState struct {
r
io
.
Reader
;
err
os
.
Error
;
base
uintptr
;
fieldnum
int
;
// the last field number read.
buf
[
1
]
byte
;
// buffer used by the decoder; here to avoid allocation.
}
...
...
@@ -333,3 +336,114 @@ func decFloat64(i *decInstr, state *DecState) {
*
(
*
float64
)(
p
)
=
v
;
}
}
// Execution engine
// The encoder engine is an array of instructions indexed by field number of the incoming
// data. It is executed with random access according to field number.
type
decEngine
struct
{
instr
[]
decInstr
}
var
decEngineMap
=
make
(
map
[
reflect
.
Type
]
*
decEngine
)
var
decOp
=
map
[
int
]
func
(
*
decInstr
,
*
DecState
)
{
reflect
.
BoolKind
:
decBool
,
reflect
.
IntKind
:
decInt
,
reflect
.
Int8Kind
:
decInt8
,
reflect
.
Int16Kind
:
decInt16
,
reflect
.
Int32Kind
:
decInt32
,
reflect
.
Int64Kind
:
decInt64
,
reflect
.
UintKind
:
decUint
,
reflect
.
Uint8Kind
:
decUint8
,
reflect
.
Uint16Kind
:
decUint16
,
reflect
.
Uint32Kind
:
decUint32
,
reflect
.
Uint64Kind
:
decUint64
,
reflect
.
FloatKind
:
decFloat
,
reflect
.
Float32Kind
:
decFloat32
,
reflect
.
Float64Kind
:
decFloat64
,
}
func
compileDec
(
rt
reflect
.
Type
,
typ
Type
)
*
decEngine
{
srt
,
ok1
:=
rt
.
(
reflect
.
StructType
);
styp
,
ok2
:=
typ
.
(
*
structType
);
if
!
ok1
||
!
ok2
{
panicln
(
"TODO: can't handle non-structs"
);
}
engine
:=
new
(
decEngine
);
engine
.
instr
=
make
([]
decInstr
,
len
(
styp
.
field
));
for
fieldnum
:=
0
;
fieldnum
<
len
(
styp
.
field
);
fieldnum
++
{
field
:=
styp
.
field
[
fieldnum
];
// TODO(r): verify compatibility with corresponding field of data.
// For now, assume perfect correspondence between struct and gob.
_name
,
ftyp
,
_tag
,
offset
:=
srt
.
Field
(
fieldnum
);
// How many indirections to the underlying data?
indir
:=
0
;
for
{
pt
,
ok
:=
ftyp
.
(
reflect
.
PtrType
);
if
!
ok
{
break
}
ftyp
=
pt
.
Sub
();
indir
++
;
}
op
,
ok
:=
decOp
[
ftyp
.
Kind
()];
if
!
ok
{
panicln
(
"can't handle decode for type"
,
ftyp
.
String
());
}
engine
.
instr
[
fieldnum
]
=
decInstr
{
op
,
fieldnum
,
indir
,
uintptr
(
offset
)};
}
return
engine
;
}
func
getDecEngine
(
rt
reflect
.
Type
)
*
decEngine
{
engine
,
ok
:=
decEngineMap
[
rt
];
if
!
ok
{
return
compileDec
(
rt
,
newType
(
rt
.
Name
(),
rt
));
decEngineMap
[
rt
]
=
engine
;
}
return
engine
;
}
func
(
engine
*
decEngine
)
decode
(
r
io
.
Reader
,
v
reflect
.
Value
)
os
.
Error
{
sv
,
ok
:=
v
.
(
reflect
.
StructValue
);
if
!
ok
{
panicln
(
"decoder can't handle non-struct values yet"
);
}
state
:=
new
(
DecState
);
state
.
r
=
r
;
state
.
base
=
uintptr
(
sv
.
Addr
());
state
.
fieldnum
=
-
1
;
for
state
.
err
==
nil
{
delta
:=
int
(
DecodeUint
(
state
));
if
state
.
err
!=
nil
||
delta
==
0
{
// struct terminator is zero delta fieldnum
break
}
fieldnum
:=
state
.
fieldnum
+
delta
;
if
fieldnum
>=
len
(
engine
.
instr
)
{
panicln
(
"TODO(r): need to handle unknown data"
);
}
instr
:=
&
engine
.
instr
[
fieldnum
];
instr
.
op
(
instr
,
state
);
state
.
fieldnum
=
fieldnum
;
}
return
state
.
err
}
func
Decode
(
r
io
.
Reader
,
e
interface
{})
os
.
Error
{
// Dereference down to the underlying object.
rt
:=
reflect
.
Typeof
(
e
);
v
:=
reflect
.
NewValue
(
e
);
for
{
pt
,
ok
:=
rt
.
(
reflect
.
PtrType
);
if
!
ok
{
break
}
rt
=
pt
.
Sub
();
v
=
reflect
.
Indirect
(
v
);
}
typeLock
.
Lock
();
engine
:=
getDecEngine
(
rt
);
typeLock
.
Unlock
();
return
engine
.
decode
(
r
,
v
);
}
src/pkg/gob/encode.go
View file @
c701af8c
...
...
@@ -5,17 +5,24 @@
package
gob
import
(
"gob"
;
"io"
;
"math"
;
"os"
;
"reflect"
;
"sync"
;
"unsafe"
;
)
// The global execution state of an instance of the encoder.
// Field numbers are delta encoded and always increase. The field
// number is initialized to -1 so 0 comes out as delta(1). A delta of
// 0 terminates the structure.
type
EncState
struct
{
w
io
.
Writer
;
base
uintptr
;
// the base address of the data structure being written
err
os
.
Error
;
// error encountered during encoding;
fieldnum
int
;
// the last field number written.
buf
[
16
]
byte
;
// buffer used by the encoder; here to avoid allocation.
}
...
...
@@ -86,7 +93,7 @@ func encBool(i *encInstr, state *EncState) {
}
b
:=
*
(
*
bool
)(
p
);
if
b
{
EncodeUint
(
state
,
uint64
(
i
.
field
));
EncodeUint
(
state
,
uint64
(
i
.
field
-
state
.
fieldnum
));
EncodeUint
(
state
,
1
);
}
}
...
...
@@ -100,7 +107,7 @@ func encInt(i *encInstr, state *EncState) {
}
v
:=
int64
(
*
(
*
int
)(
p
));
if
v
!=
0
{
EncodeUint
(
state
,
uint64
(
i
.
field
));
EncodeUint
(
state
,
uint64
(
i
.
field
-
state
.
fieldnum
));
EncodeInt
(
state
,
v
);
}
}
...
...
@@ -114,7 +121,7 @@ func encUint(i *encInstr, state *EncState) {
}
v
:=
uint64
(
*
(
*
uint
)(
p
));
if
v
!=
0
{
EncodeUint
(
state
,
uint64
(
i
.
field
));
EncodeUint
(
state
,
uint64
(
i
.
field
-
state
.
fieldnum
));
EncodeUint
(
state
,
v
);
}
}
...
...
@@ -128,7 +135,7 @@ func encInt8(i *encInstr, state *EncState) {
}
v
:=
int64
(
*
(
*
int8
)(
p
));
if
v
!=
0
{
EncodeUint
(
state
,
uint64
(
i
.
field
));
EncodeUint
(
state
,
uint64
(
i
.
field
-
state
.
fieldnum
));
EncodeInt
(
state
,
v
);
}
}
...
...
@@ -142,7 +149,7 @@ func encUint8(i *encInstr, state *EncState) {
}
v
:=
uint64
(
*
(
*
uint8
)(
p
));
if
v
!=
0
{
EncodeUint
(
state
,
uint64
(
i
.
field
));
EncodeUint
(
state
,
uint64
(
i
.
field
-
state
.
fieldnum
));
EncodeUint
(
state
,
v
);
}
}
...
...
@@ -156,7 +163,7 @@ func encInt16(i *encInstr, state *EncState) {
}
v
:=
int64
(
*
(
*
int16
)(
p
));
if
v
!=
0
{
EncodeUint
(
state
,
uint64
(
i
.
field
));
EncodeUint
(
state
,
uint64
(
i
.
field
-
state
.
fieldnum
));
EncodeInt
(
state
,
v
);
}
}
...
...
@@ -170,7 +177,7 @@ func encUint16(i *encInstr, state *EncState) {
}
v
:=
uint64
(
*
(
*
uint16
)(
p
));
if
v
!=
0
{
EncodeUint
(
state
,
uint64
(
i
.
field
));
EncodeUint
(
state
,
uint64
(
i
.
field
-
state
.
fieldnum
));
EncodeUint
(
state
,
v
);
}
}
...
...
@@ -184,7 +191,7 @@ func encInt32(i *encInstr, state *EncState) {
}
v
:=
int64
(
*
(
*
int32
)(
p
));
if
v
!=
0
{
EncodeUint
(
state
,
uint64
(
i
.
field
));
EncodeUint
(
state
,
uint64
(
i
.
field
-
state
.
fieldnum
));
EncodeInt
(
state
,
v
);
}
}
...
...
@@ -198,7 +205,7 @@ func encUint32(i *encInstr, state *EncState) {
}
v
:=
uint64
(
*
(
*
uint32
)(
p
));
if
v
!=
0
{
EncodeUint
(
state
,
uint64
(
i
.
field
));
EncodeUint
(
state
,
uint64
(
i
.
field
-
state
.
fieldnum
));
EncodeUint
(
state
,
v
);
}
}
...
...
@@ -212,7 +219,7 @@ func encInt64(i *encInstr, state *EncState) {
}
v
:=
*
(
*
int64
)(
p
);
if
v
!=
0
{
EncodeUint
(
state
,
uint64
(
i
.
field
));
EncodeUint
(
state
,
uint64
(
i
.
field
-
state
.
fieldnum
));
EncodeInt
(
state
,
v
);
}
}
...
...
@@ -226,7 +233,7 @@ func encUint64(i *encInstr, state *EncState) {
}
v
:=
*
(
*
uint64
)(
p
);
if
v
!=
0
{
EncodeUint
(
state
,
uint64
(
i
.
field
));
EncodeUint
(
state
,
uint64
(
i
.
field
-
state
.
fieldnum
));
EncodeUint
(
state
,
v
);
}
}
...
...
@@ -257,7 +264,7 @@ func encFloat(i *encInstr, state *EncState) {
f
:=
float
(
*
(
*
float
)(
p
));
if
f
!=
0
{
v
:=
floatBits
(
float64
(
f
));
EncodeUint
(
state
,
uint64
(
i
.
field
));
EncodeUint
(
state
,
uint64
(
i
.
field
-
state
.
fieldnum
));
EncodeUint
(
state
,
v
);
}
}
...
...
@@ -272,7 +279,7 @@ func encFloat32(i *encInstr, state *EncState) {
f
:=
float32
(
*
(
*
float32
)(
p
));
if
f
!=
0
{
v
:=
floatBits
(
float64
(
f
));
EncodeUint
(
state
,
uint64
(
i
.
field
));
EncodeUint
(
state
,
uint64
(
i
.
field
-
state
.
fieldnum
));
EncodeUint
(
state
,
v
);
}
}
...
...
@@ -287,7 +294,118 @@ func encFloat64(i *encInstr, state *EncState) {
f
:=
*
(
*
float64
)(
p
);
if
f
!=
0
{
v
:=
floatBits
(
f
);
EncodeUint
(
state
,
uint64
(
i
.
field
));
EncodeUint
(
state
,
uint64
(
i
.
field
-
state
.
fieldnum
));
EncodeUint
(
state
,
v
);
}
}
// The end of a struct is marked by a delta field number of 0.
func
encStructTerminator
(
i
*
encInstr
,
state
*
EncState
)
{
EncodeUint
(
state
,
0
);
}
// Execution engine
// The encoder engine is an array of instructions indexed by field number of the encoding
// data, typically a struct. It is executed top to bottom, walking the struct.
type
encEngine
struct
{
instr
[]
encInstr
}
var
encEngineMap
=
make
(
map
[
reflect
.
Type
]
*
encEngine
)
var
encOp
=
map
[
int
]
func
(
*
encInstr
,
*
EncState
)
{
reflect
.
BoolKind
:
encBool
,
reflect
.
IntKind
:
encInt
,
reflect
.
Int8Kind
:
encInt8
,
reflect
.
Int16Kind
:
encInt16
,
reflect
.
Int32Kind
:
encInt32
,
reflect
.
Int64Kind
:
encInt64
,
reflect
.
UintKind
:
encUint
,
reflect
.
Uint8Kind
:
encUint8
,
reflect
.
Uint16Kind
:
encUint16
,
reflect
.
Uint32Kind
:
encUint32
,
reflect
.
Uint64Kind
:
encUint64
,
reflect
.
FloatKind
:
encFloat
,
reflect
.
Float32Kind
:
encFloat32
,
reflect
.
Float64Kind
:
encFloat64
,
}
// The local Type was compiled from the actual value, so we know
// it's compatible.
// TODO(r): worth checking? typ is unused here.
func
compileEnc
(
rt
reflect
.
Type
,
typ
Type
)
*
encEngine
{
srt
,
ok
:=
rt
.
(
reflect
.
StructType
);
if
!
ok
{
panicln
(
"TODO: can't handle non-structs"
);
}
engine
:=
new
(
encEngine
);
engine
.
instr
=
make
([]
encInstr
,
srt
.
Len
()
+
1
);
// +1 for terminator
for
fieldnum
:=
0
;
fieldnum
<
srt
.
Len
();
fieldnum
++
{
_name
,
ftyp
,
_tag
,
offset
:=
srt
.
Field
(
fieldnum
);
// How many indirections to the underlying data?
indir
:=
0
;
for
{
pt
,
ok
:=
ftyp
.
(
reflect
.
PtrType
);
if
!
ok
{
break
}
ftyp
=
pt
.
Sub
();
indir
++
;
}
op
,
ok
:=
encOp
[
ftyp
.
Kind
()];
if
!
ok
{
panicln
(
"encode can't handle type"
,
ftyp
.
String
());
}
engine
.
instr
[
fieldnum
]
=
encInstr
{
op
,
fieldnum
,
indir
,
uintptr
(
offset
)};
}
engine
.
instr
[
srt
.
Len
()]
=
encInstr
{
encStructTerminator
,
0
,
0
,
0
};
return
engine
;
}
// typeLock must be held.
func
getEncEngine
(
rt
reflect
.
Type
)
*
encEngine
{
engine
,
ok
:=
encEngineMap
[
rt
];
if
!
ok
{
engine
=
compileEnc
(
rt
,
newType
(
rt
.
Name
(),
rt
));
encEngineMap
[
rt
]
=
engine
;
}
return
engine
}
func
(
engine
*
encEngine
)
encode
(
w
io
.
Writer
,
v
reflect
.
Value
)
os
.
Error
{
sv
,
ok
:=
v
.
(
reflect
.
StructValue
);
if
!
ok
{
panicln
(
"encoder can't handle non-struct values yet"
);
}
state
:=
new
(
EncState
);
state
.
w
=
w
;
state
.
base
=
uintptr
(
sv
.
Addr
());
state
.
fieldnum
=
-
1
;
for
i
:=
0
;
i
<
len
(
engine
.
instr
);
i
++
{
instr
:=
&
engine
.
instr
[
i
];
instr
.
op
(
instr
,
state
);
if
state
.
err
!=
nil
{
break
}
state
.
fieldnum
=
i
;
}
return
state
.
err
}
func
Encode
(
w
io
.
Writer
,
e
interface
{})
os
.
Error
{
// Dereference down to the underlying object.
rt
:=
reflect
.
Typeof
(
e
);
v
:=
reflect
.
NewValue
(
e
);
for
{
pt
,
ok
:=
rt
.
(
reflect
.
PtrType
);
if
!
ok
{
break
}
rt
=
pt
.
Sub
();
v
=
reflect
.
Indirect
(
v
);
}
typeLock
.
Lock
();
engine
:=
getEncEngine
(
rt
);
typeLock
.
Unlock
();
return
engine
.
encode
(
w
,
v
);
}
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