From 417c904022813713c2792a037b59cf3c2f8c13d0 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Sat, 7 Oct 2023 00:00:21 -0700 Subject: [PATCH 01/27] stable release prep --- asn.go | 151 +++++++++++++++++++++++---------------------------- asn_test.go | 98 +++++++++++++++++++++++++++++++-- doc_test.go | 2 +- dot_test.go | 47 ++++++++++++++++ misc.go | 53 ++++++++++++++++++ nanf.go | 73 +++++++------------------ nanf_test.go | 75 +++++++++++++++++++++++++ nf.go | 46 ++++++++-------- oid.go | 111 ++++++++++++++++++------------------- oid_test.go | 20 ++++++- 10 files changed, 451 insertions(+), 225 deletions(-) diff --git a/asn.go b/asn.go index 3e67c1c..56132fb 100644 --- a/asn.go +++ b/asn.go @@ -52,11 +52,12 @@ func (a ASN1Notation) Len() int { return len(a) } IsZero returns a boolean indicative of whether the receiver is unset. */ -func (a ASN1Notation) IsZero() bool { - if &a == nil { - return true +func (a ASN1Notation) IsZero() (is bool) { + if is = &a == nil; !is { + is = a.Len() == 0 } - return a.Len() == 0 + + return } /* @@ -68,21 +69,19 @@ func (a ASN1Notation) Index(idx int) (nanf NameAndNumberForm, ok bool) { L := a.Len() // Bail if receiver is empty. - if L == 0 { - return - } - - if idx < 0 { - var x int = L + idx - if x < 0 { - nanf = a[0] + if L > 0 { + if idx < 0 { + var x int = L + idx + if x < 0 { + nanf = a[0] + } else { + nanf = a[x] + } + } else if idx > L { + nanf = a[L-1] } else { - nanf = a[x] + nanf = a[idx] } - } else if idx > L { - nanf = a[L-1] - } else { - nanf = a[idx] } // Make sure the instance was produced @@ -104,39 +103,37 @@ func NewASN1Notation(x any) (a *ASN1Notation, err error) { // prepare temporary instance t := new(ASN1Notation) + var nfs []string switch tv := x.(type) { case string: - f := fields(condenseWHSP(trimR(trimL(tv, `{`), `}`))) - for i := 0; i < len(f); i++ { - var nanf *NameAndNumberForm - if nanf, err = NewNameAndNumberForm(f[i]); err != nil { - return - } - *t = append(*t, *nanf) - } + nfs = fields(condenseWHSP(trimR(trimL(tv, `{`), `}`))) case []string: - for i := 0; i < len(tv); i++ { - var nanf *NameAndNumberForm - if nanf, err = NewNameAndNumberForm(condenseWHSP(tv[i])); err != nil { - return - } - *t = append(*t, *nanf) - } + nfs = tv default: err = errorf("Unsupported %T input type: %#v\n", x, x) return } - // verify content is valid - if !t.Valid() { - err = errorf("%T instance did not pass validity checks: %#v", t, *t) + for i := 0; i < len(nfs) && err == nil; i++ { + var nanf *NameAndNumberForm + if nanf, err = NewNameAndNumberForm(nfs[i]); nanf != nil { + *t = append(*t, *nanf) + } + } + + if err != nil { return } - // transfer temporary content - // to return value instance. - a = new(ASN1Notation) - *a = *t + // verify content is valid + err = errorf("%T instance did not pass validity checks: %#v", t, *t) + if t.Valid() { + // transfer temporary content + // to return value instance. + a = new(ASN1Notation) + *a = *t + err = nil + } return } @@ -145,28 +142,25 @@ func NewASN1Notation(x any) (a *ASN1Notation, err error) { Valid returns a boolean value indicative of whether the receiver's length is greater than or equal to one (1) slice member. */ -func (a ASN1Notation) Valid() bool { +func (a ASN1Notation) Valid() (is bool) { // Don't waste time on // zero instances. - if a.Len() == 0 { - return false - } - - // bail out if any of the slice - // values are unparsed. - for i := 0; i < a.Len(); i++ { - if !a[i].parsed { - return false + if L := a.Len(); L > 0 { + // bail out if any of the slice + // values are unparsed. + for i := 0; i < L; i++ { + if !a[i].parsed { + return false + } } - } - root, ok := a.Index(0) - if !ok { - return false + if root, ok := a.Index(0); ok { + // root cannot be greater than 2 + is = root.NumberForm().Lt(3) + } } - // root cannot be greater than 2 - return root.NumberForm().Lt(3) + return } /* @@ -177,12 +171,10 @@ Empty slices of DotNotation are returned if the dotNotation value within the receiver is less than two (2) NumberForm values in length. */ func (a ASN1Notation) Ancestry() (anc []ASN1Notation) { - if a.Len() < 2 { - return - } - - for i := a.Len(); i > 0; i-- { - anc = append(anc, a[:i]) + if a.Len() >= 2 { + for i := a.Len(); i > 0; i-- { + anc = append(anc, a[:i]) + } } return @@ -195,23 +187,18 @@ subordinate value. This creates a fully-qualified child ASN1Notation value of the receiver. */ func (a ASN1Notation) NewSubordinate(nanf any) *ASN1Notation { - // Don't bother processing - if a.Len() == 0 { - return nil - } - - // Prepare the new leaf numberForm, - // or die trying. - n, err := NewNameAndNumberForm(nanf) - if err != nil { - return nil - } - - A := make(ASN1Notation, a.Len()+1, a.Len()+1) - for i := 0; i < a.Len(); i++ { - A[i] = a[i] + var A ASN1Notation + if a.Len() > 0 { + // Prepare the new leaf numberForm, + // or die trying. + if n, err := NewNameAndNumberForm(nanf); err == nil { + A = make(ASN1Notation, a.Len()+1, a.Len()+1) + for i := 0; i < a.Len(); i++ { + A[i] = a[i] + } + A[A.Len()-1] = *n + } } - A[A.Len()-1] = *n return &A } @@ -234,15 +221,13 @@ func (a ASN1Notation) AncestorOf(asn any) bool { return false } case *ASN1Notation: - if tv == nil { - return false + if tv != nil { + A = tv } - A = tv case ASN1Notation: - if tv.Len() == 0 { - return false + if tv.Len() >= 0 { + A = &tv } - A = &tv default: return false } diff --git a/asn_test.go b/asn_test.go index 0607dc0..08fe8b5 100644 --- a/asn_test.go +++ b/asn_test.go @@ -1,6 +1,7 @@ package objectid import ( + "fmt" "testing" ) @@ -10,10 +11,89 @@ const ( testASN1Bogus = `iso(1) identified-organization(3}` ) +func ExampleASN1Notation_Index() { + aNot, err := NewASN1Notation(`{iso(1) identified-organization(3) dod(6) internet(1) private(4) enterprise(1) 56521 example(999)}`) + if err != nil { + fmt.Println(err) + return + } + + nanf, _ := aNot.Index(1) + fmt.Printf("%s", nanf) + // Output: identified-organization(3) +} + +func ExampleASN1Notation_Leaf() { + aNot, err := NewASN1Notation(`{iso(1) identified-organization(3) dod(6) internet(1) private(4) enterprise(1) 56521 example(999)}`) + if err != nil { + fmt.Println(err) + return + } + + fmt.Printf("%s", aNot.Leaf()) + // Output: example(999) +} + +func ExampleASN1Notation_Parent() { + aNot, err := NewASN1Notation(`{iso(1) identified-organization(3) dod(6) internet(1) private(4) enterprise(1) 56521 example(999)}`) + if err != nil { + fmt.Println(err) + return + } + + fmt.Printf("%s", aNot.Parent()) + // Output: 56521 +} + +func ExampleASN1Notation_String() { + aNot, err := NewASN1Notation(`{iso(1) identified-organization(3) dod(6) internet(1) private(4) enterprise(1) 56521 example(999)}`) + if err != nil { + fmt.Println(err) + return + } + + fmt.Printf("%s", aNot) + // Output: {iso(1) identified-organization(3) dod(6) internet(1) private(4) enterprise(1) 56521 example(999)} +} + +func ExampleASN1Notation_Root() { + aNot, err := NewASN1Notation(`{iso(1) identified-organization(3) dod(6) internet(1) private(4) enterprise(1) 56521 example(999)}`) + if err != nil { + fmt.Println(err) + return + } + + fmt.Printf("%s", aNot.Root()) + // Output: iso(1) +} + +func ExampleASN1Notation_Len() { + aNot, err := NewASN1Notation(`{iso(1) identified-organization(3) dod(6) internet(1) private(4) enterprise(1) 56521 example(999)}`) + if err != nil { + fmt.Println(err) + return + } + + fmt.Printf("Length: %d", aNot.Len()) + // Output: Length: 8 +} + +func ExampleASN1Notation_IsZero() { + var aNot ASN1Notation + fmt.Printf("Is Zero: %t", aNot.IsZero()) + // Output: Is Zero: true +} + +func ExampleASN1Notation_Valid() { + var aNot ASN1Notation + fmt.Printf("Is Valid: %t", aNot.Valid()) + // Output: Is Valid: false +} + func TestASN1Notation001(t *testing.T) { asn, err := NewASN1Notation(testASN1NotationISO) if err != nil { - t.Errorf("%s error: %s\n", t.Name(), err.Error()) + t.Errorf("%s error: %s", t.Name(), err.Error()) return } @@ -29,7 +109,7 @@ func TestASN1Notation001(t *testing.T) { func TestASN1Notation_Index(t *testing.T) { asn, err := NewASN1Notation(testASN1JesseExample) if err != nil { - t.Errorf("%s error: %s\n", t.Name(), err.Error()) + t.Errorf("%s error: %s", t.Name(), err.Error()) return } @@ -60,7 +140,7 @@ func TestASN1Notation_Index(t *testing.T) { func TestASN1Notation_bogus(t *testing.T) { if _, err := NewASN1Notation(testASN1Bogus); err == nil { - t.Errorf("%s successfully parsed bogus value; expected an error\n", t.Name()) + t.Errorf("%s successfully parsed bogus value; expected an error", t.Name()) return } } @@ -104,8 +184,16 @@ func TestASN1Notation_IsZero(t *testing.T) { } func TestASN1Notation_AncestorOf(t *testing.T) { - asn, _ := NewASN1Notation(`{joint-iso-itu-t(2) asn1(1)}`) - child, _ := NewASN1Notation(`{iso(1) identified-organization(3) dod(6) internet(1)}`) + asn, err := NewASN1Notation(`{joint-iso-itu-t(2) asn1(1)}`) + if err != nil { + t.Errorf("%s failed: %v", t.Name(), err) + return + } + child, err := NewASN1Notation(`{iso(1) identified-organization(3) dod(6) internet(1)}`) + if err != nil { + t.Errorf("%s failed: %v", t.Name(), err) + return + } if asn.AncestorOf(child) { t.Errorf("%s failed: ancestry check returned bogus result", t.Name()) diff --git a/doc_test.go b/doc_test.go index b72563e..bbcf336 100644 --- a/doc_test.go +++ b/doc_test.go @@ -11,7 +11,7 @@ func ExampleNewNumberForm() { fmt.Println(err) return } - fmt.Printf("%s\n", arc) + fmt.Printf("%s", arc) // Output: 987895962269883002155146617097157934 } diff --git a/dot_test.go b/dot_test.go index 643e6d5..0dd0cc4 100644 --- a/dot_test.go +++ b/dot_test.go @@ -1,9 +1,56 @@ package objectid import ( + "fmt" "testing" ) +func ExampleDotNotation_Index() { + dot, err := NewDotNotation(`1.3.6.1.4.1.56521.999.5`) + if err != nil { + fmt.Println(err) + return + } + + arc, _ := dot.Index(1) + fmt.Printf("%s", arc) + // Output: 3 +} + +func ExampleDotNotation_IsZero() { + var dot DotNotation + fmt.Printf("Is Zero: %t", dot.IsZero()) + // Output: Is Zero: true +} + +func ExampleDotNotation_Valid() { + var dot DotNotation + fmt.Printf("Is Valid: %t", dot.Valid()) + // Output: Is Valid: false +} + +func ExampleDotNotation_Len() { + dot, err := NewDotNotation(`1.3.6.1.4.1.56521.999.5`) + if err != nil { + fmt.Println(err) + return + } + + fmt.Printf("Length: %d", dot.Len()) + // Output: Length: 9 +} + +func ExampleDotNotation_String() { + dot, err := NewDotNotation(`1.3.6.1.4.1.56521.999.5`) + if err != nil { + fmt.Println(err) + return + } + + fmt.Printf("%s", dot) + // Output: 1.3.6.1.4.1.56521.999.5 +} + func TestDotNotation_badInit(t *testing.T) { var d DotNotation want := false diff --git a/misc.go b/misc.go index 6db9c95..a82b509 100644 --- a/misc.go +++ b/misc.go @@ -73,6 +73,59 @@ func isNumber(val string) bool { return true } +/* +isAlnum returns a Boolean value indicative of whether rune r represents +an alphanumeric character. Specifically, one (1) of the following ranges +must evaluate as true: + + - 0-9 (ASCII characters 48 through 57) + - A-Z (ASCII characters 65 through 90) + - a-z (ASCII characters 97 through 122) +*/ +func isAlnum(r rune) bool { + return isLower(r) || isUpper(r) || isDigit(r) +} + +/* +isIdentifier scans the input string val and judges whether +it appears to qualify as an identifier, in that: + +- it begins with a lower alpha +- it contains only alphanumeric characters, hyphens or semicolons + +This is used, specifically, it identify an LDAP attributeType (with +or without a tag), or an LDAP matchingRule. +*/ +func isIdentifier(val string) bool { + if len(val) == 0 { + return false + } + + // must begin with lower alpha. + if !isLower(rune(val[0])) { + return false + } + + // can only end in alnum. + if !isAlnum(rune(val[len(val)-1])) { + return false + } + + for i := 0; i < len(val); i++ { + ch := rune(val[i]) + switch { + case isAlnum(ch): + // ok + case ch == ';', ch == '-': + // ok + default: + return false + } + } + + return true +} + /* compare slice members of two (2) []int instances. */ diff --git a/nanf.go b/nanf.go index 3dd57e8..e5d0113 100644 --- a/nanf.go +++ b/nanf.go @@ -55,9 +55,17 @@ func (nanf NameAndNumberForm) String() (val string) { Equal returns a boolean value indicative of whether instance n of NameAndNumberForm matches the receiver. */ -func (nanf NameAndNumberForm) Equal(n NameAndNumberForm) bool { - return nanf.identifier == n.identifier && - nanf.primaryIdentifier.Equal(n.primaryIdentifier) +func (nanf NameAndNumberForm) Equal(n any) (is bool) { + switch tv := n.(type) { + case NameAndNumberForm: + is = nanf.identifier == tv.identifier && + nanf.primaryIdentifier.Equal(tv.primaryIdentifier) + case *NameAndNumberForm: + is = nanf.identifier == tv.identifier && + nanf.primaryIdentifier.Equal(tv.primaryIdentifier) + } + + return } /* @@ -92,61 +100,22 @@ func parseNaNFstr(x string) (nanf *NameAndNumberForm, err error) { // Parse/verify what appears to be the // identifier string value. - var valid bool - if valid, err = identifierIsValid(x[:idx-1]); !valid { + var identifier string = x[:idx] + if !isIdentifier(identifier) { + err = errorf("Invalid identifier [%s]; syntax must conform to: LOWER *[ [-] +[ UPPER / LOWER / DIGIT ] ]", identifier) return } // parse the string numberForm value into // an instance of NumberForm, or bail out. - prid, err := NewNumberForm(n) - if err != nil { - return - } - - // Prepare to return valid information. - nanf = new(NameAndNumberForm) - nanf.parsed = true - nanf.primaryIdentifier = prid - nanf.identifier = x[:idx] - return -} - -/* -identifierIsValid returns a boolean and an error, each indicative of -parsing outcome based on the input nameForm value (val). -*/ -func identifierIsValid(val string) (valid bool, err error) { - for c := 0; c < len(val)-1; c++ { - ch := rune(val[c]) - - // The first character CANNOT be a number, nor - // can it be an UPPER case character. - if c == 0 { - if !isLower(ch) { - err = errorf("Bad identifier '%s' at char #%d [%c] [hint: must only start with lowercase alpha]", val, c, ch) - return - } - } - - // If identifier is anything other than a-z, A-Z or - // 0-9, then bail out. - if !(isDigit(ch) || isLetter(ch) || ch == '-') { - err = errorf("Bad identifier '%s' at char #%d [%c], unsupported character(s) [hint: must be A-Z, a-z, 0-9 or '-']", val, c, ch) - return - } - - // The final character MUST NOT be a hyphen (dash) - if c == len(val)-1 { - if ch == '-' { - err = errorf("Bad identifier '%s' at char #%d [%c] [hint: final identifier character cannot be a hyphen]", val, c, ch) - return - } - } + var prid NumberForm + if prid, err = NewNumberForm(n); err == nil { + // Prepare to return valid information. + nanf = new(NameAndNumberForm) + nanf.parsed = true + nanf.primaryIdentifier = prid + nanf.identifier = x[:idx] } - - // Seems legit. - valid = true return } diff --git a/nanf_test.go b/nanf_test.go index 5ac6638..ce2bd75 100644 --- a/nanf_test.go +++ b/nanf_test.go @@ -1,9 +1,84 @@ package objectid import ( + "fmt" "testing" ) +func ExampleNewNameAndNumberForm() { + nanf, err := NewNameAndNumberForm(`enterprise(1)`) + if err != nil { + fmt.Println(err) + return + } + + fmt.Printf("%s", nanf) + // Output: enterprise(1) +} + +func ExampleNameAndNumberForm_String() { + nanf, err := NewNameAndNumberForm(`enterprise(1)`) + if err != nil { + fmt.Println(err) + return + } + + fmt.Printf("%s", nanf) + // Output: enterprise(1) +} + +func ExampleNameAndNumberForm_IsZero() { + nanf, err := NewNameAndNumberForm(`enterprise(1)`) + if err != nil { + fmt.Println(err) + return + } + + fmt.Printf("Zero: %t", nanf.IsZero()) + // Output: Zero: false +} + +func ExampleNameAndNumberForm_Identifier() { + nanf, err := NewNameAndNumberForm(`enterprise(1)`) + if err != nil { + fmt.Println(err) + return + } + + fmt.Printf("%s", nanf.Identifier()) + // Output: enterprise +} + +func ExampleNameAndNumberForm_NumberForm() { + nanf, err := NewNameAndNumberForm(`enterprise(1)`) + if err != nil { + fmt.Println(err) + return + } + + fmt.Printf("%s", nanf.NumberForm()) + // Output: 1 +} + +func ExampleNameAndNumberForm_Equal() { + var nanf1, nanf2 *NameAndNumberForm + var err error + + if nanf1, err = NewNameAndNumberForm(`enterprise(1)`); err != nil { + fmt.Println(err) + return + } + + // bogus + if nanf2, err = NewNameAndNumberForm(`enterprise(10)`); err != nil { + fmt.Println(err) + return + } + + fmt.Printf("Equal: %t", nanf1.Equal(nanf2)) + // Output: Equal: false +} + func TestNewNameAndNumberForm(t *testing.T) { if _, err := NewNameAndNumberForm("enterprise(1)"); err != nil { t.Errorf("%s failed: %s", diff --git a/nf.go b/nf.go index d1d5b85..b48d457 100644 --- a/nf.go +++ b/nf.go @@ -27,14 +27,14 @@ type NumberForm struct { } // isZero returns true if a == 0. -func (a NumberForm) IsZero() bool { - if &a == nil { - return true +func (a NumberForm) IsZero() (is bool) { + is = true + if &a != nil { + // NOTE: we do not compare against Zero, because that + // is a global variable that could be modified. + is = (a.lo == uint64(0) && a.hi == uint64(0)) } - - // NOTE: we do not compare against Zero, because that - // is a global variable that could be modified. - return a.lo == uint64(0) && a.hi == uint64(0) + return } /* @@ -43,23 +43,23 @@ the value provided. Valid input types are string, uint64, int and NumberForm. Any input that represents a negative number guarantees a false return. */ -func (a NumberForm) Equal(n any) bool { +func (a NumberForm) Equal(n any) (is bool) { switch tv := n.(type) { case NumberForm: - return a == tv + is = a == tv case string: if nf, err := NewNumberForm(tv); err == nil { - return a == nf + is = a == nf } case uint64: - return a.lo == tv && a.hi == 0 + is = a.lo == tv && a.hi == 0 case int: if 0 <= tv { - return a.lo == uint64(tv) && a.hi == 0 + is = a.lo == uint64(tv) && a.hi == 0 } } - return false + return } /* @@ -68,18 +68,18 @@ the value provided. Valid input types are string, uint64, int and NumberForm. Any input that represents a negative number guarantees a false return. */ -func (a NumberForm) Gt(n any) bool { +func (a NumberForm) Gt(n any) (is bool) { switch tv := n.(type) { case NumberForm, string: - return a.gtLt(tv, false) + is = a.gtLt(tv, false) case uint64: - return a.lo > tv && a.hi == uint64(0) + is = a.lo > tv && a.hi == uint64(0) case int: if 0 <= tv { - return a.lo > uint64(tv) && a.hi == uint64(0) + is = a.lo > uint64(tv) && a.hi == uint64(0) } } - return false + return } /* @@ -88,18 +88,18 @@ the value provided. Valid input types are string, uint64, int and NumberForm. Any input that represents a negative number guarantees a false return. */ -func (a NumberForm) Lt(n any) bool { +func (a NumberForm) Lt(n any) (is bool) { switch tv := n.(type) { case NumberForm, string: - return a.gtLt(tv, true) + is = a.gtLt(tv, true) case uint64: - return a.lo < tv && a.hi == uint64(0) + is = a.lo < tv && a.hi == uint64(0) case int: if 0 <= tv { - return a.lo < uint64(tv) && a.hi == uint64(0) + is = a.lo < uint64(tv) && a.hi == uint64(0) } } - return false + return } func (a NumberForm) gtLt(x any, lt bool) bool { diff --git a/oid.go b/oid.go index cf86e6b..f98d602 100644 --- a/oid.go +++ b/oid.go @@ -13,11 +13,10 @@ type OID struct { IsZero checks the receiver for nilness and returns a boolean indicative of the result. */ func (id OID) IsZero() (is bool) { - if &id == nil { - return false + if &id != nil { + is = len(id.nanf) == 0 && id.parsed } - is = len(id.nanf) == 0 && id.parsed return } @@ -25,56 +24,55 @@ func (id OID) IsZero() (is bool) { Dot returns a DotNotation instance based on the contents of the underlying ASN1Notation instance found within the receiver. */ -func (id OID) Dot() DotNotation { - if (&id).IsZero() { - return DotNotation{} +func (id OID) Dot() (d DotNotation) { + if !(&id).IsZero() { + d = make(DotNotation, len(id.nanf)) + for i := 0; i < len(id.nanf); i++ { + d[i] = id.nanf[i].NumberForm() + } } - d := make(DotNotation, len(id.nanf)) - for i := 0; i < len(id.nanf); i++ { - d[i] = id.nanf[i].NumberForm() - } - return d + return } /* ASN returns the underlying ASN1Notation instance found within the receiver. */ -func (id OID) ASN() ASN1Notation { - if (&id).IsZero() { - return ASN1Notation{} +func (id OID) ASN() (a ASN1Notation) { + if !(&id).IsZero() { + a = id.nanf } - return id.nanf + return } /* Valid returns a boolean value indicative of whether the receiver's state is considered value. */ -func (id OID) Valid() bool { - if id.IsZero() { - return false - } - nanf, ok := id.nanf.Index(0) - if !ok { - return false - } - for i := 0; i < 3; i++ { - if nanf.NumberForm().Equal(i) { - return true +func (id OID) Valid() (ok bool) { + if !id.IsZero() { + var nanf NameAndNumberForm + if nanf, ok = id.nanf.Index(0); ok { + var found bool + for i := 0; i < 3; i++ { + if nanf.NumberForm().Equal(i) { + found = true + break + } + } + ok = found } } - return false + return } /* Len returns the integer length of all underlying NumberForm values present within the receiver. */ func (id OID) Len() (i int) { - if id.IsZero() { - return + if !id.IsZero() { + i = len(id.nanf) } - i = len(id.nanf) return } @@ -82,10 +80,9 @@ func (id OID) Len() (i int) { Leaf returns the leaf-node instance of NameAndNumberForm. */ func (id OID) Leaf() (nanf NameAndNumberForm) { - if id.IsZero() { - return + if !id.IsZero() { + nanf, _ = id.nanf.Index(-1) } - nanf, _ = id.nanf.Index(-1) return } @@ -93,10 +90,9 @@ func (id OID) Leaf() (nanf NameAndNumberForm) { Parent returns the leaf-node's Parent instance of NameAndNumberForm. */ func (id OID) Parent() (nanf NameAndNumberForm) { - if id.IsZero() { - return + if !id.IsZero() { + nanf, _ = id.nanf.Index(-2) } - nanf, _ = id.nanf.Index(-2) return } @@ -104,10 +100,9 @@ func (id OID) Parent() (nanf NameAndNumberForm) { Root returns the root node instance of NameAndNumberForm. */ func (id OID) Root() (nanf NameAndNumberForm) { - if id.IsZero() { - return + if !id.IsZero() { + nanf, _ = id.nanf.Index(0) } - nanf, _ = id.nanf.Index(0) return } @@ -127,37 +122,35 @@ Not all NameAndNumberForm values (arcs) require actual names; they can be number func NewOID(x any) (o *OID, err error) { t := new(OID) + var nfs []string switch tv := x.(type) { case string: - f := fields(condenseWHSP(trimR(trimL(tv, `{`), `}`))) - for i := 0; i < len(f); i++ { - var nanf *NameAndNumberForm - if nanf, err = NewNameAndNumberForm(f[i]); err != nil { - return - } - t.nanf = append(t.nanf, *nanf) - } + nfs = fields(condenseWHSP(trimR(trimL(tv, `{`), `}`))) case []string: - for i := 0; i < len(tv); i++ { - var nanf *NameAndNumberForm - if nanf, err = NewNameAndNumberForm(tv[i]); err != nil { - return - } - t.nanf = append(t.nanf, *nanf) - } + nfs = tv default: err = errorf("Unsupported %T input type: %#v\n", x, x) return } - if !t.Valid() { - err = errorf("%T instance did not pass validity checks: %#v", t, *t) + for i := 0; i < len(nfs) && err == nil; i++ { + var nanf *NameAndNumberForm + if nanf, err = NewNameAndNumberForm(nfs[i]); nanf != nil { + t.nanf = append(t.nanf, *nanf) + } + } + + if err != nil { return } - o = new(OID) - o.parsed = true - *o = *t + err = errorf("%T instance did not pass validity checks: %#v", t, *t) + if t.Valid() { + o = new(OID) + o.parsed = true + *o = *t + err = nil + } return } diff --git a/oid_test.go b/oid_test.go index ccadbc6..b639722 100644 --- a/oid_test.go +++ b/oid_test.go @@ -5,7 +5,23 @@ import ( ) func TestNewOID(t *testing.T) { - if _, err := NewOID(`{iso(1) identified-organization(3) dod(6) internet(1) private(4) enterprise(1) 56521 example(999)}`); err != nil { - t.Errorf("%s failed: %s", t.Name(), err.Error()) + for _, typ := range []any{ + []string{ + `iso(1)`, + `identified-organization(3)`, + `dod(6)`, + `internet(1)`, + `private(4)`, + `enterprise(1)`, + `56521`, + `example(999)`, + }, + `{iso(1) identified-organization(3) dod(6) internet(1) private(4) enterprise(1) 56521 example(999)}`, + } { + + if _, err := NewOID(typ); err != nil { + t.Errorf("%s failed: %v", t.Name(), err) + return + } } } From e0c9f796fd3818d4b4d9e4a6e201d373a8b5458c Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Sat, 7 Oct 2023 00:47:06 -0700 Subject: [PATCH 02/27] stable release prep --- misc.go | 28 ++++++++++--- misc_test.go | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+), 5 deletions(-) create mode 100644 misc_test.go diff --git a/misc.go b/misc.go index a82b509..bb51576 100644 --- a/misc.go +++ b/misc.go @@ -43,20 +43,38 @@ func errorf(msg any, x ...any) error { return nil } +/* +strInSlice returns a Boolean value indicative of whether the +specified string (str) is present within slice. Please note +that case is a significant element in the matching process. +*/ func strInSlice(str string, slice []string) bool { - if len(str) == 0 || len(slice) == 0 { - return false + for i := 0; i < len(slice); i++ { + if str == slice[i] { + return true + } } + return false +} - for _, val := range slice { - if eq(val, str) { +/* +strInSliceFold returns a Boolean value indicative of whether +the specified string (str) is present within slice. Case is +not significant in the matching process. +*/ +func strInSliceFold(str string, slice []string) bool { + for i := 0; i < len(slice); i++ { + if eq(str, slice[i]) { return true } } - return false } +func isPowerOfTwo(x int) bool { + return x&(x-1) == 0 +} + /* is 'val' an unsigned number? */ diff --git a/misc_test.go b/misc_test.go new file mode 100644 index 0000000..c6b4fb7 --- /dev/null +++ b/misc_test.go @@ -0,0 +1,108 @@ +package objectid + +import ( + "testing" +) + +var strInSliceMap map[int]map[int][]bool = map[int]map[int][]bool{ + // case match + 0: { + 0: {true, true, true, true, true}, + 1: {true, true, true, true, true}, + }, + + // case fold + 1: { + 0: {true, true, true, true, true}, + 1: {true, true, true, true, true}, + }, +} + +func TestStrInSlice(t *testing.T) { + for idx, fn := range []func(string, []string) bool{ + strInSlice, + strInSliceFold, + } { + for i, values := range [][]string{ + {`cAndidate1`, `blarGetty`, `CANndidate7`, `squatcobbler`, ``}, + {`Ó-aîï4Åø´øH«w%);%d] failed; []byte(%v) in %v: %t (wanted %t)", + t.Name(), i, j, []byte(val), values, result_received, result_expected) + return + } + } + } + } +} + +func TestMisc_codecov(t *testing.T) { + _ = errorf("this is a string %s", `error`) + _ = errorf(errorf("this is an error")) + + intSlices := [][]int{ + {1, 2, 3, 4}, + {1, 2, 3, 4}, + } + + strSlices := [][]string{ + {`1`, `2`, `3`, `4`}, + {`1`, `3`, `2`, `4`}, + } + + if !intSliceEqual(intSlices[0], intSlices[1]) { + t.Errorf("%s failed: matching int slices not deemed equal", t.Name()) + return + } + + if strSliceEqual(strSlices[0], strSlices[1]) { + t.Errorf("%s failed: non-matching int slices deemed equal", t.Name()) + return + } + + for idx, candidate := range []string{ + `1`, + `t18`, + `17`, + `S`, + `8`, + `~ej`, + `11`, + `S&*(D`, + `100`, + ``, + `9919387`, + } { + var err error + is := isNumber(candidate) + if is && idx%2 != 0 { + err = errorf("%s failed: good value [%s] not cleared as number", t.Name(), candidate) + } else if !is && idx%2 == 0 { + err = errorf("%s failed: bogus value [%s] cleared as number", t.Name(), candidate) + } + + if err != nil { + t.Errorf("%v", err) + return + } + } +} From a3bd3220f6fb7ef32c6d4a3700c255a8de1404c6 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Sat, 7 Oct 2023 01:20:29 -0700 Subject: [PATCH 03/27] stable release prep --- misc.go | 8 ++++---- misc_test.go | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/misc.go b/misc.go index bb51576..43efd12 100644 --- a/misc.go +++ b/misc.go @@ -32,15 +32,15 @@ var ( isUpper func(rune) bool = unicode.IsUpper ) -func errorf(msg any, x ...any) error { +func errorf(msg any, x ...any) (err error) { switch tv := msg.(type) { case string: - return errors.New(sprintf(tv, x...)) + err = errors.New(sprintf(tv, x...)) case error: - return errors.New(sprintf(tv.Error(), x...)) + err = errors.New(sprintf(tv.Error(), x...)) } - return nil + return } /* diff --git a/misc_test.go b/misc_test.go index c6b4fb7..744a82b 100644 --- a/misc_test.go +++ b/misc_test.go @@ -58,7 +58,9 @@ func TestStrInSlice(t *testing.T) { func TestMisc_codecov(t *testing.T) { _ = errorf("this is a string %s", `error`) _ = errorf(errorf("this is an error")) +} +func TestSlices(t *testing.T) { intSlices := [][]int{ {1, 2, 3, 4}, {1, 2, 3, 4}, @@ -74,11 +76,24 @@ func TestMisc_codecov(t *testing.T) { return } + if intSliceEqual([]int{1, 2, 3}, []int{4, 5, 6, 7}) { + t.Errorf("%s failed: non-matching int slices deemed equal", t.Name()) + return + } + if strSliceEqual(strSlices[0], strSlices[1]) { t.Errorf("%s failed: non-matching int slices deemed equal", t.Name()) return } + if strSliceEqual([]string{`1`, `2`, `3`}, []string{`4`, `5`, `6`, `7`}) { + t.Errorf("%s failed: non-matching int slices deemed equal", t.Name()) + return + } + +} + +func TestIsNumber(t *testing.T) { for idx, candidate := range []string{ `1`, `t18`, @@ -106,3 +121,32 @@ func TestMisc_codecov(t *testing.T) { } } } + +func TestIsIdentifier(t *testing.T) { + for idx, candidate := range []string{ + `enterprise`, + `Enterprise`, + `iso`, + `ISO`, + `telcoCompany`, + `-enterprise`, + `identified-organization`, + `100`, + `joint-iso-itu-t`, + ``, + `itu-t`, + } { + var err error + is := isIdentifier(candidate) + if is && idx%2 != 0 { + err = errorf("%s failed: good value [%s] not cleared as an identifier", t.Name(), candidate) + } else if !is && idx%2 == 0 { + err = errorf("%s failed: bogus value [%s] cleared as an identifier", t.Name(), candidate) + } + + if err != nil { + t.Errorf("%v", err) + return + } + } +} From 197141beba9bfe68b66d729872456a18524a528e Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Sat, 7 Oct 2023 01:27:39 -0700 Subject: [PATCH 04/27] stable release prep --- misc.go | 12 ++++++------ misc_test.go | 3 ++- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/misc.go b/misc.go index 43efd12..1a90a67 100644 --- a/misc.go +++ b/misc.go @@ -153,12 +153,12 @@ func intSliceEqual(s1, s2 []int) (equal bool) { } for i := 0; i < len(s1); i++ { - if s1[i] != s2[i] { - return + if equal = s1[i] == s2[i]; equal { + continue } + break } - equal = true return } @@ -171,12 +171,12 @@ func strSliceEqual(s1, s2 []string) (equal bool) { } for i := 0; i < len(s1); i++ { - if s1[i] != s2[i] { - return + if equal = s1[i] == s2[i]; equal { + continue } + break } - equal = true return } diff --git a/misc_test.go b/misc_test.go index 744a82b..a4ec252 100644 --- a/misc_test.go +++ b/misc_test.go @@ -127,7 +127,7 @@ func TestIsIdentifier(t *testing.T) { `enterprise`, `Enterprise`, `iso`, - `ISO`, + `itu-`, `telcoCompany`, `-enterprise`, `identified-organization`, @@ -135,6 +135,7 @@ func TestIsIdentifier(t *testing.T) { `joint-iso-itu-t`, ``, `itu-t`, + `itu?t`, } { var err error is := isIdentifier(candidate) From c2b83d757754171c8ac9d1d34c0ed85e1d1c5a2c Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Sat, 7 Oct 2023 01:40:31 -0700 Subject: [PATCH 05/27] stable release prep --- misc.go | 10 +++---- misc_test.go | 83 +++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 67 insertions(+), 26 deletions(-) diff --git a/misc.go b/misc.go index 1a90a67..1623c7d 100644 --- a/misc.go +++ b/misc.go @@ -153,10 +153,9 @@ func intSliceEqual(s1, s2 []int) (equal bool) { } for i := 0; i < len(s1); i++ { - if equal = s1[i] == s2[i]; equal { - continue + if equal = s1[i] == s2[i]; !equal { + break } - break } return @@ -171,10 +170,9 @@ func strSliceEqual(s1, s2 []string) (equal bool) { } for i := 0; i < len(s1); i++ { - if equal = s1[i] == s2[i]; equal { - continue + if equal = s1[i] == s2[i]; !equal { + break } - break } return diff --git a/misc_test.go b/misc_test.go index a4ec252..c85f865 100644 --- a/misc_test.go +++ b/misc_test.go @@ -60,31 +60,73 @@ func TestMisc_codecov(t *testing.T) { _ = errorf(errorf("this is an error")) } -func TestSlices(t *testing.T) { - intSlices := [][]int{ - {1, 2, 3, 4}, - {1, 2, 3, 4}, - } - - strSlices := [][]string{ - {`1`, `2`, `3`, `4`}, - {`1`, `3`, `2`, `4`}, +func TestIntSlices(t *testing.T) { + for idx, pair := range [][][]int{ + { + {1, 2, 3, 4}, + {1, 2, 3, 4}, + }, + { + {1, 2, 3}, + {4, 5, 6, 7}, + }, + { + {8, 8}, + {8, 8}, + }, + { + {1, 2, 3, 5}, + {1, 5, 3, 7}, + }, + } { + eql := intSliceEqual(pair[0], pair[1]) + if !eql && idx%2 == 0 { + t.Errorf("%s failed: matching int slices not deemed equal", t.Name()) + return + } else if eql && idx%2 != 0 { + t.Errorf("%s failed: non-matching int slices deemed equal", t.Name()) + return + } } +} - if !intSliceEqual(intSlices[0], intSlices[1]) { - t.Errorf("%s failed: matching int slices not deemed equal", t.Name()) - return +func TestStrSlices(t *testing.T) { + for idx, pair := range [][][]string{ + { + {`1`, `2`, `3`, `4`}, + {`1`, `2`, `3`, `4`}, + }, + { + {`1`, `2`, `3`}, + {`4`, `5`, `6`, `7`}, + }, + { + {`8`, `8`}, + {`8`, `8`}, + }, + { + {`1`, `2`, `3`, `5`}, + {`1`, `5`, `3`, `7`}, + }, + } { + eql := strSliceEqual(pair[0], pair[1]) + if !eql && idx%2 == 0 { + t.Errorf("%s failed: matching str slices not deemed equal", t.Name()) + return + } else if eql && idx%2 != 0 { + t.Errorf("%s failed: non-matching str slices deemed equal", t.Name()) + return + } } +} - if intSliceEqual([]int{1, 2, 3}, []int{4, 5, 6, 7}) { - t.Errorf("%s failed: non-matching int slices deemed equal", t.Name()) - return - } +/* +func TestStrSlices(t *testing.T) { - if strSliceEqual(strSlices[0], strSlices[1]) { - t.Errorf("%s failed: non-matching int slices deemed equal", t.Name()) - return - } + strSlices := [][]string{ + {`1`, `2`, `3`, `4`}, + {`1`, `3`, `2`, `4`}, + } if strSliceEqual([]string{`1`, `2`, `3`}, []string{`4`, `5`, `6`, `7`}) { t.Errorf("%s failed: non-matching int slices deemed equal", t.Name()) @@ -92,6 +134,7 @@ func TestSlices(t *testing.T) { } } +*/ func TestIsNumber(t *testing.T) { for idx, candidate := range []string{ From 7ce13eb15c192527a1868d0a2f75ea4d3e8ed384 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Sat, 7 Oct 2023 01:49:42 -0700 Subject: [PATCH 06/27] stable release prep --- misc.go | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/misc.go b/misc.go index 1623c7d..80b116e 100644 --- a/misc.go +++ b/misc.go @@ -211,16 +211,15 @@ func condenseWHSP(b string) (a string) { sscan is a closure function used by the NumberForm stringer for interoperability with fmt.Sscan. */ -func sscan(s fmt.ScanState, ch rune, u *NumberForm) error { +func sscan(s fmt.ScanState, ch rune, u *NumberForm) (err error) { i := new(big.Int) - if err := i.Scan(s, ch); err != nil { - return err - } else if i.Sign() < 0 { - return errorf("value cannot be negative") - } else if i.BitLen() > 128 { - return errorf("value overflows uint128") + if err = i.Scan(s, ch); err == nil { + err = errorf("Value cannot be negative, nor can it have a bit length >128") + if 0 <= i.Sign() && i.BitLen() < 128 { + u.lo = i.Uint64() + u.hi = i.Rsh(i, 64).Uint64() + err = nil + } } - u.lo = i.Uint64() - u.hi = i.Rsh(i, 64).Uint64() - return nil + return } From dcdd9a8b3e267c9c109accbac68b7d5728bd877f Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Sat, 7 Oct 2023 02:18:52 -0700 Subject: [PATCH 07/27] stable release prep --- nf_test.go | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/nf_test.go b/nf_test.go index 336d6fa..4593b85 100644 --- a/nf_test.go +++ b/nf_test.go @@ -1,14 +1,28 @@ package objectid import ( + "fmt" "testing" ) func TestNewNumberForm(t *testing.T) { - nf := `3849141823758536772162786183725055278` - if _, err := NewNumberForm(nf); err != nil { - t.Errorf("%s failed: %s", t.Name(), err.Error()) + for idx, num := range []any{ + `3849141823758536772162786183725055278`, + -103, + 4874893, + ``, + } { + _, err := NewNumberForm(num) + ok := err == nil + if !ok && idx%2 == 0 { + t.Errorf("%s failed: valid number not parsed: %v", t.Name(), err) + return + } else if ok && idx%2 != 0 { + t.Errorf("%s failed: bogus number parsed without error", t.Name()) + return + } } + } func TestBogusNewNumberForm(t *testing.T) { @@ -55,7 +69,7 @@ func TestNumberForm_Equal(t *testing.T) { t.Errorf("%s failed: Gt evaluation returned a bogus value", t.Name()) } - if nf, _ = NewNumberForm(`437829765`); !nf.Equal(437829765) { + if nf, _ = NewNumberForm(`437829765`); !nf.Equal(`437829765`) { t.Errorf("%s failed: Gt evaluation returned a bogus value", t.Name()) } @@ -63,3 +77,36 @@ func TestNumberForm_Equal(t *testing.T) { t.Errorf("%s failed: Gt evaluation returned a bogus value", t.Name()) } } + +func ExampleNumberForm_Equal() { + nf1, _ := NewNumberForm(4658) + nf2, _ := NewNumberForm(4657) + fmt.Printf("Instances are equal: %t", nf1.Equal(nf2)) + // Output: Instances are equal: false +} + +func ExampleNumberForm_Valid() { + nf, _ := NewNumberForm(4658) + fmt.Printf("Valid: %t", nf.Valid()) + // Output: Valid: true +} + +func ExampleNumberForm_String() { + nf, _ := NewNumberForm(4658) + fmt.Printf("%s", nf) + // Output: 4658 +} + +func ExampleNumberForm_Gt() { + nf, _ := NewNumberForm(4658) + oth := 4501 + fmt.Printf("%s > %d: %t", nf, oth, nf.Gt(oth)) + // Output: 4658 > 4501: true +} + +func ExampleNumberForm_Lt() { + nf, _ := NewNumberForm(4658) + oth := 4501 + fmt.Printf("%s < %d: %t", nf, oth, nf.Lt(oth)) + // Output: 4658 < 4501: false +} From 7b4c99b0484972c4b16f23dcca1178146c289922 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Sat, 7 Oct 2023 02:23:27 -0700 Subject: [PATCH 08/27] stable release prep --- nf_test.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/nf_test.go b/nf_test.go index 4593b85..5513a29 100644 --- a/nf_test.go +++ b/nf_test.go @@ -104,9 +104,23 @@ func ExampleNumberForm_Gt() { // Output: 4658 > 4501: true } +func ExampleNumberForm_Gt_byString() { + nf, _ := NewNumberForm(`4658`) + oth := `4501` + fmt.Printf("%s > %s: %t", nf, oth, nf.Gt(oth)) + // Output: 4658 > 4501: true +} + func ExampleNumberForm_Lt() { nf, _ := NewNumberForm(4658) oth := 4501 fmt.Printf("%s < %d: %t", nf, oth, nf.Lt(oth)) // Output: 4658 < 4501: false } + +func ExampleNumberForm_Lt_byString() { + nf, _ := NewNumberForm(`4658`) + oth := `4501` + fmt.Printf("%s < %s: %t", nf, oth, nf.Lt(oth)) + // Output: 4658 < 4501: false +} From abd1340c40992ceb6dee8d04c82d062f7c8ddc67 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Sat, 7 Oct 2023 02:40:38 -0700 Subject: [PATCH 09/27] stable release prep --- nf_test.go | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/nf_test.go b/nf_test.go index 5513a29..683be67 100644 --- a/nf_test.go +++ b/nf_test.go @@ -27,10 +27,17 @@ func TestNewNumberForm(t *testing.T) { func TestBogusNewNumberForm(t *testing.T) { bogus := `-48675` - if _, err := NewNumberForm(bogus); err == nil { + crap, err := NewNumberForm(bogus) + if err == nil { t.Errorf("%s failed: bogus NumberForm '%v' accepted without error", t.Name(), bogus) + return } + + var junk NumberForm + + _ = crap.String() + _ = junk.String() } func TestNumberForm_Gt(t *testing.T) { @@ -99,8 +106,8 @@ func ExampleNumberForm_String() { func ExampleNumberForm_Gt() { nf, _ := NewNumberForm(4658) - oth := 4501 - fmt.Printf("%s > %d: %t", nf, oth, nf.Gt(oth)) + oth, _ := NewNumberForm(4501) + fmt.Printf("%s > %s: %t", nf, oth, nf.Gt(oth)) // Output: 4658 > 4501: true } @@ -111,10 +118,17 @@ func ExampleNumberForm_Gt_byString() { // Output: 4658 > 4501: true } +func ExampleNumberForm_Gt_byUint64() { + nf, _ := NewNumberForm(uint64(4658)) + oth := uint64(4501) + fmt.Printf("%s > %d: %t", nf, oth, nf.Gt(oth)) + // Output: 4658 > 4501: true +} + func ExampleNumberForm_Lt() { nf, _ := NewNumberForm(4658) - oth := 4501 - fmt.Printf("%s < %d: %t", nf, oth, nf.Lt(oth)) + oth, _ := NewNumberForm(4501) + fmt.Printf("%s < %s: %t", nf, oth, nf.Lt(oth)) // Output: 4658 < 4501: false } @@ -124,3 +138,10 @@ func ExampleNumberForm_Lt_byString() { fmt.Printf("%s < %s: %t", nf, oth, nf.Lt(oth)) // Output: 4658 < 4501: false } + +func ExampleNumberForm_Lt_byUint64() { + nf, _ := NewNumberForm(uint64(4658)) + oth := uint64(4501) + fmt.Printf("%s < %d: %t", nf, oth, nf.Lt(oth)) + // Output: 4658 < 4501: false +} From 2ecd30c06816d1793edcbd9b9c350e0c8093ebd9 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Sat, 7 Oct 2023 02:46:33 -0700 Subject: [PATCH 10/27] stable release prep --- nf_test.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/nf_test.go b/nf_test.go index 683be67..70b8981 100644 --- a/nf_test.go +++ b/nf_test.go @@ -12,7 +12,7 @@ func TestNewNumberForm(t *testing.T) { 4874893, ``, } { - _, err := NewNumberForm(num) + nf, err := NewNumberForm(num) ok := err == nil if !ok && idx%2 == 0 { t.Errorf("%s failed: valid number not parsed: %v", t.Name(), err) @@ -21,8 +21,9 @@ func TestNewNumberForm(t *testing.T) { t.Errorf("%s failed: bogus number parsed without error", t.Name()) return } - } + _ = nf.len() + } } func TestBogusNewNumberForm(t *testing.T) { From a7df2ab4fda61f02756fce3c9b0862ed5fcd82ee Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Sat, 7 Oct 2023 03:05:37 -0700 Subject: [PATCH 11/27] stable release prep --- dot.go | 137 ++++++++++++++++++++++++---------------------------- dot_test.go | 12 +++++ 2 files changed, 74 insertions(+), 75 deletions(-) diff --git a/dot.go b/dot.go index 6f58b79..c850087 100644 --- a/dot.go +++ b/dot.go @@ -49,11 +49,11 @@ func (d DotNotation) Parent() NumberForm { IsZero returns a boolean indicative of whether the receiver is unset. */ -func (d DotNotation) IsZero() bool { - if &d == nil { - return true +func (d DotNotation) IsZero() (is bool) { + if &d != nil { + is = d.Len() == 0 } - return d.Len() == 0 + return } /* @@ -62,16 +62,15 @@ value indicative of success. */ func NewDotNotation(id string) (d *DotNotation, err error) { if len(id) == 0 { + err = errorf("input value is zero-length") return } ids := split(id, `.`) var t *DotNotation = new(DotNotation) - for i := 0; i < len(ids); i++ { + for i := 0; i < len(ids) && err == nil; i++ { var a NumberForm - if a, err = NewNumberForm(ids[i]); err != nil { - break - } + a, err = NewNumberForm(ids[i]) *t = append(*t, a) } @@ -120,24 +119,22 @@ func (d DotNotation) Index(idx int) (a NumberForm, ok bool) { L := len(d) // Bail if receiver is empty. - if L == 0 { - return - } - - if idx < 0 { - var x int = L + idx - if x < 0 { - a = d[0] + if L > 0 { + if idx < 0 { + var x int = L + idx + if x < 0 { + a = d[0] + } else { + a = d[x] + } + } else if idx > L { + a = d[L-1] } else { - a = d[x] + a = d[idx] } - } else if idx > L { - a = d[L-1] - } else { - a = d[idx] + ok = true } - ok = true return } @@ -149,12 +146,10 @@ Empty slices of DotNotation are returned if the dotNotation value within the receiver is less than two (2) NumberForm values in length. */ func (d DotNotation) Ancestry() (anc []DotNotation) { - if d.Len() == 0 { - return - } - - for i := d.Len(); i > 0; i-- { - anc = append(anc, d[:i]) + if d.Len() > 0 { + for i := d.Len(); i > 0; i-- { + anc = append(anc, d[:i]) + } } return @@ -164,38 +159,35 @@ func (d DotNotation) Ancestry() (anc []DotNotation) { AncestorOf returns a boolean value indicative of whether the receiver is an ancestor of the input value, which can be string or DotNotation. */ -func (d DotNotation) AncestorOf(dot any) bool { - if d.IsZero() { - return false - } - - var D *DotNotation - - switch tv := dot.(type) { - case string: - var err error - if D, err = NewDotNotation(tv); err != nil { +func (d DotNotation) AncestorOf(dot any) (is bool) { + if !d.IsZero() { + var D *DotNotation + + switch tv := dot.(type) { + case string: + var err error + if D, err = NewDotNotation(tv); err != nil { + return false + } + case *DotNotation: + if tv != nil { + D = tv + } + case DotNotation: + if tv.Len() > 0 { + *D = tv + } + default: return false } - case *DotNotation: - if tv == nil { + if D.Len() <= d.Len() { return false } - D = tv - case DotNotation: - if tv.Len() == 0 { - return false - } - *D = tv - default: - return false - } - if D.Len() <= d.Len() { - return false + is = d.matchDotNot(D) } - return d.matchDotNot(D) + return } func (d DotNotation) matchDotNot(dot *DotNotation) bool { @@ -219,26 +211,21 @@ contents of the receiver as well as the input NumberForm subordinate value. This creates a fully-qualified child DotNotation value of the receiver. */ -func (d DotNotation) NewSubordinate(nf any) *DotNotation { - // Don't bother processing - if d.Len() == 0 { - return nil - } - - // Prepare the new leaf numberForm, - // or die trying. - a, err := NewNumberForm(nf) - if err != nil { - return nil - } - - D := make(DotNotation, d.Len()+1, d.Len()+1) - for i := 0; i < d.Len(); i++ { - D[i] = d[i] +func (d DotNotation) NewSubordinate(nf any) (dot *DotNotation) { + if d.Len() > 0 { + // Prepare the new leaf numberForm, + // or die trying. + if a, err := NewNumberForm(nf); err == nil { + D := make(DotNotation, d.Len()+1, d.Len()+1) + for i := 0; i < d.Len(); i++ { + D[i] = d[i] + } + D[D.Len()-1] = a + dot = &D + } } - D[D.Len()-1] = a - return &D + return } /* @@ -247,10 +234,10 @@ Valid returns a boolean value indicative of the following: • Receiver's length is greater than or equal to one (1) slice member, and ... • The first slice in the receiver contains a decimal value that is less than three (3) */ -func (d DotNotation) Valid() bool { - if d.IsZero() { - return false +func (d DotNotation) Valid() (is bool) { + if !d.IsZero() { + is = d.Root().Lt(3) } - return d.Root().Lt(3) + return } diff --git a/dot_test.go b/dot_test.go index 0dd0cc4..862188d 100644 --- a/dot_test.go +++ b/dot_test.go @@ -58,6 +58,7 @@ func TestDotNotation_badInit(t *testing.T) { if want != got { t.Errorf("%s failed: wanted validity of %t, got %t", t.Name(), want, got) + return } } @@ -66,6 +67,7 @@ func TestDotNotation_Ancestry(t *testing.T) { if err != nil { t.Errorf("%s failed: %s", t.Name(), err.Error()) + return } anc := dot.Ancestry() @@ -75,6 +77,7 @@ func TestDotNotation_Ancestry(t *testing.T) { if want != got { t.Errorf("%s failed: wanted length of %d, got %d", t.Name(), want, got) + return } } @@ -88,6 +91,7 @@ func TestDotNotation_NewSubordinate(t *testing.T) { if want != got { t.Errorf("%s failed: wanted %s, got %s", t.Name(), want, got) + return } } @@ -96,6 +100,7 @@ func TestDotNotation_IsZero(t *testing.T) { if !dot.IsZero() { t.Errorf("%s failed: bogus IsZero return", t.Name()) + return } } @@ -108,5 +113,12 @@ func TestDotNotation_AncestorOf(t *testing.T) { if !dot.AncestorOf(child) { t.Errorf("%s failed: ancestry check returned bogus result", t.Name()) + return } } + +func TestDotNotation_codecov(t *testing.T) { + var dot DotNotation + _, _ = dot.IntSlice() + _ = dot.String() +} From d33b2106c978242fe67f8c57b8211af778045144 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Sat, 7 Oct 2023 12:39:20 -0700 Subject: [PATCH 12/27] stable release prep --- dot.go | 14 +++++++++----- dot_test.go | 7 ++++--- nanf_test.go | 28 +++++++++++++++++++++++++--- 3 files changed, 38 insertions(+), 11 deletions(-) diff --git a/dot.go b/dot.go index c850087..b21b061 100644 --- a/dot.go +++ b/dot.go @@ -9,12 +9,16 @@ type DotNotation []NumberForm String is a stringer method that returns the dotNotation form of the receiver (e.g.: "1.3.6.1"). */ -func (d DotNotation) String() string { - var x []string - for i := 0; i < len(d); i++ { - x = append(x, d[i].String()) +func (d DotNotation) String() (s string) { + if !d.IsZero() { + var x []string + for i := 0; i < len(d); i++ { + x = append(x, d[i].String()) + } + + s = join(x, `.`) } - return join(x, `.`) + return } /* diff --git a/dot_test.go b/dot_test.go index 862188d..ead2fd1 100644 --- a/dot_test.go +++ b/dot_test.go @@ -118,7 +118,8 @@ func TestDotNotation_AncestorOf(t *testing.T) { } func TestDotNotation_codecov(t *testing.T) { - var dot DotNotation - _, _ = dot.IntSlice() - _ = dot.String() + if _, err := NewDotNotation(``); err == nil { + t.Errorf("%s failed: zero length OID parsed without error", t.Name()) + return + } } diff --git a/nanf_test.go b/nanf_test.go index ce2bd75..d5f39b7 100644 --- a/nanf_test.go +++ b/nanf_test.go @@ -80,10 +80,32 @@ func ExampleNameAndNumberForm_Equal() { } func TestNewNameAndNumberForm(t *testing.T) { - if _, err := NewNameAndNumberForm("enterprise(1)"); err != nil { - t.Errorf("%s failed: %s", - t.Name(), err.Error()) + var err error + var nf NumberForm + if nf, err = NewNumberForm(177); err != nil { + t.Errorf("%s failed: %s", t.Name(), err.Error()) + return } + + for idx, v := range []any{ + `enterprise(1)`, + `enterprise1)`, + 77, + ``, + nf, + `blarg`, + } { + _, err = NewNameAndNumberForm(v) + if idx%2 == 0 && err != nil { + t.Errorf("%s failed: %v", t.Name(), err) + return + } else if err == nil && idx%2 != 0 { + t.Errorf("%s failed: parsed bogus value without error", t.Name()) + return + } + } + + _, _ = NewNameAndNumberForm(nil) } func TestBogusNameAndNumberForm(t *testing.T) { From 47554d653ae5de0fd44f10f37da5524f107f0a9d Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Sat, 7 Oct 2023 13:25:59 -0700 Subject: [PATCH 13/27] stable release prep --- doc_test.go | 33 --------------------- oid.go | 11 ++++--- oid_test.go | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 87 insertions(+), 40 deletions(-) diff --git a/doc_test.go b/doc_test.go index bbcf336..44fcc93 100644 --- a/doc_test.go +++ b/doc_test.go @@ -27,39 +27,6 @@ func ExampleNewOID() { // Output: ASN.1 Notation: {joint-iso-itu-t(2) uuid(25) ans(987895962269883002155146617097157934)} } -func ExampleOID_Leaf() { - a := `{joint-iso-itu-t(2) uuid(25) ans(987895962269883002155146617097157934)}` - id, err := NewOID(a) - if err != nil { - fmt.Println(err) - return - } - fmt.Printf("Leaf node: %s", id.Leaf()) - // Output: Leaf node: ans(987895962269883002155146617097157934) -} - -func ExampleOID_Parent() { - a := `{joint-iso-itu-t(2) uuid(25) ans(987895962269883002155146617097157934)}` - id, err := NewOID(a) - if err != nil { - fmt.Println(err) - return - } - fmt.Printf("Leaf node parent: %s", id.Parent()) - // Output: Leaf node parent: uuid(25) -} - -func ExampleOID_Root() { - a := `{joint-iso-itu-t(2) uuid(25) ans(987895962269883002155146617097157934)}` - id, err := NewOID(a) - if err != nil { - fmt.Println(err) - return - } - fmt.Printf("Root node: %s", id.Root()) - // Output: Root node: joint-iso-itu-t(2) -} - func ExampleNewDotNotation() { a := `2.25.987895962269883002155146617097157934` id, err := NewDotNotation(a) diff --git a/oid.go b/oid.go index f98d602..10908a8 100644 --- a/oid.go +++ b/oid.go @@ -12,11 +12,10 @@ type OID struct { /* IsZero checks the receiver for nilness and returns a boolean indicative of the result. */ -func (id OID) IsZero() (is bool) { - if &id != nil { - is = len(id.nanf) == 0 && id.parsed +func (id *OID) IsZero() (is bool) { + if id != nil { + is = len(id.nanf) == 0 } - return } @@ -25,7 +24,7 @@ Dot returns a DotNotation instance based on the contents of the underlying ASN1N instance found within the receiver. */ func (id OID) Dot() (d DotNotation) { - if !(&id).IsZero() { + if !id.IsZero() { d = make(DotNotation, len(id.nanf)) for i := 0; i < len(id.nanf); i++ { d[i] = id.nanf[i].NumberForm() @@ -39,7 +38,7 @@ func (id OID) Dot() (d DotNotation) { ASN returns the underlying ASN1Notation instance found within the receiver. */ func (id OID) ASN() (a ASN1Notation) { - if !(&id).IsZero() { + if !id.IsZero() { a = id.nanf } return diff --git a/oid_test.go b/oid_test.go index b639722..a559f27 100644 --- a/oid_test.go +++ b/oid_test.go @@ -1,6 +1,7 @@ package objectid import ( + "fmt" "testing" ) @@ -19,9 +20,89 @@ func TestNewOID(t *testing.T) { `{iso(1) identified-organization(3) dod(6) internet(1) private(4) enterprise(1) 56521 example(999)}`, } { - if _, err := NewOID(typ); err != nil { + _, err := NewOID(typ) + if err != nil { t.Errorf("%s failed: %v", t.Name(), err) return } } } + +func ExampleOID_Dot() { + raw := `{iso(1) identified-organization(3) dod(6) internet(1) private(4) enterprise(1) 56521 example(999)}` + id, err := NewOID(raw) + if err != nil { + fmt.Println(err) + return + } + fmt.Printf("%s", id.Dot()) + // Output: 1.3.6.1.4.1.56521.999 +} + +func ExampleOID_Len() { + raw := `{iso(1) identified-organization(3) dod(6) internet(1) private(4) enterprise(1) 56521 example(999)}` + id, err := NewOID(raw) + if err != nil { + fmt.Println(err) + return + } + fmt.Printf("%d", id.Len()) + // Output: 8 +} + +func ExampleOID_ASN() { + raw := `{iso(1) identified-organization(3) dod(6) internet(1) private(4) enterprise(1) 56521 example(999)}` + id, err := NewOID(raw) + if err != nil { + fmt.Println(err) + return + } + + fmt.Printf("%s", id.ASN()) + // Output: {iso(1) identified-organization(3) dod(6) internet(1) private(4) enterprise(1) 56521 example(999)} +} + +func ExampleOID_IsZero() { + var z OID + fmt.Printf("Zero: %t", z.IsZero()) + // Output: Zero: true +} + +func ExampleOID_Valid() { + var o OID + fmt.Printf("Valid: %t", o.Valid()) + // Output: Valid: false +} + +func ExampleOID_Leaf() { + a := `{joint-iso-itu-t(2) uuid(25) ans(987895962269883002155146617097157934)}` + id, err := NewOID(a) + if err != nil { + fmt.Println(err) + return + } + fmt.Printf("Leaf node: %s", id.Leaf()) + // Output: Leaf node: ans(987895962269883002155146617097157934) +} + +func ExampleOID_Parent() { + a := `{joint-iso-itu-t(2) uuid(25) ans(987895962269883002155146617097157934)}` + id, err := NewOID(a) + if err != nil { + fmt.Println(err) + return + } + fmt.Printf("Leaf node parent: %s", id.Parent()) + // Output: Leaf node parent: uuid(25) +} + +func ExampleOID_Root() { + a := `{joint-iso-itu-t(2) uuid(25) ans(987895962269883002155146617097157934)}` + id, err := NewOID(a) + if err != nil { + fmt.Println(err) + return + } + fmt.Printf("Root node: %s", id.Root()) + // Output: Root node: joint-iso-itu-t(2) +} From a73d7257448ae653c9d0ea2d2d91bb552adbcc2e Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Sat, 7 Oct 2023 13:47:02 -0700 Subject: [PATCH 14/27] stable release prep --- asn_test.go | 66 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 17 deletions(-) diff --git a/asn_test.go b/asn_test.go index 08fe8b5..8893a2f 100644 --- a/asn_test.go +++ b/asn_test.go @@ -104,36 +104,51 @@ func TestASN1Notation001(t *testing.T) { t.Name(), want, got) return } + + asn, err = NewASN1Notation([]string{ + `iso(1)`, + `identified-organization(3)`, + `dod(6)`, + `internet(1)`, + `private(4)`, + `enterprise(1)`, + `56521`, + `example(999)`}) + + if l := asn.Len(); l != 8 { + t.Errorf("%s failed: want '%d', got '%d'", + t.Name(), 8, l) + return + } + + if _, err = NewASN1Notation(float64(123)); err == nil { + t.Errorf("%s failed; no error where one was expected", t.Name()) + return + } } func TestASN1Notation_Index(t *testing.T) { - asn, err := NewASN1Notation(testASN1JesseExample) + aNot, err := NewASN1Notation(testASN1JesseExample) if err != nil { - t.Errorf("%s error: %s", t.Name(), err.Error()) + fmt.Println(err) return } - want := `example(999)` - got := asn.Leaf() - if want != got.String() { - t.Errorf("%s failed: want '%s', got '%s'", - t.Name(), want, got) + nanf, _ := aNot.Index(1) + if nanf.Identifier() != `identified-organization` { + t.Errorf("%s failed: unable to call index 1 from %T; got '%s'", t.Name(), nanf, nanf.Identifier()) return } - want = `56521` - got = asn.Parent() - if want != got.String() { - t.Errorf("%s failed: want '%s', got '%s'", - t.Name(), want, got) + nanf, _ = aNot.Index(-1) + if nanf.NumberForm().String() != `999` { + t.Errorf("%s failed: unable to call index -1 from %T", t.Name(), nanf) return } - want = `iso(1)` - got = asn.Root() - if want != got.String() { - t.Errorf("%s failed: want '%s', got '%s'", - t.Name(), want, got) + nanf, _ = aNot.Index(100) + if nanf.NumberForm().String() != `999` { + t.Errorf("%s failed: unable to call index 100 from %T", t.Name(), nanf) return } } @@ -150,6 +165,7 @@ func TestASN1Notation_Ancestry(t *testing.T) { if err != nil { t.Errorf("%s failed: %s", t.Name(), err.Error()) + return } anc := asn.Ancestry() @@ -159,6 +175,7 @@ func TestASN1Notation_Ancestry(t *testing.T) { if want != got { t.Errorf("%s failed: wanted length of %d, got %d", t.Name(), want, got) + return } } @@ -172,6 +189,7 @@ func TestASN1Notation_NewSubordinate(t *testing.T) { if want != got { t.Errorf("%s failed: wanted %s, got %s", t.Name(), want, got) + return } } @@ -180,6 +198,7 @@ func TestASN1Notation_IsZero(t *testing.T) { if !asn.IsZero() { t.Errorf("%s failed: bogus IsZero return", t.Name()) + return } } @@ -197,5 +216,18 @@ func TestASN1Notation_AncestorOf(t *testing.T) { if asn.AncestorOf(child) { t.Errorf("%s failed: ancestry check returned bogus result", t.Name()) + return + } + + if asn.AncestorOf(*child) { + t.Errorf("%s failed: ancestry check returned bogus result", + t.Name()) + return + } + + if asn.AncestorOf(child.String()) { + t.Errorf("%s failed: ancestry check returned bogus result", + t.Name()) + return } } From 663a5c14e03f01d22a11f6a8e5b78fdbb380515c Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Sat, 7 Oct 2023 14:09:40 -0700 Subject: [PATCH 15/27] stable release prep --- asn_test.go | 1 + dot.go | 7 +++---- dot_test.go | 32 +++++++++++++++++++++++++++++++- 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/asn_test.go b/asn_test.go index 8893a2f..d0b12f8 100644 --- a/asn_test.go +++ b/asn_test.go @@ -208,6 +208,7 @@ func TestASN1Notation_AncestorOf(t *testing.T) { t.Errorf("%s failed: %v", t.Name(), err) return } + child, err := NewASN1Notation(`{iso(1) identified-organization(3) dod(6) internet(1)}`) if err != nil { t.Errorf("%s failed: %v", t.Name(), err) diff --git a/dot.go b/dot.go index b21b061..375e9da 100644 --- a/dot.go +++ b/dot.go @@ -53,8 +53,8 @@ func (d DotNotation) Parent() NumberForm { IsZero returns a boolean indicative of whether the receiver is unset. */ -func (d DotNotation) IsZero() (is bool) { - if &d != nil { +func (d *DotNotation) IsZero() (is bool) { + if d != nil { is = d.Len() == 0 } return @@ -94,8 +94,7 @@ a zero slice is returned. Successful output can be cast as an instance of asn1.ObjectIdentifier, if desired. */ func (d DotNotation) IntSlice() (slice []int, err error) { - if len(d) == 0 { - err = errorf("%T instance is nil", d) + if d.IsZero() { return } diff --git a/dot_test.go b/dot_test.go index ead2fd1..54768ff 100644 --- a/dot_test.go +++ b/dot_test.go @@ -118,8 +118,38 @@ func TestDotNotation_AncestorOf(t *testing.T) { } func TestDotNotation_codecov(t *testing.T) { - if _, err := NewDotNotation(``); err == nil { + _, err := NewDotNotation(``) + if err == nil { t.Errorf("%s failed: zero length OID parsed without error", t.Name()) return } + + var X DotNotation + _, _ = X.IntSlice() +} + +func TestDotNotation_Index(t *testing.T) { + dot, err := NewDotNotation(`1.3.6.1.4.1.56521.999.5`) + if err != nil { + fmt.Println(err) + return + } + + nf, _ := dot.Index(1) + if nf.String() != `3` { + t.Errorf("%s failed: unable to call index 1 from %T", t.Name(), nf) + return + } + + nf, _ = dot.Index(-1) + if nf.String() != `5` { + t.Errorf("%s failed: unable to call index -1 from %T", t.Name(), nf) + return + } + + nf, _ = dot.Index(100) + if nf.String() != `5` { + t.Errorf("%s failed: unable to call index 100 from %T", t.Name(), nf) + return + } } From 7b045b3fd9199abe256e1d9eaa06734e7d553c81 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Sat, 7 Oct 2023 14:28:14 -0700 Subject: [PATCH 16/27] stable release prep --- dot.go | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/dot.go b/dot.go index 375e9da..b1798c8 100644 --- a/dot.go +++ b/dot.go @@ -119,15 +119,10 @@ value indicative of success. This method supports the use of negative indices. */ func (d DotNotation) Index(idx int) (a NumberForm, ok bool) { - L := len(d) - - // Bail if receiver is empty. - if L > 0 { + if L := len(d); L > 0 { if idx < 0 { - var x int = L + idx - if x < 0 { - a = d[0] - } else { + a = d[0] + if x := L + idx; x >= 0 { a = d[x] } } else if idx > L { From efe4e169f668fedd1d2829b8ffff3cf88e73915b Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Sat, 7 Oct 2023 15:30:29 -0700 Subject: [PATCH 17/27] stable release prep --- nf.go | 48 ++++++++++++++++++++++++++---------------------- nf_test.go | 22 ++++++++++++++++++++++ 2 files changed, 48 insertions(+), 22 deletions(-) diff --git a/nf.go b/nf.go index b48d457..08297f1 100644 --- a/nf.go +++ b/nf.go @@ -26,10 +26,12 @@ type NumberForm struct { parsed bool } -// isZero returns true if a == 0. -func (a NumberForm) IsZero() (is bool) { - is = true - if &a != nil { +/* +IsZero returns a Boolean value indicative of whether the +receiver instance is nil, or unset. +*/ +func (a *NumberForm) IsZero() (is bool) { + if is = a == nil; !is { // NOTE: we do not compare against Zero, because that // is a global variable that could be modified. is = (a.lo == uint64(0) && a.hi == uint64(0)) @@ -146,27 +148,28 @@ func (a NumberForm) len() int { return 128 - a.leadingZeros() } -// String returns the base-10 representation of a as a string. +/* +String returns the base-10 string representation of the receiver +instance. +*/ func (a NumberForm) String() string { - if a.IsZero() { - return "0" - } else if !a.parsed { - return "0" - } - - buf := []byte("0000000000000000000000000000000000000000") // log10(2^128) < 40 - for i := len(buf); ; i -= 19 { - q, r := a.quoRem64(1e19) // largest power of 10 that fits in a uint64 - var n int - for ; r != 0; r /= 10 { - n++ - buf[i-n] += byte(r % 10) + if !a.IsZero() { + buf := []byte("0000000000000000000000000000000000000000") // log10(2^128) < 40 + for i := len(buf); ; i -= 19 { + q, r := a.quoRem64(1e19) // largest power of 10 that fits in a uint64 + var n int + for ; r != 0; r /= 10 { + n++ + buf[i-n] += byte(r % 10) + } + if q.IsZero() { + return string(buf[i-n:]) + } + a = q } - if q.IsZero() { - return string(buf[i-n:]) - } - a = q } + + return "-1" } /* @@ -179,6 +182,7 @@ func (a *NumberForm) Scan(s fmt.ScanState, ch rune) error { } // quoRem64 returns q = u/v and r = u%v. +// Credit: Luke Champine func (a NumberForm) quoRem64(v uint64) (q NumberForm, r uint64) { if a.hi < v { q.lo, r = bits.Div64(a.hi, a.lo, v) diff --git a/nf_test.go b/nf_test.go index 70b8981..4a8b0d2 100644 --- a/nf_test.go +++ b/nf_test.go @@ -23,6 +23,22 @@ func TestNewNumberForm(t *testing.T) { } _ = nf.len() + _ = nf.String() + } +} + +func TestQuorem64(t *testing.T) { + x, _ := NewNumberForm(`17238`) + for _, y := range []uint64{ + // don't send zero + uint64(13), + uint64(17284), + uint64(1), + uint64(14895623), + uint64(1234), + uint64(4895623), + } { + _, _ = x.quoRem64(y) } } @@ -105,6 +121,12 @@ func ExampleNumberForm_String() { // Output: 4658 } +func ExampleNumberForm_IsZero() { + var nf NumberForm + fmt.Printf("Zero: %t", nf.IsZero()) + // Output: Zero: true +} + func ExampleNumberForm_Gt() { nf, _ := NewNumberForm(4658) oth, _ := NewNumberForm(4501) From ab2f72e66e3c8a2b6d6368fb9a13d8a38c0f4d36 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Sat, 7 Oct 2023 15:57:13 -0700 Subject: [PATCH 18/27] stable release prep --- asn.go | 73 ++++++++++++++++++++++-------------------------------- nf_test.go | 4 +++ 2 files changed, 33 insertions(+), 44 deletions(-) diff --git a/asn.go b/asn.go index 56132fb..7aec7cc 100644 --- a/asn.go +++ b/asn.go @@ -110,7 +110,7 @@ func NewASN1Notation(x any) (a *ASN1Notation, err error) { case []string: nfs = tv default: - err = errorf("Unsupported %T input type: %#v\n", x, x) + err = errorf("Unsupported %T input type: %#v", x, x) return } @@ -146,14 +146,6 @@ func (a ASN1Notation) Valid() (is bool) { // Don't waste time on // zero instances. if L := a.Len(); L > 0 { - // bail out if any of the slice - // values are unparsed. - for i := 0; i < L; i++ { - if !a[i].parsed { - return false - } - } - if root, ok := a.Index(0); ok { // root cannot be greater than 2 is = root.NumberForm().Lt(3) @@ -207,49 +199,42 @@ func (a ASN1Notation) NewSubordinate(nanf any) *ASN1Notation { AncestorOf returns a boolean value indicative of whether the receiver is an ancestor of the input value, which can be string or ASN1Notation. */ -func (a ASN1Notation) AncestorOf(asn any) bool { - if a.IsZero() { - return false - } - - var A *ASN1Notation - - switch tv := asn.(type) { - case string: - var err error - if A, err = NewASN1Notation(tv); err != nil { - return false - } - case *ASN1Notation: - if tv != nil { - A = tv - } - case ASN1Notation: - if tv.Len() >= 0 { - A = &tv +func (a ASN1Notation) AncestorOf(asn any) (anc bool) { + if !a.IsZero() { + var A *ASN1Notation + + switch tv := asn.(type) { + case string: + A, _ = NewASN1Notation(tv) + case *ASN1Notation: + if tv != nil { + A = tv + } + case ASN1Notation: + if tv.Len() >= 0 { + A = &tv + } } - default: - return false - } - if A.Len() < a.Len() { - return false + if A.Len() > a.Len() { + anc = a.matchASN1(A) + } } - return a.matchASN1(A) + return } -func (a ASN1Notation) matchASN1(asn *ASN1Notation) bool { - for i := 0; i < a.Len(); i++ { +func (a ASN1Notation) matchASN1(asn *ASN1Notation) (matched bool) { + L := a.Len() + ct := 0 + for i := 0; i < L; i++ { x, _ := a.Index(i) - y, ok := asn.Index(i) - if !ok { - return false - } - if !x.Equal(y) { - return false + if y, ok := asn.Index(i); ok { + if x.Equal(y) { + ct++ + } } } - return true + return ct == L } diff --git a/nf_test.go b/nf_test.go index 4a8b0d2..5f120de 100644 --- a/nf_test.go +++ b/nf_test.go @@ -25,6 +25,10 @@ func TestNewNumberForm(t *testing.T) { _ = nf.len() _ = nf.String() } + + var nf NumberForm + _ = nf.gtLt(nil, true) // codecov + _ = nf.gtLt(nil, false) // codecov } func TestQuorem64(t *testing.T) { From df5e1abdfbbb529e3e96884f64d23f25028d0bdb Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Sat, 7 Oct 2023 16:07:15 -0700 Subject: [PATCH 19/27] stable release prep --- dot.go | 34 ++++++++++++++-------------------- dot_test.go | 5 +++++ 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/dot.go b/dot.go index b1798c8..c1fec9a 100644 --- a/dot.go +++ b/dot.go @@ -163,44 +163,38 @@ func (d DotNotation) AncestorOf(dot any) (is bool) { switch tv := dot.(type) { case string: - var err error - if D, err = NewDotNotation(tv); err != nil { - return false - } + D, _ = NewDotNotation(tv) case *DotNotation: if tv != nil { D = tv } case DotNotation: - if tv.Len() > 0 { - *D = tv + if tv.Len() >= 0 { + D = &tv } - default: - return false - } - if D.Len() <= d.Len() { - return false } - is = d.matchDotNot(D) + if D.Len() > d.Len() { + is = d.matchDotNot(D) + } } return } func (d DotNotation) matchDotNot(dot *DotNotation) bool { - for i := 0; i < d.Len(); i++ { + L := d.Len() + ct := 0 + for i := 0; i < L; i++ { x, _ := d.Index(i) - y, ok := dot.Index(i) - if !ok { - return false - } - if !x.Equal(y) { - return false + if y, ok := dot.Index(i); ok { + if x.Equal(y) { + ct++ + } } } - return true + return ct == L } /* diff --git a/dot_test.go b/dot_test.go index 54768ff..21d3b7a 100644 --- a/dot_test.go +++ b/dot_test.go @@ -93,6 +93,11 @@ func TestDotNotation_NewSubordinate(t *testing.T) { t.Name(), want, got) return } + + if !dot.Valid() { + t.Errorf("%s failed %T validity checks", t.Name(), dot) + return + } } func TestDotNotation_IsZero(t *testing.T) { From 942bcdb35e4dd74061d2bd3bdd67df8c33357ea0 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Sat, 7 Oct 2023 16:11:08 -0700 Subject: [PATCH 20/27] stable release prep --- dot_test.go | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/dot_test.go b/dot_test.go index 21d3b7a..3bab113 100644 --- a/dot_test.go +++ b/dot_test.go @@ -111,15 +111,24 @@ func TestDotNotation_IsZero(t *testing.T) { func TestDotNotation_AncestorOf(t *testing.T) { dot, _ := NewDotNotation(`1.3.6`) - child, err := NewDotNotation(`1.3.6.1.4`) + chstr := `1.3.6.1.4` + child, err := NewDotNotation(chstr) if err != nil { t.Errorf(err.Error()) - } - if !dot.AncestorOf(child) { - t.Errorf("%s failed: ancestry check returned bogus result", - t.Name()) return } + + for _, d := range []any{ + chstr, + child, + *child, + } { + if !dot.AncestorOf(d) { + t.Errorf("%s failed: ancestry check returned bogus result", + t.Name()) + return + } + } } func TestDotNotation_codecov(t *testing.T) { From 2018f65cadfceb4b9e9a37d4266c0f176058cbe1 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Sat, 7 Oct 2023 16:26:59 -0700 Subject: [PATCH 21/27] stable release prep --- nanf.go | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/nanf.go b/nanf.go index e5d0113..db44548 100644 --- a/nanf.go +++ b/nanf.go @@ -133,33 +133,30 @@ and (non-negative) int. */ func NewNameAndNumberForm(x any) (nanf *NameAndNumberForm, err error) { + err = errorf("%T must conform to: identifier LPAREN numberForm RPAREN", nanf) switch tv := x.(type) { case string: if !isNumber(tv) { nanf, err = parseNaNFstr(tv) } else { var a NumberForm - a, err = NewNumberForm(tv) - if err != nil { - break + if a, err = NewNumberForm(tv); err == nil { + nanf = &NameAndNumberForm{primaryIdentifier: a} } - nanf = &NameAndNumberForm{primaryIdentifier: a} } case NumberForm: nanf = new(NameAndNumberForm) nanf.primaryIdentifier = tv + err = nil case uint64: nanf = new(NameAndNumberForm) u, _ := NewNumberForm(tv) // skip error checking, we know it won't overflow. nanf.primaryIdentifier = u + err = nil case int: - if tv < 0 { - err = errorf("NumberForm component of %T CANNOT be negative", nanf) - break + if tv >= 0 { + nanf, err = NewNameAndNumberForm(uint64(tv)) } - // cast int as uint64 and resubmit - // to this function. - return NewNameAndNumberForm(uint64(tv)) default: err = errorf("Unsupported NameAndNumberForm input type '%T'", tv) } From c9203eb842048ea3721c42877f5f35ca5d4e471c Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Sat, 7 Oct 2023 16:33:53 -0700 Subject: [PATCH 22/27] stable release prep --- nanf.go | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/nanf.go b/nanf.go index db44548..1a4e85f 100644 --- a/nanf.go +++ b/nanf.go @@ -92,30 +92,26 @@ func parseNaNFstr(x string) (nanf *NameAndNumberForm, err error) { // select the numerical characters, // or bail out ... - n := x[idx+1 : len(x)-1] - if !isNumber(n) { - err = errorf("Bad primaryIdentifier '%s'", n) - return - } - - // Parse/verify what appears to be the - // identifier string value. - var identifier string = x[:idx] - if !isIdentifier(identifier) { + err = errorf("Bad numberForm: value must fall within 0 and ^uint128") + if n := x[idx+1 : len(x)-1]; isNumber(n) { + // Parse/verify what appears to be the + // identifier string value. + var identifier string = x[:idx] err = errorf("Invalid identifier [%s]; syntax must conform to: LOWER *[ [-] +[ UPPER / LOWER / DIGIT ] ]", identifier) - return + if isIdentifier(identifier) { + // parse the string numberForm value into + // an instance of NumberForm, or bail out. + var prid NumberForm + if prid, err = NewNumberForm(n); err == nil { + // Prepare to return valid information. + nanf = new(NameAndNumberForm) + nanf.parsed = true + nanf.primaryIdentifier = prid + nanf.identifier = x[:idx] + } + } } - // parse the string numberForm value into - // an instance of NumberForm, or bail out. - var prid NumberForm - if prid, err = NewNumberForm(n); err == nil { - // Prepare to return valid information. - nanf = new(NameAndNumberForm) - nanf.parsed = true - nanf.primaryIdentifier = prid - nanf.identifier = x[:idx] - } return } From c5c7862fda5a4d2ab51b06fba73c29c688a99ddd Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Sat, 7 Oct 2023 16:50:02 -0700 Subject: [PATCH 23/27] stable release prep --- asn_test.go | 27 +++++++++++---------------- oid.go | 18 ++++++++---------- oid_test.go | 10 +++++++--- 3 files changed, 26 insertions(+), 29 deletions(-) diff --git a/asn_test.go b/asn_test.go index d0b12f8..be755c5 100644 --- a/asn_test.go +++ b/asn_test.go @@ -134,22 +134,17 @@ func TestASN1Notation_Index(t *testing.T) { return } - nanf, _ := aNot.Index(1) - if nanf.Identifier() != `identified-organization` { - t.Errorf("%s failed: unable to call index 1 from %T; got '%s'", t.Name(), nanf, nanf.Identifier()) - return - } - - nanf, _ = aNot.Index(-1) - if nanf.NumberForm().String() != `999` { - t.Errorf("%s failed: unable to call index -1 from %T", t.Name(), nanf) - return - } - - nanf, _ = aNot.Index(100) - if nanf.NumberForm().String() != `999` { - t.Errorf("%s failed: unable to call index 100 from %T", t.Name(), nanf) - return + for key, value := range map[int]string{ + 1: `identified-organization`, + -1: `example`, + -18: `iso`, + 100: `example`, + } { + if nanf, _ := aNot.Index(key); nanf.Identifier() != value { + t.Errorf("%s failed: unable to call index %d from %T;\nwant '%s'\ngot '%s'", + t.Name(), key, nanf, value, nanf.Identifier()) + return + } } } diff --git a/oid.go b/oid.go index 10908a8..8a1c35b 100644 --- a/oid.go +++ b/oid.go @@ -139,16 +139,14 @@ func NewOID(x any) (o *OID, err error) { } } - if err != nil { - return - } - - err = errorf("%T instance did not pass validity checks: %#v", t, *t) - if t.Valid() { - o = new(OID) - o.parsed = true - *o = *t - err = nil + if err == nil { + err = errorf("%T instance did not pass validity checks: %#v", t, *t) + if t.Valid() { + o = new(OID) + o.parsed = true + *o = *t + err = nil + } } return diff --git a/oid_test.go b/oid_test.go index a559f27..ac0d924 100644 --- a/oid_test.go +++ b/oid_test.go @@ -6,7 +6,7 @@ import ( ) func TestNewOID(t *testing.T) { - for _, typ := range []any{ + for idx, typ := range []any{ []string{ `iso(1)`, `identified-organization(3)`, @@ -17,13 +17,17 @@ func TestNewOID(t *testing.T) { `56521`, `example(999)`, }, + nil, `{iso(1) identified-organization(3) dod(6) internet(1) private(4) enterprise(1) 56521 example(999)}`, + float32(1), } { - _, err := NewOID(typ) - if err != nil { + if err != nil && idx%2 == 0 { t.Errorf("%s failed: %v", t.Name(), err) return + } else if err == nil && idx%2 != 0 { + t.Errorf("%s failed: no error where one was expected", t.Name()) + return } } } From 23cabc59caacf443fe305bdccd98cde28f9e1df4 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Sat, 7 Oct 2023 17:20:06 -0700 Subject: [PATCH 24/27] stable release prep --- nf_test.go | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/nf_test.go b/nf_test.go index 5f120de..d707a5e 100644 --- a/nf_test.go +++ b/nf_test.go @@ -32,17 +32,26 @@ func TestNewNumberForm(t *testing.T) { } func TestQuorem64(t *testing.T) { - x, _ := NewNumberForm(`17238`) - for _, y := range []uint64{ - // don't send zero - uint64(13), - uint64(17284), - uint64(1), - uint64(14895623), - uint64(1234), - uint64(4895623), + for _, z := range []int{ + 0, + 1, + 225, + 18457, + 9, } { - _, _ = x.quoRem64(y) + x, _ := NewNumberForm(z) + for _, y := range []uint64{ + // don't send zero + uint64(13), + uint64(17284), + ^uint64(0), + uint64(1), + uint64(14895623), + uint64(1234), + uint64(4895623), + } { + _, _ = x.quoRem64(y) + } } } From 132738ddfbf00a9e8a7a40e793041a27e7421fe8 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Sat, 7 Oct 2023 17:28:54 -0700 Subject: [PATCH 25/27] stable release prep --- nf.go | 24 ++++++++++++++++++++++++ nf_test.go | 46 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/nf.go b/nf.go index 08297f1..6669e92 100644 --- a/nf.go +++ b/nf.go @@ -84,6 +84,18 @@ func (a NumberForm) Gt(n any) (is bool) { return } +/* +Ge returns a boolean value indicative of whether the receiver is greater than +or equal to the value provided. Valid input types are string, uint64, int and +NumberForm. This method is merely a convenient wrapper to an ORed call of the +NumberForm.Gt and NumberForm.Equal methods. + +Any input that represents a negative number guarantees a false return. +*/ +func (a NumberForm) Ge(n any) (is bool) { + return a.Gt(n) || a.Equal(n) +} + /* Lt returns a boolean value indicative of whether the receiver is less than the value provided. Valid input types are string, uint64, int and NumberForm. @@ -104,6 +116,18 @@ func (a NumberForm) Lt(n any) (is bool) { return } +/* +Le returns a boolean value indicative of whether the receiver is less than or +equal to the value provided. Valid input types are string, uint64, int and +NumberForm. This method is merely a convenient wrapper to an ORed call of the +NumberForm.Lt and NumberForm.Equal methods. + +Any input that represents a negative number guarantees a false return. +*/ +func (a NumberForm) Le(n any) (is bool) { + return a.Lt(n) || a.Equal(n) +} + func (a NumberForm) gtLt(x any, lt bool) bool { var nf NumberForm diff --git a/nf_test.go b/nf_test.go index d707a5e..b1fc711 100644 --- a/nf_test.go +++ b/nf_test.go @@ -80,11 +80,26 @@ func TestNumberForm_Gt(t *testing.T) { t.Errorf("%s failed: Gt evaluation returned a bogus value", t.Name()) } - if nf, _ = NewNumberForm(uint64(829765)); !nf.Lt(500000000) { + if nf, _ = NewNumberForm(uint64(829765)); nf.Gt(500000000) { t.Errorf("%s failed: Gt evaluation returned a bogus value", t.Name()) } } +func TestNumberForm_Ge(t *testing.T) { + nf, _ := NewNumberForm(4658) + if !nf.Ge(3700) { + t.Errorf("%s failed: Ge evaluation returned a bogus value", t.Name()) + } + + if nf, _ = NewNumberForm(`437829765`); nf.Ge(500000000) { + t.Errorf("%s failed: Ge evaluation returned a bogus value", t.Name()) + } + + if nf, _ = NewNumberForm(uint64(829765)); nf.Ge(500000000) { + t.Errorf("%s failed: Ge evaluation returned a bogus value", t.Name()) + } +} + func TestNumberForm_Lt(t *testing.T) { nf, _ := NewNumberForm(4658) if nf.Lt(3700) { @@ -100,6 +115,21 @@ func TestNumberForm_Lt(t *testing.T) { } } +func TestNumberForm_Le(t *testing.T) { + nf, _ := NewNumberForm(4658) + if nf.Le(3700) { + t.Errorf("%s failed: Le evaluation returned a bogus value", t.Name()) + } + + if nf, _ = NewNumberForm(`437829765`); !nf.Le(500000000) { + t.Errorf("%s failed: Le evaluation returned a bogus value", t.Name()) + } + + if nf, _ = NewNumberForm(uint64(329856)); !nf.Le(500000000) { + t.Errorf("%s failed: Le evaluation returned a bogus value", t.Name()) + } +} + func TestNumberForm_Equal(t *testing.T) { nf, _ := NewNumberForm(4658) if nf.Equal(3700) { @@ -140,6 +170,13 @@ func ExampleNumberForm_IsZero() { // Output: Zero: true } +func ExampleNumberForm_Ge() { + nf, _ := NewNumberForm(4658) + oth, _ := NewNumberForm(4501) + fmt.Printf("%s >= %s: %t", nf, oth, nf.Ge(oth)) + // Output: 4658 >= 4501: true +} + func ExampleNumberForm_Gt() { nf, _ := NewNumberForm(4658) oth, _ := NewNumberForm(4501) @@ -168,6 +205,13 @@ func ExampleNumberForm_Lt() { // Output: 4658 < 4501: false } +func ExampleNumberForm_Le() { + nf, _ := NewNumberForm(4658) + oth, _ := NewNumberForm(4501) + fmt.Printf("%s =< %s: %t", nf, oth, nf.Le(oth)) + // Output: 4658 =< 4501: false +} + func ExampleNumberForm_Lt_byString() { nf, _ := NewNumberForm(`4658`) oth := `4501` From f31f451e3bfe6cba71de63bea699c27bb7f5c76b Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Sat, 7 Oct 2023 17:57:34 -0700 Subject: [PATCH 26/27] stable release prep --- README.md | 13 ++----------- doc.go | 19 +++++++++++++------ uint128.LICENSE | 21 +++++++++++++++++++++ 3 files changed, 36 insertions(+), 17 deletions(-) create mode 100644 uint128.LICENSE diff --git a/README.md b/README.md index 03d1bcf..2b56528 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,6 @@ # go-objectid -[![Go Report Card](https://goreportcard.com/badge/JesseCoretta/go-objectid)](https://goreportcard.com/report/github.com/JesseCoretta/go-objectid) [![Go Reference](https://pkg.go.dev/badge/github.com/JesseCoretta/go-objectid.svg)](https://pkg.go.dev/github.com/JesseCoretta/go-objectid) [![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat)](https://github.com/JesseCoretta/go-objectid/blob/main/LICENSE) [![codecov](https://codecov.io/gh/JesseCoretta/go-objectid/graph/badge.svg?token=RLW4DHLKQP)](https://codecov.io/gh/JesseCoretta/go-objectid) [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/JesseCoretta/go-objectid/issues) [![GitHub Workflow Status (with event)](https://img.shields.io/github/actions/workflow/status/JesseCoretta/go-objectid/go.yml)](https://github.com/JesseCoretta/go-objectid/actions/workflows/go.yml) [![Author](https://img.shields.io/badge/author-Jesse_Coretta-darkred?label=%F0%9F%94%BA&labelColor=indigo&color=maroon)](https://www.linkedin.com/in/jessecoretta/) [![Libraries.io dependency status for GitHub repo](https://img.shields.io/librariesio/github/JesseCoretta/go-objectid)](https://github/JesseCoretta/go-objectid) [![Help Animals](https://img.shields.io/badge/donations-yellow?label=%F0%9F%98%BA&labelColor=Yellow)](https://github.com/JesseCoretta/JesseCoretta/blob/main/DONATIONS.md) +[![Go Report Card](https://goreportcard.com/badge/JesseCoretta/go-objectid)](https://goreportcard.com/report/github.com/JesseCoretta/go-objectid) [![Go Reference](https://pkg.go.dev/badge/github.com/JesseCoretta/go-objectid.svg)](https://pkg.go.dev/github.com/JesseCoretta/go-objectid) [![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat)](https://github.com/JesseCoretta/go-objectid/blob/main/LICENSE) [![codecov](https://codecov.io/gh/JesseCoretta/go-objectid/graph/badge.svg?token=RLW4DHLKQP)](https://codecov.io/gh/JesseCoretta/go-objectid) [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/JesseCoretta/go-objectid/issues) [![GitHub Workflow Status (with event)](https://img.shields.io/github/actions/workflow/status/JesseCoretta/go-objectid/go.yml)](https://github.com/JesseCoretta/go-objectid/actions/workflows/go.yml) [![Author](https://img.shields.io/badge/author-Jesse_Coretta-darkred?label=%F0%9F%94%BA&labelColor=indigo&color=maroon)](https://www.linkedin.com/in/jessecoretta/) [![Help Animals](https://img.shields.io/badge/donations-yellow?label=%F0%9F%98%BA&labelColor=Yellow)](https://github.com/JesseCoretta/JesseCoretta/blob/main/DONATIONS.md) - +Package objectid offers convenient ASN.1 Object Identifier types with useful methods and uint128 support. - - -Package objectid offers a convenient ASN.1 Object Identifier type and associated methods. - -ASN.1 Object Identifiers encompass information that goes beyond their dotted representation. This tiny package merely facilitates the handling of ASN.1 NameAndNumberForm values and alternate names that may be associated with a given OID in the wild. - -## Uint128 Support - -Unsigned 128-bit integer support for individual NumberForm values is made possible due to the private incorporation of Luke Champine's awesome Uint128 type, which manifests here through instances of the package-provided NumberForm type. diff --git a/doc.go b/doc.go index d7ae673..b04f3ca 100644 --- a/doc.go +++ b/doc.go @@ -3,16 +3,23 @@ Package objectid implements ASN.1 Object Identifier types and methods. # Features -• Unsigned 128-bit numberForm support (i.e.: such as the registrations found below {joint-iso-itu-t(2) uuid(25)}) + - Unsigned 128-bit numberForm support (allows for expressing registrations found below {joint-iso-itu-t(2) uuid(25)}, per X.670) + - Flexible index support, allowing interrogation through negative indices without the risk of panic + - Convenient Leaf, Parent and Root index alias methods, wherever applicable + - Ge, Gt, Le, Lt, Equal comparison methods for interacting with NumberForm instances -• Flexible index support, allowing interrogation through negative indices without the risk of panic +# License -• Convenient Leaf, Parent and Root index alias methods, wherever allowed +The go-objectid package is available under the terms of the MIT license. -# Uint128 Support +For further details, see the LICENSE file within the root of the source repository. -Unsigned 128-bit integer support for individual NumberForm values is made possible due to the private incorporation of Luke Champine's awesome Uint128 type, which manifests here through instances of the package-provided NumberForm type. +# NumberForm Maximum -Valid NumberForm instances may fall between the minimum decimal value of zero (0) and the maximum decimal value of 340,282,366,920,938,463,463,374,607,431,768,211,455 (three hundred forty undecillion and change). This ensures no panics occur when parsing valid UUID-based object identifiers. +Valid NumberForm instances may fall between the minimum decimal value of zero (0) and the maximum decimal value of 340,282,366,920,938,463,463,374,607,431,768,211,455 (three hundred forty undecillion and change). This ensures no panics occur when parsing valid UUID-based object identifiers, such as those found beneath joint-iso-itu-t(2) uuid(25) per X.670. + +# Special Credit + +A special thanks to Luke Champine for his excellent Uint128 package (found at https://github.com/lukechampine/uint128), which is incorporated within this package for X.670 support within NumberForm instances. */ package objectid diff --git a/uint128.LICENSE b/uint128.LICENSE new file mode 100644 index 0000000..a14c6cf --- /dev/null +++ b/uint128.LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2019 Luke Champine + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. From 7a3868364ac795fa9d2e652f7ba0f796b98cace0 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Sat, 7 Oct 2023 17:59:29 -0700 Subject: [PATCH 27/27] stable release prep --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2b56528..234419f 100644 --- a/README.md +++ b/README.md @@ -2,5 +2,5 @@ [![Go Report Card](https://goreportcard.com/badge/JesseCoretta/go-objectid)](https://goreportcard.com/report/github.com/JesseCoretta/go-objectid) [![Go Reference](https://pkg.go.dev/badge/github.com/JesseCoretta/go-objectid.svg)](https://pkg.go.dev/github.com/JesseCoretta/go-objectid) [![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat)](https://github.com/JesseCoretta/go-objectid/blob/main/LICENSE) [![codecov](https://codecov.io/gh/JesseCoretta/go-objectid/graph/badge.svg?token=RLW4DHLKQP)](https://codecov.io/gh/JesseCoretta/go-objectid) [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/JesseCoretta/go-objectid/issues) [![GitHub Workflow Status (with event)](https://img.shields.io/github/actions/workflow/status/JesseCoretta/go-objectid/go.yml)](https://github.com/JesseCoretta/go-objectid/actions/workflows/go.yml) [![Author](https://img.shields.io/badge/author-Jesse_Coretta-darkred?label=%F0%9F%94%BA&labelColor=indigo&color=maroon)](https://www.linkedin.com/in/jessecoretta/) [![Help Animals](https://img.shields.io/badge/donations-yellow?label=%F0%9F%98%BA&labelColor=Yellow)](https://github.com/JesseCoretta/JesseCoretta/blob/main/DONATIONS.md) -Package objectid offers convenient ASN.1 Object Identifier types with useful methods and uint128 support. +Package objectid offers convenient ASN.1 Object Identifier types with useful methods and a uint128-based NumberForm type allowing X.670 support.