File: ipaddrstrparams.go

package info (click to toggle)
golang-github-seancfoley-ipaddress-go 1.5.4-3
  • links: PTS, VCS
  • area: main
  • in suites: experimental, forky, sid, trixie
  • size: 3,700 kB
  • sloc: makefile: 3
file content (966 lines) | stat: -rw-r--r-- 42,618 bytes parent folder | download
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
//
// Copyright 2020-2022 Sean C Foley
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

package addrstrparam

import "strings"

// CopyIPAddressStringParams produces an immutable copy of the original IPAddressStringParams.
// Copying an IPAddressStringParams created by an IPAddressStringParamsBuilder is unnecessary since it is already immutable.
func CopyIPAddressStringParams(orig IPAddressStringParams) IPAddressStringParams {
	if p, ok := orig.(*ipAddressStringParameters); ok {
		return p
	}
	return new(IPAddressStringParamsBuilder).Set(orig).ToParams()
}

// IPAddressStringParams provides parameters for parsing IP address strings,
// indicating what to allow, what to disallow, and other options.
//
// This allows you to control the validation performed by IPAddressString.
//
// IPAddressString uses a default permissive IPAddressStringParams instance when you do not specify one.
//
// If you wish to use parameters different from the default, then use this interface.  Immutable instances can be constructed with IPAddressStringParamsBuilder.
type IPAddressStringParams interface {
	AddressStringParams

	// AllowsPrefix indicates whether addresses with prefix length like 1.2.0.0/16 are allowed.
	AllowsPrefix() bool

	// EmptyStrParsedAs determines how a zero-length empty string is translated to an address.
	// If the option is ZeroAddressOption or LoopbackOption, then if defers to GetPreferredVersion() for the version.
	EmptyStrParsedAs() EmptyStrOption

	// AllStrParsedAs determines how the "all" string "*" is translated to addresses.
	// If the option is AllPreferredIPVersion, then it defers to GetPreferredVersion() for the version.
	AllStrParsedAs() AllStrOption

	// AllowsMask allows masks to follow valid addresses, such as 1.2.3.4/255.255.0.0 which has the mask 255.255.0.0
	// If the mask is the mask for a network prefix length, this is interpreted as the subnet for that network prefix length.
	// Otherwise the address is simply masked by the mask.
	// For instance, 1.2.3.4/255.0.255.0 is 1.0.3.0, while 1.2.3.4/255.255.0.0 is 1.2.0.0/16.
	AllowsMask() bool

	// GetPreferredVersion indicates the version to use for ambiguous addresses strings,
	// like prefix lengths less than 32 bits which are translated to masks,
	// the "all" address or the "empty" address.
	// The default is IPv6.
	//
	// If either of AllowsIPv4() or AllowsIPv6() returns false, then those settings take precedence over this setting.
	GetPreferredVersion() IPVersion

	// AllowsIPv4 allows IPv4 addresses and subnets.
	AllowsIPv4() bool

	// AllowsIPv6 allows IPv6 addresses and subnets.
	AllowsIPv6() bool

	// GetIPv4Params returns the parameters that apply specifically to IPv4 addresses and subnets.
	GetIPv4Params() IPv4AddressStringParams

	// GetIPv6Params returns the parameters that apply specifically to IPv6 addresses and subnets.
	GetIPv6Params() IPv6AddressStringParams
}

// EmptyStrOption is an option indicating how to translate an empty address string to an address.
type EmptyStrOption string

const (
	// NoAddressOption indicates that empty strings are not translated to addresses.
	NoAddressOption EmptyStrOption = "none"

	// ZeroAddressOption is the default, which means empty strings are translated to zero addresses.
	ZeroAddressOption EmptyStrOption = ""

	// LoopbackOption indicates empty strings are translated to loopback addresses.
	LoopbackOption EmptyStrOption = "loopback"
)

// AllStrOption is an option indicating how to translate an all address string, such as "*", to an address.
type AllStrOption string

const (
	// AllAddresses is the default, indicating the all address string refers to all addresses of all IP versions.
	AllAddresses AllStrOption = "" // the default

	// AllPreferredIPVersion indicates the all address string refers to all addresses of the preferred IP version.
	AllPreferredIPVersion AllStrOption = "preferred"
)

var _ IPAddressStringParams = &ipAddressStringParameters{}

// IPv4AddressStringParams provides parameters specific to IPv4 addresses and subnets
type IPv4AddressStringParams interface {
	IPAddressStringFormatParams

	// Allows_inet_aton_hex allows IPv4 inet_aton hexadecimal format "0xa.0xb.0xc.0cd".
	Allows_inet_aton_hex() bool

	// Allows_inet_aton_octal allows IPv4 inet_aton octal format, "04.05.06.07" being an example.
	// Can be overridden by allowLeadingZeros
	Allows_inet_aton_octal() bool

	// Allows_inet_aton_joinedSegments allows IPv4 joined segments like "1.2.3", "1.2", or just "1".
	//
	// For the case of just 1 segment, the behaviour is controlled by allowSingleSegment.
	Allows_inet_aton_joinedSegments() bool

	// Allows_inet_aton_single_segment_mask indicates whether you allow a mask that looks like a prefix length when you allow IPv4 joined segments: "1.2.3.5/255".
	Allows_inet_aton_single_segment_mask() bool

	// Allows_inet_aton_leading_zeros allows IPv4 inet_aton hexadecimal or octal to have leading zeros, such as in the first two segments of "0x0a.00b.c.d".
	// The first 0 is not considered a leading zero, it either denotes octal or hex depending on whether it is followed by an 'x'.
	// Zeros that appear afterwards are inet_aton leading zeros.
	Allows_inet_aton_leading_zeros() bool
}

var _ IPv4AddressStringParams = &ipv4AddressStringParameters{}

