Commit 98fb1987 authored by Kirill Smelkov's avatar Kirill Smelkov Committed by Kamil Kisiel

encoder: Fix Ref wrt protocol version

- we can use BINPERSID only if protocol >= 1
- we can use text PERSID only if protocol < 4 and Ref string does not
  contain \n - else encoding have to fail.

Tests for Ref encoding at protocols 3 & 4 will follow after string
encoding is fixed.
parent 33d1926f
...@@ -2,6 +2,7 @@ package ogórek ...@@ -2,6 +2,7 @@ package ogórek
import ( import (
"encoding/binary" "encoding/binary"
"errors"
"fmt" "fmt"
"io" "io"
"math" "math"
...@@ -383,17 +384,25 @@ func (e *Encoder) encodeClass(v *Class) error { ...@@ -383,17 +384,25 @@ func (e *Encoder) encodeClass(v *Class) error {
return e.emit(opStackGlobal) return e.emit(opStackGlobal)
} }
var errP0PersIDStringLineOnly = errors.New(`protocol 0: persistent ID must be string without \n`)
func (e *Encoder) encodeRef(v *Ref) error { func (e *Encoder) encodeRef(v *Ref) error {
if pids, ok := v.Pid.(string); ok && !strings.Contains(pids, "\n") { // protocol 0: pid must be string without \n
return e.emitf("%c%s\n", opPersid, pids) if e.config.Protocol == 0 {
} else { pids, ok := v.Pid.(string)
// XXX we can use opBinpersid only if .protocol >= 1 if !ok || strings.Contains(pids, "\n") {
err := e.encode(reflectValueOf(v.Pid)) return errP0PersIDStringLineOnly
if err != nil {
return err
} }
return e.emit(opBinpersid)
return e.emitf("%c%s\n", opPersid, pids)
}
// protocol >= 1: we can use opBinpersid which allows arbitrary object as argument
err := e.encode(reflectValueOf(v.Pid))
if err != nil {
return err
} }
return e.emit(opBinpersid)
} }
func (e *Encoder) encodeStruct(st reflect.Value) error { func (e *Encoder) encodeStruct(st reflect.Value) error {
......
...@@ -238,12 +238,17 @@ var tests = []TestEntry{ ...@@ -238,12 +238,17 @@ var tests = []TestEntry{
I("cfoo\nbar\nS'bing'\n\x85R.")), // GLOBAL + STRING + TUPLE1 + REDUCE I("cfoo\nbar\nS'bing'\n\x85R.")), // GLOBAL + STRING + TUPLE1 + REDUCE
X(`persref("abc")`, Ref{"abc"}, X(`persref("abc")`, Ref{"abc"},
P0("Pabc\n.")), // PERSID P0("Pabc\n."), // PERSID
P12("U\x03abcQ.")), // SHORT_BINSTRING + BINPERSID
X(`persref("abc\nd")`, Ref{"abc\nd"}, X(`persref("abc\nd")`, Ref{"abc\nd"},
P12("U\x05abc\ndQ.")), // SHORT_BINSTRING + BINPERSID P0(errP0PersIDStringLineOnly), // cannot be encoded
P12("U\x05abc\ndQ.")), // SHORT_BINSTRING + BINPERSID
X(`persref((1, 2))`, Ref{Tuple{int64(1), int64(2)}}, X(`persref((1, 2))`, Ref{Tuple{int64(1), int64(2)}},
P0(errP0PersIDStringLineOnly), // cannot be encoded
P1("(K\x01K\x02tQ."), // MARK + BININT1 + TUPLE + BINPERSID
P2_("K\x01K\x02\x86Q."), // BININT1 + TUPLE2 + BINPERSID
I("(I1\nI2\ntQ.")), I("(I1\nI2\ntQ.")),
// decode only // decode only
...@@ -584,7 +589,7 @@ func TestPersistentRefs(t *testing.T) { ...@@ -584,7 +589,7 @@ func TestPersistentRefs(t *testing.T) {
} }
dconf := &DecoderConfig{PersistentLoad: loadref} dconf := &DecoderConfig{PersistentLoad: loadref}
econf := &EncoderConfig{PersistentRef: getref} econf := &EncoderConfig{PersistentRef: getref, Protocol: 1}
testv := []struct { testv := []struct {
input string input string
......
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