diff --git a/binary/binary.go b/binary/binary.go index 7db7175b..92f2a90b 100644 --- a/binary/binary.go +++ b/binary/binary.go @@ -1,6 +1,7 @@ package binary import ( + "encoding/json" "io" "reflect" ) @@ -28,6 +29,30 @@ func WriteBinary(o interface{}, w io.Writer, n *int64, err *error) { writeReflect(rv, rt, w, n, err) } +func ReadJSON(o interface{}, bytes []byte, err *error) interface{} { + var parsed interface{} + *err = json.Unmarshal(bytes, &parsed) + if *err != nil { + return o + } + + rv, rt := reflect.ValueOf(o), reflect.TypeOf(o) + if rv.Kind() == reflect.Ptr { + readReflectJSON(rv.Elem(), rt.Elem(), parsed, err) + return o + } else { + ptrRv := reflect.New(rt) + readReflectJSON(ptrRv.Elem(), rt, parsed, err) + return ptrRv.Elem().Interface() + } +} + +func WriteJSON(o interface{}, w io.Writer, n *int64, err *error) { + rv := reflect.ValueOf(o) + rt := reflect.TypeOf(o) + writeReflectJSON(rv, rt, w, n, err) +} + // Write all of bz to w // Increment n and set err accordingly. func WriteTo(bz []byte, w io.Writer, n *int64, err *error) { diff --git a/binary/log.go b/binary/log.go index 9eacec2a..cc6c6372 100644 --- a/binary/log.go +++ b/binary/log.go @@ -11,8 +11,8 @@ var log = log15.New("module", "binary") func init() { log.SetHandler( log15.LvlFilterHandler( - //log15.LvlWarn, - log15.LvlDebug, + log15.LvlWarn, + //log15.LvlDebug, log15.StreamHandler(os.Stderr, log15.LogfmtFormat()), ), ) diff --git a/binary/reflect.go b/binary/reflect.go index a7965538..9d34665c 100644 --- a/binary/reflect.go +++ b/binary/reflect.go @@ -1,8 +1,9 @@ package binary import ( + "encoding/hex" + "encoding/json" "errors" - "fmt" "io" "reflect" "sync" @@ -127,7 +128,7 @@ func RegisterType(info *TypeInfo) *TypeInfo { zero := reflect.Zero(rt) typeByte := zero.Interface().(HasTypeByte).TypeByte() if info.HasTypeByte && info.TypeByte != typeByte { - panic(fmt.Sprintf("Type %v expected TypeByte of %X", rt, typeByte)) + panic(Fmt("Type %v expected TypeByte of %X", rt, typeByte)) } else { info.HasTypeByte = true info.TypeByte = typeByte @@ -136,7 +137,7 @@ func RegisterType(info *TypeInfo) *TypeInfo { zero := reflect.Zero(ptrRt) typeByte := zero.Interface().(HasTypeByte).TypeByte() if info.HasTypeByte && info.TypeByte != typeByte { - panic(fmt.Sprintf("Type %v expected TypeByte of %X", ptrRt, typeByte)) + panic(Fmt("Type %v expected TypeByte of %X", ptrRt, typeByte)) } else { info.HasTypeByte = true info.TypeByte = typeByte @@ -178,7 +179,7 @@ func readReflect(rv reflect.Value, rt reflect.Type, r Unreader, n *int64, err *e typeByte := ReadByte(r, n, err) log.Debug("Read typebyte", "typeByte", typeByte) if typeByte != typeInfo.TypeByte { - *err = errors.New(fmt.Sprintf("Expected TypeByte of %X but got %X", typeInfo.TypeByte, typeByte)) + *err = errors.New(Fmt("Expected TypeByte of %X but got %X", typeInfo.TypeByte, typeByte)) return } } @@ -284,7 +285,7 @@ func readReflect(rv reflect.Value, rt reflect.Type, r Unreader, n *int64, err *e rv.SetUint(uint64(num)) default: - panic(fmt.Sprintf("Unknown field type %v", rt.Kind())) + panic(Fmt("Unknown field type %v", rt.Kind())) } } @@ -311,8 +312,6 @@ func writeReflect(rv reflect.Value, rt reflect.Type, w io.Writer, n *int64, err if rt.Kind() == reflect.Ptr { rt = rt.Elem() rv = rv.Elem() - // RegisterType registers the ptr type, - // so typeInfo is already for the ptr. } // Write TypeByte prefix @@ -383,6 +382,256 @@ func writeReflect(rv reflect.Value, rt reflect.Type, w io.Writer, n *int64, err WriteUvarint(uint(rv.Uint()), w, n, err) default: - panic(fmt.Sprintf("Unknown field type %v", rt.Kind())) + panic(Fmt("Unknown field type %v", rt.Kind())) + } +} + +//----------------------------------------------------------------------------- + +func readTypeByteJSON(o interface{}) (typeByte byte, rest interface{}, err error) { + oSlice, ok := o.([]interface{}) + if !ok { + err = errors.New(Fmt("Expected type [TypeByte,?] but got type %v", reflect.TypeOf(o))) + return + } + if len(oSlice) != 2 { + err = errors.New(Fmt("Expected [TypeByte,?] len 2 but got len %v", len(oSlice))) + return + } + typeByte_, ok := oSlice[0].(float64) + typeByte = byte(typeByte_) + rest = oSlice[1] + return +} + +func readReflectJSON(rv reflect.Value, rt reflect.Type, o interface{}, err *error) { + + log.Debug("Read reflect json", "type", rt) + + // Get typeInfo + typeInfo := GetTypeInfo(rt) + + // Create a new struct if rv is nil pointer. + if rt.Kind() == reflect.Ptr && rv.IsNil() { + newRv := reflect.New(rt.Elem()) + rv.Set(newRv) + rv = newRv + } + + // Dereference pointer + // Still addressable, thus settable! + if rv.Kind() == reflect.Ptr { + rv, rt = rv.Elem(), rt.Elem() + } + + // Read TypeByte prefix + if typeInfo.HasTypeByte { + typeByte, rest, err_ := readTypeByteJSON(o) + if err_ != nil { + *err = err_ + return + } + if typeByte != typeInfo.TypeByte { + *err = errors.New(Fmt("Expected TypeByte of %X but got %X", typeInfo.TypeByte, byte(typeByte))) + return + } + o = rest + } + + switch rt.Kind() { + case reflect.Interface: + typeByte, _, err_ := readTypeByteJSON(o) + if err_ != nil { + *err = err_ + return + } + concreteType, ok := typeInfo.ConcreteTypes[typeByte] + if !ok { + panic(Fmt("TypeByte %X not registered for interface %v", typeByte, rt)) + } + newRv := reflect.New(concreteType) + readReflectJSON(newRv.Elem(), concreteType, o, err) + rv.Set(newRv.Elem()) + + case reflect.Slice: + elemRt := rt.Elem() + if elemRt.Kind() == reflect.Uint8 { + // Special case: Byteslices + oString, ok := o.(string) + if !ok { + *err = errors.New(Fmt("Expected string but got type %v", reflect.TypeOf(o))) + return + } + byteslice, err_ := hex.DecodeString(oString) + if err_ != nil { + *err = err_ + return + } + log.Debug("Read byteslice", "bytes", byteslice) + rv.Set(reflect.ValueOf(byteslice)) + } else { + // Read length + oSlice, ok := o.([]interface{}) + if !ok { + *err = errors.New(Fmt("Expected array but got type %v", reflect.TypeOf(o))) + return + } + length := len(oSlice) + log.Debug(Fmt("Read length: %v", length)) + sliceRv := reflect.MakeSlice(rt, length, length) + // Read elems + for i := 0; i < length; i++ { + elemRv := sliceRv.Index(i) + readReflectJSON(elemRv, elemRt, oSlice[i], err) + } + rv.Set(sliceRv) + } + + case reflect.Struct: + oMap, ok := o.(map[string]interface{}) + if !ok { + *err = errors.New(Fmt("Expected map but got type %v", reflect.TypeOf(o))) + return + } + // TODO: ensure that all fields are set? + for name, value := range oMap { + field, ok := rt.FieldByName(name) + if !ok { + *err = errors.New(Fmt("Attempt to set unknown field %v", field.Name)) + return + } + // JAE: I don't think golang reflect lets us set unexported fields, but just in case: + if field.PkgPath != "" { + *err = errors.New(Fmt("Attempt to set unexported field %v", field.Name)) + return + } + fieldRv := rv.FieldByName(name) + readReflectJSON(fieldRv, field.Type, value, err) + } + + case reflect.String: + str, ok := o.(string) + if !ok { + *err = errors.New(Fmt("Expected string but got type %v", reflect.TypeOf(o))) + return + } + log.Debug(Fmt("Read string: %v", str)) + rv.SetString(str) + + case reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8, reflect.Int: + num, ok := o.(float64) + if !ok { + *err = errors.New(Fmt("Expected numeric but got type %v", reflect.TypeOf(o))) + return + } + log.Debug(Fmt("Read num: %v", num)) + rv.SetInt(int64(num)) + + case reflect.Uint64, reflect.Uint32, reflect.Uint16, reflect.Uint8, reflect.Uint: + num, ok := o.(float64) + if !ok { + *err = errors.New(Fmt("Expected numeric but got type %v", reflect.TypeOf(o))) + return + } + if num < 0 { + *err = errors.New(Fmt("Expected unsigned numeric but got %v", num)) + return + } + log.Debug(Fmt("Read num: %v", num)) + rv.SetUint(uint64(num)) + + default: + panic(Fmt("Unknown field type %v", rt.Kind())) + } +} + +func writeReflectJSON(rv reflect.Value, rt reflect.Type, w io.Writer, n *int64, err *error) { + + // Get typeInfo + typeInfo := GetTypeInfo(rt) + + // Custom encoder, say for an interface type rt. + if typeInfo.Encoder != nil { + typeInfo.Encoder(rv.Interface(), w, n, err) + return + } + + // Dereference interface + if rt.Kind() == reflect.Interface { + rv = rv.Elem() + rt = rv.Type() + // If interface type, get typeInfo of underlying type. + typeInfo = GetTypeInfo(rt) + } + + // Dereference pointer + if rt.Kind() == reflect.Ptr { + rt = rt.Elem() + rv = rv.Elem() + } + + // Write TypeByte prefix + if typeInfo.HasTypeByte { + WriteTo([]byte(Fmt("[%v,", typeInfo.TypeByte)), w, n, err) + } + + switch rt.Kind() { + case reflect.Slice: + elemRt := rt.Elem() + if elemRt.Kind() == reflect.Uint8 { + // Special case: Byteslices + byteslice := rv.Bytes() + WriteTo([]byte(Fmt("\"%X\"", byteslice)), w, n, err) + //WriteByteSlice(byteslice, w, n, err) + } else { + WriteTo([]byte("["), w, n, err) + // Write elems + length := rv.Len() + for i := 0; i < length; i++ { + elemRv := rv.Index(i) + writeReflectJSON(elemRv, elemRt, w, n, err) + if i < length-1 { + WriteTo([]byte(","), w, n, err) + } + } + WriteTo([]byte("]"), w, n, err) + } + + case reflect.Struct: + WriteTo([]byte("{"), w, n, err) + numFields := rt.NumField() + for i := 0; i < numFields; i++ { + field := rt.Field(i) + if field.PkgPath != "" { + continue + } + fieldRv := rv.Field(i) + WriteTo([]byte(Fmt("\"%v\":", field.Name)), w, n, err) + writeReflectJSON(fieldRv, field.Type, w, n, err) + if i < numFields-1 { + WriteTo([]byte(","), w, n, err) + } + } + WriteTo([]byte("}"), w, n, err) + + case reflect.String: + fallthrough + case reflect.Uint64, reflect.Uint32, reflect.Uint16, reflect.Uint8, reflect.Uint: + fallthrough + case reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8, reflect.Int: + jsonBytes, err_ := json.Marshal(rv.Interface()) + if err_ != nil { + *err = err_ + return + } + WriteTo(jsonBytes, w, n, err) + + default: + panic(Fmt("Unknown field type %v", rt.Kind())) + } + + // Write TypeByte close bracket + if typeInfo.HasTypeByte { + WriteTo([]byte("]"), w, n, err) } } diff --git a/binary/reflect_test.go b/binary/reflect_test.go index 5a2c8660..58db7e2d 100644 --- a/binary/reflect_test.go +++ b/binary/reflect_test.go @@ -58,51 +58,40 @@ var _ = RegisterInterface( //------------------------------------- -func TestBasic(t *testing.T) { +type Constructor func() interface{} +type Instantiator func() (o interface{}, ptr interface{}) +type Validator func(o interface{}, t *testing.T) + +type TestCase struct { + Constructor + Instantiator + Validator +} + +//------------------------------------- + +func constructBasic() interface{} { cat := Cat{ SimpleStruct{ String: "String", Bytes: []byte("Bytes"), }, } + return cat +} - buf, n, err := new(bytes.Buffer), new(int64), new(error) - WriteBinary(cat, buf, n, err) - if *err != nil { - t.Fatalf("Failed to write cat: %v", *err) - } - t.Logf("Wrote bytes: %X", buf.Bytes()) - bufBytes := buf.Bytes() +func instantiateBasic() (interface{}, interface{}) { + return Cat{}, &Cat{} +} - // Read onto a struct - cat2_ := ReadBinary(Cat{}, buf, n, err) - if *err != nil { - t.Fatalf("Failed to read cat: %v", *err) +func validateBasic(o interface{}, t *testing.T) { + cat := o.(Cat) + if cat.String != "String" { + t.Errorf("Expected cat2.String == 'String', got %v", cat.String) } - cat2 := cat2_.(Cat) - - if cat2.String != "String" { - t.Errorf("Expected cat2.String == 'String', got %v", cat2.String) + if string(cat.Bytes) != "Bytes" { + t.Errorf("Expected cat2.Bytes == 'Bytes', got %X", cat.Bytes) } - if string(cat2.Bytes) != "Bytes" { - t.Errorf("Expected cat2.Bytes == 'Bytes', got %X", cat2.Bytes) - } - - // Read onto a ptr - r := bytes.NewReader(bufBytes) - cat3_ := ReadBinary(&Cat{}, r, n, err) - if *err != nil { - t.Fatalf("Failed to read cat: %v", *err) - } - cat3 := cat3_.(*Cat) - - if cat3.String != "String" { - t.Errorf("Expected cat3.String == 'String', got %v", cat3.String) - } - if string(cat3.Bytes) != "Bytes" { - t.Errorf("Expected cat3.Bytes == 'Bytes', got %X", cat3.Bytes) - } - } //------------------------------------- @@ -112,38 +101,22 @@ type ComplexStruct struct { Animal Animal } -func TestComplexStruct(t *testing.T) { +func constructComplex() interface{} { c := ComplexStruct{ - Name: "Complex", - Animal: Cat{ - SimpleStruct{ - String: "String", - Bytes: []byte("Bytes"), - }, - }, + Name: "Complex", + Animal: constructBasic(), } + return c +} - buf, n, err := new(bytes.Buffer), new(int64), new(error) - WriteBinary(c, buf, n, err) - if *err != nil { - t.Fatalf("Failed to write c: %v", *err) - } - - t.Logf("Wrote bytes: %X", buf.Bytes()) - - c2_ := ReadBinary(&ComplexStruct{}, buf, n, err) - if *err != nil { - t.Fatalf("Failed to read c: %v", *err) - } - c2 := c2_.(*ComplexStruct) +func instantiateComplex() (interface{}, interface{}) { + return ComplexStruct{}, &ComplexStruct{} +} +func validateComplex(o interface{}, t *testing.T) { + c2 := o.(ComplexStruct) if cat, ok := c2.Animal.(Cat); ok { - if cat.String != "String" { - t.Errorf("Expected cat.String == 'String', got %v", cat.String) - } - if string(cat.Bytes) != "Bytes" { - t.Errorf("Expected cat.Bytes == 'Bytes', got %X", cat.Bytes) - } + validateBasic(cat, t) } else { t.Errorf("Expected c2.Animal to be of type cat, got %v", reflect.ValueOf(c2.Animal).Elem().Type()) } @@ -151,12 +124,91 @@ func TestComplexStruct(t *testing.T) { //------------------------------------- -type ComplexArrayStruct struct { +type ComplexStruct2 struct { + Cat Cat + Dog *Dog + Snake Snake + Snake2 *Snake + Viper Viper + Viper2 *Viper +} + +func constructComplex2() interface{} { + snake_ := Snake([]byte("hiss")) + snakePtr_ := &snake_ + + c := ComplexStruct2{ + Cat: Cat{ + SimpleStruct{ + String: "String", + Bytes: []byte("Bytes"), + }, + }, + Dog: &Dog{ + SimpleStruct{ + String: "Woof", + Bytes: []byte("Bark"), + }, + }, + Snake: Snake([]byte("hiss")), + Snake2: snakePtr_, + Viper: Viper{Bytes: []byte("hizz")}, + Viper2: &Viper{Bytes: []byte("hizz")}, + } + return c +} + +func instantiateComplex2() (interface{}, interface{}) { + return ComplexStruct2{}, &ComplexStruct2{} +} + +func validateComplex2(o interface{}, t *testing.T) { + c2 := o.(ComplexStruct2) + cat := c2.Cat + if cat.String != "String" { + t.Errorf("Expected cat.String == 'String', got %v", cat.String) + } + if string(cat.Bytes) != "Bytes" { + t.Errorf("Expected cat.Bytes == 'Bytes', got %X", cat.Bytes) + } + + dog := c2.Dog + if dog.String != "Woof" { + t.Errorf("Expected dog.String == 'Woof', got %v", dog.String) + } + if string(dog.Bytes) != "Bark" { + t.Errorf("Expected dog.Bytes == 'Bark', got %X", dog.Bytes) + } + + snake := c2.Snake + if string(snake) != "hiss" { + t.Errorf("Expected string(snake) == 'hiss', got %v", string(snake)) + } + + snake2 := c2.Snake2 + if string(*snake2) != "hiss" { + t.Errorf("Expected string(snake2) == 'hiss', got %v", string(*snake2)) + } + + viper := c2.Viper + if string(viper.Bytes) != "hizz" { + t.Errorf("Expected string(viper.Bytes) == 'hizz', got %v", string(viper.Bytes)) + } + + viper2 := c2.Viper2 + if string(viper2.Bytes) != "hizz" { + t.Errorf("Expected string(viper2.Bytes) == 'hizz', got %v", string(viper2.Bytes)) + } +} + +//------------------------------------- + +type ComplexStructArray struct { Animals []Animal } -func TestComplexArrayStruct(t *testing.T) { - c := ComplexArrayStruct{ +func constructComplexArray() interface{} { + c := ComplexStructArray{ Animals: []Animal{ Cat{ SimpleStruct{ @@ -176,21 +228,15 @@ func TestComplexArrayStruct(t *testing.T) { }, }, } + return c +} - buf, n, err := new(bytes.Buffer), new(int64), new(error) - WriteBinary(c, buf, n, err) - if *err != nil { - t.Fatalf("Failed to write c: %v", *err) - } - - t.Logf("Wrote bytes: %X", buf.Bytes()) - - c2_ := ReadBinary(&ComplexArrayStruct{}, buf, n, err) - if *err != nil { - t.Fatalf("Failed to read c: %v", *err) - } - c2 := c2_.(*ComplexArrayStruct) +func instantiateComplexArray() (interface{}, interface{}) { + return ComplexStructArray{}, &ComplexStructArray{} +} +func validateComplexArray(o interface{}, t *testing.T) { + c2 := o.(ComplexStructArray) if cat, ok := c2.Animals[0].(Cat); ok { if cat.String != "String" { t.Errorf("Expected cat.String == 'String', got %v", cat.String) @@ -230,88 +276,92 @@ func TestComplexArrayStruct(t *testing.T) { } } -//------------------------------------- +//----------------------------------------------------------------------------- -type ComplexStruct2 struct { - Cat Cat - Dog *Dog - Snake Snake - Snake2 *Snake - Viper Viper - Viper2 *Viper +var testCases = []TestCase{} + +func init() { + testCases = append(testCases, TestCase{constructBasic, instantiateBasic, validateBasic}) + testCases = append(testCases, TestCase{constructComplex, instantiateComplex, validateComplex}) + testCases = append(testCases, TestCase{constructComplex2, instantiateComplex2, validateComplex2}) + testCases = append(testCases, TestCase{constructComplexArray, instantiateComplexArray, validateComplexArray}) } -func TestComplexStruct2(t *testing.T) { +func TestBinary(t *testing.T) { - snake_ := Snake([]byte("hiss")) - snakePtr_ := &snake_ + for _, testCase := range testCases { - c := ComplexStruct2{ - Cat: Cat{ - SimpleStruct{ - String: "String", - Bytes: []byte("Bytes"), - }, - }, - Dog: &Dog{ - SimpleStruct{ - String: "Woof", - Bytes: []byte("Bark"), - }, - }, - Snake: Snake([]byte("hiss")), - Snake2: snakePtr_, - Viper: Viper{Bytes: []byte("hizz")}, - Viper2: &Viper{Bytes: []byte("hizz")}, + // Construct an object + o := testCase.Constructor() + + // Write the object + data := BinaryBytes(o) + t.Logf("Binary: %X", data) + + instance, instancePtr := testCase.Instantiator() + + // Read onto a struct + n, err := new(int64), new(error) + res := ReadBinary(instance, bytes.NewReader(data), n, err) + if *err != nil { + t.Fatalf("Failed to read cat: %v", *err) + } + + // Validate object + testCase.Validator(res, t) + + // Read onto a pointer + n, err = new(int64), new(error) + res = ReadBinary(instancePtr, bytes.NewReader(data), n, err) + if *err != nil { + t.Fatalf("Failed to read cat: %v", *err) + } + + if res != instancePtr { + t.Errorf("Expected pointer to pass through") + } + + // Validate object + testCase.Validator(reflect.ValueOf(res).Elem().Interface(), t) + } + +} + +func TestJSON(t *testing.T) { + + for _, testCase := range testCases { + + // Construct an object + o := testCase.Constructor() + + // Write the object + data := JSONBytes(o) + t.Logf("JSON: %v", string(data)) + + instance, instancePtr := testCase.Instantiator() + + // Read onto a struct + err := new(error) + res := ReadJSON(instance, data, err) + if *err != nil { + t.Fatalf("Failed to read cat: %v", *err) + } + + // Validate object + testCase.Validator(res, t) + + // Read onto a pointer + res = ReadJSON(instancePtr, data, err) + if *err != nil { + t.Fatalf("Failed to read cat: %v", *err) + } + + if res != instancePtr { + t.Errorf("Expected pointer to pass through") + } + + // Validate object + testCase.Validator(reflect.ValueOf(res).Elem().Interface(), t) } - buf, n, err := new(bytes.Buffer), new(int64), new(error) - WriteBinary(c, buf, n, err) - if *err != nil { - t.Fatalf("Failed to write c: %v", *err) - } - - t.Logf("Wrote bytes: %X", buf.Bytes()) - - c2_ := ReadBinary(&ComplexStruct2{}, buf, n, err) - if *err != nil { - t.Fatalf("Failed to read c: %v", *err) - } - c2 := c2_.(*ComplexStruct2) - - cat := c2.Cat - if cat.String != "String" { - t.Errorf("Expected cat.String == 'String', got %v", cat.String) - } - if string(cat.Bytes) != "Bytes" { - t.Errorf("Expected cat.Bytes == 'Bytes', got %X", cat.Bytes) - } - - dog := c2.Dog - if dog.String != "Woof" { - t.Errorf("Expected dog.String == 'Woof', got %v", dog.String) - } - if string(dog.Bytes) != "Bark" { - t.Errorf("Expected dog.Bytes == 'Bark', got %X", dog.Bytes) - } - - snake := c2.Snake - if string(snake) != "hiss" { - t.Errorf("Expected string(snake) == 'hiss', got %v", string(snake)) - } - - snake2 := c2.Snake2 - if string(*snake2) != "hiss" { - t.Errorf("Expected string(snake2) == 'hiss', got %v", string(*snake2)) - } - - viper := c2.Viper - if string(viper.Bytes) != "hizz" { - t.Errorf("Expected string(viper.Bytes) == 'hizz', got %v", string(viper.Bytes)) - } - - viper2 := c2.Viper2 - if string(viper2.Bytes) != "hizz" { - t.Errorf("Expected string(viper2.Bytes) == 'hizz', got %v", string(viper2.Bytes)) - } } diff --git a/binary/util.go b/binary/util.go index e1b0c7d8..d27e28bd 100644 --- a/binary/util.go +++ b/binary/util.go @@ -15,6 +15,15 @@ func BinaryBytes(o interface{}) []byte { return w.Bytes() } +func JSONBytes(o interface{}) []byte { + w, n, err := new(bytes.Buffer), new(int64), new(error) + WriteJSON(o, w, n, err) + if *err != nil { + panic(err) + } + return w.Bytes() +} + // NOTE: does not care about the type, only the binary representation. func BinaryEqual(a, b interface{}) bool { aBytes := BinaryBytes(a) diff --git a/rpc/mempool.go b/rpc/mempool.go index 40de6e59..a559e6e1 100644 --- a/rpc/mempool.go +++ b/rpc/mempool.go @@ -2,7 +2,6 @@ package rpc import ( "bytes" - "encoding/json" "fmt" "net/http" @@ -31,10 +30,7 @@ func MempoolHandler(w http.ResponseWriter, r *http.Request) { ReturnJSON(API_ERROR, Fmt("Error broadcasting transaction: %v", err)) } - jsonBytes, err := json.MarshalIndent(tx, "", " ") - if err != nil { - panic(err) - } + jsonBytes := JSONBytes(tx) fmt.Println(">>", string(jsonBytes)) ReturnJSON(API_OK, Fmt("Broadcasted tx: %X", tx))