// IPv6AddressStringParams provides parameters specific to IPv6 addresses and subnets.
type IPv6AddressStringParams interface {
	IPAddressStringFormatParams

	// AllowsMixed allows mixed-in embedded IPv4 like "a:b:c:d:e:f:1.2.3.4".
	AllowsMixed() bool

	// AllowsZone allows zones like "a:b:c:d:e:f:a:b%zone".
	AllowsZone() bool

	// AllowsEmptyZone allows the zone character % with no following zone.
	AllowsEmptyZone() bool

	// AllowsBase85 allows IPv6 single-segment base 85 addresses.
	AllowsBase85() bool

	// GetMixedParams provides the IP parameters that for parsing the embedded IPv4 section of a mixed IPv6/v4 address, if AllowsMixed is true.
	GetMixedParams() IPAddressStringParams

	// GetEmbeddedIPv4AddressParams returns the IPv4 parameters for parsing the embedded IPv4 section of a mixed IPv6/v4 address.
	GetEmbeddedIPv4AddressParams() IPv4AddressStringParams
}

var _ IPv6AddressStringParams = &ipv6AddressStringParameters{}

// IPAddressStringFormatParams provides format parameters that apply to all IP addresses, but can be different for IPv4 or IPv6,
// allowing for cases where you may wish to allow something for one version but not the same for the other version.
type IPAddressStringFormatParams interface {
	AddressStringFormatParams

	// AllowsPrefixesBeyondAddressSize allows prefix length values greater than 32 for IPv4 or greater than 128 for IPv6.
	AllowsPrefixesBeyondAddressSize() bool

	// AllowsPrefixLenLeadingZeros allows leading zeros in the prefix length like "1.2.3.4/016".
	AllowsPrefixLenLeadingZeros() bool

	// AllowsBinary allows binary addresses like "11111111.0.1.0" or "1111111111111111::".
	AllowsBinary() bool
}

func init() {
	defaultEmbeddedBuilder.
		AllowEmpty(false).
		AllowPrefix(false).
		AllowMask(false).
		AllowAll(false).
		AllowIPv6(false).
		GetIPv6AddressParamsBuilder().
		AllowZone(true).
		AllowEmptyZone(true)
	defaultEmbeddedParams =
		defaultEmbeddedBuilder.
			ToParams().(*ipAddressStringParameters)
}

var defaultEmbeddedBuilder IPAddressStringParamsBuilder
var defaultEmbeddedParams *ipAddressStringParameters

// ipAddressStringParameters has parameters for parsing IP address strings.
// They are immutable and can be constructed using an IPAddressStringParamsBuilder.
type ipAddressStringParameters struct {
	addressStringParameters
	ipv4Params ipv4AddressStringParameters
	ipv6Params ipv6AddressStringParameters

	emptyStringOption EmptyStrOption
	allStringOption   AllStrOption
	preferredVersion  IPVersion

	//emptyIsNotLoopback,
	//noPrefixOnly,
	noPrefix, noMask, noIPv6, noIPv4 bool
}

// AllowsPrefix indicates whether addresses with prefix length like 1.2.0.0/16 are allowed.
func (params *ipAddressStringParameters) AllowsPrefix() bool {
	return !params.noPrefix
}

// EmptyStrParsedAs determines how a zero-length empty string is translated to an address.
// If the option is ZeroAddressOption or LoopbackOption, then if defers to GetPreferredVersion() for the version.
func (params *ipAddressStringParameters) EmptyStrParsedAs() EmptyStrOption {
	return params.emptyStringOption
}

// AllStrParsedAs determines how the "all" string "*" is translated to addresses.
// If the option is AllPreferredIPVersion, then it defers to GetPreferredVersion() for the version.
func (params *ipAddressStringParameters) AllStrParsedAs() AllStrOption {
	return params.allStringOption
}

// GetPreferredVersion indicates the version to use for ambiguous addresses strings,
// like prefix lengths less than 32 bits which are translated to masks,
// the "all" address or the "empty" address.
// The default is IPv6.
//
// If either of AllowsIPv4() or AllowsIPv6() returns false, then those settings take precedence over this setting.
func (params *ipAddressStringParameters) GetPreferredVersion() IPVersion {
	return params.preferredVersion
}

// AllowsMask allows masks to follow valid addresses, such as 1.2.3.4/255.255.0.0 which has the mask 255.255.0.0
// If the mask is the mask for a network prefix length, this is interpreted as the subnet for that network prefix length.
// Otherwise the address is simply masked by the mask.
// For instance, 1.2.3.4/255.0.255.0 is 1.0.3.0, while 1.2.3.4/255.255.0.0 is 1.2.0.0/16.
func (params *ipAddressStringParameters) AllowsMask() bool {
	return !params.noMask
}

// AllowsIPv4 allows IPv4 addresses and subnets.
func (params *ipAddressStringParameters) AllowsIPv4() bool {
	return !params.noIPv4
}

// AllowsIPv6 allows IPv6 addresses and subnets.
func (params *ipAddressStringParameters) AllowsIPv6() bool {
	return !params.noIPv6
}

// GetIPv4Params returns the parameters that apply specifically to IPv4 addresses and subnets.
func (params *ipAddressStringParameters) GetIPv4Params() IPv4AddressStringParams {
	return &params.ipv4Params
}

// GetIPv6Params returns the parameters that apply specifically to IPv6 addresses and subnets.
func (params *ipAddressStringParameters) GetIPv6Params() IPv6AddressStringParams {
	return &params.ipv6Params
}

// IPAddressStringParamsBuilder builds an immutable IPAddressStringParameters for controlling parsing of IP address strings.
type IPAddressStringParamsBuilder struct {
	params ipAddressStringParameters
	AddressStringParamsBuilder
	ipv4Builder IPv4AddressStringParamsBuilder
	ipv6Builder IPv6AddressStringParamsBuilder

	parent *HostNameParamsBuilder
}

