-
Notifications
You must be signed in to change notification settings - Fork 0
/
schema_ptr.go
114 lines (102 loc) · 2.21 KB
/
schema_ptr.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package schema
import (
"io"
"unsafe"
"github.com/hsfzxjy/imbed/core/pos"
"github.com/hsfzxjy/imbed/util/fastbuf"
)
type _Ptr[T any] struct {
def optional[*T]
elemSchema schema[T]
}
func (s *_Ptr[T]) decodeMsg(r *fastbuf.R, target unsafe.Pointer) *schemaError {
{
head, err := r.ReadBool()
if err != nil {
return newError(err)
}
if !head {
*(**T)(target) = nil
return nil
}
}
holder := new(T)
err := s.elemSchema.decodeMsg(r, unsafe.Pointer(holder))
if err != nil {
return err
}
*(**T)(target) = holder
return nil
}
func (s *_Ptr[T]) scanFrom(r Scanner, target unsafe.Pointer) (pos.P, *schemaError) {
holder := new(T)
pos, err := s.elemSchema.scanFrom(r, unsafe.Pointer(holder))
if err != nil {
err = s.setDefault(unsafe.Pointer(&holder))
if err != nil {
return pos, err
}
}
*(**T)(target) = holder
return pos, nil
}
func (s *_Ptr[T]) encodeMsg(w *fastbuf.W, source unsafe.Pointer) {
data := (**T)(source)
if *data == nil {
w.WriteBool(false)
return
}
w.WriteBool(true)
s.elemSchema.encodeMsg(w, unsafe.Pointer(*data))
}
func (s *_Ptr[T]) visit(v Visitor, source unsafe.Pointer) *schemaError {
data := *(**T)(source)
var isNil, isDefault bool
var def *T
if s.hasDefault() {
s.setDefault(unsafe.Pointer(&def))
isDefault = s.equal(data, def)
}
isNil = data == nil
ev, err := v.VisitPtr(isNil, isDefault)
if err != nil {
return newError(err)
}
if ev == nil || isNil {
return nil
}
return s.elemSchema.visit(ev, unsafe.Pointer(data))
}
func (s *_Ptr[T]) setDefault(target unsafe.Pointer) *schemaError {
if !s.hasDefault() {
return newError(ErrRequired)
}
if s.def.IsValid {
*(**T)(target) = s.def.Value
return nil
}
holder := new(T)
err := s.elemSchema.setDefault(unsafe.Pointer(holder))
if err != nil {
return err
}
*(**T)(target) = holder
return nil
}
func (s *_Ptr[T]) hasDefault() bool {
return s.def.IsValid || s.elemSchema.hasDefault()
}
func (s *_Ptr[T]) equal(a, b *T) bool {
if a == nil && b == nil {
return true
}
if a == nil || b == nil {
return false
}
return s.elemSchema.equal(*a, *b)
}
func (s *_Ptr[T]) writeTypeInfo(w io.Writer) error {
_, err := w.Write([]byte{'P'})
return err
}
func (s *_Ptr[T]) _schema_stub(*T) {}