Commit bb7b117b authored by Kirill Smelkov's avatar Kirill Smelkov Committed by Kamil Kisiel

encoder: Fix dict wrt protocol version

- we can use EMPTY_DICT only if protocol >= 1

Also: similarly to list (33d1926f), since we are now using EMPTY_DICT
only optionally, it is logical to swit to

	MARK + ... + DICT

from

	EMPTY_DICT (or MARK + DICT @proto=0) + MARK + ... + SETITEMS

which is at least 1 byte longer.

For the reference - SETITEMS is also from protocol 1, while DICT is from
protocol 0.
parent 89930c10
...@@ -376,37 +376,33 @@ func (e *Encoder) encodeMap(m reflect.Value) error { ...@@ -376,37 +376,33 @@ func (e *Encoder) encodeMap(m reflect.Value) error {
l := len(keys) l := len(keys)
err := e.emit(opEmptyDict) // protocol >= 1: ø dict -> EMPTY_DICT
if e.config.Protocol >= 1 && l == 0 {
return e.emit(opEmptyDict)
}
// MARK + ... + DICT
// TODO detect cycles and double references to the same object
// XXX sort keys, so the output is stable?
err := e.emit(opMark)
if err != nil { if err != nil {
return err return err
} }
if l > 0 { for _, k := range keys {
err := e.emit(opMark) err = e.encode(k)
if err != nil { if err != nil {
return err return err
} }
v := m.MapIndex(k)
for _, k := range keys { err = e.encode(v)
err = e.encode(k)
if err != nil {
return err
}
v := m.MapIndex(k)
err = e.encode(v)
if err != nil {
return err
}
}
err = e.emit(opSetitems)
if err != nil { if err != nil {
return err return err
} }
} }
return nil return e.emit(opDict)
} }
func (e *Encoder) encodeCall(v *Call) error { func (e *Encoder) encodeCall(v *Call) error {
......
...@@ -263,9 +263,27 @@ var tests = []TestEntry{ ...@@ -263,9 +263,27 @@ var tests = []TestEntry{
X("dict({})", make(map[interface{}]interface{}), X("dict({})", make(map[interface{}]interface{}),
P0("(d."), // MARK + DICT
P1_("}."), // EMPTY_DICT
I("(dp0\n.")), I("(dp0\n.")),
X("dict({'a': '1'})", map[interface{}]interface{}{"a": "1"},
P0("(S\"a\"\nS\"1\"\nd."), // MARK + STRING + DICT
P12("(U\x01aU\x011d."), // MARK + SHORT_BINSTRING + DICT
P3("(X\x01\x00\x00\x00aX\x01\x00\x00\x001d."), // MARK + BINUNICODE + DICT
P4_("(\x8c\x01a\x8c\x011d.")), // MARK + SHORT_BINUNICODE + DICT
X("dict({'a': '1', 'b': '2'})", map[interface{}]interface{}{"a": "1", "b": "2"}, X("dict({'a': '1', 'b': '2'})", map[interface{}]interface{}{"a": "1", "b": "2"},
// map iteration order is not stable - test only decoding
I("(S\"a\"\nS\"1\"\nS\"b\"\nS\"2\"\nd."), // P0: MARK + STRING + DICT
I("(U\x01aU\x011U\x01bU\x012d."), // P12: MARK + SHORT_BINSTRING + DICT
// P3: MARK + BINUNICODE + DICT
I("(X\x01\x00\x00\x00aX\x01\x00\x00\x001X\x01\x00\x00\x00bX\x01\x00\x00\x002d."),
I("(\x8c\x01a\x8c\x011\x8c\x01b\x8c\x012d."), // P4_: MARK + SHORT_BINUNICODE + DICT
I("(dS'a'\nS'1'\nsS'b'\nS'2'\ns."), // MARK + DICT + STRING + SETITEM
I("}(U\x01aU\x011U\x01bU\x012u."), // EMPTY_DICT + MARK + SHORT_BINSTRING + SETITEMS
I("(dp0\nS'a'\np1\nS'1'\np2\nsS'b'\np3\nS'2'\np4\ns.")), I("(dp0\nS'a'\np1\nS'1'\np2\nsS'b'\np3\nS'2'\np4\ns.")),
X("foo.bar # global", Class{Module: "foo", Name: "bar"}, X("foo.bar # global", Class{Module: "foo", Name: "bar"},
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment