Fix binapigen decoding and minor improvements
[govpp.git] / binapigen / gen_helpers.go
1 //  Copyright (c) 2020 Cisco and/or its affiliates.
2 //
3 //  Licensed under the Apache License, Version 2.0 (the "License");
4 //  you may not use this file except in compliance with the License.
5 //  You may obtain a copy of the License at:
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 //  Unless required by applicable law or agreed to in writing, software
10 //  distributed under the License is distributed on an "AS IS" BASIS,
11 //  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 //  See the License for the specific language governing permissions and
13 //  limitations under the License.
14
15 package binapigen
16
17 func init() {
18         //RegisterPlugin("convert", GenerateConvert)
19 }
20
21 // library dependencies
22 const (
23         fmtPkg     = GoImportPath("fmt")
24         netPkg     = GoImportPath("net")
25         stringsPkg = GoImportPath("strings")
26 )
27
28 func genIPConversion(g *GenFile, structName string, ipv int) {
29         // ParseIPXAddress method
30         g.P("func Parse", structName, "(s string) (", structName, ", error) {")
31         if ipv == 4 {
32                 g.P("   ip := ", netPkg.Ident("ParseIP"), "(s).To4()")
33         } else {
34                 g.P("   ip := ", netPkg.Ident("ParseIP"), "(s).To16()")
35         }
36         g.P("   if ip == nil {")
37         g.P("           return ", structName, "{}, ", fmtPkg.Ident("Errorf"), "(\"invalid IP address: %s\", s)")
38         g.P("   }")
39         g.P("   var ipaddr ", structName)
40         if ipv == 4 {
41                 g.P("   copy(ipaddr[:], ip.To4())")
42         } else {
43                 g.P("   copy(ipaddr[:], ip.To16())")
44         }
45         g.P("   return ipaddr, nil")
46         g.P("}")
47         g.P()
48
49         // ToIP method
50         g.P("func (x ", structName, ") ToIP() ", netPkg.Ident("IP"), " {")
51         if ipv == 4 {
52                 g.P("   return ", netPkg.Ident("IP"), "(x[:]).To4()")
53         } else {
54                 g.P("   return ", netPkg.Ident("IP"), "(x[:]).To16()")
55         }
56         g.P("}")
57
58         // String method
59         g.P("func (x ", structName, ") String() string {")
60         g.P("   return x.ToIP().String()")
61         g.P("}")
62
63         // MarshalText method
64         g.P("func (x *", structName, ") MarshalText() ([]byte, error) {")
65         g.P("   return []byte(x.String()), nil")
66         g.P("}")
67
68         // UnmarshalText method
69         g.P("func (x *", structName, ") UnmarshalText(text []byte) error {")
70         g.P("   ipaddr, err := Parse", structName, "(string(text))")
71         g.P("   if err !=nil {")
72         g.P("           return err")
73         g.P("   }")
74         g.P("   *x = ipaddr")
75         g.P("   return nil")
76         g.P("}")
77         g.P()
78 }
79
80 func genAddressConversion(g *GenFile, structName string) {
81         // ParseAddress method
82         g.P("func Parse", structName, "(s string) (", structName, ", error) {")
83         g.P("   ip := ", netPkg.Ident("ParseIP"), "(s)")
84         g.P("   if ip == nil {")
85         g.P("           return ", structName, "{}, ", fmtPkg.Ident("Errorf"), "(\"invalid address: %s\", s)")
86         g.P("   }")
87         g.P("   var addr ", structName)
88         g.P("   if ip.To4() == nil {")
89         g.P("           addr.Af = ADDRESS_IP6")
90         g.P("           var ip6 IP6Address")
91         g.P("           copy(ip6[:], ip.To16())")
92         g.P("           addr.Un.SetIP6(ip6)")
93         g.P("   } else {")
94         g.P("           addr.Af = ADDRESS_IP4")
95         g.P("           var ip4 IP4Address")
96         g.P("           copy(ip4[:], ip.To4())")
97         g.P("           addr.Un.SetIP4(ip4)")
98         g.P("   }")
99         g.P("   return addr, nil")
100         g.P("}")
101
102         // ToIP method
103         g.P("func (x ", structName, ") ToIP() ", netPkg.Ident("IP"), " {")
104         g.P("   if x.Af == ADDRESS_IP6 {")
105         g.P("           ip6 := x.Un.GetIP6()")
106         g.P("           return ", netPkg.Ident("IP"), "(ip6[:]).To16()")
107         g.P("   } else {")
108         g.P("           ip4 := x.Un.GetIP4()")
109         g.P("           return ", netPkg.Ident("IP"), "(ip4[:]).To4()")
110         g.P("   }")
111         g.P("}")
112
113         // String method
114         g.P("func (x ", structName, ") String() string {")
115         g.P("   return x.ToIP().String()")
116         g.P("}")
117
118         // MarshalText method
119         g.P("func (x *", structName, ") MarshalText() ([]byte, error) {")
120         g.P("   return []byte(x.String()), nil")
121         g.P("}")
122
123         // UnmarshalText method
124         g.P("func (x *", structName, ") UnmarshalText(text []byte) error {")
125         g.P("   addr, err := Parse", structName, "(string(text))")
126         g.P("   if err != nil {")
127         g.P("           return err")
128         g.P("   }")
129         g.P("   *x = addr")
130         g.P("   return nil")
131         g.P("}")
132         g.P()
133 }
134
135 func genIPPrefixConversion(g *GenFile, structName string, ipv int) {
136         // ParsePrefix method
137         g.P("func Parse", structName, "(s string) (prefix ", structName, ", err error) {")
138         g.P("   hasPrefix := ", stringsPkg.Ident("Contains"), "(s, \"/\")")
139         g.P("   if hasPrefix {")
140         g.P("           ip, network, err := ", netPkg.Ident("ParseCIDR"), "(s)")
141         g.P("           if err != nil {")
142         g.P("                   return ", structName, "{}, ", fmtPkg.Ident("Errorf"), "(\"invalid IP %s: %s\", s, err)")
143         g.P("           }")
144         g.P("           maskSize, _ := network.Mask.Size()")
145         g.P("           prefix.Len = byte(maskSize)")
146         if ipv == 4 {
147                 g.P("           prefix.Address, err = ParseIP4Address(ip.String())")
148         } else {
149                 g.P("           prefix.Address, err = ParseIP6Address(ip.String())")
150         }
151         g.P("           if err != nil {")
152         g.P("                   return ", structName, "{}, ", fmtPkg.Ident("Errorf"), "(\"invalid IP %s: %s\", s, err)")
153         g.P("           }")
154         g.P("   } else {")
155         g.P("           ip :=  ", netPkg.Ident("ParseIP"), "(s)")
156         g.P("           defaultMaskSize, _ := ", netPkg.Ident("CIDRMask"), "(32, 32).Size()")
157         g.P("           if ip.To4() == nil {")
158         g.P("                   defaultMaskSize, _ =", netPkg.Ident("CIDRMask"), "(128, 128).Size()")
159         g.P("           }")
160         g.P("           prefix.Len = byte(defaultMaskSize)")
161         if ipv == 4 {
162                 g.P("           prefix.Address, err = ParseIP4Address(ip.String())")
163         } else {
164                 g.P("           prefix.Address, err = ParseIP6Address(ip.String())")
165         }
166         g.P("           if err != nil {")
167         g.P("                   return ", structName, "{}, ", fmtPkg.Ident("Errorf"), "(\"invalid IP %s: %s\", s, err)")
168         g.P("           }")
169         g.P("   }")
170         g.P("   return prefix, nil")
171         g.P("}")
172
173         // ToIPNet method
174         g.P("func (x ", structName, ") ToIPNet() *", netPkg.Ident("IPNet"), " {")
175         if ipv == 4 {
176                 g.P("   mask := ", netPkg.Ident("CIDRMask"), "(int(x.Len), 32)")
177         } else {
178                 g.P("   mask := ", netPkg.Ident("CIDRMask"), "(int(x.Len), 128)")
179         }
180         g.P("   ipnet := &", netPkg.Ident("IPNet"), "{IP: x.Address.ToIP(), Mask: mask}")
181         g.P("   return ipnet")
182         g.P("}")
183
184         // String method
185         g.P("func (x ", structName, ") String() string {")
186         g.P("   ip := x.Address.String()")
187         g.P("   return ip + \"/\" + ", strconvPkg.Ident("Itoa"), "(int(x.Len))")
188         /*if ipv == 4 {
189                 g.P("   mask := ", netPkg.Ident("CIDRMask"), "(int(x.Len), 32)")
190           } else {
191                 g.P("   mask := ", netPkg.Ident("CIDRMask"), "(int(x.Len), 128)")
192           }
193           g.P(" ipnet := &", netPkg.Ident("IPNet"), "{IP: x.Address.ToIP(), Mask: mask}")
194           g.P(" return ipnet.String()")*/
195         g.P("}")
196
197         // MarshalText method
198         g.P("func (x *", structName, ") MarshalText() ([]byte, error) {")
199         g.P("   return []byte(x.String()), nil")
200         g.P("}")
201
202         // UnmarshalText method
203         g.P("func (x *", structName, ") UnmarshalText(text []byte) error {")
204         g.P("   prefix, err := Parse", structName, "(string(text))")
205         g.P("   if err != nil {")
206         g.P("           return err")
207         g.P("   }")
208         g.P("   *x = prefix")
209         g.P("   return nil")
210         g.P("}")
211         g.P()
212 }
213
214 func genPrefixConversion(g *GenFile, structName string) {
215         // ParsePrefix method
216         g.P("func Parse", structName, "(ip string) (prefix ", structName, ", err error) {")
217         g.P("   hasPrefix := ", stringsPkg.Ident("Contains"), "(ip, \"/\")")
218         g.P("   if hasPrefix {")
219         g.P("           netIP, network, err := ", netPkg.Ident("ParseCIDR"), "(ip)")
220         g.P("           if err != nil {")
221         g.P("                   return Prefix{}, ", fmtPkg.Ident("Errorf"), "(\"invalid IP %s: %s\", ip, err)")
222         g.P("           }")
223         g.P("           maskSize, _ := network.Mask.Size()")
224         g.P("           prefix.Len = byte(maskSize)")
225         g.P("           prefix.Address, err = ParseAddress(netIP.String())")
226         g.P("           if err != nil {")
227         g.P("                   return Prefix{}, ", fmtPkg.Ident("Errorf"), "(\"invalid IP %s: %s\", ip, err)")
228         g.P("           }")
229         g.P("   } else {")
230         g.P("           netIP :=  ", netPkg.Ident("ParseIP"), "(ip)")
231         g.P("           defaultMaskSize, _ := ", netPkg.Ident("CIDRMask"), "(32, 32).Size()")
232         g.P("           if netIP.To4() == nil {")
233         g.P("                   defaultMaskSize, _ =", netPkg.Ident("CIDRMask"), "(128, 128).Size()")
234         g.P("           }")
235         g.P("           prefix.Len = byte(defaultMaskSize)")
236         g.P("           prefix.Address, err = ParseAddress(netIP.String())")
237         g.P("           if err != nil {")
238         g.P("                   return Prefix{}, ", fmtPkg.Ident("Errorf"), "(\"invalid IP %s: %s\", ip, err)")
239         g.P("           }")
240         g.P("   }")
241         g.P("   return prefix, nil")
242         g.P("}")
243
244         // ToIPNet method
245         g.P("func (x ", structName, ") ToIPNet() *", netPkg.Ident("IPNet"), " {")
246         g.P("   var mask ", netPkg.Ident("IPMask"))
247         g.P("   if x.Address.Af == ADDRESS_IP4 {")
248         g.P("   mask = ", netPkg.Ident("CIDRMask"), "(int(x.Len), 32)")
249         g.P("   } else {")
250         g.P("   mask = ", netPkg.Ident("CIDRMask"), "(int(x.Len), 128)")
251         g.P("   }")
252         g.P("   ipnet := &", netPkg.Ident("IPNet"), "{IP: x.Address.ToIP(), Mask: mask}")
253         g.P("   return ipnet")
254         g.P("}")
255
256         // String method
257         g.P("func (x ", structName, ") String() string {")
258         g.P("   ip := x.Address.String()")
259         g.P("   return ip + \"/\" + ", strconvPkg.Ident("Itoa"), "(int(x.Len))")
260         g.P("}")
261
262         // MarshalText method
263         g.P("func (x *", structName, ") MarshalText() ([]byte, error) {")
264         g.P("   return []byte(x.String()), nil")
265         g.P("}")
266
267         // UnmarshalText method
268         g.P("func (x *", structName, ") UnmarshalText(text []byte) error {")
269         g.P("   prefix, err := Parse", structName, "(string(text))")
270         g.P("   if err !=nil {")
271         g.P("           return err")
272         g.P("   }")
273         g.P("   *x = prefix")
274         g.P("   return nil")
275         g.P("}")
276         g.P()
277 }
278
279 func genAddressWithPrefixConversion(g *GenFile, structName string) {
280         // ParseAddressWithPrefix method
281         g.P("func Parse", structName, "(s string) (", structName, ", error) {")
282         g.P("   prefix, err := ParsePrefix(s)")
283         g.P("   if err != nil {")
284         g.P("           return ", structName, "{}, err")
285         g.P("   }")
286         g.P("   return ", structName, "(prefix), nil")
287         g.P("}")
288
289         // String method
290         g.P("func (x ", structName, ") String() string {")
291         g.P("   return Prefix(x).String()")
292         g.P("}")
293
294         // MarshalText method
295         g.P("func (x *", structName, ") MarshalText() ([]byte, error) {")
296         g.P("   return []byte(x.String()), nil")
297         g.P("}")
298
299         // UnmarshalText method
300         g.P("func (x *", structName, ") UnmarshalText(text []byte) error {")
301         g.P("   prefix, err := Parse", structName, "(string(text))")
302         g.P("   if err != nil {")
303         g.P("           return err")
304         g.P("   }")
305         g.P("   *x = prefix")
306         g.P("   return nil")
307         g.P("}")
308         g.P()
309 }
310
311 func genMacAddressConversion(g *GenFile, structName string) {
312         // ParseMAC method
313         g.P("func Parse", structName, "(s string) (", structName, ", error) {")
314         g.P("   var macaddr ", structName)
315         g.P("   mac, err := ", netPkg.Ident("ParseMAC"), "(s)")
316         g.P("   if err != nil {")
317         g.P("           return macaddr, err")
318         g.P("   }")
319         g.P("   copy(macaddr[:], mac[:])")
320         g.P("   return macaddr, nil")
321         g.P("}")
322
323         // ToMAC method
324         g.P("func (x ", structName, ") ToMAC() ", netPkg.Ident("HardwareAddr"), " {")
325         g.P("   return ", netPkg.Ident("HardwareAddr"), "(x[:])")
326         g.P("}")
327
328         // String method
329         g.P("func (x ", structName, ") String() string {")
330         g.P("   return x.ToMAC().String()")
331         g.P("}")
332
333         // MarshalText method
334         g.P("func (x *", structName, ") MarshalText() ([]byte, error) {")
335         g.P("   return []byte(x.String()), nil")
336         g.P("}")
337
338         // UnmarshalText method
339         g.P("func (x *", structName, ") UnmarshalText(text []byte) error {")
340         g.P("   mac, err := Parse", structName, "(string(text))")
341         g.P("   if err != nil {")
342         g.P("           return err")
343         g.P("   }")
344         g.P("   *x = mac")
345         g.P("   return nil")
346         g.P("}")
347         g.P()
348 }