github.com/gogf/gf/v2@v2.7.4/util/gconv/gconv_z_unit_struct_marshal_unmarshal_test.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/gogf/gf. 6 7 package gconv_test 8 9 import ( 10 "testing" 11 "time" 12 13 "github.com/gogf/gf/v2/crypto/gcrc32" 14 "github.com/gogf/gf/v2/encoding/gbinary" 15 "github.com/gogf/gf/v2/errors/gerror" 16 "github.com/gogf/gf/v2/frame/g" 17 "github.com/gogf/gf/v2/os/gtime" 18 "github.com/gogf/gf/v2/test/gtest" 19 "github.com/gogf/gf/v2/util/gconv" 20 ) 21 22 type MyTime struct { 23 time.Time 24 } 25 26 type MyTimeSt struct { 27 ServiceDate MyTime 28 } 29 30 func (st *MyTimeSt) UnmarshalValue(v interface{}) error { 31 m := gconv.Map(v) 32 t, err := gtime.StrToTime(gconv.String(m["ServiceDate"])) 33 if err != nil { 34 return err 35 } 36 st.ServiceDate = MyTime{t.Time} 37 return nil 38 } 39 40 func TestStructUnmarshalValue1(t *testing.T) { 41 gtest.C(t, func(t *gtest.T) { 42 st := &MyTimeSt{} 43 err := gconv.Struct(g.Map{"ServiceDate": "2020-10-10 12:00:01"}, st) 44 t.AssertNil(err) 45 t.Assert(st.ServiceDate.Time.Format("2006-01-02 15:04:05"), "2020-10-10 12:00:01") 46 }) 47 gtest.C(t, func(t *gtest.T) { 48 st := &MyTimeSt{} 49 err := gconv.Struct(g.Map{"ServiceDate": nil}, st) 50 t.AssertNil(err) 51 t.Assert(st.ServiceDate.Time.IsZero(), true) 52 }) 53 gtest.C(t, func(t *gtest.T) { 54 st := &MyTimeSt{} 55 err := gconv.Struct(g.Map{"ServiceDate": "error"}, st) 56 t.AssertNE(err, nil) 57 }) 58 } 59 60 type Pkg struct { 61 Length uint16 // Total length. 62 Crc32 uint32 // CRC32. 63 Data []byte 64 } 65 66 // NewPkg creates and returns a package with given data. 67 func NewPkg(data []byte) *Pkg { 68 return &Pkg{ 69 Length: uint16(len(data) + 6), 70 Crc32: gcrc32.Encrypt(data), 71 Data: data, 72 } 73 } 74 75 // Marshal encodes the protocol struct to bytes. 76 func (p *Pkg) Marshal() []byte { 77 b := make([]byte, 6+len(p.Data)) 78 copy(b, gbinary.EncodeUint16(p.Length)) 79 copy(b[2:], gbinary.EncodeUint32(p.Crc32)) 80 copy(b[6:], p.Data) 81 return b 82 } 83 84 // UnmarshalValue decodes bytes to protocol struct. 85 func (p *Pkg) UnmarshalValue(v interface{}) error { 86 b := gconv.Bytes(v) 87 if len(b) < 6 { 88 return gerror.New("invalid package length") 89 } 90 p.Length = gbinary.DecodeToUint16(b[:2]) 91 if len(b) < int(p.Length) { 92 return gerror.New("invalid data length") 93 } 94 p.Crc32 = gbinary.DecodeToUint32(b[2:6]) 95 p.Data = b[6:] 96 if gcrc32.Encrypt(p.Data) != p.Crc32 { 97 return gerror.New("crc32 validation failed") 98 } 99 return nil 100 } 101 102 func TestStructUnmarshalValue2(t *testing.T) { 103 gtest.C(t, func(t *gtest.T) { 104 var p1, p2 *Pkg 105 p1 = NewPkg([]byte("123")) 106 err := gconv.Struct(p1.Marshal(), &p2) 107 t.AssertNil(err) 108 t.Assert(p1, p2) 109 }) 110 }