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