// GetParentBuilder returns the original HostNameParamsBuilder builder that this was obtained from, if this builder was obtained from a HostNameParamsBuilder.
func (builder *IPAddressStringParamsBuilder) GetParentBuilder() *HostNameParamsBuilder {
	return builder.parent
}

// ToParams returns an immutable IPAddressStringParams instance built by this builder.
func (builder *IPAddressStringParamsBuilder) ToParams() IPAddressStringParams {
	// We do not return a pointer to builder.params because that would make it possible to change a ipAddressStringParameters
	// by continuing to use the same builder,
	// and we want immutable objects for concurrency-safety,
	// so we cannot allow it
	result := builder.params
	result.addressStringParameters = *builder.AddressStringParamsBuilder.ToParams().(*addressStringParameters)
	result.ipv4Params = *builder.ipv4Builder.ToParams().(*ipv4AddressStringParameters)
	result.ipv6Params = *builder.ipv6Builder.ToParams().(*ipv6AddressStringParameters)
	return &result
}

// GetIPv6AddressParamsBuilder returns a builder that builds the IPv6AddressStringParams for the IPAddressStringParams being built by this builder.
func (builder *IPAddressStringParamsBuilder) GetIPv6AddressParamsBuilder() (result *IPv6AddressStringParamsBuilder) {
	result = &builder.ipv6Builder
	result.parent = builder
	return
}

// GetIPv4AddressParamsBuilder returns a builder that builds the IPv4AddressStringParams for the IPAddressStringParams being built by this builder.
func (builder *IPAddressStringParamsBuilder) GetIPv4AddressParamsBuilder() (result *IPv4AddressStringParamsBuilder) {
	result = &builder.ipv4Builder
	result.parent = builder
	return
}

// Set populates this builder with the values from the given IPAddressStringParams.
func (builder *IPAddressStringParamsBuilder) Set(params IPAddressStringParams) *IPAddressStringParamsBuilder {
	return builder.set(params, false)
}

func (builder *IPAddressStringParamsBuilder) set(params IPAddressStringParams, isMixed bool) *IPAddressStringParamsBuilder {
	if p, ok := params.(*ipAddressStringParameters); ok {
		builder.params = *p
	} else {
		builder.params = ipAddressStringParameters{
			preferredVersion:  params.GetPreferredVersion(),
			emptyStringOption: params.EmptyStrParsedAs(),
			allStringOption:   params.AllStrParsedAs(),
			noPrefix:          !params.AllowsPrefix(),
			noMask:            !params.AllowsMask(),
			noIPv6:            !params.AllowsIPv6(),
			noIPv4:            !params.AllowsIPv4(),
		}
	}
	builder.AddressStringParamsBuilder.set(params)
	builder.ipv4Builder.Set(params.GetIPv4Params())
	builder.ipv6Builder.set(params.GetIPv6Params(), isMixed)
	return builder
}

// AllowEmpty dictates whether to allow empty zero-length address strings.
func (builder *IPAddressStringParamsBuilder) AllowEmpty(allow bool) *IPAddressStringParamsBuilder {
	builder.allowEmpty(allow)
	return builder
}

// AllowSingleSegment dictates whether to allow an address to be specified as a single value, eg "ffffffff", without the standard use of segments like "1.2.3.4" or "1:2:4:3:5:6:7:8".
func (builder *IPAddressStringParamsBuilder) AllowSingleSegment(allow bool) *IPAddressStringParamsBuilder {
	builder.allowSingleSegment(allow)
	return builder
}

// AllowAll dictates whether to alloww the string of just the wildcard "*" to denote all addresses of all version.
// If false, then for IP addresses we check the preferred version with GetPreferredVersion, and then check AllowsWildcardedSeparator,
// to determine if the string represents all addresses of that version.
func (builder *IPAddressStringParamsBuilder) AllowAll(allow bool) *IPAddressStringParamsBuilder {
	builder.allowAll(allow)
	return builder
}

// ParseEmptyStrAs dictates how a zero-length empty string is translated to an address.
// If the option is ZeroAddressOption or LoopbackOption, then if defers to GetPreferredVersion for the version.
func (builder *IPAddressStringParamsBuilder) ParseEmptyStrAs(option EmptyStrOption) *IPAddressStringParamsBuilder {
	builder.params.emptyStringOption = option
	builder.AllowEmpty(true)
	return builder
}

// ParseAllStrAs dictates how the "all" string "*" is translated to addresses.
//// If the option is AllPreferredIPVersion, then it defers to GetPreferredVersion for the version.
func (builder *IPAddressStringParamsBuilder) ParseAllStrAs(option AllStrOption) *IPAddressStringParamsBuilder {
	builder.params.allStringOption = option
	return builder
}

// SetPreferredVersion dictates the version to use for ambiguous addresses strings,
// like prefix lengths less than 32 bits which are translated to masks,
// the "all" address or the "empty" address.
// The default is IPv6.
//
// If either of AllowsIPv4 or AllowsIPv6 returns false, then those settings take precedence over this setting.
func (builder *IPAddressStringParamsBuilder) SetPreferredVersion(version IPVersion) *IPAddressStringParamsBuilder {
	builder.params.preferredVersion = version
	return builder
}

// AllowPrefix dictates whether to allow addresses with prefix length like "1.2.0.0/16" are allowed.
func (builder *IPAddressStringParamsBuilder) AllowPrefix(allow bool) *IPAddressStringParamsBuilder {
	builder.params.noPrefix = !allow
	return builder
}

// AllowMask dictates whether to allow masks to follow valid addresses, such as "1.2.3.4/255.255.0.0" which has the mask "255.255.0.0".
// If the mask is the mask for a network prefix length, this is interpreted as the subnet for that network prefix length.
// Otherwise the address is simply masked by the mask.
// For instance, "1.2.3.4/255.0.255.0" is "1.0.3.0", while "1.2.3.4/255.255.0.0" is "1.2.0.0/16".
func (builder *IPAddressStringParamsBuilder) AllowMask(allow bool) *IPAddressStringParamsBuilder {
	builder.params.noMask = !allow
	return builder
}

