Implement error-free marshalText methods.
This commit is contained in:
parent
d5f9ab1f20
commit
e5fcf16e62
@ -29,24 +29,13 @@ type UI1 uint8
|
|||||||
|
|
||||||
var _ SOAPValue = new(UI1)
|
var _ SOAPValue = new(UI1)
|
||||||
|
|
||||||
// toStringNoError converts `v` to a string, returning empty string on error.
|
|
||||||
// This should only be used for String() implementations if no error can be
|
|
||||||
// returned by v.MarshalText().
|
|
||||||
func toStringNoError(v encoding.TextMarshaler) string {
|
|
||||||
b, err := v.MarshalText()
|
|
||||||
if err != nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return string(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewUI1(v uint8) *UI1 {
|
func NewUI1(v uint8) *UI1 {
|
||||||
v2 := UI1(v)
|
v2 := UI1(v)
|
||||||
return &v2
|
return &v2
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *UI1) String() string {
|
func (v *UI1) String() string {
|
||||||
return toStringNoError(v)
|
return strconv.FormatUint(uint64(*v), 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *UI1) MarshalText() ([]byte, error) {
|
func (v *UI1) MarshalText() ([]byte, error) {
|
||||||
@ -69,7 +58,7 @@ func NewUI2(v uint16) *UI2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (v *UI2) String() string {
|
func (v *UI2) String() string {
|
||||||
return toStringNoError(v)
|
return strconv.FormatUint(uint64(*v), 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *UI2) MarshalText() ([]byte, error) {
|
func (v *UI2) MarshalText() ([]byte, error) {
|
||||||
@ -92,7 +81,7 @@ func NewUI4(v uint32) *UI4 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (v *UI4) String() string {
|
func (v *UI4) String() string {
|
||||||
return toStringNoError(v)
|
return strconv.FormatUint(uint64(*v), 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *UI4) MarshalText() ([]byte, error) {
|
func (v *UI4) MarshalText() ([]byte, error) {
|
||||||
@ -115,7 +104,7 @@ func NewUI8(v uint64) *UI8 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (v *UI8) String() string {
|
func (v *UI8) String() string {
|
||||||
return toStringNoError(v)
|
return strconv.FormatUint(uint64(*v), 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *UI8) MarshalText() ([]byte, error) {
|
func (v *UI8) MarshalText() ([]byte, error) {
|
||||||
@ -138,7 +127,7 @@ func NewI1(v int8) *I1 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (v *I1) String() string {
|
func (v *I1) String() string {
|
||||||
return toStringNoError(v)
|
return strconv.FormatInt(int64(*v), 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *I1) MarshalText() ([]byte, error) {
|
func (v *I1) MarshalText() ([]byte, error) {
|
||||||
@ -161,7 +150,7 @@ func NewI2(v int16) *I2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (v *I2) String() string {
|
func (v *I2) String() string {
|
||||||
return toStringNoError(v)
|
return strconv.FormatInt(int64(*v), 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *I2) MarshalText() ([]byte, error) {
|
func (v *I2) MarshalText() ([]byte, error) {
|
||||||
@ -184,7 +173,7 @@ func NewI4(v int32) *I4 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (v *I4) String() string {
|
func (v *I4) String() string {
|
||||||
return toStringNoError(v)
|
return strconv.FormatInt(int64(*v), 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *I4) MarshalText() ([]byte, error) {
|
func (v *I4) MarshalText() ([]byte, error) {
|
||||||
@ -207,7 +196,7 @@ func NewI8(v int64) *I8 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (v *I8) String() string {
|
func (v *I8) String() string {
|
||||||
return toStringNoError(v)
|
return strconv.FormatInt(int64(*v), 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *I8) MarshalText() ([]byte, error) {
|
func (v *I8) MarshalText() ([]byte, error) {
|
||||||
@ -230,11 +219,15 @@ func NewR4(v float32) *R4 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (v *R4) String() string {
|
func (v *R4) String() string {
|
||||||
return toStringNoError(v)
|
return string(v.marshalText(nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *R4) marshalText(b []byte) []byte {
|
||||||
|
return strconv.AppendFloat(b, float64(*v), 'g', -1, 32)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *R4) MarshalText() ([]byte, error) {
|
func (v *R4) MarshalText() ([]byte, error) {
|
||||||
return strconv.AppendFloat(nil, float64(*v), 'g', -1, 32), nil
|
return v.marshalText(nil), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *R4) UnmarshalText(b []byte) error {
|
func (v *R4) UnmarshalText(b []byte) error {
|
||||||
@ -253,11 +246,15 @@ func NewR8(v float64) *R8 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (v *R8) String() string {
|
func (v *R8) String() string {
|
||||||
return toStringNoError(v)
|
return string(v.marshalText(nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *R8) marshalText(b []byte) []byte {
|
||||||
|
return strconv.AppendFloat(nil, float64(*v), 'g', -1, 64)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *R8) MarshalText() ([]byte, error) {
|
func (v *R8) MarshalText() ([]byte, error) {
|
||||||
return strconv.AppendFloat(nil, float64(*v), 'g', -1, 64), nil
|
return v.marshalText(nil), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *R8) UnmarshalText(b []byte) error {
|
func (v *R8) UnmarshalText(b []byte) error {
|
||||||
@ -360,15 +357,22 @@ func (v Fixed14_4) Float64() float64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (v *Fixed14_4) String() string {
|
func (v *Fixed14_4) String() string {
|
||||||
return toStringNoError(v)
|
return string(v.marshalText(nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *Fixed14_4) MarshalText() ([]byte, error) {
|
func (v *Fixed14_4) marshalText(b []byte) []byte {
|
||||||
intPart, fracPart := v.Parts()
|
intPart, fracPart := v.Parts()
|
||||||
if fracPart < 0 {
|
if fracPart < 0 {
|
||||||
fracPart = -fracPart
|
fracPart = -fracPart
|
||||||
}
|
}
|
||||||
return []byte(fmt.Sprintf("%d.%04d", intPart, fracPart)), nil
|
b = strconv.AppendInt(b, intPart, 10)
|
||||||
|
b = append(b, '.')
|
||||||
|
b = appendInt(b, int64(fracPart), 4)
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Fixed14_4) MarshalText() ([]byte, error) {
|
||||||
|
return v.marshalText(nil), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var decimalByte = []byte{'.'}
|
var decimalByte = []byte{'.'}
|
||||||
@ -482,6 +486,32 @@ func parseInt(b []byte, err *error) int {
|
|||||||
return int(v)
|
return int(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var zeroDigits []byte = []byte("000")
|
||||||
|
|
||||||
|
// appendInt appends `n` in decimal to `b`, with up to 3 digits of
|
||||||
|
// zero-padding to fill to a minimum of 4 digits.
|
||||||
|
func appendInt(b []byte, n int64, padding int) []byte {
|
||||||
|
if n > -1000 && n < 1000 {
|
||||||
|
if n < 0 {
|
||||||
|
n = -n
|
||||||
|
b = append(b, '-')
|
||||||
|
}
|
||||||
|
var digits int
|
||||||
|
if n < 10 {
|
||||||
|
digits = 1
|
||||||
|
} else if n < 100 {
|
||||||
|
digits = 2
|
||||||
|
} else if n < 1000 {
|
||||||
|
digits = 3
|
||||||
|
}
|
||||||
|
numZeros := padding - digits
|
||||||
|
if numZeros > 0 {
|
||||||
|
b = append(b, zeroDigits[:numZeros]...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return strconv.AppendInt(b, n, 10)
|
||||||
|
}
|
||||||
|
|
||||||
var dateRegexps = []*regexp.Regexp{
|
var dateRegexps = []*regexp.Regexp{
|
||||||
// yyyy[-mm[-dd]]
|
// yyyy[-mm[-dd]]
|
||||||
regexp.MustCompile(`^(\d{4})(?:-(\d{2})(?:-(\d{2}))?)?$`),
|
regexp.MustCompile(`^(\d{4})(?:-(\d{2})(?:-(\d{2}))?)?$`),
|
||||||
@ -551,7 +581,7 @@ func (tod TimeOfDay) ToDuration() time.Duration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (tod *TimeOfDay) String() string {
|
func (tod *TimeOfDay) String() string {
|
||||||
return toStringNoError(tod)
|
return string(tod.marshalText(nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsValid returns true iff v is positive and <= 24 hours.
|
// IsValid returns true iff v is positive and <= 24 hours.
|
||||||
@ -573,11 +603,20 @@ func (tod *TimeOfDay) clear() {
|
|||||||
tod.Second = 0
|
tod.Second = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (tod *TimeOfDay) marshalText(b []byte) []byte {
|
||||||
|
b = appendInt(b, int64(tod.Hour), 2)
|
||||||
|
b = append(b, ':')
|
||||||
|
b = appendInt(b, int64(tod.Minute), 2)
|
||||||
|
b = append(b, ':')
|
||||||
|
b = appendInt(b, int64(tod.Second), 2)
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
func (tod *TimeOfDay) MarshalText() ([]byte, error) {
|
func (tod *TimeOfDay) MarshalText() ([]byte, error) {
|
||||||
if err := tod.CheckValid(); err != nil {
|
if err := tod.CheckValid(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return []byte(fmt.Sprintf("%02d:%02d:%02d", tod.Hour, tod.Minute, tod.Second)), nil
|
return tod.marshalText(nil), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var timeRegexps = []*regexp.Regexp{
|
var timeRegexps = []*regexp.Regexp{
|
||||||
@ -623,7 +662,7 @@ type TimeOfDayTZ struct {
|
|||||||
var _ SOAPValue = &TimeOfDayTZ{}
|
var _ SOAPValue = &TimeOfDayTZ{}
|
||||||
|
|
||||||
func (todz *TimeOfDayTZ) String() string {
|
func (todz *TimeOfDayTZ) String() string {
|
||||||
return toStringNoError(todz)
|
return string(todz.TZ.marshalText(nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear removes data from v, setting to default values.
|
// clear removes data from v, setting to default values.
|
||||||
@ -633,12 +672,9 @@ func (todz *TimeOfDayTZ) clear() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (todz *TimeOfDayTZ) MarshalText() ([]byte, error) {
|
func (todz *TimeOfDayTZ) MarshalText() ([]byte, error) {
|
||||||
result, err := todz.TimeOfDay.MarshalText()
|
b := todz.TimeOfDay.marshalText(nil)
|
||||||
if err != nil {
|
b = todz.TZ.marshalText(b)
|
||||||
return nil, err
|
return b, nil
|
||||||
}
|
|
||||||
result = append(result, []byte(todz.TZ.String())...)
|
|
||||||
return result, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (todz *TimeOfDayTZ) UnmarshalText(b []byte) error {
|
func (todz *TimeOfDayTZ) UnmarshalText(b []byte) error {
|
||||||
@ -679,7 +715,7 @@ func (d Date) ToTime(loc *time.Location) time.Time {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Date) String() string {
|
func (d *Date) String() string {
|
||||||
return toStringNoError(d)
|
return string(d.marshalText(nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckValid returns an error if the date components are out of range.
|
// CheckValid returns an error if the date components are out of range.
|
||||||
@ -698,8 +734,17 @@ func (d *Date) clear() {
|
|||||||
d.Day = 0
|
d.Day = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *Date) marshalText(b []byte) []byte {
|
||||||
|
b = appendInt(b, int64(d.Year), 2)
|
||||||
|
b = append(b, '-')
|
||||||
|
b = appendInt(b, int64(d.Month), 2)
|
||||||
|
b = append(b, '-')
|
||||||
|
b = appendInt(b, int64(d.Day), 2)
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
func (d *Date) MarshalText() ([]byte, error) {
|
func (d *Date) MarshalText() ([]byte, error) {
|
||||||
return []byte(fmt.Sprintf("%04d-%02d-%02d", d.Year, d.Month, d.Day)), nil
|
return d.marshalText(nil), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Date) UnmarshalText(b []byte) error {
|
func (d *Date) UnmarshalText(b []byte) error {
|
||||||
@ -749,7 +794,7 @@ func DateTimeFromTime(v time.Time) DateTime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (dt *DateTime) String() string {
|
func (dt *DateTime) String() string {
|
||||||
return toStringNoError(dt)
|
return string(dt.marshalText(nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dt DateTime) ToTime(loc *time.Location) time.Time {
|
func (dt DateTime) ToTime(loc *time.Location) time.Time {
|
||||||
@ -764,20 +809,15 @@ func (dt *DateTime) clear() {
|
|||||||
dt.TimeOfDay.clear()
|
dt.TimeOfDay.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (dt *DateTime) marshalText(b []byte) []byte {
|
||||||
|
b = dt.Date.marshalText(b)
|
||||||
|
b = append(b, 'T')
|
||||||
|
b = dt.TimeOfDay.marshalText(b)
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
func (dt *DateTime) MarshalText() ([]byte, error) {
|
func (dt *DateTime) MarshalText() ([]byte, error) {
|
||||||
var result []byte
|
return dt.marshalText(nil), nil
|
||||||
d, err := dt.Date.MarshalText()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
t, err := dt.TimeOfDay.MarshalText()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
result = append(result, d...)
|
|
||||||
result = append(result, 'T')
|
|
||||||
result = append(result, t...)
|
|
||||||
return result, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dt *DateTime) UnmarshalText(b []byte) error {
|
func (dt *DateTime) UnmarshalText(b []byte) error {
|
||||||
@ -816,7 +856,7 @@ func DateTimeTZFromTime(t time.Time) DateTimeTZ {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (dtz *DateTimeTZ) String() string {
|
func (dtz *DateTimeTZ) String() string {
|
||||||
return toStringNoError(dtz)
|
return string(dtz.marshalText(nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Time converts `dtz` to time.Time, using defaultLoc as the default location if
|
// Time converts `dtz` to time.Time, using defaultLoc as the default location if
|
||||||
@ -841,21 +881,16 @@ func (dtz *DateTimeTZ) clear() {
|
|||||||
dtz.TZ.clear()
|
dtz.TZ.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (dtz *DateTimeTZ) marshalText(b []byte) []byte {
|
||||||
|
b = dtz.Date.marshalText(b)
|
||||||
|
b = append(b, 'T')
|
||||||
|
b = dtz.TimeOfDay.marshalText(b)
|
||||||
|
b = dtz.TZ.marshalText(b)
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
func (dtz *DateTimeTZ) MarshalText() ([]byte, error) {
|
func (dtz *DateTimeTZ) MarshalText() ([]byte, error) {
|
||||||
var result []byte
|
return dtz.marshalText(nil), nil
|
||||||
d, err := dtz.Date.MarshalText()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
t, err := dtz.TimeOfDay.MarshalText()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
result = append(result, d...)
|
|
||||||
result = append(result, 'T')
|
|
||||||
result = append(result, t...)
|
|
||||||
result = append(result, []byte(dtz.TZ.String())...)
|
|
||||||
return result, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dtz *DateTimeTZ) UnmarshalText(b []byte) error {
|
func (dtz *DateTimeTZ) UnmarshalText(b []byte) error {
|
||||||
@ -921,23 +956,8 @@ func (tzd TZD) Location(defaultLoc *time.Location) *time.Location {
|
|||||||
return time.FixedZone(tzd.String(), tzd.Offset)
|
return time.FixedZone(tzd.String(), tzd.Offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tzd TZD) String() string {
|
func (tzd *TZD) String() string {
|
||||||
if !tzd.HasTZ {
|
return string(tzd.marshalText(nil))
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
if tzd.Offset == 0 {
|
|
||||||
return "Z"
|
|
||||||
}
|
|
||||||
|
|
||||||
offsetMins := tzd.Offset / 60
|
|
||||||
sign := '+'
|
|
||||||
if offsetMins < 1 {
|
|
||||||
offsetMins = -offsetMins
|
|
||||||
sign = '-'
|
|
||||||
}
|
|
||||||
h, m := offsetMins/60, offsetMins%60
|
|
||||||
return fmt.Sprintf("%c%02d:%02d", sign, h, m)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear removes offset information from `v`.
|
// clear removes offset information from `v`.
|
||||||
@ -946,6 +966,30 @@ func (tzd *TZD) clear() {
|
|||||||
tzd.HasTZ = false
|
tzd.HasTZ = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (tzd *TZD) marshalText(b []byte) []byte {
|
||||||
|
if !tzd.HasTZ {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
if tzd.Offset == 0 {
|
||||||
|
b = append(b, 'Z')
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
offsetMins := tzd.Offset / 60
|
||||||
|
var sign byte = '+'
|
||||||
|
if offsetMins < 1 {
|
||||||
|
offsetMins = -offsetMins
|
||||||
|
sign = '-'
|
||||||
|
}
|
||||||
|
h, m := offsetMins/60, offsetMins%60
|
||||||
|
b = append(b, sign)
|
||||||
|
b = appendInt(b, int64(h), 2)
|
||||||
|
b = append(b, ':')
|
||||||
|
b = appendInt(b, int64(m), 2)
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
// (+|-)(hh):(mm)
|
// (+|-)(hh):(mm)
|
||||||
var timezoneRegexp = regexp.MustCompile(`^([+-])(\d{2}):(\d{2})$`)
|
var timezoneRegexp = regexp.MustCompile(`^([+-])(\d{2}):(\d{2})$`)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user