...
1 package pgtype
2
3 import (
4 "database/sql/driver"
5 "fmt"
6 )
7
8
9
10
11 type EnumCodec struct {
12 membersMap map[string]string
13 }
14
15 func (EnumCodec) FormatSupported(format int16) bool {
16 return format == TextFormatCode || format == BinaryFormatCode
17 }
18
19 func (EnumCodec) PreferredFormat() int16 {
20 return TextFormatCode
21 }
22
23 func (EnumCodec) PlanEncode(m *Map, oid uint32, format int16, value any) EncodePlan {
24 switch format {
25 case TextFormatCode, BinaryFormatCode:
26 switch value.(type) {
27 case string:
28 return encodePlanTextCodecString{}
29 case []byte:
30 return encodePlanTextCodecByteSlice{}
31 case TextValuer:
32 return encodePlanTextCodecTextValuer{}
33 }
34 }
35
36 return nil
37 }
38
39 func (c *EnumCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
40 switch format {
41 case TextFormatCode, BinaryFormatCode:
42 switch target.(type) {
43 case *string:
44 return &scanPlanTextAnyToEnumString{codec: c}
45 case *[]byte:
46 return scanPlanAnyToNewByteSlice{}
47 case TextScanner:
48 return &scanPlanTextAnyToEnumTextScanner{codec: c}
49 }
50 }
51
52 return nil
53 }
54
55 func (c *EnumCodec) DecodeDatabaseSQLValue(m *Map, oid uint32, format int16, src []byte) (driver.Value, error) {
56 return c.DecodeValue(m, oid, format, src)
57 }
58
59 func (c *EnumCodec) DecodeValue(m *Map, oid uint32, format int16, src []byte) (any, error) {
60 if src == nil {
61 return nil, nil
62 }
63
64 return c.lookupAndCacheString(src), nil
65 }
66
67
68 func (c *EnumCodec) lookupAndCacheString(src []byte) string {
69 if c.membersMap == nil {
70 c.membersMap = make(map[string]string)
71 }
72
73 if s, found := c.membersMap[string(src)]; found {
74 return s
75 }
76
77 s := string(src)
78 c.membersMap[s] = s
79 return s
80 }
81
82 type scanPlanTextAnyToEnumString struct {
83 codec *EnumCodec
84 }
85
86 func (plan *scanPlanTextAnyToEnumString) Scan(src []byte, dst any) error {
87 if src == nil {
88 return fmt.Errorf("cannot scan NULL into %T", dst)
89 }
90
91 p := (dst).(*string)
92 *p = plan.codec.lookupAndCacheString(src)
93
94 return nil
95 }
96
97 type scanPlanTextAnyToEnumTextScanner struct {
98 codec *EnumCodec
99 }
100
101 func (plan *scanPlanTextAnyToEnumTextScanner) Scan(src []byte, dst any) error {
102 scanner := (dst).(TextScanner)
103
104 if src == nil {
105 return scanner.ScanText(Text{})
106 }
107
108 return scanner.ScanText(Text{String: plan.codec.lookupAndCacheString(src), Valid: true})
109 }
110
View as plain text