// AllowIPv4 dictates whether to allow IPv4 addresses and subnets
func (builder *IPAddressStringParamsBuilder) AllowIPv4(allow bool) *IPAddressStringParamsBuilder {
	builder.params.noIPv4 = !allow
	return builder
}

// AllowIPv6 dictates whether to allow IPv6 addresses and subnets
func (builder *IPAddressStringParamsBuilder) AllowIPv6(allow bool) *IPAddressStringParamsBuilder {
	builder.params.noIPv6 = !allow
	return builder
}

// AllowWildcardedSeparator dictates whether the wildcard '*' or '%' can replace the segment separators '.' and ':'.
// If so, then you can write addresses like *.* or *:*
func (builder *IPAddressStringParamsBuilder) AllowWildcardedSeparator(allow bool) *IPAddressStringParamsBuilder {
	builder.GetIPv4AddressParamsBuilder().AllowWildcardedSeparator(allow)
	builder.GetIPv6AddressParamsBuilder().AllowWildcardedSeparator(allow)
	return builder
}

// SetRangeParams populates this builder with the values from the given RangeParams.
func (builder *IPAddressStringParamsBuilder) SetRangeParams(rangeParams RangeParams) *IPAddressStringParamsBuilder {
	builder.GetIPv4AddressParamsBuilder().SetRangeParams(rangeParams)
	builder.GetIPv6AddressParamsBuilder().SetRangeParams(rangeParams)
	return builder
}

// Allow_inet_aton dictates whether to allow any IPv4 inet_aton format, whether hex, octal, or joined segments.
func (builder *IPAddressStringParamsBuilder) Allow_inet_aton(allow bool) *IPAddressStringParamsBuilder {
	builder.GetIPv4AddressParamsBuilder().Allow_inet_aton(allow)
	builder.GetIPv6AddressParamsBuilder().Allow_mixed_inet_aton(allow)
	return builder
}

type ipAddressStringFormatParameters struct {
	addressStringFormatParameters

	allowPrefixesBeyondAddrSize,
	noPrefixLengthLeadingZeros,
	noBinary bool
}

// AllowsPrefixesBeyondAddressSize allows prefix length values greater than 32 for IPv4 or greater than 128 for IPv6.
func (params *ipAddressStringFormatParameters) AllowsPrefixesBeyondAddressSize() bool {
	return params.allowPrefixesBeyondAddrSize
}

// AllowsPrefixLenLeadingZeros allows leading zeros in the prefix length like "1.2.3.4/016".
func (params *ipAddressStringFormatParameters) AllowsPrefixLenLeadingZeros() bool {
	return !params.noPrefixLengthLeadingZeros
}

// AllowsBinary allows binary addresses like "11111111.0.1.0" or "1111111111111111::".
func (params *ipAddressStringFormatParameters) AllowsBinary() bool {
	return !params.noBinary
}

// IPAddressStringFormatParamsBuilder builds an immutable IPAddressStringFormatParams for controlling parsing of IP address strings.
type IPAddressStringFormatParamsBuilder struct {
	AddressStringFormatParamsBuilder

	ipParams ipAddressStringFormatParameters

	parent *IPAddressStringParamsBuilder
}

// GetParentBuilder returns the original IPAddressStringParamsBuilder builder that this was obtained from, if this builder was obtained from a IPAddressStringParamsBuilder.
func (builder *IPAddressStringFormatParamsBuilder) GetParentBuilder() *IPAddressStringParamsBuilder {
	return builder.parent
}

// ToParams returns an immutable IPAddressStringFormatParams instance built by this builder
func (builder *IPAddressStringFormatParamsBuilder) ToParams() IPAddressStringFormatParams {
	result := &builder.ipParams
	result.addressStringFormatParameters = *builder.AddressStringFormatParamsBuilder.ToParams().(*addressStringFormatParameters)
	return result
}

func (builder *IPAddressStringFormatParamsBuilder) set(params IPAddressStringFormatParams) {
	if p, ok := params.(*ipAddressStringFormatParameters); ok {
		builder.ipParams = *p
	} else {
		builder.ipParams = ipAddressStringFormatParameters{
			allowPrefixesBeyondAddrSize: params.AllowsPrefixesBeyondAddressSize(),
			noPrefixLengthLeadingZeros:  !params.AllowsPrefixLenLeadingZeros(),
			noBinary:                    !params.AllowsBinary(),
		}
	}
	builder.AddressStringFormatParamsBuilder.set(params)
}

// AllowsPrefixesBeyondAddressSize allows prefix length values greater than 32 for IPv4 or greater than 128 for IPv6.
func (builder *IPAddressStringFormatParamsBuilder) AllowsPrefixesBeyondAddressSize() bool {
	return builder.ipParams.AllowsPrefixesBeyondAddressSize()
}

// AllowsPrefixLenLeadingZeros allows leading zeros in the prefix length like "1.2.3.4/016".
func (builder *IPAddressStringFormatParamsBuilder) AllowsPrefixLenLeadingZeros() bool {
	return builder.ipParams.AllowsPrefixLenLeadingZeros()
}

// AllowsBinary allows binary addresses like 11111111.0.1.0 or 1111111111111111::
func (builder *IPAddressStringFormatParamsBuilder) AllowsBinary() bool {
	return builder.ipParams.AllowsBinary()
}

func (builder *IPAddressStringFormatParamsBuilder) allowBinary(allow bool) {
	builder.ipParams.noBinary = !allow
}

func (builder *IPAddressStringFormatParamsBuilder) allowPrefixesBeyondAddressSize(allow bool) {
	builder.ipParams.allowPrefixesBeyondAddrSize = allow
}

