Initial work on marshalling/unmarshalling SOAP types.
So far added: * fixed.14.4 * char * date
This commit is contained in:
parent
ef1de8df74
commit
17abe5294a
60
soap/types.go
Normal file
60
soap/types.go
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
package soap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
"unicode/utf8"
|
||||||
|
)
|
||||||
|
|
||||||
|
func MarshalFixed14_4(v float64) (string, error) {
|
||||||
|
if v >= 1e14 || v <= -1e14 {
|
||||||
|
return "", fmt.Errorf("soap fixed14.4: value %v out of bounds", v)
|
||||||
|
}
|
||||||
|
return strconv.FormatFloat(v, 'f', 4, 64), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnmarshalFixed14_4(s string) (float64, error) {
|
||||||
|
v, err := strconv.ParseFloat(s, 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
if v >= 1e14 || v <= -1e14 {
|
||||||
|
return 0, fmt.Errorf("soap fixed14.4: value %q out of bounds", s)
|
||||||
|
}
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func MarshalChar(v rune) (string, error) {
|
||||||
|
if v == 0 {
|
||||||
|
return "", errors.New("soap char: rune 0 is not allowed")
|
||||||
|
}
|
||||||
|
return string(v), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnmarshalChar(s string) (rune, error) {
|
||||||
|
if len(s) == 0 {
|
||||||
|
return 0, errors.New("soap char: got empty string")
|
||||||
|
}
|
||||||
|
r, n := utf8.DecodeRune([]byte(s))
|
||||||
|
if n != len(s) {
|
||||||
|
return 0, fmt.Errorf("soap char: value %q is not a single rune", s)
|
||||||
|
}
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func MarshalDate(v time.Time) (string, error) {
|
||||||
|
return v.Format("2006-01-02"), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var dateFmts = []string{"2006-01-02", "20060102"}
|
||||||
|
|
||||||
|
func UnmarshalDate(s string) (time.Time, error) {
|
||||||
|
for _, f := range dateFmts {
|
||||||
|
if t, err := time.Parse(f, s); err == nil {
|
||||||
|
return t, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return time.Time{}, fmt.Errorf("soap date: value %q is not in a recognized date format", s)
|
||||||
|
}
|
107
soap/types_test.go
Normal file
107
soap/types_test.go
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
package soap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type convTest interface {
|
||||||
|
Marshal() (string, error)
|
||||||
|
Unmarshal(string) (interface{}, error)
|
||||||
|
Equal(result interface{}) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type testCase struct {
|
||||||
|
value convTest
|
||||||
|
str string
|
||||||
|
wantMarshalErr bool
|
||||||
|
wantUnmarshalErr bool
|
||||||
|
noMarshal bool
|
||||||
|
noUnMarshal bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type Fixed14_4Test float64
|
||||||
|
|
||||||
|
func (v Fixed14_4Test) Marshal() (string, error) {
|
||||||
|
return MarshalFixed14_4(float64(v))
|
||||||
|
}
|
||||||
|
func (v Fixed14_4Test) Unmarshal(s string) (interface{}, error) {
|
||||||
|
return UnmarshalFixed14_4(s)
|
||||||
|
}
|
||||||
|
func (v Fixed14_4Test) Equal(result interface{}) bool {
|
||||||
|
return math.Abs(float64(v)-result.(float64)) < 0.001
|
||||||
|
}
|
||||||
|
|
||||||
|
type CharTest rune
|
||||||
|
|
||||||
|
func (v CharTest) Marshal() (string, error) {
|
||||||
|
return MarshalChar(rune(v))
|
||||||
|
}
|
||||||
|
func (v CharTest) Unmarshal(s string) (interface{}, error) {
|
||||||
|
return UnmarshalChar(s)
|
||||||
|
}
|
||||||
|
func (v CharTest) Equal(result interface{}) bool {
|
||||||
|
return rune(v) == result.(rune)
|
||||||
|
}
|
||||||
|
|
||||||
|
type DateTest struct{ time.Time }
|
||||||
|
|
||||||
|
func (v DateTest) Marshal() (string, error) {
|
||||||
|
return MarshalDate(time.Time(v.Time))
|
||||||
|
}
|
||||||
|
func (v DateTest) Unmarshal(s string) (interface{}, error) {
|
||||||
|
return UnmarshalDate(s)
|
||||||
|
}
|
||||||
|
func (v DateTest) Equal(result interface{}) bool {
|
||||||
|
return v.Time.Equal(result.(time.Time))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test(t *testing.T) {
|
||||||
|
tests := []testCase{
|
||||||
|
// Fixed14_4
|
||||||
|
{str: "0.0000", value: Fixed14_4Test(0)},
|
||||||
|
{str: "1.0000", value: Fixed14_4Test(1)},
|
||||||
|
{str: "1.2346", value: Fixed14_4Test(1.23456)},
|
||||||
|
{str: "-1.0000", value: Fixed14_4Test(-1)},
|
||||||
|
{str: "-1.2346", value: Fixed14_4Test(-1.23456)},
|
||||||
|
{str: "10000000000000.0000", value: Fixed14_4Test(1e13)},
|
||||||
|
{str: "100000000000000.0000", value: Fixed14_4Test(1e14), wantMarshalErr: true, wantUnmarshalErr: true},
|
||||||
|
{str: "-10000000000000.0000", value: Fixed14_4Test(-1e13)},
|
||||||
|
{str: "-100000000000000.0000", value: Fixed14_4Test(-1e14), wantMarshalErr: true, wantUnmarshalErr: true},
|
||||||
|
|
||||||
|
// Char
|
||||||
|
{str: "a", value: CharTest('a')},
|
||||||
|
{str: "z", value: CharTest('z')},
|
||||||
|
{str: "\u1234", value: CharTest(0x1234)},
|
||||||
|
{str: "aa", value: CharTest(0), wantMarshalErr: true, wantUnmarshalErr: true},
|
||||||
|
{str: "", value: CharTest(0), wantMarshalErr: true, wantUnmarshalErr: true},
|
||||||
|
|
||||||
|
// Date
|
||||||
|
{str: "2013-10-08", value: DateTest{time.Date(2013, 10, 8, 0, 0, 0, 0, time.UTC)}},
|
||||||
|
{str: "20131008", value: DateTest{time.Date(2013, 10, 8, 0, 0, 0, 0, time.UTC)}, noMarshal: true},
|
||||||
|
{str: "2013-10-08T10:30:50", value: DateTest{}, wantUnmarshalErr: true, noMarshal: true},
|
||||||
|
{str: "", value: DateTest{}, wantMarshalErr: true, wantUnmarshalErr: true, noMarshal: true},
|
||||||
|
{str: "-1", value: DateTest{}, wantUnmarshalErr: true, noMarshal: true},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
if test.noMarshal {
|
||||||
|
} else if resultStr, err := test.value.Marshal(); err != nil && !test.wantMarshalErr {
|
||||||
|
t.Errorf("For %s, want %q, got error: %v", test.value, test.str, err)
|
||||||
|
} else if err == nil && test.wantMarshalErr {
|
||||||
|
t.Errorf("For %s, want error, got %q", test.value, resultStr)
|
||||||
|
} else if err == nil && resultStr != test.str {
|
||||||
|
t.Errorf("For %s, want %q, got %q", test.value, test.str, resultStr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if test.noUnMarshal {
|
||||||
|
} else if resultValue, err := test.value.Unmarshal(test.str); err != nil && !test.wantUnmarshalErr {
|
||||||
|
t.Errorf("For %q, want %v, got error: %v", test.str, test.value, err)
|
||||||
|
} else if err == nil && test.wantUnmarshalErr {
|
||||||
|
t.Errorf("For %q, want error, got %v", test.str, resultValue)
|
||||||
|
} else if err == nil && !test.value.Equal(resultValue) {
|
||||||
|
t.Errorf("For %q, want %v, got %v", test.str, test.value, resultValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user