Skip to content

Commit

Permalink
adjusted framework to consolidate prefix methods, minor code clean-ups
Browse files Browse the repository at this point in the history
  • Loading branch information
seancfoley committed Jan 3, 2023
1 parent 01109b8 commit 2cb73d9
Show file tree
Hide file tree
Showing 19 changed files with 113 additions and 68 deletions.
2 changes: 1 addition & 1 deletion ipaddr/addrstr/stringopts.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
Package addrstr provides interfaces for specifying how to create specific strings from addresses and address sections,
as well as builder types to construct instances of those interfaces.
For example, StringOptionsBuilder produces instances implementing StringOptions for specifiying generic strings.
For example, StringOptionsBuilder produces instances implementing StringOptions for specifying generic strings.
More specific builders and corresponding interface types exist for more specific address versions and types.
Each instance produced by a builders is immutable.
Expand Down
14 changes: 11 additions & 3 deletions ipaddr/addrtrienode.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,19 @@ import (
)

// TrieKeyConstraint is the generic type constraint used for tree keys, which are individual addresses and prefix block subnets.
type TrieKeyConstraint[T AddressType] interface {
type TrieKeyConstraint[T any] interface {
comparable
AddressType

ToPrefixBlockLen(prefLen BitCount) T
BitItem

fmt.Stringer

PrefixedConstraint[T]

IsOneBit(index BitCount) bool // AddressComponent

ToAddressBase() *Address // AddressType - used by MatchBits

toMaxLower() T
toMinUpper() T
trieCompare(other *Address) int
Expand Down
1 change: 0 additions & 1 deletion ipaddr/allocator.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ type PrefixBlockConstraint[T any] interface {
SequentialRangeConstraint[T]

MergeToPrefixBlocks(...T) []T
SetPrefixLen(BitCount) T
PrefixBlockIterator() Iterator[T]
}

Expand Down
10 changes: 6 additions & 4 deletions ipaddr/cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,16 +249,18 @@ func main() {
addrStrPref := ipaddr.NewIPAddressString("1.2-11.0.0/15")
pAddr = addrStrPref.GetAddress()
newIter := pAddr.GetSection().PrefixBlockIterator()
fmt.Printf("\nto iterate: %+v", pAddr)
fmt.Printf("\niterate prefix blocks (prefix len 15):\n")
fmt.Println()
fmt.Printf("to iterate: %+v", pAddr)
fmt.Println("iterate prefix blocks (prefix len 15):")
for newIter.HasNext() {
fmt.Printf("%v ", newIter.Next())
}
addrStrPref = ipaddr.NewIPAddressString("1.2-11.0.0/16")
pAddr = addrStrPref.GetAddress()
fmt.Printf("\nto iterate: %+v", pAddr)
fmt.Println()
fmt.Printf("to iterate: %+v", pAddr)
newIter = pAddr.GetSection().BlockIterator(2)
fmt.Printf("\niterate a section's first two blocks:\n")
fmt.Println("iterate a section's first two blocks:")
for newIter.HasNext() {
fmt.Printf("%v ", newIter.Next())
}
Expand Down
12 changes: 6 additions & 6 deletions ipaddr/delimitedaddrstrs.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,14 @@ func (str DelimitedAddressString) ParseDelimitedSegments() Iterator[string] {
s := string(str)
for i := 0; i < strlen; i++ {
c := str[i]
if isDelimitedBoundary(c) {
if delimitedList != nil {
if isDelimitedBoundary(c) { // end of segment or range boundary
if len(delimitedList) > 0 {
if parts == nil {
parts = make([][]string, 0, IPv6SegmentCount)
}
parts, delimitedList = addParts(s, parts, lastSegmentStartIndex, lastPartIndex, lastDelimiterIndex, delimitedList, i)
parts, _ = addParts(s, parts, lastSegmentStartIndex, lastPartIndex, lastDelimiterIndex, delimitedList, i)
lastPartIndex = i
delimitedList = nil
delimitedList = delimitedList[:0]
}
lastDelimiterIndex = i + 1
lastSegmentStartIndex = lastDelimiterIndex
Expand All @@ -93,11 +93,11 @@ func (str DelimitedAddressString) ParseDelimitedSegments() Iterator[string] {
}
}
if anyDelimited {
if delimitedList != nil {
if len(delimitedList) > 0 {
if parts == nil {
parts = make([][]string, 0, IPv6SegmentCount)
}
parts, delimitedList = addParts(s, parts, lastSegmentStartIndex, lastPartIndex, lastDelimiterIndex, delimitedList, len(str))
parts, _ = addParts(s, parts, lastSegmentStartIndex, lastPartIndex, lastDelimiterIndex, delimitedList, len(str))
} else {
parts = append(parts, []string{s[lastPartIndex:]})
}
Expand Down
1 change: 0 additions & 1 deletion ipaddr/division.go
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,6 @@ func (div *addressDivisionInternal) toNetworkDivision(divPrefixLength PrefixLen,
return div.toAddressDivision()
}
} else {
withPrefixLength = false
divPrefixLength = nil
if div.getDivisionPrefixLength() == nil {
return div.toAddressDivision()
Expand Down
82 changes: 53 additions & 29 deletions ipaddr/framework.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import (
"github.com/seancfoley/ipaddress-go/ipaddr/addrerr"
)

type bitItem interface {
type BitItem interface {
// GetByteCount returns the number of bytes required for each value comprising this address item,
// rounding up if the bit count is not a multiple of 8.
GetByteCount() int
Expand All @@ -37,12 +37,7 @@ type bitItem interface {
// AddressItem represents all addresses, division groupings, divisions, and sequential ranges.
// Any address item can be compared to any other.
type AddressItem interface {
// GetByteCount returns the number of bytes required for each value comprising this address item,
// rounding up if the bit count is not a multiple of 8.
GetByteCount() int

// GetBitCount returns the number of bits in each value comprising this address item.
GetBitCount() BitCount
BitItem

// GetValue returns the lowest individual address item in the address item range as an integer value.
GetValue() *big.Int
Expand Down Expand Up @@ -138,6 +133,56 @@ type AddressItem interface {
fmt.Stringer
}

type Prefixed interface {
// IsPrefixed returns whether this item has an associated prefix length.
IsPrefixed() bool

// GetPrefixLen returns the prefix length, or nil if there is no prefix length.
//
// A prefix length indicates the number of bits in the initial part (most significant bits) of the series that comprise the prefix.
//
// A prefix is a part of the series that is not specific to that series but common amongst a group, such as a CIDR prefix block subnet.
GetPrefixLen() PrefixLen

// IsPrefixBlock returns whether this item has a prefix length and includes the block associated with that prefix length.
// If the prefix length matches the bit count, this returns true.
//
// This is different from ContainsPrefixBlock in that this method returns
// false if this item has no prefix length, or it has a prefix length that differs from a prefix length for which ContainsPrefixBlock returns true.
IsPrefixBlock() bool

// IsSinglePrefixBlock returns whether the range of values matches a single subnet block for the prefix length.
//
// This is different from ContainsSinglePrefixBlock in that this method returns
// false if this series has no prefix length or a prefix length that differs from a prefix length for which ContainsSinglePrefixBlock returns true.
IsSinglePrefixBlock() bool
}

type PrefixedConstraint[T any] interface {
Prefixed

// WithoutPrefixLen provides the same item but with no prefix length. The values remain unchanged.
WithoutPrefixLen() T

// ToPrefixBlock returns the item whose prefix matches the prefix of this item, while the remaining bits span all values.
// If this item has no prefix length, then this item is returned.
//
// The returned item will include all items with the same prefix as this item, known as the prefix "block".
ToPrefixBlock() T

// ToPrefixBlockLen returns the item associated with the prefix length provided,
// the item whose prefix of that length matches the prefix of that length in this item, and the remaining bits span all values.
//
// The returned address will include all items with the same prefix as this one, known as the prefix "block".
ToPrefixBlockLen(BitCount) T

// SetPrefixLen sets the prefix length, returning a new item with the same values but with the new prefix length.
//
// A prefix length will not be set to a value lower than zero or beyond the bit length of the item.
// The provided prefix length will be adjusted to these boundaries if necessary.
SetPrefixLen(BitCount) T
}

// AddressDivisionSeries serves as a common interface to all division groupings, address sections, and addresses.
type AddressDivisionSeries interface {
AddressItem
Expand Down Expand Up @@ -166,28 +211,7 @@ type AddressDivisionSeries interface {
// Generally, this means that any division covering a range of values must be followed by divisions that are full range, covering all values.
IsSequential() bool

// IsPrefixBlock returns whether this address division series has a prefix length and includes the block associated with its prefix length.
// If the prefix length matches the bit count, this returns true.
//
// This is different from ContainsPrefixBlock in that this method returns
// false if the series has no prefix length, or a prefix length that differs from a prefix length for which ContainsPrefixBlock returns true.
IsPrefixBlock() bool

// IsSinglePrefixBlock returns whether the range of values matches a single subnet block for the prefix length.
//
// This is different from ContainsSinglePrefixBlock in that this method returns
// false if this series has no prefix length or a prefix length that differs from a prefix length for which ContainsSinglePrefixBlock returns true.
IsSinglePrefixBlock() bool

// IsPrefixed returns whether this address has an associated prefix length.
IsPrefixed() bool

// GetPrefixLen returns the prefix length, or nil if there is no prefix length.
//
// A prefix length indicates the number of bits in the initial part (most significant bits) of the series that comprise the prefix.
//
// A prefix is a part of the series that is not specific to that series but common amongst a group, such as a CIDR prefix block subnet.
GetPrefixLen() PrefixLen
Prefixed

// GetGenericDivision returns the division at the given index as a DivisionType.
// The first division is at index 0.
Expand Down
2 changes: 1 addition & 1 deletion ipaddr/groupingbase.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ func (grouping *addressDivisionGroupingBase) isMultiple() bool {
}

// hasNoDivisions() returns whether this grouping is the zero grouping,
// which is what you get when contructing a grouping or section with no divisions
// which is what you get when constructing a grouping or section with no divisions
func (grouping *addressDivisionGroupingBase) hasNoDivisions() bool {
divisions := grouping.divisions
return divisions == nil || divisions.getDivisionCount() == 0
Expand Down
2 changes: 1 addition & 1 deletion ipaddr/ipsection.go
Original file line number Diff line number Diff line change
Expand Up @@ -2459,7 +2459,7 @@ func createSegments(
segments = createSegmentArray(segmentCount)
for segmentIndex := 0; segmentIndex < segmentCount; segmentIndex++ {
segmentPrefixLength := getSegmentPrefixLength(bitsPerSegment, prefixLength, segmentIndex)
var value, value2 SegInt = 0, 0
var value, value2 SegInt
if lowerValueProvider == nil {
value = upperValueProvider(segmentIndex)
value2 = value
Expand Down
20 changes: 15 additions & 5 deletions ipaddr/ipseqrange.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@ type SequentialRangeConstraint[T any] interface {

ToIP() *IPAddress

PrefixedConstraint[T]

Increment(int64) T
WithoutPrefixLen() T
GetLower() T
GetUpper() T
ToPrefixBlockLen(BitCount) T

CoverWithPrefixBlockTo(T) T
SpanWithPrefixBlocksTo(T) []T
Expand Down Expand Up @@ -1011,6 +1011,7 @@ func newSequRange[T SequentialRangeConstraint[T]](first, other T) *SequentialRan
upper = lower
}
} else {
// We find the lowest and the highest from both supplied addresses
firstLower := first.GetLower()
otherLower := other.GetLower()
firstUpper := first.GetUpper()
Expand All @@ -1026,14 +1027,23 @@ func newSequRange[T SequentialRangeConstraint[T]](first, other T) *SequentialRan
isMult = true
upper = otherUpper
} else {
isMult = comp > 0
isMult = isMult || comp > 0
upper = firstUpper
}
lower = lower.WithoutPrefixLen()
if isMult = isMult || compareLowIPAddressValues(lower, upper) != 0; isMult {
lower = lower.WithoutPrefixLen()
upper = upper.WithoutPrefixLen()
} else {
upper = lower
if lower.IsPrefixed() {
if upper.IsPrefixed() {
lower = lower.WithoutPrefixLen()
upper = lower
} else {
lower = upper
}
} else {
upper = lower
}
}
}
return newSequRangeUnchecked(lower, upper, isMult)
Expand Down
4 changes: 2 additions & 2 deletions ipaddr/macsection.go
Original file line number Diff line number Diff line change
Expand Up @@ -486,12 +486,12 @@ func (section *MACAddressSection) GetUpper() *MACAddressSection {
return section.getUpper().ToMAC()
}

// Uint64Value returns the lowest indiviudal address section in the address section collection as a uint64.
// Uint64Value returns the lowest individual address section in the address section collection as a uint64.
func (section *MACAddressSection) Uint64Value() uint64 {
return section.getLongValue(true)
}

// UpperUint64Value returns the highest indiviudal address section in the address section collection as a uint64.
// UpperUint64Value returns the highest individual address section in the address section collection as a uint64.
func (section *MACAddressSection) UpperUint64Value() uint64 {
return section.getLongValue(false)
}
Expand Down
6 changes: 4 additions & 2 deletions ipaddr/partition.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@ func (part *Partition[T]) predicateForAny(predicate func(address T) bool, return
type SpanPartitionConstraint[T any] interface {
AddressDivisionSeries

WithoutPrefixLen() T
PrefixedConstraint[T]

SpanWithPrefixBlocks() []T
}

Expand Down Expand Up @@ -238,7 +239,8 @@ func PartitionIPv4WithSingleBlockSize(newAddr *IPv4Address) *Partition[*IPv4Addr
type IteratePartitionConstraint[T any] interface {
AddressDivisionSeries

WithoutPrefixLen() T
PrefixedConstraint[T]

AssignMinPrefixForBlock() T
PrefixBlockIterator() Iterator[T]
Iterator() Iterator[T]
Expand Down
5 changes: 2 additions & 3 deletions ipaddr/test/ipaddrrangetest.go
Original file line number Diff line number Diff line change
Expand Up @@ -3231,7 +3231,7 @@ func (t ipAddressRangeTester) testMerge2Impl(result, result2 string, prefix bool
//got [1:2:3:4:0-3fff:*:*:* 1:2:3:6:*:*:*:*]
if len(merged3) != 2 || !ipaddr.AddrsMatchOrdered(merged, merged3) {
t.addFailure(newIPAddrFailure("merge prefix mismatch merging "+strings.Join(addresses, ",")+" expected "+asSliceString(expected)+" got "+asSliceString(merged3), resultAddr))
merged3 = getMergedPrefixBlocksAltRange(joinAddrToAddresses(mergers, addr2))
//merged3 = getMergedPrefixBlocksAltRange(joinAddrToAddresses(mergers, addr2))
}
if len(merged4) != 2 || !ipaddr.AddrsMatchOrdered(merged, merged4) {
t.addFailure(newIPAddrFailure("merge prefix mismatch merging "+strings.Join(addresses, ",")+" expected "+asSliceString(expected)+" got "+asSliceString(merged4), resultAddr))
Expand Down Expand Up @@ -3493,8 +3493,7 @@ func (t ipAddressRangeTester) testInetAtonCombos(w *ipaddr.IPAddressString, ipAd
} else {
origStr := str
count := 0
pos := -1
for pos = strings.IndexByte(str, ipaddr.IPv4SegmentSeparator); pos >= 0 && pos < len(str); {
for pos := strings.IndexByte(str, ipaddr.IPv4SegmentSeparator); pos >= 0 && pos < len(str); {
//for ((pos = str.indexOf(ipaddr.IPv4SegmentSeparator)) >= 0){
str = str[pos+1:]
pos = strings.IndexByte(str, ipaddr.IPv4SegmentSeparator)
Expand Down
2 changes: 1 addition & 1 deletion ipaddr/test/macaddrrangetest.go
Original file line number Diff line number Diff line change
Expand Up @@ -716,7 +716,7 @@ func (t macAddressRangeTester) testMACPrefixCountImpl(w *ipaddr.MACAddressString
}

func (t macAddressRangeTester) testPrefixBlock(prefixedAddressStr string, expectedPref ipaddr.BitCount) {
//starting with prefixed address like 1:2:3:*:*:*, get lower (whcih should retain prefix except for allsubnets)
//starting with prefixed address like 1:2:3:*:*:*, get lower (which should retain prefix except for allsubnets)
//check if prefix block (not), then for all subnets assign prefix, then for all call toPrefixBlock, compare with original and also the prefix
prefixedAddressString := t.createMACAddress(prefixedAddressStr)
prefixedAddress := prefixedAddressString.GetAddress()
Expand Down
2 changes: 1 addition & 1 deletion ipaddr/test/macaddrtest.go
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,7 @@ func (t macAddressTester) testMACValuesBig(segs []int, decimal, negativeDecimal
addr[i] = t.createMACAddress(strb.String()).GetAddress()
i++
addr[i] = t.createMACAddressFromUint64(longval, len(segs) == 8)
i++
//i++
for j := 0; j < len(addr); j++ {
for k := j; k < len(addr); k++ {
if !addr[k].Equal(addr[j]) || !addr[j].Equal(addr[k]) {
Expand Down
5 changes: 3 additions & 2 deletions ipaddr/test/specialtypestest.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,10 +220,11 @@ func (t specialTypesTester) testIPv6Strings(addr string,
}

func (t specialTypesTester) testEmptyValues() {
//zeroHostOptions := new(ipaddr.HostNameParamsBuilder).ParseEmptyStrAs(ipaddr.LoopbackOption).ToParams()
t.testEmptyValuesOpts(hostOptionsSpecial, addressOptionsSpecial)

zeroHostOptions := new(addrstrparam.HostNameParamsBuilder).GetIPAddressParamsBuilder().ParseEmptyStrAs(addrstrparam.LoopbackOption).GetParentBuilder().ToParams()
zeroAddrOptions := new(addrstrparam.IPAddressStringParamsBuilder).ParseEmptyStrAs(addrstrparam.LoopbackOption).ToParams()
t.testEmptyValuesOpts(hostOptionsSpecial, addressOptionsSpecial)
t.testEmptyValuesOpts(zeroHostOptions, zeroAddrOptions)

zeroHostOptions = new(addrstrparam.HostNameParamsBuilder).GetIPAddressParamsBuilder().ParseEmptyStrAs(addrstrparam.ZeroAddressOption).GetParentBuilder().ToParams()
zeroAddrOptions = new(addrstrparam.IPAddressStringParamsBuilder).ParseEmptyStrAs(addrstrparam.ZeroAddressOption).ToParams()
Expand Down
4 changes: 2 additions & 2 deletions ipaddr/test/trietest.go
Original file line number Diff line number Diff line change
Expand Up @@ -858,7 +858,7 @@ func (t trieTesterGeneric) testIterationContainmentTree(

func (t trieTesterGeneric) testIterate(tree *AddressTrie) {

type triePtr = (*AddressTrie)
type triePtr = *AddressTrie
t.testIteratorRem(tree, func(trie *AddressTrie) ipaddr.IteratorWithRemove[*AddressTrieNode] {
return trie.BlockSizeNodeIterator(true)
}, triePtr.Size)
Expand Down Expand Up @@ -1368,7 +1368,7 @@ func (t trieTesterGeneric) testMap(trie *ipaddr.AssociativeTrie[*ipaddr.Address,
if !reflect.DeepEqual(v, expected) { //reflect deep equal
//fmt.Println(trie)
t.addFailure(newAssocTrieFailure(fmt.Sprintf("got mismatch, got %v, not %v for %v", v, expected, addr), trie))
v, _ = trie.Get(addr)
//v, _ = trie.Get(addr)
}
}
// all trie2 from now on
Expand Down
2 changes: 1 addition & 1 deletion ipaddr/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ func bigAbsIsOne(val *BigDivInt) bool {
return len(bits) == 1 && bits[0] == 1
}

func checkSubnet(item bitItem, prefixLength BitCount) BitCount {
func checkSubnet(item BitItem, prefixLength BitCount) BitCount {
return checkBitCount(prefixLength, item.GetBitCount())
}

Expand Down
Loading

0 comments on commit 2cb73d9

Please sign in to comment.