func (builder *IPAddressStringFormatParamsBuilder) allowPrefixLengthLeadingZeros(allow bool) {
	builder.ipParams.noPrefixLengthLeadingZeros = !allow
}

type ipv6AddressStringParameters struct {
	ipAddressStringFormatParameters

	noMixed, noZone, noBase85, noEmptyZone bool

	embeddedParams *ipAddressStringParameters
}

// AllowsMixed allows mixed-in embedded IPv4 like "a:b:c:d:e:f:1.2.3.4".
func (params *ipv6AddressStringParameters) AllowsMixed() bool {
	return !params.noMixed
}

// AllowsZone allows zones like "a:b:c:d:e:f:a:b%zone".
func (params *ipv6AddressStringParameters) AllowsZone() bool {
	return !params.noZone
}

// AllowsEmptyZone allows the zone character % with no following zone'
func (params *ipv6AddressStringParameters) AllowsEmptyZone() bool {
	return !params.noEmptyZone
}

// AllowsBase85 allows IPv6 single-segment base 85 addresses'
func (params *ipv6AddressStringParameters) AllowsBase85() bool {
	return !params.noBase85
}

// GetMixedParams provides the parameters that for parsing the embedded IPv4 section of a mixed IPv6/v4 address, if AllowsMixed is true'
func (params *ipv6AddressStringParameters) GetMixedParams() IPAddressStringParams {
	result := params.embeddedParams
	if result == nil {
		result = defaultEmbeddedParams
	}
	return result
}

// GetEmbeddedIPv4AddressParams returns the IPv4 parameters for parsing the embedded IPv4 section of a mixed IPv6/v4 address'
func (params *ipv6AddressStringParameters) GetEmbeddedIPv4AddressParams() IPv4AddressStringParams {
	return params.embeddedParams.GetIPv4Params()
}

// IPv6AddressStringParamsBuilder builds an immutable IPv6AddressStringParams for controlling parsing of IPv6 address strings'
type IPv6AddressStringParamsBuilder struct {
	// This is not anonymous since it clashes with IPAddressStringFormatParamsBuilder,
	// both have ipAddressStringFormatParameters and AddressStringFormatParams
	// and thee builder IPAddressStringFormatParamsBuilder takes precedence
	params ipv6AddressStringParameters

	embeddedBuilder *IPAddressStringParamsBuilder

	IPAddressStringFormatParamsBuilder
}

// ToParams returns an immutable IPv6AddressStringParams instance built by this builder'
func (builder *IPv6AddressStringParamsBuilder) ToParams() IPv6AddressStringParams {
	result := &builder.params
	result.ipAddressStringFormatParameters = *builder.IPAddressStringFormatParamsBuilder.ToParams().(*ipAddressStringFormatParameters)
	if emb := builder.embeddedBuilder; emb == nil {
		result.embeddedParams = defaultEmbeddedParams
	} else {
		result.embeddedParams = emb.ToParams().(*ipAddressStringParameters)
	}
	return result
}

// GetRangeParamsBuilder returns a builder that builds the range parameters for these IPv6 address string parameters.
func (builder *IPv6AddressStringParamsBuilder) GetRangeParamsBuilder() *RangeParamsBuilder {
	result := &builder.rangeParamsBuilder
	result.parent = builder
	return result
}

// AllowsMixed allows mixed-in embedded IPv4 like "a:b:c:d:e:f:1.2.3.4".
func (builder *IPv6AddressStringParamsBuilder) AllowsMixed() bool {
	return builder.params.AllowsMixed()
}

// AllowsZone allows zones like "a:b:c:d:e:f:a:b%zone".
func (builder *IPv6AddressStringParamsBuilder) AllowsZone() bool {
	return builder.params.AllowsZone()
}

// AllowsEmptyZone allows the zone character % with no following zone.
func (builder *IPv6AddressStringParamsBuilder) AllowsEmptyZone() bool {
	return builder.params.AllowsEmptyZone()
}

// AllowsBase85 allows IPv6 single-segment base 85 addresses.
func (builder *IPv6AddressStringParamsBuilder) AllowsBase85() bool {
	return builder.params.AllowsBase85()
}

// AllowBase85 dictates whether to allow IPv6 single-segment base 85 addresses.
func (builder *IPv6AddressStringParamsBuilder) AllowBase85(allow bool) *IPv6AddressStringParamsBuilder {
	builder.params.noBase85 = !allow
	return builder
}

// Set populates this builder with the values from the given IPv6AddressStringParams.
func (builder *IPv6AddressStringParamsBuilder) Set(params IPv6AddressStringParams) *IPv6AddressStringParamsBuilder {
	return builder.set(params, false)
}

func (builder *IPv6AddressStringParamsBuilder) set(params IPv6AddressStringParams, isMixed bool) *IPv6AddressStringParamsBuilder {
	if p, ok := params.(*ipv6AddressStringParameters); ok {
		builder.params = *p
	} else {
		builder.params = ipv6AddressStringParameters{
			noMixed:     !params.AllowsMixed(),
			noZone:      !params.AllowsZone(),
			noEmptyZone: !params.AllowsEmptyZone(),
			noBase85:    !params.AllowsBase85(),
		}
	}
	builder.IPAddressStringFormatParamsBuilder.set(params)
	if !isMixed {
		builder.getEmbeddedIPv4ParametersBuilder().ipv4Builder.Set(params.GetEmbeddedIPv4AddressParams())
	}
	return builder
}

// AllowZone dictates whether to allow zones like "a:b:c:d:e:f:a:b%zone".
func (builder *IPv6AddressStringParamsBuilder) AllowZone(allow bool) *IPv6AddressStringParamsBuilder {
	builder.params.noZone = !allow

	//we must decide whether to treat the % character as a zone when parsing the mixed part
	//if considered zone, then the zone character is actually part of the encompassing IPv6 address
	//otherwise, the zone character is an sql wildcard that is part of the mixed address
	//So whether we consider the % character a zone must match the same setting for the encompassing address

	// ipv4Builder can be nil when builder == &defaultEmbeddedBuilder.ipv6Builder, see getEmbeddedIPv4ParametersBuilder()
	if ipv4Builder := builder.getEmbeddedIPv4ParametersBuilder(); ipv4Builder != nil {
		ipv4Builder.GetIPv6AddressParamsBuilder().params.noZone = !allow
	}
	return builder
}

// AllowEmptyZone dictates whether to allow the zone character % with no following zone
func (builder *IPv6AddressStringParamsBuilder) AllowEmptyZone(allow bool) *IPv6AddressStringParamsBuilder {
	builder.params.noEmptyZone = !allow
	if ipv4Builder := builder.getEmbeddedIPv4ParametersBuilder(); ipv4Builder != nil {
		ipv4Builder.GetIPv6AddressParamsBuilder().params.noEmptyZone = !allow
	}
	return builder
}

// AllowMixed dictates whether to allow mixed-in embedded IPv4 like "a:b:c:d:e:f:1.2.3.4".
func (builder *IPv6AddressStringParamsBuilder) AllowMixed(allow bool) *IPv6AddressStringParamsBuilder {
	builder.params.noMixed = !allow
	return builder
}

func (builder *IPv6AddressStringParamsBuilder) getEmbeddedIPv4ParametersBuilder() (result *IPAddressStringParamsBuilder) {
	if builder == &defaultEmbeddedBuilder.ipv6Builder {
		return nil
	}
	if result = builder.embeddedBuilder; result == nil {
		result = &IPAddressStringParamsBuilder{}
		// copy in proper default values for embedded IPv4 addresses, which differ from defaults for typical ipv4AddrType addresses
		*result = defaultEmbeddedBuilder
		builder.embeddedBuilder = result
	}
	result.GetIPv4AddressParamsBuilder().mixedParent = builder
	return
}

// GetEmbeddedIPv4AddressParamsBuilder returns a builder to build the IPv4 parameters that controls parsing of the embedded IPv4 section of a mixed IPv6/v4 address.
func (builder *IPv6AddressStringParamsBuilder) GetEmbeddedIPv4AddressParamsBuilder() (result *IPv4AddressStringParamsBuilder) {
	return builder.getEmbeddedIPv4ParametersBuilder().GetIPv4AddressParamsBuilder()
}

// Allow_mixed_inet_aton dictates whether to allow inet_aton style formats, whether hex, octal, or joined segments, in the embedded IPv4 section of a mixed IPv6/v4 address.
func (builder *IPv6AddressStringParamsBuilder) Allow_mixed_inet_aton(allow bool) *IPv6AddressStringParamsBuilder {
	builder.getEmbeddedIPv4ParametersBuilder().GetIPv4AddressParamsBuilder().Allow_inet_aton(allow)
	if allow { // if we allow inet_aton in the mixed part, then of course that insinuates that we allow the mixed part
		builder.AllowMixed(allow)
	}
	return builder
}

// AllowBinary dictates whether to allow binary addresses like "11111111.0.1.0" or "1111111111111111::".
func (builder *IPv6AddressStringParamsBuilder) AllowBinary(allow bool) *IPv6AddressStringParamsBuilder {
	builder.GetEmbeddedIPv4AddressParamsBuilder().AllowBinary(allow)
	builder.allowBinary(allow)
	return builder
}

// AllowWildcardedSeparator dictates whether the wildcard '*' or '%' can replace the segment separators '.' and ':'.
// If so, then you can write addresses like *.* or *:*
func (builder *IPv6AddressStringParamsBuilder) AllowWildcardedSeparator(allow bool) *IPv6AddressStringParamsBuilder {
	builder.GetEmbeddedIPv4AddressParamsBuilder().AllowWildcardedSeparator(allow)
	builder.allowWildcardedSeparator(allow)
	return builder
}

// AllowLeadingZeros dictates whether to allow addresses with segments that have leasing zeros like "001.2.3.004" or "1:000a::".
// For IPV4, this option overrides inet_aton octal.
//
// Single segment addresses that must have the requisite length to be parsed are not affected by this flag.
func (builder *IPv6AddressStringParamsBuilder) AllowLeadingZeros(allow bool) *IPv6AddressStringParamsBuilder {
	builder.GetEmbeddedIPv4AddressParamsBuilder().allowLeadingZeros(allow)
	builder.allowLeadingZeros(allow)
	return builder
}

// AllowUnlimitedLeadingZeros dictates whether to allow leading zeros that extend segments
// beyond the usual segment length, which is 3 for IPv4 dotted-decimal and 4 for IPv6.
// However, this only takes effect if leading zeros are allowed, which is when
// AllowsLeadingZeros is true or the address is IPv4 and Allows_inet_aton_octal is true.
//
// For example, this determines whether you allow 0001.0002.0003.0004
func (builder *IPv6AddressStringParamsBuilder) AllowUnlimitedLeadingZeros(allow bool) *IPv6AddressStringParamsBuilder {
	builder.GetEmbeddedIPv4AddressParamsBuilder().AllowUnlimitedLeadingZeros(allow)
	builder.allowUnlimitedLeadingZeros(allow)
	return builder
}

// SetRangeParams populates this builder with the values from the given RangeParams.
func (builder *IPv6AddressStringParamsBuilder) SetRangeParams(rangeParams RangeParams) *IPv6AddressStringParamsBuilder {
	builder.GetEmbeddedIPv4AddressParamsBuilder().SetRangeParams(rangeParams)
	builder.setRangeParameters(rangeParams)
	return builder
}

// AllowPrefixesBeyondAddressSize dictates whether to allow prefix length values greater than 32 for IPv4 or greater than 128 for IPv6.
func (builder *IPv6AddressStringParamsBuilder) AllowPrefixesBeyondAddressSize(allow bool) *IPv6AddressStringParamsBuilder {
	builder.allowPrefixesBeyondAddressSize(allow)
	return builder
}

// AllowPrefixLenLeadingZeros dictates whether to allow leading zeros in the prefix length like "1.2.3.4/016".
func (builder *IPv6AddressStringParamsBuilder) AllowPrefixLenLeadingZeros(allow bool) *IPv6AddressStringParamsBuilder {
	builder.allowPrefixLengthLeadingZeros(allow)
	return builder
}

type ipv4AddressStringParameters struct {
	ipAddressStringFormatParameters

	no_inet_aton_hex,
	no_inet_aton_octal,
	no_inet_aton_joinedSegments,
	inet_aton_single_segment_mask,
	no_inet_aton_leading_zeros bool
}

// Allows_inet_aton_hex allows IPv4 inet_aton hexadecimal format "0xa.0xb.0xc.0cd".
func (params *ipv4AddressStringParameters) Allows_inet_aton_hex() bool {
	return !params.no_inet_aton_hex
}

// Allows_inet_aton_octal allows IPv4 inet_aton octal format, "04.05.06.07" being an example.
// Can be overridden by AllowLeadingZeros
func (params *ipv4AddressStringParameters) Allows_inet_aton_octal() bool {
	return !params.no_inet_aton_octal
}

// Allows_inet_aton_joinedSegments allows IPv4 joined segments like "1.2.3", "1.2', or just "1".
//
// For the case of just 1 segment, the behaviour is controlled by allowSingleSegment
func (params *ipv4AddressStringParameters) Allows_inet_aton_joinedSegments() bool {
	return !params.no_inet_aton_joinedSegments
}

// Allows_inet_aton_single_segment_mask indicates whether you allow a mask that looks like a prefix length when you allow IPv4 joined segments: "1.2.3.5/255".
func (params *ipv4AddressStringParameters) Allows_inet_aton_single_segment_mask() bool {
	return params.inet_aton_single_segment_mask
}

// Allows_inet_aton_leading_zeros allows IPv4 inet_aton hexadecimal or octal to have leading zeros, such as in the first two segments of "0x0a.00b.c.d".
// The first 0 is not considered a leading zero, it either denotes octal or hex depending on whether it is followed by an 'x'.
// Zeros that appear afterwards are inet_aton leading zeros.
func (params *ipv4AddressStringParameters) Allows_inet_aton_leading_zeros() bool {
	return !params.no_inet_aton_leading_zeros
}

// IPv4AddressStringParamsBuilder builds an immutable IPv4AddressStringParams for controlling parsing of IPv4 address strings.
type IPv4AddressStringParamsBuilder struct {
	// This is not anonymous since it clashes with IPAddressStringFormatParamsBuilder,
	// both have ipAddressStringFormatParameters and AddressStringFormatParams
	// IPAddressStringFormatParamsBuilder takes precedence
	params ipv4AddressStringParameters

	IPAddressStringFormatParamsBuilder

	mixedParent *IPv6AddressStringParamsBuilder
}

// ToParams returns an immutable IPv4AddressStringParams instance built by this builder.
func (builder *IPv4AddressStringParamsBuilder) ToParams() IPv4AddressStringParams {
	result := &builder.params
	result.ipAddressStringFormatParameters = *builder.IPAddressStringFormatParamsBuilder.ToParams().(*ipAddressStringFormatParameters)
	return result
}

// GetEmbeddedIPv4AddressParentBuilder the parent IPv6AddressStringParamsBuilder,
// if this builder was obtained by a call to getEmbeddedIPv4ParamsBuilder() from IPv6AddressStringParamsBuilder.
func (builder *IPv4AddressStringParamsBuilder) GetEmbeddedIPv4AddressParentBuilder() *IPv6AddressStringParamsBuilder {
	return builder.mixedParent
}

// GetRangeParamsBuilder returns a builder that builds the range parameters for these IPv4 address string parameters.
func (builder *IPv4AddressStringParamsBuilder) GetRangeParamsBuilder() *RangeParamsBuilder {
	result := &builder.rangeParamsBuilder
	result.parent = builder
	return result
}

// Set populates this builder with the values from the given IPv4AddressStringParams.
func (builder *IPv4AddressStringParamsBuilder) Set(params IPv4AddressStringParams) *IPv4AddressStringParamsBuilder {
	if p, ok := params.(*ipv4AddressStringParameters); ok {
		builder.params = *p
	} else {
		builder.params = ipv4AddressStringParameters{
			no_inet_aton_hex:              !params.Allows_inet_aton_hex(),
			no_inet_aton_octal:            !params.Allows_inet_aton_octal(),
			no_inet_aton_joinedSegments:   !params.Allows_inet_aton_joinedSegments(),
			inet_aton_single_segment_mask: params.Allows_inet_aton_single_segment_mask(),
			no_inet_aton_leading_zeros:    !params.Allows_inet_aton_leading_zeros(),
		}
	}
	builder.IPAddressStringFormatParamsBuilder.set(params)
	return builder
}

// Allow_inet_aton dictates whether to allow any IPv4 inet_aton format, whether hex, octal, or joined segments.
func (builder *IPv4AddressStringParamsBuilder) Allow_inet_aton(allow bool) *IPv4AddressStringParamsBuilder {
	builder.params.no_inet_aton_joinedSegments = !allow
	builder.params.no_inet_aton_octal = !allow
	builder.params.no_inet_aton_hex = !allow
	builder.allowUnlimitedLeadingZeros(allow)
	return builder
}

// Allow_inet_aton_hex dictates whether to allow IPv4 inet_aton hexadecimal format "0xa.0xb.0xc.0cd".
func (builder *IPv4AddressStringParamsBuilder) Allow_inet_aton_hex(allow bool) *IPv4AddressStringParamsBuilder {
	builder.params.no_inet_aton_hex = !allow
	return builder
}

// Allow_inet_aton_octal dictates whether to allow IPv4 inet_aton octal format, "04.05.06.07" being an example.
func (builder *IPv4AddressStringParamsBuilder) Allow_inet_aton_octal(allow bool) *IPv4AddressStringParamsBuilder {
	builder.params.no_inet_aton_octal = !allow
	return builder
}

// Allow_inet_aton_leading_zeros dictates whether to allow IPv4 inet_aton hexadecimal or octal to have leading zeros, such as in the first two segments of "0x0a.00b.c.d".
//	The first 0 is not considered a leading zero, it either denotes octal or hex depending on whether it is followed by an 'x'.
//	Zeros that appear afterwards are inet_aton leading zeros.
func (builder *IPv4AddressStringParamsBuilder) Allow_inet_aton_leading_zeros(allow bool) *IPv4AddressStringParamsBuilder {
	builder.params.no_inet_aton_leading_zeros = !allow
	return builder
}

// Allow_inet_aton_joinedSegments dictates whether to allow IPv4 joined segments like "1.2.3", "1.2", or just "1".
//
// For the case of just 1 segment, the behaviour is controlled by AllowSingleSegment.
func (builder *IPv4AddressStringParamsBuilder) Allow_inet_aton_joinedSegments(allow bool) *IPv4AddressStringParamsBuilder {
	builder.params.no_inet_aton_joinedSegments = !allow
	return builder
}

// Allow_inet_aton_single_segment_mask dictates whether to allow a mask that looks like a prefix length when you allow IPv4 joined segments: "1.2.3.5/255".
func (builder *IPv4AddressStringParamsBuilder) Allow_inet_aton_single_segment_mask(allow bool) *IPv4AddressStringParamsBuilder {
	builder.params.inet_aton_single_segment_mask = allow
	return builder
}

// AllowWildcardedSeparator dictates whether the wildcard '*' or '%' can replace the segment separators '.' and ':'.
// If so, then you can write addresses like *.* or *:*
func (builder *IPv4AddressStringParamsBuilder) AllowWildcardedSeparator(allow bool) *IPv4AddressStringParamsBuilder {
	builder.allowWildcardedSeparator(allow)
	return builder
}

// AllowLeadingZeros dictates whether to allow addresses with segments that have leasing zeros like "001.2.3.004" or "1:000a::".
// For IPV4, this option overrides inet_aton octal.
//
// Single segment addresses that must have the requisite length to be parsed are not affected by this flag.
func (builder *IPv4AddressStringParamsBuilder) AllowLeadingZeros(allow bool) *IPv4AddressStringParamsBuilder {
	builder.allowLeadingZeros(allow)
	return builder
}

// AllowUnlimitedLeadingZeros dictates whether to allow leading zeros that extend segments
// beyond the usual segment length, which is 3 for IPv4 dotted-decimal and 4 for IPv6.
// However, this only takes effect if leading zeros are allowed, which is when
// AllowsLeadingZeros is true or the address is IPv4 and Allows_inet_aton_octal is true.
//
// For example, this determines whether you allow "0001.0002.0003.0004">
func (builder *IPv4AddressStringParamsBuilder) AllowUnlimitedLeadingZeros(allow bool) *IPv4AddressStringParamsBuilder {
	builder.allowUnlimitedLeadingZeros(allow)
	return builder
}

// SetRangeParams populates this builder with the values from the given RangeParams.
func (builder *IPv4AddressStringParamsBuilder) SetRangeParams(rangeParams RangeParams) *IPv4AddressStringParamsBuilder {
	builder.setRangeParameters(rangeParams)
	return builder
}

// AllowPrefixesBeyondAddressSize dictates whether to allow prefix length values greater than 32 for IPv4 or greater than 128 for IPv6.
func (builder *IPv4AddressStringParamsBuilder) AllowPrefixesBeyondAddressSize(allow bool) *IPv4AddressStringParamsBuilder {
	builder.allowPrefixesBeyondAddressSize(allow)
	return builder
}

// AllowPrefixLenLeadingZeros dictates whether to allow leading zeros in the prefix length like "1.2.3.4/016".
func (builder *IPv4AddressStringParamsBuilder) AllowPrefixLenLeadingZeros(allow bool) *IPv4AddressStringParamsBuilder {
	builder.allowPrefixLengthLeadingZeros(allow)
	return builder
}

// AllowBinary dictates whether to allow binary addresses like "11111111.0.1.0" or "1111111111111111::".
func (builder *IPv4AddressStringParamsBuilder) AllowBinary(allow bool) *IPv4AddressStringParamsBuilder {
	builder.allowBinary(allow)
	return builder
}

// IPVersion is the version type used by IP string parameters.
// It is interchangeable with the ipaddr.Version, the more generic version type used by the library as a whole.
type IPVersion string

const (
	// IndeterminateIPVersion represents an unspecified IP address version.
	IndeterminateIPVersion IPVersion = ""

	// IPv4 represents Internet Protocol version 4.
	IPv4 IPVersion = "IPv4"

	// IPv6 represents Internet Protocol version 6.
	IPv6 IPVersion = "IPv6"
)

// IsIPv6 returns true if this represents version 6.
func (version IPVersion) IsIPv6() bool {
	return strings.EqualFold(string(version), string(IPv6))
}

// IsIPv4 returns true if this represents version 4.
func (version IPVersion) IsIPv4() bool {
	return strings.EqualFold(string(version), string(IPv4))
}

// IsIndeterminate returns true if this represents an unspecified IP address version.
func (version IPVersion) IsIndeterminate() bool {
	if len(version) == 4 {
		// we allow mixed case in the event code is converted a string to IPVersion
		dig := version[3]
		return (dig != '4' && dig != '6') || !strings.EqualFold(string(version[:3]), "IPv")
	}
	return true
}

// String returns "IPv4", "IPv6", or the zero-value "" representing an indeterminate version.
func (version IPVersion) String() string {
	return string(version)
}