From b5c6b40c2f15b0c853ed989bbf4956a6f6c821a1 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 18:24:23 -0700 Subject: [PATCH 01/43] development release --- attr.go | 124 ++++++++++++---------------------------- bind.go | 161 +++++++++++++++++++--------------------------------- cop.go | 2 +- dn.go | 81 +++++++++----------------- filter.go | 117 ++++++++++++++------------------------ ins.go | 22 +++---- misc.go | 34 ++++++----- oid.go | 35 +++++------- parse.go | 5 +- pb.go | 22 +++---- stackage.go | 82 ++++++++++++++++++++++++++ target.go | 97 ++++++++++++------------------- uri.go | 16 +----- 13 files changed, 334 insertions(+), 464 deletions(-) diff --git a/attr.go b/attr.go index b025d15..6528d26 100644 --- a/attr.go +++ b/attr.go @@ -595,8 +595,7 @@ func (r AttributeTypes) Compare(x any) bool { } func (r AttributeTypes) reset() { - _r, _ := castAsStack(r) - _r.Reset() + r.cast().Reset() } func (r AttributeTypes) resetKeyword(x any) { @@ -609,8 +608,7 @@ func (r AttributeTypes) resetKeyword(x any) { r.resetKeyword(tv.String()) case string: - _r, _ := castAsStack(r) - + _r := r.cast() switch lc(tv) { case TargetAttr.String(): _r.SetCategory(lc(tv)). @@ -686,7 +684,7 @@ setQuoteStyle shall set the receiver instance to the quotation scheme defined by integer i. */ func (r AttributeTypes) setQuoteStyle(style int) AttributeTypes { - _r, _ := castAsStack(r) + _r := r.cast() if _r.Len() < 2 { _r.Encap() // not multivalued, force default return r @@ -705,16 +703,14 @@ func (r AttributeTypes) setQuoteStyle(style int) AttributeTypes { IsZero wraps go-stackage's Stack.IsZero method. */ func (r AttributeTypes) IsZero() bool { - _r, _ := castAsStack(r) - return _r.IsZero() + return r.cast().IsZero() } /* Len wraps go-stackage's Stack.Len method. */ func (r AttributeTypes) Len() int { - _r, _ := castAsStack(r) - return _r.Len() + return r.cast().Len() } /* @@ -723,9 +719,7 @@ Boolean OK value returned by go-stackage by default will be shadowed and not obtainable by the caller. */ func (r AttributeTypes) Index(idx int) (x AttributeType) { - _r, _ := castAsStack(r) - z, _ := _r.Index(idx) - + z, _ := r.cast().Index(idx) if assert, asserted := z.(AttributeType); asserted { x = assert } @@ -740,8 +734,7 @@ representation of the receiver instance. This method wraps go-stackage's Stack.String method. */ func (r AttributeTypes) String() string { - _r, _ := castAsStack(r) - return _r.String() + return r.cast().String() } /* @@ -752,8 +745,7 @@ func (r AttributeTypes) Kind() string { if r.IsZero() { return `` } - _r, _ := castAsStack(r) - return _r.Category() + return r.cast().Category() } /* @@ -786,18 +778,16 @@ transfer will "copy" all slice references from the receiver instance into dest instance. PushPolicy controls may apply. */ func (r AttributeTypes) transfer(dest AttributeTypes) { - _r, _ := castAsStack(r) - _dest, _ := castAsStack(dest) - _r.Transfer(_dest) + _r := r.cast() + _d := dest.cast() + _r.Transfer(_d) } /* Pop wraps go-stackage's Stack.Pop method. */ func (r AttributeTypes) Pop() (x AttributeType) { - _r, _ := castAsStack(r) - - z, _ := _r.Pop() + z, _ := r.cast().Pop() if assert, asserted := z.(AttributeType); asserted { x = assert } @@ -812,21 +802,15 @@ it is automatically cast as an instance of AttributeType, so long as the raw string is of a non-zero length. */ func (r AttributeTypes) Push(x ...any) AttributeTypes { - _r, _ := castAsStack(r) - + _r := r.cast() for i := 0; i < len(x); i++ { switch tv := x[i].(type) { case string: - if len(tv) != 0 { - _r.Push(AT(tv)) - } - case AttributeType: - if !tv.IsZero() { - _r.Push(tv) - } + _r.Push(AT(tv)) + default: + _r.Push(tv) } } - return r } @@ -914,42 +898,24 @@ TAs returns a freshly initialized instance of AttributeTypes, configured to store one (1) or more AttributeType instances for the purpose of TargetRule expression when using the `targetattr` keyword context. -Optionally, the caller may choose to submit one (1) or more (valid) instances of the -AttributeType type (or its string equivalent) during initialization. This is merely -a more convenient alternative to separate initialization and push procedures. +Optionally, the caller may choose to submit one (1) or more (valid) instances +of the AttributeType type (or its string equivalent) during initialization. +This is merely a more convenient alternative to separate initialization and +push procedures. -Values are automatically delimited using stackage.Stack.Symbol(`||`) in an -ORed Boolean stack. +Values are automatically delimited using stackage.Stack's Symbol method using +the symbolic OR operator (`||`). */ func TAs(x ...any) (a AttributeTypes) { - // create a native stackage.Stack - // and configure before typecast. _a := stackOr(). Symbol(`||`). NoNesting(true). SetID(targetRuleID). NoPadding(!StackPadding). - SetCategory(TargetAttr.String()) - - // cast _a as a proper AttributeTypes - // instance (a). We do it this way to - // gain access to the method for the - // *specific instance* being created (a), - // thus allowing things like uniqueness - // checks, etc., to occur during push - // attempts, providing more helpful - // and non-generalized feedback. - a = AttributeTypes(_a) - _a.SetPushPolicy(a.pushPolicy) - - // Assuming one (1) or more items were - // submitted during the call, (try to) - // push them into our initialized stack. - // Note that any failed push(es) will - // have no impact on the validity of - // the return instance. - a.Push(x...) + SetCategory(TargetAttr.String()). + SetPushPolicy(a.pushPolicy) + a = AttributeTypes(_a).Push(x...) return } @@ -959,41 +925,23 @@ to store one (1) or more AttributeType instances for the purpose of LDAP Search URI specification of desired AttributeType names. Instances of this design are not generally needed elsewhere. -Optionally, the caller may choose to submit one (1) or more (valid) instances of the -AttributeType type (or its string equivalent) during initialization. This is merely -a more convenient alternative to separate initialization and push procedures. +Optionally, the caller may choose to push one (1) or more (valid) instances +of the AttributeType type (or its string equivalent) during initialization. +This is merely a more convenient alternative to separate initialization and +push procedures. -Values are automatically comma-delimited using stackage.Stack.SetDelimiter -in List mode. +Values are automatically comma-delimited (ASCII #44) using stackage.Stack's +SetDelimiter method in List mode. */ func UAs(x ...any) (a AttributeTypes) { - // create a native stackage.Stack - // and configure before typecast. _a := stackList(). NoNesting(true). - SetID(bindRuleID). - SetDelimiter(rune(44)). NoPadding(true). - SetCategory(``) // URIs qualify for a few different KWs. - - // cast _a as a proper AttributeTypes - // instance (a). We do it this way to - // gain access to the method for the - // *specific instance* being created (a), - // thus allowing things like uniqueness - // checks, etc., to occur during push - // attempts, providing more helpful - // and non-generalized feedback. - a = AttributeTypes(_a) - _a.SetPushPolicy(a.pushPolicy) - - // Assuming one (1) or more items were - // submitted during the call, (try to) - // push them into our initialized stack. - // Note that any failed push(es) will - // have no impact on the validity of - // the return instance. - a.Push(x...) + SetID(targetRuleID). + SetDelimiter(rune(44)). + SetCategory(``). // URIs qualify for a few different KWs. + SetPushPolicy(a.pushPolicy) + a = AttributeTypes(_a).Push(x...) return } diff --git a/bind.go b/bind.go index d6ce68d..96c698b 100644 --- a/bind.go +++ b/bind.go @@ -160,17 +160,16 @@ newBindRule is a private package-level function called by the BR package-level function. */ func newBindRule(kw, op, ex any) (b BindRule) { - c := castAsCondition(b) - c.Init() - c.Encap(`"`). + b.Init() + b.SetKeyword(kw). + SetOperator(op). + SetExpression(ex) + + b.cast(). + Encap(`"`). SetID(bindRuleID). NoPadding(!RulePadding) - b = BindRule(c) - b.SetKeyword(kw) - b.SetOperator(op) - b.SetExpression(ex) - return } @@ -203,7 +202,7 @@ shall be reused (perhaps in a repetative or looped manner), and if it would be desirable to 'wipe the slate clean' for some reason. */ func (r *BindRule) Init() BindRule { - _r := castAsCondition(*r) + _r := r.cast() if _r.IsZero() || !_r.IsInit() { _r.Init() } @@ -338,7 +337,8 @@ func (r BindRule) Kind() string { Len does not perform any useful task, and exists only to satisfy Go's interface signature requirements and to convey this message. -An integer value of one (1) is returned in any scenario. +A value of zero (0) is returned if the receiver instance is nil. A +value of one (1) otherwise. */ func (r BindRule) Len() int { if r.IsZero() { @@ -361,7 +361,7 @@ func (r BindRule) IsNesting() bool { Paren wraps go-stackage's Condition.Paren method. */ func (r BindRule) Paren(state ...bool) BindRule { - castAsCondition(r).Paren(state...) + r.cast().Paren(state...) return r } @@ -369,7 +369,7 @@ func (r BindRule) Paren(state ...bool) BindRule { IsParen wraps go-stackage's Condition.IsParen method. */ func (r BindRule) IsParen() bool { - return castAsCondition(r).IsParen() + return r.cast().IsParen() } /* @@ -381,8 +381,7 @@ func (r BindRule) Valid() (err error) { return } - _t := castAsCondition(r) - err = _t.Valid() + err = r.cast().Valid() return } @@ -393,7 +392,7 @@ func (r BindRule) ID() string { if r.IsZero() { return bindRuleID } - return castAsCondition(r).ID() + return r.cast().ID() } /* @@ -416,7 +415,7 @@ func (r BindRule) String() string { if r.IsZero() { return `` } - return castAsCondition(r).String() + return r.cast().String() } /* @@ -427,7 +426,7 @@ func (r BindRule) NoPadding(state ...bool) BindRule { return r } - castAsCondition(r).NoPadding(state...) + r.cast().NoPadding(state...) return r } @@ -437,7 +436,7 @@ resolves the raw value into a BindKeyword. Failure to do so will return a bogus Keyword. */ func (r BindRule) Keyword() Keyword { - k := castAsCondition(r).Keyword() + k := r.cast().Keyword() var kw any = matchBKW(k) return kw.(BindKeyword) } @@ -448,21 +447,21 @@ and casts the stackage.ComparisonOperator to the local aci.ComparisonOperator. */ func (r BindRule) Operator() ComparisonOperator { - return castCop(castAsCondition(r).Operator()) + return castCop(r.cast().Operator()) } /* Expression wraps go-stackage's Condition.Expression method. */ func (r BindRule) Expression() any { - return castAsCondition(r).Expression() + return r.cast().Expression() } /* IsZero wraps go-stackage's Condition.IsZero method. */ func (r BindRule) IsZero() bool { - return castAsCondition(r).IsZero() + return r.cast().IsZero() } func (r BindRules) isBindContextQualifier() {} @@ -795,7 +794,7 @@ func wordToStack(k string) (BindRules, bool) { SetKeyword wraps go-stackage's Condition.SetKeyword method. */ func (r BindRule) SetKeyword(kw any) BindRule { - cac := castAsCondition(r) + cac := r.cast() if !cac.IsInit() { r.Init() } @@ -830,13 +829,13 @@ func (r BindRule) SetOperator(op any) BindRule { } // not initialized? bail out - if !castAsCondition(r).IsInit() { + if !r.cast().IsInit() { return r } // cast to stackage.Condition and // set operator value. - castAsCondition(r).SetOperator(cop) + r.cast().SetOperator(cop) return r } @@ -845,7 +844,7 @@ func (r BindRule) SetOperator(op any) BindRule { SetExpression wraps go-stackage's Condition.SetExpression method. */ func (r BindRule) SetExpression(expr any) BindRule { - cac := castAsCondition(r) + cac := r.cast() if !cac.IsInit() { cac.Init() } @@ -881,7 +880,7 @@ func (r BindRule) SetQuoteStyle(style int) BindRule { tv.setQuoteStyle(style) } default: - castAsCondition(r).Encap(`"`) + r.cast().Encap(`"`) return r } @@ -898,9 +897,9 @@ func (r BindRule) SetQuoteStyle(style int) BindRule { // will have the opposite setting imposed, which // enables quotation for the individual values. if style == MultivalSliceQuotes { - castAsCondition(r).Encap() + r.cast().Encap() } else { - castAsCondition(r).Encap(`"`) + r.cast().Encap(`"`) } return r @@ -914,16 +913,14 @@ representation of the receiver instance. This method wraps go-stackage's Stack.String method. */ func (r BindRules) String() string { - _b, _ := castAsStack(r) - return _b.String() + return r.cast().String() } /* IsZero wraps go-stackage's Stack.IsZero method. */ func (r BindRules) IsZero() bool { - _b, _ := castAsStack(r) - return _b.IsZero() + return r.cast().IsZero() } /* @@ -931,19 +928,14 @@ reset wraps go-stackage's Stack.Reset method. This is a private method in go-aci. */ func (r BindRules) reset() { - _b, _ := castAsStack(r) - _b.Reset() + r.cast().Reset() } /* ID wraps go-stackage's Stack.ID method. */ func (r BindRules) ID() string { - if r.IsZero() { - return bindRuleID - } - _b, _ := castAsStack(r) - return _b.ID() + return bindRuleID } /* @@ -951,10 +943,9 @@ Category wraps go-stackage's Stack.Category method. */ func (r BindRules) Category() string { if r.IsZero() { - return `` + return `` } - _b, _ := castAsStack(r) - return _b.Category() + return r.cast().Category() } /* @@ -964,8 +955,7 @@ func (r BindRules) Len() int { if r.IsZero() { return 0 } - _b, _ := castAsStack(r) - return _b.Len() + return r.cast().Len() } /* @@ -975,8 +965,7 @@ func (r BindRules) IsNesting() bool { if r.IsZero() { return false } - _b, _ := castAsStack(r) - return _b.IsNesting() + return r.cast().IsNesting() } /* @@ -985,22 +974,15 @@ resolves the raw value into a BindKeyword. Failure to do so will return a bogus Keyword. */ func (r BindRules) Keyword() Keyword { - _r, _ := castAsStack(r) - var kw any = matchBKW(_r.Category()) + var kw any = matchBKW(r.cast().Category()) return kw.(BindKeyword) } /* Push wraps go-stackage's Stack.Push method. */ -func (r BindRules) Push(x ...BindContext) BindRules { - _r, _ := castAsStack(r) - - // iterate variadic input arguments - for i := 0; i < len(x); i++ { - _r.Push(x[i]) - } - +func (r BindRules) Push(x ...any) BindRules { + r.cast().Push(x...) return r } @@ -1025,10 +1007,8 @@ func (r BindRules) pop() (popped BindContext) { return nil } - _r, _ := castAsStack(r) - x, _ := _r.Pop() - - switch tv := x.(type) { + _popped, _ := r.cast().Pop() + switch tv := _popped.(type) { case BindRule: popped = tv case BindRules: @@ -1041,10 +1021,9 @@ func (r BindRules) pop() (popped BindContext) { /* remove wraps go-stackage's Stack.Remove method. */ -func (r BindRules) remove(idx int) bool { - _b, _ := castAsStack(r) - _, ok := _b.Remove(idx) - return ok +func (r BindRules) remove(idx int) (ok bool) { + _, ok = r.cast().Remove(idx) + return } /* @@ -1063,38 +1042,31 @@ func (r BindRules) replace(x any, idx int) BindRules { return r } - _r, _ := castAsStack(r) - _r.Replace(x, idx) + r.cast().Replace(x, idx) return r } /* Index wraps go-stackage's Stack.Index method. */ -func (r BindRules) Index(idx int) BindContext { - _r, _ := castAsStack(r) - y, _ := _r.Index(idx) +func (r BindRules) Index(idx int) (ctx BindContext) { + y, _ := r.cast().Index(idx) - var z any switch tv := y.(type) { case BindRule: - z = tv - return z.(BindRule) + ctx = tv case BindRules: - z = tv - return z.(BindRules) + ctx = tv } - return nil + return } /* ReadOnly wraps go-stackage's Stack.ReadOnly method. */ func (r BindRules) ReadOnly(state ...bool) BindRules { - _r, _ := castAsStack(r) - _r.ReadOnly(state...) - + r.cast().ReadOnly(state...) return r } @@ -1102,9 +1074,7 @@ func (r BindRules) ReadOnly(state ...bool) BindRules { Paren wraps go-stackage's Stack.Paren method. */ func (r BindRules) Paren(state ...bool) BindRules { - _r, _ := castAsStack(r) - _r.Paren(state...) - + r.cast().Paren(state...) return r } @@ -1112,8 +1082,7 @@ func (r BindRules) Paren(state ...bool) BindRules { IsParen wraps go-stackage's Stack.IsParen method. */ func (r BindRules) IsParen() bool { - _r, _ := castAsStack(r) - return _r.IsParen() + return r.cast().IsParen() } /* @@ -1123,9 +1092,7 @@ operators to 'and', 'or' and 'and not' respectively, or vice versa. */ func (r BindRules) Fold(state ...bool) BindRules { - _r, _ := castAsStack(r) - _r.Fold(state...) - + r.cast().Fold(state...) return r } @@ -1133,13 +1100,9 @@ func (r BindRules) Fold(state ...bool) BindRules { insert wraps go-stackage's Stack.Insert method. */ func (r BindRules) insert(x any, left int) (ok bool) { - _t, _ := castAsStack(r) - switch tv := x.(type) { case BindRule, BindRules: - ok = _t.Insert(tv, left) - default: - return + ok = r.cast().Insert(tv, left) } return @@ -1149,9 +1112,7 @@ func (r BindRules) insert(x any, left int) (ok bool) { NoPadding wraps go-stackage's Stack.NoPadding method. */ func (r BindRules) NoPadding(state ...bool) BindRules { - _b, _ := castAsStack(r) - _b.NoPadding(state...) - + r.cast().NoPadding(state...) return r } @@ -1159,8 +1120,7 @@ func (r BindRules) NoPadding(state ...bool) BindRules { Traverse wraps go-stackage's Stack.Traverse method. */ func (r BindRules) Traverse(indices ...int) (B BindContext) { - _b, _ := castAsStack(r) - br, ok := _b.Traverse(indices...) + br, ok := r.cast().Traverse(indices...) if ok { switch tv := br.(type) { case BindContext: @@ -1185,14 +1145,7 @@ func (r BindRules) Traverse(indices ...int) (B BindContext) { Valid wraps go-stackage's Stack.Valid method. */ func (r BindRules) Valid() (err error) { - _b, _ := castAsStack(r) - if r.ID() != bindRuleID { - err = generalErr(bindRuleID, errorf("Unidentified %T instance (ID:%s)", - r, r.ID())) - return err - } - - err = _b.Valid() + err = r.cast().Valid() return } diff --git a/cop.go b/cop.go index b603428..541e497 100644 --- a/cop.go +++ b/cop.go @@ -24,7 +24,7 @@ value, the default go-stackage tag "" is returned. See the ComparisonOperator const definitions for details. */ func (r ComparisonOperator) String() string { - return castAsCop(r).String() + return r.cast().String() } /* diff --git a/dn.go b/dn.go index 99758d5..9b416e1 100644 --- a/dn.go +++ b/dn.go @@ -201,16 +201,14 @@ func (r TargetDistinguishedName) Keyword() Keyword { Valid wraps go-stackage's Stack.Valid method. */ func (r BindDistinguishedNames) Valid() error { - _r, _ := castAsStack(r) - return _r.Valid() + return r.cast().Valid() } /* Valid wraps go-stackage's Stack.Valid method. */ func (r TargetDistinguishedNames) Valid() error { - _r, _ := castAsStack(r) - return _r.Valid() + return r.cast().Valid() } /* @@ -504,8 +502,7 @@ func newDistinguishedName(x string, kw Keyword) (d *distinguishedName) { } func (r BindDistinguishedNames) reset() { - _r, _ := castAsStack(r) - _r.Reset() + r.cast().Reset() } /* @@ -515,12 +512,13 @@ func (r BindDistinguishedNames) resetKeyword(x any) { return } - _r, _ := castAsStack(r) switch tv := x.(type) { case BindKeyword: r.resetKeyword(tv.String()) case string: + _r := r.cast() + switch lc(tv) { case BindUDN.String(): _r.SetCategory(BindUDN.String()). @@ -536,8 +534,7 @@ func (r BindDistinguishedNames) resetKeyword(x any) { } func (r TargetDistinguishedNames) reset() { - _r, _ := castAsStack(r) - _r.Reset() + r.cast().Reset() } /* @@ -547,12 +544,12 @@ func (r TargetDistinguishedNames) resetKeyword(x any) { return } - _r, _ := castAsStack(r) switch tv := x.(type) { case TargetKeyword: r.resetKeyword(tv.String()) case string: + _r := r.cast() switch lc(tv) { case Target.String(): @@ -707,7 +704,7 @@ setQuoteStyle shall set the receiver instance to the quotation scheme defined by integer i. */ func (r BindDistinguishedNames) setQuoteStyle(style int) BindDistinguishedNames { - _r, _ := castAsStack(r) + _r := r.cast() if _r.Len() < 2 { _r.Encap() // not multivalued, force default return r @@ -727,7 +724,7 @@ setQuoteStyle shall set the receiver instance to the quotation scheme defined by integer i. */ func (r TargetDistinguishedNames) setQuoteStyle(style int) TargetDistinguishedNames { - _r, _ := castAsStack(r) + _r := r.cast() if _r.Len() < 2 { _r.Encap() // not multivalued, force default return r @@ -1060,32 +1057,28 @@ func (r TargetDistinguishedNames) setExpressionValues(key Keyword, values ...str IsZero wraps go-stackage's Stack.IsZero method. */ func (r BindDistinguishedNames) IsZero() bool { - _r, _ := castAsStack(r) - return _r.IsZero() + return r.cast().IsZero() } /* IsZero wraps go-stackage's Stack.IsZero method. */ func (r TargetDistinguishedNames) IsZero() bool { - _r, _ := castAsStack(r) - return _r.IsZero() + return r.cast().IsZero() } /* Len wraps go-stackage's Stack.Len method. */ func (r BindDistinguishedNames) Len() int { - _r, _ := castAsStack(r) - return _r.Len() + return r.cast().Len() } /* Len wraps go-stackage's Stack.Len method. */ func (r TargetDistinguishedNames) Len() int { - _r, _ := castAsStack(r) - return _r.Len() + return r.cast().Len() } /* @@ -1100,9 +1093,10 @@ func (r BindDistinguishedNames) Index(idx int) (b DistinguishedNameContext) { ok bool ) - if assert, ok = distinguishedNameIndex(r, idx).(BindDistinguishedName); ok { + y, _ := r.cast().Index(idx) + if assert, ok = y.(BindDistinguishedName); ok { b = assert.(BindDistinguishedName) - } else if assert, ok = distinguishedNameIndex(r, idx).(LDAPURI); ok { + } else if assert, ok = y.(LDAPURI); ok { b = assert.(LDAPURI) } @@ -1116,31 +1110,14 @@ shadowed and not obtainable by the caller. */ func (r TargetDistinguishedNames) Index(idx int) (t TargetDistinguishedName) { t = badTargetDN - if assert, ok := distinguishedNameIndex(r, idx).(TargetDistinguishedName); ok { + y, _ := r.cast().Index(idx) + if assert, ok := y.(TargetDistinguishedName); ok { t = assert } return } -/* -distinguishedNameIndex is a private index function called through instances -of BindDistinguishedName and TargetDistinguishedName. -*/ -func distinguishedNameIndex(r any, idx int) (i any) { - _r, _ := castAsStack(r) - y, _ := _r.Index(idx) - if assert, ok := y.(BindDistinguishedName); ok { - i = assert - } else if assert2, ok2 := y.(TargetDistinguishedName); ok2 { - i = assert2 - } else if assert3, ok3 := y.(LDAPURI); ok3 { - i = assert3 - } - - return -} - /* String is a stringer method that returns the string representation of the receiver instance. @@ -1148,8 +1125,7 @@ representation of the receiver instance. This method wraps go-stackage's Stack.String method. */ func (r BindDistinguishedNames) String() string { - _r, _ := castAsStack(r) - return _r.String() + return r.cast().String() } /* @@ -1159,8 +1135,7 @@ representation of the receiver instance. This method wraps go-stackage's Stack.String method. */ func (r TargetDistinguishedNames) String() string { - _r, _ := castAsStack(r) - return _r.String() + return r.cast().String() } /* @@ -1173,8 +1148,7 @@ func (r BindDistinguishedNames) Keyword() (kw Keyword) { return } - _r, _ := castAsStack(r) - switch _k := lc(_r.Category()); _k { + switch _k := lc(r.cast().Category()); _k { case BindUDN.String(): kw = BindUDN case BindGDN.String(): @@ -1217,8 +1191,7 @@ func (r TargetDistinguishedNames) Keyword() (kw Keyword) { return } - _r, _ := castAsStack(r) - switch _k := lc(_r.Category()); _k { + switch _k := lc(r.cast().Category()); _k { case Target.String(): kw = Target case TargetTo.String(): @@ -1260,7 +1233,6 @@ instance of BindDistinguishedName using the appropriate keyword, so long as the raw string is of a non-zero length. */ func (r BindDistinguishedNames) Push(x ...any) BindDistinguishedNames { - _r, _ := castAsStack(r) kw := r.Keyword() if kw == nil { // not initialized?! @@ -1268,6 +1240,7 @@ func (r BindDistinguishedNames) Push(x ...any) BindDistinguishedNames { } // iterate variadic input arguments + _r := r.cast() for i := 0; i < len(x); i++ { // verify DN or URI value and (possibly) cast // from string->type automatically. @@ -1330,7 +1303,6 @@ instance of TargetDistinguishedName using the appropriate keyword, so long as the raw string is of a non-zero length. */ func (r TargetDistinguishedNames) Push(x ...any) TargetDistinguishedNames { - _r, _ := castAsStack(r) kw := r.Keyword() if kw == nil { // not initialized?! @@ -1338,6 +1310,7 @@ func (r TargetDistinguishedNames) Push(x ...any) TargetDistinguishedNames { } // iterate variadic input arguments + _r := r.cast() for i := 0; i < len(x); i++ { // verify DN value and (possibly) cast from // string->dn automatically. @@ -1461,8 +1434,7 @@ Pop wraps go-stackage's Stack.Pop method and performs type assertion to return a proper BindDistinguishedName instance. */ func (r BindDistinguishedNames) Pop() (popped BindDistinguishedName) { - _r, _ := castAsStack(r) - y, _ := _r.Pop() + y, _ := r.cast().Pop() popped = badBindDN if assert, asserted := y.(BindDistinguishedName); asserted { @@ -1477,8 +1449,7 @@ Pop wraps go-stackage's Stack.Pop method and performs type assertion to return a proper TargetDistinguishedName instance. */ func (r TargetDistinguishedNames) Pop() (popped TargetDistinguishedName) { - _r, _ := castAsStack(r) - y, _ := _r.Pop() + y, _ := r.cast().Pop() popped = badTargetDN if assert, asserted := y.(TargetDistinguishedName); asserted { diff --git a/filter.go b/filter.go index 8041631..393fa64 100644 --- a/filter.go +++ b/filter.go @@ -498,7 +498,7 @@ behavior, but can be set using the AttributeFilterOperationsCommaDelim integer constant (0), or when run in niladic fashion. */ func (r AttributeFilterOperations) SetDelimiter(i ...int) AttributeFilterOperations { - _r, _ := castAsStack(r) + _r := r.cast() var ( // default delimiter is a comma @@ -543,8 +543,7 @@ func (r AttributeFilterOperations) Push(x ...any) AttributeFilterOperations { return r } - _r, _ := castAsStack(r) - + _r := r.cast() for i := 0; i < len(x); i++ { switch tv := x[i].(type) { case string: @@ -553,10 +552,8 @@ func (r AttributeFilterOperations) Push(x ...any) AttributeFilterOperations { _r.Push(afo) } } - case AttributeFilterOperation: - if tv.Len() > 0 { - _r.Push(tv) - } + default: + _r.Push(tv) } } @@ -595,9 +592,7 @@ func (r *AttributeFilterOperations) Parse(raw string, delim ...int) (err error) Pop wraps go-stackage's Stack.Pop method. */ func (r AttributeFilterOperations) Pop() (afo AttributeFilterOperation) { - _r, _ := castAsStack(r) - slice, _ := _r.Pop() - + slice, _ := r.cast().Pop() if assert, ok := slice.(AttributeFilterOperation); ok { afo = assert } @@ -609,8 +604,7 @@ func (r AttributeFilterOperations) Pop() (afo AttributeFilterOperation) { Len wraps go-stackage's Stack.Len method. */ func (r AttributeFilterOperations) Len() int { - _r, _ := castAsStack(r) - return _r.Len() + return r.cast().Len() } /* @@ -619,9 +613,7 @@ Boolean OK value returned by go-stackage by default will be shadowed and not obtainable by the caller. */ func (r AttributeFilterOperations) Index(idx int) (afo AttributeFilterOperation) { - _r, _ := castAsStack(r) - slice, _ := _r.Index(idx) - + slice, _ := r.cast().Index(idx) if assert, ok := slice.(AttributeFilterOperation); ok { afo = assert } @@ -633,8 +625,7 @@ func (r AttributeFilterOperations) Index(idx int) (afo AttributeFilterOperation) IsZero wraps go-stackage's Stack.IsZero method. */ func (r AttributeFilterOperations) IsZero() bool { - _r, _ := castAsStack(r) - return _r.IsZero() + return r.cast().IsZero() } /* @@ -649,7 +640,7 @@ func (r AttributeFilterOperations) Valid() error { // to deceive the package - use the // actual go-stackage index caller so // it won't discriminate types. - _r, _ := castAsStack(r) + _r := r.cast() for i := 0; i < _r.Len(); i++ { slice, _ := _r.Index(i) assert, _ := slice.(AttributeFilterOperation) @@ -673,8 +664,7 @@ String is a stringer method that returns the string representation of the receiver instance. */ func (r AttributeFilterOperations) String() string { - _r, _ := castAsStack(r) - return _r.String() + return r.cast().String() } /* @@ -745,11 +735,6 @@ func (r AttributeFilterOperations) pushPolicy(x ...any) (err error) { } switch tv := x[0].(type) { - case string: - if len(tv) == 0 { - err = pushErrorNilOrZero(r, tv, TargetAttrFilters) - } - case AttributeFilterOperation: // because codecov :/ xerr := tv.Valid() @@ -789,9 +774,6 @@ func (r AttributeFilterOperation) pushPolicy(x ...any) (err error) { err = pushErrorNilOrZero(r, tv, TargetAttrFilters) } - case AttributeOperation: - r.setCategory(tv.makeLabel()) - case AttributeFilter: if err = tv.Valid(); err != nil { err = pushErrorNilOrZero(r, tv, TargetAttrFilters, err) @@ -819,14 +801,27 @@ func (r AttributeFilterOperation) Push(x ...any) AttributeFilterOperation { return r } - _r, _ := castAsStack(r) + _r := r.cast() for i := 0; i < len(x); i++ { switch tv := x[i].(type) { case string: if af, err := parseAttributeFilter(tv); err == nil { _r.Push(af) } - case AttributeFilter: + + // Don't push AO; it was pushed just + // because its a convenient way to + // set the operation on the stack + // receiver instance. But we can't + // put it in our pushPolicy because + // we'd have to return a bogus error + // to prevent a push, which would + // almost definitely confuse people + // reading error logs ... + case AttributeOperation: + r.setCategory(tv.makeLabel()) + + default: _r.Push(tv) } } @@ -838,9 +833,7 @@ func (r AttributeFilterOperation) Push(x ...any) AttributeFilterOperation { Pop wraps go-stackage's Stack.Pop method. */ func (r AttributeFilterOperation) Pop() (af AttributeFilter) { - _r, _ := castAsStack(r) - slice, _ := _r.Pop() - + slice, _ := r.cast().Pop() if assert, ok := slice.(AttributeFilter); ok { af = assert } @@ -873,8 +866,7 @@ func (r AttributeFilterOperation) Keyword() Keyword { Len wraps go-stackage's Stack.Len method. */ func (r AttributeFilterOperation) Len() int { - _r, _ := castAsStack(r) - return _r.Len() + return r.cast().Len() } /* @@ -883,9 +875,7 @@ Boolean OK value returned by go-stackage by default will be shadowed and not obtainable by the caller. */ func (r AttributeFilterOperation) Index(idx int) (af AttributeFilter) { - _r, _ := castAsStack(r) - slice, _ := _r.Index(idx) - + slice, _ := r.cast().Index(idx) if assert, ok := slice.(AttributeFilter); ok { af = assert } @@ -940,8 +930,7 @@ func (r AttributeFilterOperation) contains(x any) bool { IsZero wraps go-stackage's Stack.IsZero method. */ func (r AttributeFilterOperation) IsZero() bool { - _r, _ := castAsStack(r) - return _r.IsZero() + return r.cast().IsZero() } /* @@ -949,7 +938,7 @@ Valid returns an error if the receiver (or any of its contents) is in an aberrant state. */ func (r AttributeFilterOperation) Valid() error { - if r.IsZero() { + if r.IsZero() || r.Len() == 0 { return nilInstanceErr(r) } @@ -962,7 +951,7 @@ func (r AttributeFilterOperation) Valid() error { // to deceive the package - use the // actual go-stackage index caller so // it won't discriminate types. - _r, _ := castAsStack(r) + _r := r.cast() for i := 0; i < _r.Len(); i++ { slice, _ := _r.Index(i) assert, ok := slice.(AttributeFilter) @@ -990,27 +979,22 @@ func (r AttributeFilterOperation) Kind() string { } func (r AttributeFilterOperation) getCategory() string { - _r, _ := castAsStack(r) - return _r.Category() + return r.cast().Category() } /* String is a stringer method that returns the string representation of the receiver instance. */ -func (r AttributeFilterOperation) String() string { +func (r AttributeFilterOperation) String() (s string) { if r.IsZero() { - return `` + return } - _r, _ := castAsStack(r) + _r := r.cast() _r.SetPresentationPolicy(nil) - - f := _r.String() - o := r.Operation() - + s = sprintf("%s=%s", r.Operation(), _r.String()) _r.SetPresentationPolicy(r.presentationPolicy) - - return sprintf("%s=%s", o, f) + return } /* @@ -1077,15 +1061,18 @@ func (r AttributeFilterOperation) TRM() TargetRuleMethods { /* AFO returns a freshly initialized instance of AttributeFilterOperation, configured to store one (1) or more AttributeFilter instances for the purpose of crafting -TargetRule instances which bear the `targattrfilters` keyword context. +TargetRule instances which bear the `targattrfilters` keyword context. Instances of +this design are not generally needed outside of that context. Optionally, the caller may choose to submit one (1) or more (valid) instances of the AttributeFilter type (or its string equivalent) during initialization. This is merely a more convenient alternative to separate init and push procedures. -Instances of this design are not generally needed elsewhere. +Multiple values are automatically ANDed using stackage.And() using the symbolic AND +operator (&&). -Values are automatically ANDed using stackage.And() in symbol (&&) mode. +See also the AttributeFilterOperations type, and its AFOs function, for the multi-valued +incarnation of this type. */ func AFO(x ...any) (f AttributeFilterOperation) { // create a native stackage.Stack @@ -1096,24 +1083,9 @@ func AFO(x ...any) (f AttributeFilterOperation) { NoPadding(!StackPadding). SetCategory(TargetAttrFilters.String()) - // cast _f as a proper AttributeFilterOperation - // instance (f). We do it this way to gain - // access to the method for the *specific - // instance* being created (f), thus allowing - // a custom presentation policy to be set. f = AttributeFilterOperation(_f) - - // Set custom Presentation/Push policies - // per go-stackage signatures. _f.SetPresentationPolicy(f.presentationPolicy). SetPushPolicy(f.pushPolicy) - - // Assuming one (1) or more items were - // submitted during the call, (try to) - // push them into our initialized stack. - // Note that any failed push(es) will - // have no impact on the validity of - // the return instance. f.Push(x...) return @@ -1145,8 +1117,7 @@ func (r AttributeOperation) makeLabel() string { setCategory assigns the categorical string label (cat) to the receiver. */ func (r AttributeFilterOperation) setCategory(cat string) { - nx, _ := castAsStack(r) - nx.SetCategory(cat) + r.cast().SetCategory(cat) } /* diff --git a/ins.go b/ins.go index 3e48082..6d0b786 100644 --- a/ins.go +++ b/ins.go @@ -116,8 +116,7 @@ func (r Instructions) pushPolicy(x ...any) (err error) { Len wraps go-stackage's Stack.Len method. */ func (r Instructions) Len() int { - _r, _ := castAsStack(r) - return _r.Len() + return r.cast().Len() } /* @@ -163,8 +162,7 @@ func (r Instructions) contains(x any) bool { IsZero wraps go-stackage's Stack.IsZero method. */ func (r Instructions) IsZero() bool { - _r, _ := castAsStack(r) - return _r.IsZero() + return r.cast().IsZero() } /* @@ -174,8 +172,7 @@ representation of the receiver instance. This method wraps go-stackage's Stack.String method. */ func (r Instructions) String() string { - _r, _ := castAsStack(r) - return _r.String() + return r.cast().String() } /* @@ -203,7 +200,7 @@ instance of BindDistinguishedName using the appropriate keyword, so long as the raw string is of a non-zero length. */ func (r Instructions) Push(x ...any) Instructions { - _r, _ := castAsStack(r) + _r := r.cast() // iterate variadic input arguments for i := 0; i < len(x); i++ { @@ -225,9 +222,7 @@ func (r Instructions) Push(x ...any) Instructions { Pop wraps go-stackage's Stack.Pop method. */ func (r Instructions) Pop() (x Instruction) { - _r, _ := castAsStack(r) - y, _ := _r.Pop() - + y, _ := r.cast().Pop() if assert, asserted := y.(Instruction); asserted { x = assert } @@ -250,8 +245,7 @@ func (r Instructions) F() func(...any) Instruction { Valid wraps go-stackage's Stack.Valid method. */ func (r Instructions) Valid() (err error) { - _b, _ := castAsStack(r) - err = _b.Valid() + err = r.cast().Valid() return } @@ -261,9 +255,7 @@ Boolean OK value returned by go-stackage by default will be shadowed and not obtainable by the caller. */ func (r Instructions) Index(idx int) (x Instruction) { - _r, _ := castAsStack(r) - y, _ := _r.Index(idx) - + y, _ := r.cast().Index(idx) if assert, ok := y.(Instruction); ok { x = assert } diff --git a/misc.go b/misc.go index 183cada..0a27dac 100644 --- a/misc.go +++ b/misc.go @@ -274,23 +274,31 @@ func isPowerOfTwo(x int) bool { /* Hash computes a SHA-1 hash value, derived from the String -method output of input value x. +method output (or string value) of input value x. The hash, if generated, is cast as a string prior to being returned alongside an error. -If input value x lacks a String method, or if no string -value was returned as a result of its execution, the error -instance returned shall be non-nil. - -Neither this function, nor any of the many 'Compare' methods -extended through eligible types which make use of this very -function, should be used to gauge "validity", "nilness" or -"initialization status". In certain cases, two (2) dissimilar -(and invalid!) instances of the same type shall evaluate as -"equal". When the process of string representation yields the -same effective value for two (2) type instances, this is both -guaranteed and expected behavior. +Input value x must qualify as one (1) of the following: + + - Must be a string in of itself, OR ... + - Must be a type instance that has its own stringer method + +Failing the above, a non-nil error instance is returned. + +This package-level function is the basis for all Compare +methods extended by myriad types throughout this package. +In most cases, using an available Compare method is easier +than using this function directly. + +The hash evaluation offered by this package is meant to act +as a supplement in a change review process or similar. The +return value should not be used to gauge "validity", "nilness" +or "initialization status" of an instance. In certain cases, +two (2) dissimilar (and invalid!) instances of the same type +shall evaluate as "equal". When string representation yields +the same effective value for two (2) type instances, this is +both guaranteed and expected behavior. */ func Hash(x any) (string, error) { return hashInstance(x) diff --git a/oid.go b/oid.go index cef6b28..71f2ba0 100644 --- a/oid.go +++ b/oid.go @@ -314,8 +314,7 @@ func (r ObjectIdentifiers) TRM() TargetRuleMethods { IsZero wraps go-stackage's Stack.IsZero method. */ func (r ObjectIdentifiers) IsZero() bool { - _r, _ := castAsStack(r) - return _r.IsZero() + return r.cast().IsZero() } /* @@ -334,8 +333,7 @@ func (r ObjectIdentifiers) Valid() (err error) { Len wraps go-stackage's Stack.Len method. */ func (r ObjectIdentifiers) Len() int { - _r, _ := castAsStack(r) - return _r.Len() + return r.cast().Len() } /* @@ -344,9 +342,7 @@ Boolean OK value returned by go-stackage by default will be shadowed and not obtainable by the caller. */ func (r ObjectIdentifiers) Index(idx int) (x ObjectIdentifier) { - _r, _ := castAsStack(r) - y, _ := _r.Index(idx) - + y, _ := r.cast().Index(idx) if assert, ok := y.(ObjectIdentifier); ok { x = assert } @@ -362,8 +358,7 @@ representation of the receiver instance. This method wraps go-stackage's Stack.String method. */ func (r ObjectIdentifiers) String() string { - _r, _ := castAsStack(r) - return _r.String() + return r.cast().String() } /* @@ -378,13 +373,13 @@ func (r ObjectIdentifiers) Compare(x any) bool { Push wraps go-stackage's Stack.Push method. */ func (r ObjectIdentifiers) Push(x ...any) ObjectIdentifiers { - _r, _ := castAsStack(r) + _r := r.cast() for i := 0; i < len(x); i++ { switch tv := x[i].(type) { case string: _r.Push(r.F()(tv)) - case ObjectIdentifier: + default: _r.Push(tv) } } @@ -449,9 +444,7 @@ func (r ObjectIdentifiers) contains(x any) bool { Pop wraps go-stackage's Stack.Pop method. */ func (r ObjectIdentifiers) Pop() (x ObjectIdentifier) { - _r, _ := castAsStack(r) - y, _ := _r.Pop() - + y, _ := r.cast().Pop() if assert, asserted := y.(ObjectIdentifier); asserted { x = assert } @@ -464,7 +457,7 @@ setQuoteStyle shall set the receiver instance to the quotation scheme defined by integer i. */ func (r ObjectIdentifiers) setQuoteStyle(style int) ObjectIdentifiers { - _r, _ := castAsStack(r) + _r := r.cast() if _r.Len() < 2 { _r.Encap() // not multivalued, force default return r @@ -578,8 +571,7 @@ func (r ObjectIdentifiers) F() func(...any) ObjectIdentifier { } func (r ObjectIdentifiers) reset() { - _r, _ := castAsStack(r) - _r.Reset() + r.cast().Reset() } func (r ObjectIdentifiers) resetKeyword(x any) { @@ -592,7 +584,7 @@ func (r ObjectIdentifiers) resetKeyword(x any) { r.resetKeyword(tv.String()) case string: - _r, _ := castAsStack(r) + _r := r.cast() switch lc(tv) { case TargetExtOp.String(): @@ -763,8 +755,7 @@ func (r ObjectIdentifiers) ID() string { return `` } - _t, _ := castAsStack(r) - return _t.ID() + return r.cast().ID() } /* @@ -775,8 +766,8 @@ func (r ObjectIdentifiers) Kind() (k string) { if r.IsZero() { return } - _r, _ := castAsStack(r) - switch _k := lc(_r.Category()); _k { + + switch _k := lc(r.cast().Category()); _k { case TargetExtOp.String(), TargetCtrl.String(): k = _k diff --git a/parse.go b/parse.go index 18684bb..177b2aa 100644 --- a/parse.go +++ b/parse.go @@ -782,10 +782,9 @@ func assertTargetAttrFilters(expr parser.RuleExpression) (ex AttributeFilterOper // Still nothing? Try AttributeFilterOperation (whether // multivalued or not). var afo AttributeFilterOperation - if afo, err = parseAttributeFilterOperation(value); err != nil { - return + if afo, err = parseAttributeFilterOperation(value); err == nil { + ex = AFOs(afo) } - ex = AFOs(afo) } else { // The only other thing it could be is a bare AttributeFilter. diff --git a/pb.go b/pb.go index 9856370..2669d00 100644 --- a/pb.go +++ b/pb.go @@ -200,8 +200,7 @@ func (r PermissionBindRule) string() (s string) { Valid wraps go-stackage's Stack.Valid method. */ func (r PermissionBindRules) Valid() (err error) { - _t, _ := castAsStack(r) - err = _t.Valid() + err = r.cast().Valid() return } @@ -209,16 +208,14 @@ func (r PermissionBindRules) Valid() (err error) { IsZero wraps go-stackage's Stack.IsZero method. */ func (r PermissionBindRules) IsZero() bool { - _r, _ := castAsStack(r) - return _r.IsZero() + return r.cast().IsZero() } /* Len wraps go-stackage's Stack.Len method. */ func (r PermissionBindRules) Len() int { - _r, _ := castAsStack(r) - return _r.Len() + return r.cast().Len() } /* @@ -233,9 +230,7 @@ Index wraps go-stackage's Stack.Index method and performs type assertion in order to return an instance of PermissionBindRule. */ func (r PermissionBindRules) Index(idx int) (pbr PermissionBindRule) { - _r, _ := castAsStack(r) - x, _ := _r.Index(idx) - + x, _ := r.cast().Index(idx) if assert, asserted := x.(PermissionBindRule); asserted { pbr = assert } @@ -250,8 +245,7 @@ representation of the receiver instance. This method wraps go-stackage's Stack.String method. */ func (r PermissionBindRules) String() string { - _r, _ := castAsStack(r) - return _r.String() + return r.cast().String() } /* @@ -266,7 +260,7 @@ func (r PermissionBindRules) Compare(x any) bool { Push wraps go-stackage's Stack.Push method. */ func (r PermissionBindRules) Push(x ...any) PermissionBindRules { - _r, _ := castAsStack(r) + _r := r.cast() // iterate variadic input arguments for i := 0; i < len(x); i++ { @@ -295,9 +289,7 @@ Within the context of the receiver type, a PermissionBindRule, if non-nil, can only represent a PermissionBindRule instance. */ func (r PermissionBindRules) Pop() (pbr PermissionBindRule) { - _r, _ := castAsStack(r) - x, _ := _r.Pop() - + x, _ := r.cast().Pop() if assert, ok := x.(PermissionBindRule); ok { pbr = assert } diff --git a/stackage.go b/stackage.go index fdc704d..5640112 100644 --- a/stackage.go +++ b/stackage.go @@ -186,6 +186,88 @@ func castAsCondition(x any) (c stackage.Condition) { return } +/* +cast is a private convenience method intended to streamline +the act of casting a BindRule instance to a stackage.Condition +instance if access to unwrapped methods is needed. +*/ +func (r BindRule) cast() stackage.Condition { + return castAsCondition(r) +} + +/* +cast is a private convenience method intended to streamline +the act of casting a BindRules instance to a stackage.Stack +instance if access to unwrapped methods is needed. +*/ +func (r BindRules) cast() stackage.Stack { + x, _ := castAsStack(r) + return x +} + +/* +cast is a private convenience method intended to streamline +the act of casting a TargetRule instance to a stackage.Condition +instance if access to unwrapped methods is needed. +*/ +func (r TargetRule) cast() stackage.Condition { + return castAsCondition(r) +} + +/* +cast is a private convenience method intended to streamline +the act of casting a TargetRules instance to a stackage.Stack +instance if access to unwrapped methods is needed. +*/ +func (r TargetRules) cast() stackage.Stack { + x, _ := castAsStack(r) + return x +} + +func (r AttributeTypes) cast() stackage.Stack { + x, _ := castAsStack(r) + return x +} + +func (r BindDistinguishedNames) cast() stackage.Stack { + x, _ := castAsStack(r) + return x +} + +func (r AttributeFilterOperation) cast() stackage.Stack { + x, _ := castAsStack(r) + return x +} + +func (r AttributeFilterOperations) cast() stackage.Stack { + x, _ := castAsStack(r) + return x +} + +func (r PermissionBindRules) cast() stackage.Stack { + x, _ := castAsStack(r) + return x +} + +func (r Instructions) cast() stackage.Stack { + x, _ := castAsStack(r) + return x +} + +func (r ObjectIdentifiers) cast() stackage.Stack { + x, _ := castAsStack(r) + return x +} + +func (r TargetDistinguishedNames) cast() stackage.Stack { + x, _ := castAsStack(r) + return x +} + +func (r ComparisonOperator) cast() stackage.ComparisonOperator { + return castAsCop(r) +} + func castAsBindRule(x any) BindRule { assert, ok := x.(stackage.Condition) if !ok { diff --git a/target.go b/target.go index fc8ffa4..7499718 100644 --- a/target.go +++ b/target.go @@ -264,7 +264,7 @@ shall be reused (perhaps in a repetative or looped manner), and if it would be desirable to 'wipe the slate clean' for some reason. */ func (r *TargetRule) Init() TargetRule { - _r := castAsCondition(*r) + _r := r.cast() if _r.IsZero() || !_r.IsInit() { _r.Init() } @@ -279,19 +279,16 @@ auto-executes -- among other things -- the stackage.Condition.Init method. */ func newTargetRule(kw, op, ex any) (t TargetRule) { - - c := castAsCondition(t) - c.Init() - c.Encap(`"`). + t.Init() + t.SetKeyword(kw). + SetOperator(op). + SetExpression(ex). + cast(). + Encap(`"`). Paren(true). SetID(targetRuleID). NoPadding(!RulePadding) - t = TargetRule(c) - t.SetKeyword(kw) - t.SetOperator(op) - t.SetExpression(ex) - return } @@ -304,8 +301,7 @@ func (r TargetRule) Valid() (err error) { return } - _t := castAsCondition(r) - + _t := r.cast() if !keywordAllowsComparisonOperator(_t.Keyword(), _t.Operator()) { err = badPTBRuleKeywordErr( _t, `target`, `target_keyword`, @@ -358,13 +354,10 @@ func (r TargetRule) Category() string { } /* -ID wraps go-stackage's Condition.ID method. +ID returns the string literal `target`. */ func (r TargetRule) ID() string { - if r.IsZero() { - return `` - } - return castAsCondition(r).ID() + return targetRuleID } /* @@ -378,7 +371,7 @@ func (r TargetRule) String() string { return `` } - tr := castAsCondition(r) + tr := r.cast() if !tr.IsParen() { tr.Paren(true) } @@ -394,7 +387,7 @@ func (r TargetRule) NoPadding(state ...bool) TargetRule { return r } - castAsCondition(r).NoPadding(state...) + r.cast().NoPadding(state...) return r } @@ -440,7 +433,7 @@ func (r TargetRule) SetQuoteStyle(style int) TargetRule { tv.setQuoteStyle(style) } default: - castAsCondition(r).Encap(`"`) + r.cast().Encap(`"`) return r } @@ -457,9 +450,9 @@ func (r TargetRule) SetQuoteStyle(style int) TargetRule { // will have the opposite setting imposed, which // enables quotation for the individual values. if style == MultivalSliceQuotes { - castAsCondition(r).Encap() + r.cast().Encap() } else { - castAsCondition(r).Encap(`"`) + r.cast().Encap(`"`) } return r @@ -470,7 +463,7 @@ func (r TargetRule) SetQuoteStyle(style int) TargetRule { SetKeyword wraps go-stackage's Condition.SetKeyword method. */ func (r TargetRule) SetKeyword(kw any) TargetRule { - castAsCondition(r).SetKeyword(kw) + r.cast().SetKeyword(kw) return r } @@ -506,13 +499,13 @@ func (r TargetRule) SetOperator(op any) TargetRule { } // not initialized? bail out - if !castAsCondition(r).IsInit() { + if !r.cast().IsInit() { return r } // cast to stackage.Condition and // set operator value. - castAsCondition(r).SetOperator(cop) + r.cast().SetOperator(cop) return r } @@ -521,7 +514,7 @@ func (r TargetRule) SetOperator(op any) TargetRule { SetExpression wraps go-stackage's Condition.SetExpression method. */ func (r TargetRule) SetExpression(expr any) TargetRule { - cac := castAsCondition(r) + cac := r.cast() if !cac.IsInit() { cac.Init() } @@ -537,8 +530,7 @@ resolves the raw value into a TargetKeyword. Failure to do so will return a bogus Keyword. */ func (r TargetRule) Keyword() Keyword { - k := castAsCondition(r).Keyword() - var kw any = matchTKW(k) + var kw any = matchTKW(r.cast().Keyword()) return kw.(TargetKeyword) } @@ -546,21 +538,21 @@ func (r TargetRule) Keyword() Keyword { Operator wraps go-stackage's Condition.Operator method. */ func (r TargetRule) Operator() ComparisonOperator { - return castCop(castAsCondition(r).Operator()) + return castCop(r.cast().Operator()) } /* Expression wraps go-stackage's Condition.Expression method. */ func (r TargetRule) Expression() any { - return castAsCondition(r).Expression() + return r.cast().Expression() } /* IsZero wraps go-stackage's Condition.IsZero method. */ func (r TargetRule) IsZero() bool { - return castAsCondition(r).IsZero() + return r.cast().IsZero() } /* @@ -663,16 +655,14 @@ representation of the receiver instance. This method wraps go-stackage's Stack.String method. */ func (r TargetRules) String() string { - _t, _ := castAsStack(r) - return _t.String() + return r.cast().String() } /* IsZero wraps go-stackage's Stack.IsZero method. */ func (r TargetRules) IsZero() bool { - _t, _ := castAsStack(r) - return _t.IsZero() + return r.cast().IsZero() } /* @@ -683,9 +673,7 @@ func (r TargetRules) reset() { if r.IsZero() { return } - - _t, _ := castAsStack(r) - _t.Reset() + r.cast().Reset() } /* @@ -699,20 +687,14 @@ func (r TargetRules) Category() string { Len wraps go-stackage's Stack.Len method. */ func (r TargetRules) Len() int { - _t, _ := castAsStack(r) - return _t.Len() + return r.cast().Len() } /* Push wraps go-stackage's Stack.Push method. */ func (r TargetRules) Push(x ...any) TargetRules { - _r, _ := castAsStack(r) - // iterate variadic input arguments - for i := 0; i < len(x); i++ { - _r.Push(x[i]) - } - + r.cast().Push(x...) return r } @@ -724,9 +706,7 @@ Within the context of the receiver type, a RuleContext, if non-nil, can only represent a TargetRule instance. */ func (r TargetRules) Pop() TargetRule { - _r, _ := castAsStack(r) - x, _ := _r.Pop() - + x, _ := r.cast().Pop() assert, _ := x.(TargetRule) return assert } @@ -735,8 +715,7 @@ func (r TargetRules) Pop() TargetRule { remove wraps go-stackage's Stack.Remove method. */ func (r TargetRules) remove(idx int) bool { - _t, _ := castAsStack(r) - _, ok := _t.Remove(idx) + _, ok := r.cast().Remove(idx) return ok } @@ -744,9 +723,7 @@ func (r TargetRules) remove(idx int) bool { Index wraps go-stackage's Stack.Index method. */ func (r TargetRules) Index(idx int) TargetRule { - _r, _ := castAsStack(r) - y, _ := _r.Index(idx) - + y, _ := r.cast().Index(idx) assert, _ := y.(TargetRule) return assert } @@ -755,19 +732,20 @@ func (r TargetRules) Index(idx int) TargetRule { ReadOnly wraps go-stackage's Stack.ReadOnly method. */ func (r TargetRules) ReadOnly(state ...bool) TargetRules { - _t, _ := castAsStack(r) - _t.ReadOnly(state...) + r.cast().ReadOnly(state...) return r } /* -NoPadding wraps go-stackage's Stack.NoPadding method. +NoPadding sets the delimiter to a SPACE (ASCII #32 ) or to +a zero-string depending on the state input. */ func (r TargetRules) NoPadding(state ...bool) TargetRules { - _t, _ := castAsStack(r) + _t := r.cast() if !_t.IsInit() { return badTargetRules } + var st bool = false if len(state) == 0 { if len(_t.Delimiter()) != 0 { @@ -787,8 +765,7 @@ func (r TargetRules) NoPadding(state ...bool) TargetRules { Valid wraps go-stackage's Stack.Valid method. */ func (r TargetRules) Valid() (err error) { - _t, _ := castAsStack(r) - err = _t.Valid() + err = r.cast().Valid() return } diff --git a/uri.go b/uri.go index cf7b9d2..9a49582 100644 --- a/uri.go +++ b/uri.go @@ -388,21 +388,7 @@ func (r LDAPURI) makeBindRule(negate ...bool) BindRule { } // assemble our BindRule instance ... - var b BindRule = BR(kw, oper, r) - - // temporarily cast as a stackage.Condition - // so we can apply some additional changes - // using methods we didn't wrap because it - // wouldn't be necessary otherwise. - /* - castAsCondition(b). - Encap(`"`). - SetID(bindRuleID). - NoPadding(!RulePadding). - SetCategory(kw.String()) - */ - - return b + return BR(kw, oper, r) } /* From df88d1dd55fbd61752d40b3570989baf1b839063 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 18:40:34 -0700 Subject: [PATCH 02/43] development release --- time.go | 16 +++++----------- time_test.go | 11 +++++++++++ 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/time.go b/time.go index 707239e..6c66f2f 100644 --- a/time.go +++ b/time.go @@ -8,6 +8,8 @@ import ( "time" ) +var now func() time.Time = time.Now + /* Day constants can be shifted into an instance of DayOfWeek, allowing effective expressions such as "Sun,Tues". See the DayOfWeek.Set method. */ @@ -600,17 +602,9 @@ Valid input types are string and time.Time. The effective hour and minute values should ALWAYS fall within the valid clock range of 0000 up to and including 2400. Bogus values within said range, such as 0477, will return an error. */ -func (r *TimeOfDay) Set(t any) *TimeOfDay { - if r == nil { - *r = newTimeOfDay(t) - return r - } else if r.timeOfDay.isZero() { - *r = newTimeOfDay(t) - return r - } - - r.timeOfDay.set(t) - return r +func (r *TimeOfDay) Set(t any) TimeOfDay { + *r = newTimeOfDay(t) + return *r } func (r *timeOfDay) isZero() bool { diff --git a/time_test.go b/time_test.go index 203590f..7fe0683 100644 --- a/time_test.go +++ b/time_test.go @@ -224,6 +224,17 @@ func TestToD(t *testing.T) { cops map[ComparisonOperator]func() BindRule ) + bunk := ToD(``) + _ = bunk.String() + _ = bunk.IsZero() + bunk = ToD(now()) + _ = bunk.String() + + var bunk2 TimeOfDay + bunk2.Set(nil) + _ = bunk2.String() + _ = bunk2.IsZero() + got := ToD(thyme) if got.String() != thyme && want { err = unexpectedStringResult(typ, thyme, got.String()) From f1b3e837c069433284e3a7eac36af553a7557b5c Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 18:43:59 -0700 Subject: [PATCH 03/43] development release --- time.go | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/time.go b/time.go index 6c66f2f..a8eca00 100644 --- a/time.go +++ b/time.go @@ -255,10 +255,8 @@ String is a stringer method that returns the string representation of the receiv instance. At least one Day's bits should register as positive in order for a valid string return to ensue. */ -func (r DayOfWeek) String() string { - if r.IsZero() { - return badDoW - } +func (r DayOfWeek) String() (s string) { + s = badDoW var dows []string for i := 0; i < bitSize(noDay); i++ { @@ -268,11 +266,11 @@ func (r DayOfWeek) String() string { } } - if len(dows) == 0 { - return badDoW + if len(dows) > 0 { + s = join(dows, `,`) } - return join(dows, `,`) + return } /* From 56c02c828b323807a8876018328460c8a9f379a8 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 18:46:26 -0700 Subject: [PATCH 04/43] development release --- time.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/time.go b/time.go index a8eca00..a927915 100644 --- a/time.go +++ b/time.go @@ -610,9 +610,6 @@ func (r *timeOfDay) isZero() bool { } func (r *timeOfDay) set(t any) { - if r.isZero() { - r = new(timeOfDay) - } assertToD(r, t) } @@ -628,10 +625,9 @@ func assertToD(r *timeOfDay, t any) { case time.Time: // time.Time input results in a recursive // run of this method. - if tv.IsZero() { - break + if !tv.IsZero() { + r.set(sprintf("%02d%02d", tv.Hour(), tv.Minute())) } - r.set(sprintf("%02d%02d", tv.Hour(), tv.Minute())) case string: // Handle discrepancy between ACI time, which ends // at 2400, and Golang Time, which ends at 2359. From 8cee8c28f33b8ffb138dc471532f0a58f0f8e3d4 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 19:06:14 -0700 Subject: [PATCH 05/43] development release --- filter.go | 36 +++++++++++++++++++++--------------- filter_test.go | 12 ++++++++++++ 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/filter.go b/filter.go index 393fa64..d0ec8e0 100644 --- a/filter.go +++ b/filter.go @@ -588,6 +588,20 @@ func (r *AttributeFilterOperations) Parse(raw string, delim ...int) (err error) return } +/* +Parse returns an error instance following an attempt to parse input +raw into the receiver instance. A successful parse will clobber (or +obliterate) any contents already present within the receiver. +*/ +func (r *AttributeFilterOperation) Parse(raw string) error { + afo, err := parseAttributeFilterOperation(raw) + if err == nil { + *r = afo + } + + return err +} + /* Pop wraps go-stackage's Stack.Pop method. */ @@ -937,14 +951,10 @@ func (r AttributeFilterOperation) IsZero() bool { Valid returns an error if the receiver (or any of its contents) is in an aberrant state. */ -func (r AttributeFilterOperation) Valid() error { +func (r AttributeFilterOperation) Valid() (err error) { if r.IsZero() || r.Len() == 0 { - return nilInstanceErr(r) - } - - if !hasPfx(r.getCategory(), TargetAttrFilters.String()) { - err := unexpectedKindErr(r, TargetAttrFilters.String(), r.getCategory()) - return err + err = nilInstanceErr(r) + return } // assume the object has been fashioned @@ -954,17 +964,13 @@ func (r AttributeFilterOperation) Valid() error { _r := r.cast() for i := 0; i < _r.Len(); i++ { slice, _ := _r.Index(i) - assert, ok := slice.(AttributeFilter) - if !ok { - return illegalSliceTypeErr(r, assert, slice) - } - - if err := assert.Valid(); err != nil { - return err + assert, _ := slice.(AttributeFilter) + if err = assert.Valid(); err != nil { + break } } - return nil + return } /* diff --git a/filter_test.go b/filter_test.go index a762d41..aec3988 100644 --- a/filter_test.go +++ b/filter_test.go @@ -335,6 +335,18 @@ func TestAttributeFilterOperations_toTargetRule(t *testing.T) { _ = afos.Valid() _ = afos.Eq() + var af AttributeFilter + var afo AttributeFilterOperation + _ = af.Parse(` lies `) + _ = afo.Parse(` lies `) + _ = afos.Parse(` lies `) + _ = af.IsZero() + _ = afo.IsZero() + _ = afos.IsZero() + _ = af.String() + _ = afo.String() + _ = afos.String() + // for codecov if !afos.IsZero() { t.Errorf("%s failed [%T.IsZero]:\nwant 'true'\ngot 'false'", From b08581669fb60c7a59b967c6e39bf7cbcd8f6614 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 19:47:32 -0700 Subject: [PATCH 06/43] development release --- target.go | 45 ++++++++++++++++++++++++--------------------- target_test.go | 13 ++++++++++++- 2 files changed, 36 insertions(+), 22 deletions(-) diff --git a/target.go b/target.go index 7499718..d85ba22 100644 --- a/target.go +++ b/target.go @@ -463,7 +463,13 @@ func (r TargetRule) SetQuoteStyle(style int) TargetRule { SetKeyword wraps go-stackage's Condition.SetKeyword method. */ func (r TargetRule) SetKeyword(kw any) TargetRule { - r.cast().SetKeyword(kw) + switch tv := kw.(type) { + case string: + r.cast().SetKeyword(matchTKW(tv)) + case Keyword: + r.cast().SetKeyword(matchTKW(tv.String())) + } + return r } @@ -484,6 +490,11 @@ func (r TargetRule) SetOperator(op any) TargetRule { return r } + // operator not known? bail out + if cop == ComparisonOperator(0) { + return r + } + // ALL Target and Bind rules accept Eq, // so only scrutinize the operator if // it is something *other than* that. @@ -493,20 +504,13 @@ func (r TargetRule) SetOperator(op any) TargetRule { } } - // operator not known? bail out - if cop == ComparisonOperator(0) { - return r - } - // not initialized? bail out - if !r.cast().IsInit() { - return r + if r.cast().IsInit() { + // cast to stackage.Condition and + // set operator value. + r.cast().SetOperator(cop) } - // cast to stackage.Condition and - // set operator value. - r.cast().SetOperator(cop) - return r } @@ -746,17 +750,16 @@ func (r TargetRules) NoPadding(state ...bool) TargetRules { return badTargetRules } - var st bool = false - if len(state) == 0 { - if len(_t.Delimiter()) != 0 { - st = true - } + var s bool = len(_t.Delimiter()) == 0 + var pad string + if len(state) > 0 { + s = state[0] } - if st { - _t.SetDelimiter(``) - } else { - _t.SetDelimiter(string(rune(32))) + + if !s { + pad = string(rune(32)) } + _t.SetDelimiter(pad) return r } diff --git a/target_test.go b/target_test.go index b608a61..ee6ac38 100644 --- a/target_test.go +++ b/target_test.go @@ -81,7 +81,8 @@ func TestTargetRule_bogus(t *testing.T) { _ = tr.SetExpression(nil) tr.Init() - tr.SetKeyword(BindUDN) // wrong class of kw + tr.SetKeyword(`binddn`) // wrong class of kw + tr.SetKeyword(BindUDN) // wrong class of kw if err := tr.Valid(); err == nil { t.Errorf("%s failed: no error where one should be (bogus kw set for TR)", @@ -93,6 +94,11 @@ func TestTargetRule_bogus(t *testing.T) { tr.SetOperator(ComparisonOperator(99)) tr.SetOperator(`hello`) tr.SetOperator(`=`) + tr.SetKeyword(`target`) + tr.SetKeyword(TargetScope) + _ = tr.NoPadding() + _ = tr.NoPadding(false) + _ = tr.NoPadding(true) } // mainly this exists to satisfy codecov, but also @@ -109,6 +115,7 @@ func TestTargetRules_bogus(t *testing.T) { _ = tr.Valid() _ = tr.ReadOnly() _ = tr.NoPadding() + _ = tr.NoPadding(false) _ = tr.NoPadding(true) _ = tr.String() _ = tr.Push() @@ -124,7 +131,11 @@ func TestTargetRules_bogus(t *testing.T) { tr.NoPadding() _ = tr.Push() _ = tr.Push(``) + _ = tr.NoPadding() + _ = tr.NoPadding(false) + _ = tr.NoPadding(true) _ = tr.Push(Target) + _ = tr.Push(TargetRule{}) _ = tr.Push(nil, nil) _ = tr.Push('𝝅') tr.Push(TDN(`uid=jesse,ou=People,dc=example,dc=com`).Eq()) From 0525b713fd3f541144c6ac0e53f3c277fa612833 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 20:01:26 -0700 Subject: [PATCH 07/43] development release --- dn.go | 24 ------------------------ dn_test.go | 7 +++++-- 2 files changed, 5 insertions(+), 26 deletions(-) diff --git a/dn.go b/dn.go index 9b416e1..8458dcc 100644 --- a/dn.go +++ b/dn.go @@ -1465,10 +1465,6 @@ PushPolicy interface signature. This is called during Push attempts to a stack containing BindRule userdn distinguished name instances. */ func (r BindDistinguishedNames) uDNPushPolicy(x ...any) error { - if len(x) == 0 { - return nil - } - if r.contains(x[0]) { return pushErrorNotUnique(r, x[0], r.Keyword()) } @@ -1481,10 +1477,6 @@ PushPolicy interface signature. This is called during Push attempts to a stack containing BindRule groupdn distinguished name instances. */ func (r BindDistinguishedNames) gDNPushPolicy(x ...any) error { - if len(x) == 0 { - return nil - } - if r.contains(x[0]) { return pushErrorNotUnique(r, x[0], r.Keyword()) } @@ -1497,10 +1489,6 @@ PushPolicy interface signature. This is called during Push attempts to a stack containing BindRule roledn distinguished name instances. */ func (r BindDistinguishedNames) rDNPushPolicy(x ...any) error { - if len(x) == 0 { - return nil - } - if r.contains(x[0]) { return pushErrorNotUnique(r, x[0], r.Keyword()) } @@ -1513,10 +1501,6 @@ PushPolicy interface signature. This is called during Push attempts to a stack containing TargetRule target_to distinguished name instances. */ func (r TargetDistinguishedNames) tToDNPushPolicy(x ...any) error { - if len(x) == 0 { - return nil - } - if r.contains(x[0]) { return pushErrorNotUnique(r, x[0], r.Keyword()) } @@ -1529,10 +1513,6 @@ PushPolicy interface signature. This is called during Push attempts to a stack containing TargetRule target_from distinguished name instances. */ func (r TargetDistinguishedNames) tFromDNPushPolicy(x ...any) error { - if len(x) == 0 { - return nil - } - if r.contains(x[0]) { return pushErrorNotUnique(r, x[0], r.Keyword()) } @@ -1545,10 +1525,6 @@ interface signature. This is called during Push attempts to a stack containing TargetRule target distinguished name instances. */ func (r TargetDistinguishedNames) tDNPushPolicy(x ...any) error { - if len(x) == 0 { - return nil - } - if r.contains(x[0]) { return pushErrorNotUnique(r, x[0], r.Keyword()) } diff --git a/dn_test.go b/dn_test.go index be378be..5fd4528 100644 --- a/dn_test.go +++ b/dn_test.go @@ -177,7 +177,6 @@ func TestBindDistinguishedNames_codecov(t *testing.T) { _ = Os.Push(`fhksjthg4`) _ = Os.Push(`_1`) _ = Os.Push(ctx) - _ = Os.Push(URI(`ldap:///ou=People,dc=example,dc=com?cn,sn,givenName?one?(&(objectClass=contractor)(status=active))`)) Os.reset() _ = Os.setQuoteStyle(0) @@ -226,13 +225,17 @@ func TestBindDistinguishedNames_codecov(t *testing.T) { // process DN O = Os.F()(dn) + Os.Push(AnyDN) + Os.Push(URI(`ldap:///?`)) + Os.Push(URI(`l`)) + Os.Push(URI(`ldap:///ou=People,dc=example,dc=com?cn,sn,givenName?one?(&(objectClass=contractor)(status=active))`)) Ol = Os.Len() Os.Push(O) Os.Push() Os.Push(``) Os.Push(nil) Os.Push('a') - Os.Push(URI(`ldap:///ou=People,dc=example,dc=com?cn,sn,givenName?one?(&(objectClass=contractor)(status=active))`)) + Os.Index(Os.Len() - 1) Os.Contains(dn) Os.Push(Os.Pop()) Os.Push(O) // try to introduce duplicate From 6e2179897b548d89a0f1c4d87dacbf2809461961 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 20:24:39 -0700 Subject: [PATCH 08/43] development release --- parse.go | 53 ++++++++++++++++++++++------------------------------- 1 file changed, 22 insertions(+), 31 deletions(-) diff --git a/parse.go b/parse.go index 177b2aa..6d35dc8 100644 --- a/parse.go +++ b/parse.go @@ -889,16 +889,12 @@ func unpackageAntlrPermission(perm parser.Permission) (*permission, error) { // process each permission one at a time var bits int // temporary storage for verification of bitshifted permission values - var err error for i := 0; i < len(perm.Rights); i++ { rite := lc(perm.Rights[i]) - r, ok := rightsNames[rite] - if !ok { - err = rightNotfound(rite) - return nil, err + if r, ok := rightsNames[rite]; ok { + bits |= int(r) + p.shift(perm.Rights[i]) } - bits |= int(r) - p.shift(perm.Rights[i]) } // The result of the above shifts MUST match the @@ -910,12 +906,12 @@ func unpackageAntlrPermission(perm parser.Permission) (*permission, error) { // rather through bit summation of the underlying // values defined in go-aci as part of its attempt // to be memory efficient. - if bits != int(*p.Right) { - err = unexpectedValueCountErr(`permission bits`, bits, int(*p.Right)) - return nil, err + err := unexpectedValueCountErr(`permission bits`, bits, int(*p.Right)) + if bits == int(*p.Right) { + err = nil } - return p, nil + return p, err } func parsePermissionBindRule(raw string) (PermissionBindRule, error) { @@ -957,12 +953,12 @@ func processPermissionBindRules(stack any) (PermissionBindRules, error) { for i := 0; i < _pbrs.Len(); i++ { slice, _ := _pbrs.Index(i) _pbr, asserted := slice.(parser.PermissionBindRule) - if !asserted { - err = illegalSliceTypeErr(PermissionBindRules{}, `pbrs`, nil) - return badPermissionBindRules, err - } var pbr PermissionBindRule - if pbr, err = processPermissionBindRule(_pbr); err != nil { + if asserted { + pbr, err = processPermissionBindRule(_pbr) + } + + if err != nil { return badPermissionBindRules, err } pbrs.Push(pbr) @@ -998,10 +994,9 @@ func (r *PermissionBindRules) Parse(raw string) error { } var _r PermissionBindRules - if _r, err = processPermissionBindRules(_pbrs); err != nil { - return err + if _r, err = processPermissionBindRules(_pbrs); err == nil { + *r = _r } - *r = _r return err } @@ -1035,22 +1030,14 @@ func (r *Instruction) Parse(raw string) (err error) { return } - // obtain the ACL (string) value; if not - // defined, fail the entire process. - if a = _r.L.String(); len(a) == 0 { - err = nilInstanceErr(_r.L) - return - } + // obtain the ACL (string) value + a = _r.L.String() // process zero (0) or more TargetRules - if t, err = processTargetRules(_r.T); err != nil { - return - } + t, _ = processTargetRules(_r.T) // process one (1) or more PermissionBindRules - if p, err = processPermissionBindRules(_r.PB); err != nil { - return - } + p, _ = processPermissionBindRules(_r.PB) // set the target rules, acl and // pbr(s) within the temporary @@ -1061,6 +1048,10 @@ func (r *Instruction) Parse(raw string) (err error) { p, ) + if err = _i.Valid(); err != nil { + return + } + // clobber receiver *r = _i From b7b6c420ae8d2cdc6dbe0fa61ecd9a4c750886b7 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 20:29:00 -0700 Subject: [PATCH 09/43] development release --- ins.go | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/ins.go b/ins.go index 6d0b786..629cbb7 100644 --- a/ins.go +++ b/ins.go @@ -96,17 +96,14 @@ func (r Instructions) pushPolicy(x ...any) (err error) { return } + err = pushErrorBadType(Instructions{}, x[0], nil) switch tv := x[0].(type) { case string: - if len(tv) == 0 { - err = nilInstanceErr(tv) + if len(tv) > 0 { + err = nil } case Instruction: - if tv.IsZero() { - err = nilInstanceErr(tv) - } - default: - err = pushErrorBadType(Instructions{}, tv, nil) + err = tv.Valid() } return From 1a0d02737769fd57562238d736fea42c0701e612 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 20:32:13 -0700 Subject: [PATCH 10/43] development releaseush --- ins.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ins.go b/ins.go index 629cbb7..bd11931 100644 --- a/ins.go +++ b/ins.go @@ -98,10 +98,6 @@ func (r Instructions) pushPolicy(x ...any) (err error) { err = pushErrorBadType(Instructions{}, x[0], nil) switch tv := x[0].(type) { - case string: - if len(tv) > 0 { - err = nil - } case Instruction: err = tv.Valid() } From dc2c040e1e0fa89ec641bec64c6b08095769632f Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 20:37:32 -0700 Subject: [PATCH 11/43] development release --- levels.go | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/levels.go b/levels.go index e0d26bb..c6c63ed 100644 --- a/levels.go +++ b/levels.go @@ -108,8 +108,9 @@ func (r Inheritance) Valid() (err error) { return nilInstanceErr(r) } - if r.inheritance.AttributeBindTypeOrValue.IsZero() { - err = nilInstanceErr(r.inheritance.AttributeBindTypeOrValue) + err = nilInstanceErr(r.inheritance.AttributeBindTypeOrValue) + if !r.inheritance.AttributeBindTypeOrValue.IsZero() { + err = nil } return @@ -526,20 +527,13 @@ func (r Levels) positive(x any) (posi bool) { var lvl Level switch tv := x.(type) { case Level: - if tv == noLvl { - return + if tv != noLvl { + lvl = tv } - lvl = tv case int: - if lvl = assertIntInheritance(tv); lvl == noLvl { - return - } + lvl = assertIntInheritance(tv) case string: - if lvl = assertStrInheritance(tv); lvl == noLvl { - return - } - default: - return + lvl = assertStrInheritance(tv) } posi = (r & Levels(lvl)) > 0 From 3b64f250aae3d9cedff88eeabcdf68028e086a96 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 20:45:45 -0700 Subject: [PATCH 12/43] development release --- misc.go | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/misc.go b/misc.go index 0a27dac..0a4a1f4 100644 --- a/misc.go +++ b/misc.go @@ -355,26 +355,24 @@ getStringFunc uses reflect to obtain and return a given type instance's String method, if present. If not, nil is returned. */ -func getStringFunc(x any) func() string { +func getStringFunc(x any) (meth func() string) { if x == nil { - return nil + return } - v := valOf(x) - if v.IsZero() { - return nil - } + if v := valOf(x); !v.IsZero() { - method := v.MethodByName(`String`) - if method.Kind() == reflect.Invalid { - return nil - } + method := v.MethodByName(`String`) + if method.Kind() == reflect.Invalid { + return nil + } - if meth, ok := method.Interface().(func() string); ok { - return meth + if _meth, ok := method.Interface().(func() string); ok { + meth = _meth + } } - return nil + return } /* From d14eb82b322717f167cd6c6cf5e7bc8b70af750e Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 20:52:33 -0700 Subject: [PATCH 13/43] development release --- oid.go | 77 ++++++++++++++++++++++++---------------------------------- 1 file changed, 32 insertions(+), 45 deletions(-) diff --git a/oid.go b/oid.go index 71f2ba0..1584f3f 100644 --- a/oid.go +++ b/oid.go @@ -157,11 +157,12 @@ Eq initializes and returns a new TargetRule instance configured to express the evaluation of the receiver value as Equal-To an `extop` or `targetcontrol` keyword context. */ -func (r ObjectIdentifier) Eq() TargetRule { - if err := r.Valid(); err != nil { - return badTargetRule +func (r ObjectIdentifier) Eq() (t TargetRule) { + t = badTargetRule + if err := r.Valid(); err == nil { + t = TR(r.objectIdentifier.TargetKeyword, Eq, r) } - return TR(r.objectIdentifier.TargetKeyword, Eq, r) + return } /* @@ -171,11 +172,12 @@ keyword context. Negated equality TargetRule instances should be used with caution. */ -func (r ObjectIdentifier) Ne() TargetRule { - if err := r.Valid(); err != nil { - return badTargetRule +func (r ObjectIdentifier) Ne() (t TargetRule) { + t = badTargetRule + if err := r.Valid(); err == nil { + t = TR(r.objectIdentifier.TargetKeyword, Ne, r) } - return TR(r.objectIdentifier.TargetKeyword, Ne, r) + return } /* @@ -515,12 +517,6 @@ executions, assuming they are keyword context-aligned with the destination stack. */ func (r ObjectIdentifiers) extOpsPushPolicy(x ...any) error { - if len(x) == 0 { - return nil - } else if x[0] == nil { - return nilInstanceErr(x[0]) - } - if r.contains(x[0]) { return pushErrorNotUnique(r, x[0], r.Keyword()) } @@ -539,12 +535,6 @@ executions, assuming they are keyword context-aligned with the destination stack. */ func (r ObjectIdentifiers) ctrlsPushPolicy(x ...any) error { - if len(x) == 0 { - return nil - } else if x[0] == nil { - return nilInstanceErr(x[0]) - } - if r.contains(x[0]) { return pushErrorNotUnique(r, x[0], r.Keyword()) } @@ -575,26 +565,23 @@ func (r ObjectIdentifiers) reset() { } func (r ObjectIdentifiers) resetKeyword(x any) { - if r.Len() > 0 { - return - } - - switch tv := x.(type) { - case TargetKeyword: - r.resetKeyword(tv.String()) - - case string: - _r := r.cast() + if r.Len() == 0 { + switch tv := x.(type) { + case TargetKeyword: + r.resetKeyword(tv.String()) - switch lc(tv) { - case TargetExtOp.String(): - _r.SetCategory(TargetExtOp.String()). - SetPushPolicy(r.extOpsPushPolicy) + case string: + _r := r.cast() - case TargetCtrl.String(): - _r.SetCategory(TargetCtrl.String()). - SetPushPolicy(r.ctrlsPushPolicy) + switch lc(tv) { + case TargetExtOp.String(): + _r.SetCategory(TargetExtOp.String()). + SetPushPolicy(r.extOpsPushPolicy) + case TargetCtrl.String(): + _r.SetCategory(TargetCtrl.String()). + SetPushPolicy(r.ctrlsPushPolicy) + } } } } @@ -629,9 +616,10 @@ func objectIdentifiersPushPolicy(r, x any, kw TargetKeyword) (err error) { // case match is a proper instance of ObjectIdentifier if err = tv.Valid(); err != nil { break - - } else if tv.Keyword() != kw { - err = badObjectIdentifierKeywordErr(tv.objectIdentifier.TargetKeyword) + } + err = badObjectIdentifierKeywordErr(tv.objectIdentifier.TargetKeyword) + if tv.Keyword() == kw { + err = nil } default: @@ -750,12 +738,11 @@ func (r ObjectIdentifiers) Ne() TargetRule { /* ID wraps go-stackage's Stack.ID method. */ -func (r ObjectIdentifiers) ID() string { - if r.IsZero() { - return `` +func (r ObjectIdentifiers) ID() (s string) { + if !r.IsZero() { + s = r.cast().ID() } - - return r.cast().ID() + return } /* From f6560367e9d76308905dfcee4c151934b3eedd8a Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 21:00:12 -0700 Subject: [PATCH 14/43] development release --- bind.go | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/bind.go b/bind.go index 96c698b..7b5f7ad 100644 --- a/bind.go +++ b/bind.go @@ -1038,11 +1038,10 @@ replace is a private method called by BindRules.Replace as well as certain ANTLR->ACI parsing procedures. */ func (r BindRules) replace(x any, idx int) BindRules { - if r.IsZero() { - return r + if !r.IsZero() { + r.cast().Replace(x, idx) } - r.cast().Replace(x, idx) return r } @@ -1126,11 +1125,7 @@ func (r BindRules) Traverse(indices ...int) (B BindContext) { case BindContext: B = tv default: - if isStackageStack(tv) { - B = castAsBindRules(tv) - } else if isStackageCondition(tv) { - B = castAsBindRule(tv) - } + B = castAsBindRule(tv) } } @@ -1158,13 +1153,6 @@ Stack alias) type instance. Only BindContext qualifiers are to be cleared for push. */ func (r BindRules) pushPolicy(x ...any) (err error) { - if len(x) == 0 { - return - } else if x[0] == nil { - err = pushErrorNilOrZero(r, x, matchBKW(r.Category())) - return - } - // perform type switch upon input value // x to determine suitability for push. switch tv := x[0].(type) { @@ -1177,13 +1165,11 @@ func (r BindRules) pushPolicy(x ...any) (err error) { err = pushErrorNilOrZero(r, tv, matchBKW(r.Category()), err) } - if tv.Keyword() == nil { - err = badPTBRuleKeywordErr(tv, `bind`, `bindkeyword`, tv.Keyword()) - break - } - - if matchBKW(tv.Keyword().String()) == BindKeyword(0x0) { + if tv.Keyword() != nil { err = badPTBRuleKeywordErr(tv, `bind`, `bindkeyword`, tv.Keyword()) + if matchBKW(tv.Keyword().String()) != BindKeyword(0x0) { + err = nil + } } default: From 4ab3f8ae914b7539907652cd17ddf81ff788737a Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 21:08:31 -0700 Subject: [PATCH 15/43] development release --- ins.go | 7 ------- ins_test.go | 4 +--- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/ins.go b/ins.go index bd11931..c83c94a 100644 --- a/ins.go +++ b/ins.go @@ -84,13 +84,6 @@ const ( ) func (r Instructions) pushPolicy(x ...any) (err error) { - if len(x) == 0 { - return - } else if x[0] == nil { - err = nilInstanceErr(x[0]) - return - } - if r.contains(x[0]) { err = pushErrorNotUnique(r, x[0], nil) return diff --git a/ins_test.go b/ins_test.go index 00d2af3..599c087 100644 --- a/ins_test.go +++ b/ins_test.go @@ -28,9 +28,7 @@ func TestInstruction(t *testing.T) { // with a DN syntax of "uid=,ou=People,dc=example,dc=com" Tar := TDN(`uid=*,ou=People,dc=example,dc=com`).Eq() - badACL := `` - - ACI(badACL, Tar, pbrule) + ACI(Tar, pbrule) _ = Ins.Valid() _ = Ins.IsZero() _ = Ins.String() From 37b1795be0f5d8c3091dbfdc7b78e12dfe2d9f0c Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 21:13:03 -0700 Subject: [PATCH 16/43] development release --- ins.go | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/ins.go b/ins.go index c83c94a..f85fd9e 100644 --- a/ins.go +++ b/ins.go @@ -289,30 +289,7 @@ or deficiencies within the receiver instance. func (r Instruction) Valid() (err error) { if r.IsZero() { err = nilInstanceErr(r) - return - } - - return r.instruction.valid() -} - -/* -valid is a private method called by instruction.Valid. -*/ -func (r instruction) valid() (err error) { - if len(r.ACL) == 0 { - err = instructionNoLabelErr() - return - } - - for _, valid := range []func() error{ - r.TRs.Valid, - r.PBRs.Valid, - } { - if err = valid(); err != nil { - break - } } - return } From f1ccd15a4d572a406af05f8e586f225278395ea1 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 21:17:44 -0700 Subject: [PATCH 17/43] development release --- cop.go | 38 ++++++++++++++++++-------------------- cop_test.go | 1 + 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/cop.go b/cop.go index 541e497..5910f46 100644 --- a/cop.go +++ b/cop.go @@ -162,7 +162,7 @@ for use in T/B rule instances. Certain keywords, such as TargetScope, allow only certain operators, while others, such as BindSSF, allow the use of ALL operators. */ -func keywordAllowsComparisonOperator(kw, op any) bool { +func keywordAllowsComparisonOperator(kw, op any) (allowed bool) { // identify the comparison operator, // save as cop var. var cop ComparisonOperator @@ -174,7 +174,7 @@ func keywordAllowsComparisonOperator(kw, op any) bool { case int: cop = ComparisonOperator(tv) default: - return false + return } // identify the keyword, and @@ -183,18 +183,18 @@ func keywordAllowsComparisonOperator(kw, op any) bool { switch tv := kw.(type) { case string: if bkw := matchBKW(tv); bkw != BindKeyword(0x0) { - return bindKeywordAllowsComparisonOperator(bkw, cop) + allowed = bindKeywordAllowsComparisonOperator(bkw, cop) } else if tkw := matchTKW(tv); tkw != TargetKeyword(0x0) { - return targetKeywordAllowsComparisonOperator(tkw, cop) + allowed = targetKeywordAllowsComparisonOperator(tkw, cop) } case BindKeyword: - return bindKeywordAllowsComparisonOperator(tv, cop) + allowed = bindKeywordAllowsComparisonOperator(tv, cop) case TargetKeyword: - return targetKeywordAllowsComparisonOperator(tv, cop) + allowed = targetKeywordAllowsComparisonOperator(tv, cop) } - return false + return } /* @@ -222,25 +222,23 @@ func matchCOP(op string) ComparisonOperator { /* bindKeywordAllowsComparisonOperator is a private function called by keywordAllowsCompariso9nOperator. */ -func bindKeywordAllowsComparisonOperator(key BindKeyword, cop ComparisonOperator) bool { +func bindKeywordAllowsComparisonOperator(key BindKeyword, cop ComparisonOperator) (allowed bool) { // look-up the keyword within the permitted cop // map; if found, obtain slices of cops allowed // by said keyword. - cops, found := permittedBindComparisonOperators[key] - if !found { - return false - } - - // iterate the cops slice, attempting to perform - // a match of the input cop candidate value and - // the current cops slice [i]. - for i := 0; i < len(cops); i++ { - if cop == cops[i] { - return true + if cops, found := permittedBindComparisonOperators[key]; found { + // iterate the cops slice, attempting to perform + // a match of the input cop candidate value and + // the current cops slice [i]. + for i := 0; i < len(cops); i++ { + if cop == cops[i] { + allowed = true + break + } } } - return false + return } /* diff --git a/cop_test.go b/cop_test.go index 7c1791b..e06c656 100644 --- a/cop_test.go +++ b/cop_test.go @@ -100,6 +100,7 @@ func TestComparisonOperator_codecov(t *testing.T) { _ = lousyCop.Description() _ = lousyCop.Valid() _ = lousyCop.Compare(Eq) + _ = lousyCop.Compare(1) _ = lousyCop.Compare(`=`) _ = lousyCop.Compare(`eq`) _ = lousyCop.Compare(`equal to`) From c3e0bb459bf4fd5127349f9860f79a819f7e110b Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 21:23:39 -0700 Subject: [PATCH 18/43] development release --- attr.go | 55 +++++++++++++++++++--------------------------------- attr_test.go | 4 +++- 2 files changed, 23 insertions(+), 36 deletions(-) diff --git a/attr.go b/attr.go index 6528d26..07bc91a 100644 --- a/attr.go +++ b/attr.go @@ -230,11 +230,7 @@ func (r *atbtv) isZero() bool { String is a stringer method that returns the string representation of the receiver. */ -func (r atbtv) String() string { - // AttributeType will always - // be used. - var at AttributeType - +func (r atbtv) String() (s string) { // Only one (1) of the following // vars will be used. var bt BindType @@ -242,29 +238,29 @@ func (r atbtv) String() string { // Assert the attributeType value // or bail out. - at, assert := r[0].(AttributeType) - if !assert { - return `` - } - - // First see if the value is a BindType - // keyword, as those are few and easily - // identified. - if bt, assert = r[1].(BindType); !assert || bt == BindType(0x0) { - // If not a BindType kw, see if it - // appears to be an AttributeValue. - if av, assert = r[1].(AttributeValue); !assert || len(*av.string) == 0 { - // value is neither an AttributeValue - // nor BindType kw; bail out. - return `` + if at, assert := r[0].(AttributeType); assert { + // First see if the value is a BindType + // keyword, as those are few and easily + // identified. + if bt, assert = r[1].(BindType); !assert || bt == BindType(0x0) { + // If not a BindType kw, see if it + // appears to be an AttributeValue. + if av, assert = r[1].(AttributeValue); !assert || len(*av.string) == 0 { + // value is neither an AttributeValue + // nor BindType kw; bail out. + return + } + + // AttributeValue wins + s = sprintf("%s#%s", at, av) + return } - // AttributeValue wins - return sprintf("%s#%s", at, av) + // BindType wins + s = sprintf("%s#%s", at, bt) } - // BindType wins - return sprintf("%s#%s", at, bt) + return } /* @@ -820,10 +816,6 @@ go-stackage. This private function is called during Push attempts to a AttributeTypes stack instance. */ func (r AttributeTypes) pushPolicy(x ...any) (err error) { - if len(x) == 0 { - return nil - } - // verify uniqueness; bail out if Boolean // false is return value. if r.contains(x[0]) { @@ -834,13 +826,6 @@ func (r AttributeTypes) pushPolicy(x ...any) (err error) { // perform type switch upon input value // x to determine suitability for push. switch tv := x[0].(type) { - - case string: - // case matches a string-based LDAP AttributeType - if len(tv) == 0 { - err = pushErrorNilOrZero(r, tv, matchTKW(r.Kind())) - } - case AttributeType: // case matches an AttributeType instance if tv.IsZero() { diff --git a/attr_test.go b/attr_test.go index 1c5015e..77492e1 100644 --- a/attr_test.go +++ b/attr_test.go @@ -679,10 +679,10 @@ func ExampleAttributeValue_Compare() { func TestAttrs_codecov(t *testing.T) { var atv AttributeBindTypeOrValue + atv.Set(AT(``)) _ = atv.Eq() _ = atv.Ne() _ = atv.Valid() - atv.Set(AT(``)) _ = atv.String() if err := atv.Parse(`fartknocker`); err == nil { @@ -695,6 +695,8 @@ func TestAttrs_codecov(t *testing.T) { return } _ = atv.Keyword() + _ = atv.Valid() + _ = atv.String() var at AttributeType _ = at.Eq() From cc5283ddd73f441bb18d0d38690bd255b0dfb806 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 21:30:40 -0700 Subject: [PATCH 19/43] development release --- filter_test.go | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/filter_test.go b/filter_test.go index aec3988..17f9403 100644 --- a/filter_test.go +++ b/filter_test.go @@ -1097,7 +1097,8 @@ func ExampleAttributeFilterOperations_Kind() { } /* -This example demonstrates the creation of an instance of AttributeFilterOperations. +This example demonstrates the creation of an instance of AttributeFilterOperations +using the AttributeFilterOperations type's Parse method. In this example, a raw string representation of an AttributeFilterOperations is used for parser input. The resultant output from the instance's String method should be @@ -1108,7 +1109,7 @@ func ExampleAttributeFilterOperations_Parse() { var afos AttributeFilterOperations err := afos.Parse(aftxt) if err != nil { - fmt.Println(err) + fmt.Println(err) // always check your parser errors return } got := afos.String() @@ -1117,6 +1118,29 @@ func ExampleAttributeFilterOperations_Parse() { // Output: Values match: true } +/* +This example demonstrates the creation of an instance of AttributeFilterOperation +using the AttributeFilterOperation type's Parse method. + +In this example, a raw string representation of an AttributeFilterOperation is used +for parser input. The resultant output from the instance's String method should be +identical to that which was fed into the Parse method. +*/ +func ExampleAttributeFilterOperation_Parse() { + af1 := `objectClass:(&(objectClass=employee)(cn=Jesse Coretta))` + af2 := `homeDirectory:(&(objectClass=accountant)(cn=Courtney Tolana))` + want := `add=` + af1 + ` && ` + af2 + + var afo AttributeFilterOperation + if err := afo.Parse(want); err != nil { + fmt.Println(err) // always check your parser errors + return + } + + fmt.Printf("%s", afo) + // Output: add=objectClass:(&(objectClass=employee)(cn=Jesse Coretta)) && homeDirectory:(&(objectClass=accountant)(cn=Courtney Tolana)) +} + /* This example demonstrates the use of the AttributeFilterOperations type's Push method to append a new (eligible) instance to the receiver. From 61fc14bd4787b7016f5dd14919598c2604e3e6ea Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 21:46:18 -0700 Subject: [PATCH 20/43] development release --- dn.go | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/dn.go b/dn.go index 8458dcc..948a8bf 100644 --- a/dn.go +++ b/dn.go @@ -1539,32 +1539,25 @@ handles any type of DN/URI. func distinguishedNamesPushPolicy(r, x any, kw Keyword) (err error) { switch tv := x.(type) { - case string: - if len(tv) == 0 { - err = pushErrorNilOrZero(r, tv, kw) - } - case Keyword: distinguishedNamesPushPolicyKeywordHandler(r, kw) case LDAPURI: - if kw.Kind() != bindRuleID { - err = errorf("Only DN or value-matching %s rule conditions may contain %T instances", - kw.Kind(), tv) - } else { + err = errorf("Only DN or value-matching %s rule conditions may contain %T instances", kw.Kind(), tv) + if kw.Kind() == bindRuleID { err = tv.Valid() } case DistinguishedNameContext: - if tv.IsZero() { - err = pushErrorNilOrZero(r, tv, kw) - - } else if tv.Keyword() != kw { + err = pushErrorNilOrZero(r, tv, kw) + if !tv.IsZero() { err = badPTBRuleKeywordErr(tv, kw.Kind(), kw, tv.Keyword()) + if tv.Keyword() == kw { + err = nil + } } - default: - err = pushErrorBadType(r, tv, kw) + err = pushErrorBadType(r, x, kw) } return From 5f9f538b5ff5a9d99f9ae0ca0862b8e9a1f8add7 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 22:07:23 -0700 Subject: [PATCH 21/43] development release --- err_test.go | 2 ++ parse.go | 79 ++++++++++++++++++++++++----------------------------- 2 files changed, 38 insertions(+), 43 deletions(-) diff --git a/err_test.go b/err_test.go index 7ad0435..30594f7 100644 --- a/err_test.go +++ b/err_test.go @@ -24,6 +24,7 @@ func TestErrorf(t *testing.T) { func TestErrorFNs_codecov(t *testing.T) { _ = badPTBRuleKeywordErr(BindRule{}, `blarg`, `userdn`, `farts`) + _ = badPTBRuleKeywordErr(BindRule{}, `blarg`, BindUDN, `farts`) _ = badObjectIdentifierKeywordErr(TargetExtOp) _ = unexpectedKindErr(PermissionBindRule{}, `pbr`, `...`) _ = illegalSliceTypeErr(AttributeFilter{}, `(objectClass=*)`, `35^`) @@ -35,6 +36,7 @@ func TestErrorFNs_codecov(t *testing.T) { _ = instructionNoLabelErr() _ = dowBadTimeErr() _ = badCopErr(badCop) + _ = rightNotfound(`barf`) _ = noPermissionDispErr() _ = fqdnInvalidLabelErr(domainLabel(`__`)) _ = parseBindRulesHierErr(BindDistinguishedNames{}, BindRules{}) diff --git a/parse.go b/parse.go index 6d35dc8..793e19c 100644 --- a/parse.go +++ b/parse.go @@ -308,14 +308,12 @@ func assertBindUGRDN(expr parser.RuleExpression, key BindKeyword) (ex any, err e // Assign the raw (DN) values to the // return value. If nothing was found, // bail out now. - if err = bdn.setExpressionValues(key, expr.Values...); err != nil { - return + if err = bdn.setExpressionValues(key, expr.Values...); err == nil { + // Envelope our DN stack within an + // 'any' instance, which is returned. + ex = bdn } - // Envelope our DN stack within an - // 'any' instance, which is returned. - ex = bdn - return } @@ -923,48 +921,45 @@ func parsePermissionBindRule(raw string) (PermissionBindRule, error) { return processPermissionBindRule(pbr) } -func processPermissionBindRule(pbr parser.PermissionBindRule) (PermissionBindRule, error) { - perm, err := unpackageAntlrPermission(pbr.P) - if err != nil { - return badPermissionBindRule, err - } - - // traverse the native stackage.Stack instance returned - // by antlraci and marshal its contents into proper - // BindRule/BindRules instances, etc. - rules, ok := convertBindRulesHierarchy(pbr.B) - if !ok { - return badPermissionBindRule, parseBindRulesHierErr(pbr.B, rules) +func processPermissionBindRule(_pbr parser.PermissionBindRule) (pbr PermissionBindRule, err error) { + var perm *permission + pbr = badPermissionBindRule + if perm, err = unpackageAntlrPermission(_pbr.P); err == nil { + // traverse the native stackage.Stack instance returned + // by antlraci and marshal its contents into proper + // BindRule/BindRules instances, etc. + rules, ok := convertBindRulesHierarchy(_pbr.B) + err = parseBindRulesHierErr(_pbr.B, rules) + if ok { + err = nil + pbr = PermissionBindRule{ + &permissionBindRule{ + P: Permission{perm}, + B: rules, + }, + } + } } - return PermissionBindRule{ - &permissionBindRule{ - P: Permission{perm}, - B: rules, - }, - }, nil + return } -func processPermissionBindRules(stack any) (PermissionBindRules, error) { - var err error - +func processPermissionBindRules(stack any) (pbrs PermissionBindRules, err error) { _pbrs, _ := castAsStack(stack) - var pbrs PermissionBindRules = PBRs() + pbrs = PBRs() + for i := 0; i < _pbrs.Len(); i++ { slice, _ := _pbrs.Index(i) - _pbr, asserted := slice.(parser.PermissionBindRule) - var pbr PermissionBindRule - if asserted { - pbr, err = processPermissionBindRule(_pbr) - } - - if err != nil { - return badPermissionBindRules, err + if _pbr, asserted := slice.(parser.PermissionBindRule); asserted { + var pbr PermissionBindRule + if pbr, err = processPermissionBindRule(_pbr); err != nil { + break + } + pbrs.Push(pbr) } - pbrs.Push(pbr) } - return pbrs, nil + return } /* @@ -1048,12 +1043,10 @@ func (r *Instruction) Parse(raw string) (err error) { p, ) - if err = _i.Valid(); err != nil { - return + if err = _i.Valid(); err == nil { + // clobber receiver + *r = _i } - // clobber receiver - *r = _i - return } From 734b13524c1c080b0b038d63864211d62fbfa072 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 22:11:01 -0700 Subject: [PATCH 22/43] development release --- dn.go | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/dn.go b/dn.go index 948a8bf..a7ac757 100644 --- a/dn.go +++ b/dn.go @@ -1537,27 +1537,29 @@ the keyword-specific DN pushPolicy functions above. This function handles any type of DN/URI. */ func distinguishedNamesPushPolicy(r, x any, kw Keyword) (err error) { - switch tv := x.(type) { + switch x.(type) { case Keyword: distinguishedNamesPushPolicyKeywordHandler(r, kw) - case LDAPURI: - err = errorf("Only DN or value-matching %s rule conditions may contain %T instances", kw.Kind(), tv) - if kw.Kind() == bindRuleID { - err = tv.Valid() - } - - case DistinguishedNameContext: - err = pushErrorNilOrZero(r, tv, kw) - if !tv.IsZero() { - err = badPTBRuleKeywordErr(tv, kw.Kind(), kw, tv.Keyword()) - if tv.Keyword() == kw { - err = nil - } - } - default: - err = pushErrorBadType(r, x, kw) + /* + case LDAPURI: + err = errorf("Only DN or value-matching %s rule conditions may contain %T instances", kw.Kind(), tv) + if kw.Kind() == bindRuleID { + err = tv.Valid() + } + + case DistinguishedNameContext: + err = pushErrorNilOrZero(r, tv, kw) + if !tv.IsZero() { + err = badPTBRuleKeywordErr(tv, kw.Kind(), kw, tv.Keyword()) + if tv.Keyword() == kw { + err = nil + } + } + default: + err = pushErrorBadType(r, x, kw) + */ } return From fa846d644ae448807709ffa46604ba5eb756ba9e Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 22:14:15 -0700 Subject: [PATCH 23/43] development release --- dn_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/dn_test.go b/dn_test.go index 5fd4528..d4b4cb3 100644 --- a/dn_test.go +++ b/dn_test.go @@ -174,6 +174,7 @@ func TestBindDistinguishedNames_codecov(t *testing.T) { _ = Os.Ne() _ = Os.Push() _ = Os.Push(``) + _ = Os.Push('a') _ = Os.Push(`fhksjthg4`) _ = Os.Push(`_1`) _ = Os.Push(ctx) From 19449c79671f4e47d11a2d074bae550665bd5cc2 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 22:21:41 -0700 Subject: [PATCH 24/43] development release --- dn_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dn_test.go b/dn_test.go index d4b4cb3..073f72f 100644 --- a/dn_test.go +++ b/dn_test.go @@ -134,7 +134,7 @@ func TestTargetDistinguishedName_codecov(t *testing.T) { } O.Set(`159`) - O.Set(``) + O.Set(`_`) _ = O.Valid() O.Set(`#barf`, kw) From 7f8bef0b4598185bdce82c55149ef13e01ff8a90 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 22:28:14 -0700 Subject: [PATCH 25/43] development release --- filter.go | 46 +++++----------------------------------------- 1 file changed, 5 insertions(+), 41 deletions(-) diff --git a/filter.go b/filter.go index d0ec8e0..4ad9c12 100644 --- a/filter.go +++ b/filter.go @@ -643,27 +643,10 @@ func (r AttributeFilterOperations) IsZero() bool { } /* -Valid returns an error if the receiver is in an aberrant state. +Valid wraps go-stackage's Stack.Valid method. */ func (r AttributeFilterOperations) Valid() error { - if r.IsZero() { - return nilInstanceErr(r) - } - - // assume the object has been fashioned - // to deceive the package - use the - // actual go-stackage index caller so - // it won't discriminate types. - _r := r.cast() - for i := 0; i < _r.Len(); i++ { - slice, _ := _r.Index(i) - assert, _ := slice.(AttributeFilterOperation) - if err := assert.Valid(); err != nil { - return err - } - } - - return nil + return r.cast().Valid() } /* @@ -753,7 +736,7 @@ func (r AttributeFilterOperations) pushPolicy(x ...any) (err error) { // because codecov :/ xerr := tv.Valid() err = pushErrorNilOrZero(r, tv, TargetAttrFilters, xerr) - if xerr == nil { + if xerr == nil && tv.Len() > 0 { err = nil } default: @@ -948,29 +931,10 @@ func (r AttributeFilterOperation) IsZero() bool { } /* -Valid returns an error if the receiver (or any of its contents) is -in an aberrant state. +Valid wraps go-stackage's Stack.Valid method. */ func (r AttributeFilterOperation) Valid() (err error) { - if r.IsZero() || r.Len() == 0 { - err = nilInstanceErr(r) - return - } - - // assume the object has been fashioned - // to deceive the package - use the - // actual go-stackage index caller so - // it won't discriminate types. - _r := r.cast() - for i := 0; i < _r.Len(); i++ { - slice, _ := _r.Index(i) - assert, _ := slice.(AttributeFilter) - if err = assert.Valid(); err != nil { - break - } - } - - return + return r.cast().Valid() } /* From 64be0eb1c8e33550b13d9362d2b540b98dadef6a Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 22:30:29 -0700 Subject: [PATCH 26/43] development release --- misc_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/misc_test.go b/misc_test.go index bb05ef8..7cadf3d 100644 --- a/misc_test.go +++ b/misc_test.go @@ -216,6 +216,8 @@ func TestOperator_codecov(t *testing.T) { return } + _ = unquote(`"quoted_string"`) + for i := 0; i < len(copMap); i++ { // attempt to resolve the operator From 1d7ebb4053a06f1cf63486154e5425d93e34b662 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 22:34:52 -0700 Subject: [PATCH 27/43] development release --- net.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/net.go b/net.go index 668c479..9b7a2f5 100644 --- a/net.go +++ b/net.go @@ -520,13 +520,6 @@ func (r FQDN) Valid() (err error) { return } - for i := 0; i < len(*r.labels); i++ { - if !validLabel(string((*r.labels)[i])) { - err = fqdnInvalidLabelErr((*r.labels)[i]) - return - } - } - // seems legit return } From e05d652da61d15f845e2e178af36844ea483203a Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 22:47:36 -0700 Subject: [PATCH 28/43] development release --- net.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/net.go b/net.go index 9b7a2f5..54aaf8b 100644 --- a/net.go +++ b/net.go @@ -418,9 +418,6 @@ func processLabel(label ...string) (dl labels, c int, ok bool) { dl = append(dl, domainLabel(sp[j])) } } else { - if !validLabel(label[i]) { - return - } c += len(label[i]) dl = append(dl, domainLabel(label[i])) } From a08a9c2c719f196f321464c7ef1d4928ce81620f Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 22:59:06 -0700 Subject: [PATCH 29/43] development release --- stackage.go | 20 ++++++++++---------- uri.go | 3 +-- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/stackage.go b/stackage.go index 5640112..30a21ec 100644 --- a/stackage.go +++ b/stackage.go @@ -268,20 +268,20 @@ func (r ComparisonOperator) cast() stackage.ComparisonOperator { return castAsCop(r) } -func castAsBindRule(x any) BindRule { - assert, ok := x.(stackage.Condition) - if !ok { - return badBindRule +func castAsBindRule(x any) (b BindRule) { + b = badBindRule + if assert, ok := x.(stackage.Condition); ok { + b = BindRule(assert) } - return BindRule(assert) + return } -func castAsBindRules(x any) BindRules { - assert, ok := x.(stackage.Stack) - if !ok { - return badBindRules +func castAsBindRules(x any) (b BindRules) { + b = badBindRules + if assert, ok := x.(stackage.Stack); ok { + b = BindRules(assert) } - return BindRules(assert) + return } /* diff --git a/uri.go b/uri.go index 9a49582..7fbfdc4 100644 --- a/uri.go +++ b/uri.go @@ -478,10 +478,9 @@ func (r ldapURI) string() string { var param string if !r.filter.IsZero() { + param = "?" if !r.attrs.IsZero() { param = sprintf("?%s", r.attrs) - } else { - param = "?" } // Be sure to call the standard scope here, From 95dc3d5313834b9837562b2f21ff2b5784c4bbd1 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 23:02:56 -0700 Subject: [PATCH 30/43] development release --- stackage.go | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/stackage.go b/stackage.go index 30a21ec..cb30da8 100644 --- a/stackage.go +++ b/stackage.go @@ -268,20 +268,14 @@ func (r ComparisonOperator) cast() stackage.ComparisonOperator { return castAsCop(r) } -func castAsBindRule(x any) (b BindRule) { - b = badBindRule - if assert, ok := x.(stackage.Condition); ok { - b = BindRule(assert) - } - return +func castAsBindRule(x any) BindRule { + _b, _ := x.(stackage.Condition) + return BindRule(_b) } -func castAsBindRules(x any) (b BindRules) { - b = badBindRules - if assert, ok := x.(stackage.Stack); ok { - b = BindRules(assert) - } - return +func castAsBindRules(x any) BindRules { + _b, _ := x.(stackage.Stack) + return BindRules(_b) } /* From a03f37ae219f6ac8a08979e06fb87358a3173ba0 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 23:12:41 -0700 Subject: [PATCH 31/43] development release --- filter.go | 51 +++++++++++++++++++++++---------------------------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/filter.go b/filter.go index 4ad9c12..327e458 100644 --- a/filter.go +++ b/filter.go @@ -1184,22 +1184,18 @@ func parseAttributeFilterOperations(raw string, delim int) (afos AttributeFilter // an AttributeOperator prefix, which // will be either `add=` or `delete=`. // Bail out if we find otherwise. - if !hasAttributeFilterOperationPrefix(value) { - err = afoMissingPrefixErr() - return + err = afoMissingPrefixErr() + if hasAttributeFilterOperationPrefix(value) { + afo, err = parseAttributeFilterOperation(value) } - - // send parseAttributeFilterOperation - // the current slice iteration, returning - // an error if one ensues. - if afo, err = parseAttributeFilterOperation(value); err != nil { - return + if err == nil { + // Push the verified AttributeFilterOperation + // instance into our AttributeFilterOperations + // stack instance. + afos.Push(afo) + continue } - - // Push the verified AttributeFilterOperation - // instance into our AttributeFilterOperations - // stack instance. - afos.Push(afo) + break } return @@ -1222,21 +1218,20 @@ func parseAttributeFilterOperation(raw string) (afo AttributeFilterOperation, er return } - if aop, val, err = parseAttrFilterOperPreamble(raw); err != nil { - return - } - - afo = aop.AFO() - cat := sprintf("%s_%s", TargetAttrFilters, aop) // TODO: Find an alternative. I really don't like this. - afo.setCategory(cat) - seq = split(trimS(val), `&&`) - - for j := 0; j < len(seq); j++ { - var af AttributeFilter - if af, err = parseAttributeFilter(trimS(seq[j])); err != nil { - return + if aop, val, err = parseAttrFilterOperPreamble(raw); err == nil { + afo = aop.AFO() + cat := sprintf("%s_%s", TargetAttrFilters, aop) // TODO: Find an alternative. I really don't like this. + afo.setCategory(cat) + seq = split(trimS(val), `&&`) + + for j := 0; j < len(seq); j++ { + var af AttributeFilter + if af, err = parseAttributeFilter(trimS(seq[j])); err == nil { + afo.Push(af) + continue + } + break } - afo.Push(af) } return From 97b05d9ac3196fc700fa093b07c40ff5838d4319 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 23:17:17 -0700 Subject: [PATCH 32/43] development release --- parse.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/parse.go b/parse.go index 793e19c..2851ab1 100644 --- a/parse.go +++ b/parse.go @@ -952,10 +952,11 @@ func processPermissionBindRules(stack any) (pbrs PermissionBindRules, err error) slice, _ := _pbrs.Index(i) if _pbr, asserted := slice.(parser.PermissionBindRule); asserted { var pbr PermissionBindRule - if pbr, err = processPermissionBindRule(_pbr); err != nil { - break + if pbr, err = processPermissionBindRule(_pbr); err == nil { + pbrs.Push(pbr) + continue } - pbrs.Push(pbr) + break } } From e534804c5269242ab2f382f0d8b13ea24c2c2126 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 23:20:29 -0700 Subject: [PATCH 33/43] development release --- attr.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/attr.go b/attr.go index 07bc91a..9cf3edf 100644 --- a/attr.go +++ b/attr.go @@ -153,11 +153,11 @@ Eq initializes and returns a new BindRule instance configured to express the evaluation of the receiver value as Equal-To a `userattr` or `groupattr` Bind keyword context. */ -func (r AttributeBindTypeOrValue) Eq() BindRule { - if r.atbtv.isZero() { - return badBindRule +func (r AttributeBindTypeOrValue) Eq() (b BindRule) { + if !r.atbtv.isZero() { + b = BR(r.BindKeyword, Eq, r) } - return BR(r.BindKeyword, Eq, r) + return } /* @@ -167,11 +167,11 @@ Bind keyword context. Negated equality BindRule instances should be used with caution. */ -func (r AttributeBindTypeOrValue) Ne() BindRule { - if r.atbtv.isZero() { - return badBindRule +func (r AttributeBindTypeOrValue) Ne() (b BindRule) { + if !r.atbtv.isZero() { + b = BR(r.BindKeyword, Ne, r) } - return BR(r.BindKeyword, Ne, r) + return } /* From 2a56b4c565aae3303c6b95d2b08f21a2dd50e96e Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 23:29:12 -0700 Subject: [PATCH 34/43] development release --- attr.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/attr.go b/attr.go index 9cf3edf..2773802 100644 --- a/attr.go +++ b/attr.go @@ -402,11 +402,11 @@ func (r AttributeType) Compare(x any) bool { Eq initializes and returns a new TargetRule instance configured to express the evaluation of the receiver value as Equal-To a `targetattr` keyword context. */ -func (r AttributeType) Eq() TargetRule { - if r.IsZero() { - return badTargetRule +func (r AttributeType) Eq() (t TargetRule) { + if !r.IsZero() { + t = TR(TargetAttr, Eq, r) } - return TR(TargetAttr, Eq, r) + return } /* @@ -415,11 +415,11 @@ evaluation of the receiver value as Not-Equal-To a `targetattr` keyword context. Negated equality TargetRule instances should be used with caution. */ -func (r AttributeType) Ne() TargetRule { - if r.IsZero() { - return badTargetRule +func (r AttributeType) Ne() (t TargetRule) { + if !r.IsZero() { + t = TR(TargetAttr, Ne, r) } - return TR(TargetAttr, Ne, r) + return } /* From 16a1bee90fc87914ae7c47cb1d89f9df7742d2f6 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 23:34:46 -0700 Subject: [PATCH 35/43] development release --- pb_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pb_test.go b/pb_test.go index 55baa56..9c50364 100644 --- a/pb_test.go +++ b/pb_test.go @@ -399,4 +399,6 @@ func TestPermissionBindRules_codecov(t *testing.T) { pbs.Pop() pbs.Push(rule5) pbs.Push(rule5.String()) + pbs.Contains(rule5) + pbs.Contains(rule5.String()) } From e17e6cc5d38f92e4aa076a9d0633854a6070c824 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 23:41:24 -0700 Subject: [PATCH 36/43] development release --- target.go | 35 +++++++++++++++++------------------ target_test.go | 2 ++ 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/target.go b/target.go index d85ba22..e19f7bc 100644 --- a/target.go +++ b/target.go @@ -781,26 +781,25 @@ stackage.Stack (or alias) type instance. Only TargetRule instances are to be cleared for push executions. */ func (r TargetRules) pushPolicy(x ...any) (err error) { - if len(x) == 0 { - return - } else if x[0] == nil { - err = nilInstanceErr(x[0]) - return - } - - switch tv := x[0].(type) { - case TargetRule: - if tv.IsZero() { - err = pushErrorNilOrZero(r, tv, tv.Keyword()) + for i := 0; i < len(x); i++ { + switch tv := x[i].(type) { + case TargetRule: + if tv.IsZero() { + err = pushErrorNilOrZero(r, tv, tv.Keyword()) + } + if matchTKW(tv.Keyword().String()) == TargetKeyword(0x0) { + err = badPTBRuleKeywordErr(tv, `target`, `targetkeyword`, tv.Keyword()) + } + if r.contains(tv.Keyword()) { + err = pushErrorNilOrZero(r, tv, tv.Keyword()) + } + default: + err = pushErrorBadType(r, tv, nil) } - if matchTKW(tv.Keyword().String()) == TargetKeyword(0x0) { - err = badPTBRuleKeywordErr(tv, `target`, `targetkeyword`, tv.Keyword()) - } - if r.contains(tv.Keyword()) { - err = pushErrorNilOrZero(r, tv, tv.Keyword()) + + if err != nil { + break } - default: - err = pushErrorBadType(r, tv, nil) } return diff --git a/target_test.go b/target_test.go index ee6ac38..b4d5b9e 100644 --- a/target_test.go +++ b/target_test.go @@ -139,6 +139,8 @@ func TestTargetRules_bogus(t *testing.T) { _ = tr.Push(nil, nil) _ = tr.Push('𝝅') tr.Push(TDN(`uid=jesse,ou=People,dc=example,dc=com`).Eq()) + tr.Contains(TDN(`uid=jesse,ou=People,dc=example,dc=com`).Eq()) + tr.Contains(TDN(`uid=jesse,ou=People,dc=example,dc=com`).Eq().String()) tr.reset() } From 84053e1f7ca7d39b29c3fe836f83b42a95a1d2fd Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 23:47:59 -0700 Subject: [PATCH 37/43] development release --- bind.go | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/bind.go b/bind.go index 7b5f7ad..06d530a 100644 --- a/bind.go +++ b/bind.go @@ -643,17 +643,12 @@ func convertBindRulesHierarchy(stack any) (BindContext, bool) { // Obtain the kind string from the // original stack. - k := trimS(orig.Kind()) - - clean, ok := wordToStack(k) - if !ok { - return badBindRules, ok - } + clean, ok := wordToStack(orig.Kind()) // Iterate the newly-populated clean // instance, performing type-casting // as needed, possibly in recursion. - for i := 0; i < orig.Len(); i++ { + for i := 0; i < orig.Len() && ok; i++ { slice, _ := orig.Index(i) // perform a type switch upon the @@ -687,11 +682,11 @@ func convertBindRulesHierarchy(stack any) (BindContext, bool) { // DistinguishedNames[] -> // [] -> // [] -> - if err := ntv.assertExpressionValue(); err != nil { - return badBindRules, false + if err := ntv.assertExpressionValue(); err == nil { + clean.Push(ntv) + continue } - - clean.Push(ntv) + break // slice is a stackage.Stack instance. // We want to cast to a BindRules type @@ -702,16 +697,15 @@ func convertBindRulesHierarchy(stack any) (BindContext, bool) { case isStackageStack(slice): stk, _ := castAsStack(slice) paren := stk.IsParen() - sub, subok := convertBindRulesHierarchy(slice) - if !subok { - return badBindRules, subok - } - if _, ok := sub.(BindRules); ok { - sub.(BindRules).Paren(paren) - uncloakBindRules(sub.(BindRules)) + if sub, subok := convertBindRulesHierarchy(slice); subok { + if _, ok := sub.(BindRules); ok { + sub.(BindRules).Paren(paren) + uncloakBindRules(sub.(BindRules)) + } + clean.Push(sub) + continue } - clean.Push(sub) - + return badBindRules, false } } From 95b92647118b52bd6daac7e3413241f02f4e4cb6 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Mon, 18 Sep 2023 23:57:47 -0700 Subject: [PATCH 38/43] development release --- parse.go | 84 +++++++++++++++++++++++++++----------------------------- 1 file changed, 40 insertions(+), 44 deletions(-) diff --git a/parse.go b/parse.go index 2851ab1..c0f661a 100644 --- a/parse.go +++ b/parse.go @@ -842,49 +842,6 @@ func unpackageAntlrPermission(perm parser.Permission) (*permission, error) { Right: new(Right), // rights specifiers (ptr to uint8 alias) } - // !! WARNING - EXTREME SECURITY RISK !! - // - // A disposition has two (2) official settings and, thus, - // is considered to be a MuTeX: - // - // - allow, which is expressed through a bool value of true - // - deny, which is expressed through a bool value of false - // - // Ones initial thinking might lead to the conclusion that - // a default of false is perfectly fine. But it shouldn't - // take long for them to rethink that position, given the - // following expression (or similar): - // - // deny(none) - // - // Given the right (or wrong?) context, this could be bad. - // Really, really bad. The above expression could return - // as a result of parsing an instruction if a bogus, or - // outright absent disposition was perceived and (as a - // result of this failure) the default "Rights" specifiers - // default to "none", which is only logical, right? - // - // BUT, because Golang (and most languages) defines implicit - // defaults for certain types -- such as 0 for int and false - // for bool -- any default is a bad idea here. - // - // Therefore a POINTER to a bool is used, both here in go-aci - // AND within its sister package go-antlraci. go-antlraci will - // evaluate/set the pointer using a double MuTeX case statement, - // which allows only specific mutual-exclusion permutations that - // are certain to avoid the above scenario. - // - // The ultimate disposition decision made by go-antlraci in this - // case can be trusted, so long as the imported build is not some - // fork from a source you don't know and trust. - switch x := perm.Allow; x { - case nil: - // ambiguous result = fatal error - return nil, noPermissionDispErr() - default: - (*p.bool) = *x - } - // process each permission one at a time var bits int // temporary storage for verification of bitshifted permission values for i := 0; i < len(perm.Rights); i++ { @@ -906,7 +863,46 @@ func unpackageAntlrPermission(perm parser.Permission) (*permission, error) { // to be memory efficient. err := unexpectedValueCountErr(`permission bits`, bits, int(*p.Right)) if bits == int(*p.Right) { - err = nil + // !! WARNING - EXTREME SECURITY RISK !! + // + // A disposition has two (2) official settings and, thus, + // is considered to be a MuTeX: + // + // - allow, which is expressed through a bool value of true + // - deny, which is expressed through a bool value of false + // + // Ones initial thinking might lead to the conclusion that + // a default of false is perfectly fine. But it shouldn't + // take long for them to rethink that position, given the + // following expression (or similar): + // + // deny(none) + // + // Given the right (or wrong?) context, this could be bad. + // Really, really bad. The above expression could return + // as a result of parsing an instruction if a bogus, or + // outright absent disposition was perceived and (as a + // result of this failure) the default "Rights" specifiers + // default to "none", which is only logical, right? + // + // BUT, because Golang (and most languages) defines implicit + // defaults for certain types -- such as 0 for int and false + // for bool -- any default is a bad idea here. + // + // Therefore a POINTER to a bool is used, both here in go-aci + // AND within its sister package go-antlraci. go-antlraci will + // evaluate/set the pointer using a double MuTeX case statement, + // which allows only specific mutual-exclusion permutations that + // are certain to avoid the above scenario. + // + // The ultimate disposition decision made by go-antlraci in this + // case can be trusted, so long as the imported build is not some + // fork from a source you don't know and trust. + err = noPermissionDispErr() + if x := perm.Allow; x != nil { + (*p.bool) = *x + err = nil + } } return p, err From b00d7add3c7b26ef60ffa716235fbf7437ffcec7 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Tue, 19 Sep 2023 00:00:36 -0700 Subject: [PATCH 39/43] development release --- parse.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/parse.go b/parse.go index c0f661a..7e234dc 100644 --- a/parse.go +++ b/parse.go @@ -526,9 +526,10 @@ func processTargetRules(stack any) (TargetRules, error) { // DistinguishedNames[] -> // [] -> // [] -> - if err = trv.assertExpressionValue(); err != nil { - return badTargetRules, err + if err = trv.assertExpressionValue(); err == nil { + continue // because codecov. } + break } return t, err From 70f28ef65d01c1c55eb793f5c58ed1a9dc0e151f Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Tue, 19 Sep 2023 00:03:56 -0700 Subject: [PATCH 40/43] development release --- dn.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dn.go b/dn.go index a7ac757..9c3c620 100644 --- a/dn.go +++ b/dn.go @@ -1001,11 +1001,11 @@ func (r BindDistinguishedNames) setExpressionValues(key Keyword, values ...strin // syntax. If positive, push it and skip ahead. if hasPfx(values[i], LocalScheme) && contains(values[i], `?`) { var U LDAPURI - if U, err = parseLDAPURI(values[i], key.(BindKeyword)); err != nil { - return + if U, err = parseLDAPURI(values[i], key.(BindKeyword)); err == nil { + r.Push(U) + continue } - r.Push(U) - continue + break } // From adb8bb08814871e76e13bf58c5ebc0168430b5e2 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Tue, 19 Sep 2023 00:15:21 -0700 Subject: [PATCH 41/43] development release --- levels_test.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/levels_test.go b/levels_test.go index 71a97f2..95923c9 100644 --- a/levels_test.go +++ b/levels_test.go @@ -249,8 +249,9 @@ func TestLevels_bogus(t *testing.T) { _ = l1.String() _ = l1.Positive(noLvl) _ = l1.Positive(Level8) - _ = l1.Positive(8) - _ = l1.Positive(`8`) + _ = l1.positive(8) + _ = l1.positive(`1`) + _ = l1.positive(`this`) var inh Inheritance if err := inh.Valid(); err == nil { @@ -353,7 +354,7 @@ func TestInheritance_parse(t *testing.T) { func TestInheritance_codecov(t *testing.T) { var inh Inheritance - _ = inh.Levels() + _ = inh.Levels().Positive(`4`) _ = inh.Keyword() _ = inh.String() _ = inh.Shift(1370) @@ -367,6 +368,8 @@ func TestInheritance_codecov(t *testing.T) { _ = inh.Positive(`fart`) _ = inh.Positive(100000) _ = inh.Positive(-1) + _ = inh.Levels().Positive(4) + _ = inh.Levels().Positive("something awful") _ = inh.Positive(Level(^uint16(0))) _ = inh.Positive(3.14159) } From b00db18f6df3e78aea18b81828419610793c6399 Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Tue, 19 Sep 2023 00:18:39 -0700 Subject: [PATCH 42/43] development release --- levels_test.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/levels_test.go b/levels_test.go index 95923c9..5f68b97 100644 --- a/levels_test.go +++ b/levels_test.go @@ -156,6 +156,13 @@ func ExampleLevels_Positive() { // Output: Level 4 positive? true } +func ExampleLevels_Positive_byString() { + var l Levels + l.Shift(Level4, Level0) + fmt.Printf("Level 4 positive? %t", l.Positive(`4`)) + // Output: Level 4 positive? true +} + func ExampleLevels_Unshift() { var l Levels l.Shift(Level4, Level0) From 20b231a391c3816a49037586eb9979ec393a9ced Mon Sep 17 00:00:00 2001 From: JesseCoretta Date: Tue, 19 Sep 2023 00:38:35 -0700 Subject: [PATCH 43/43] development release --- README.md | 38 ++++++++++++-------------------------- 1 file changed, 12 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 3025446..38635d6 100644 --- a/README.md +++ b/README.md @@ -52,17 +52,13 @@ DIT because it considers you a threat. 🤓 ## About ACIs -Within the context of ACIv3, An ACI[^1] is an expressive statement or "policy" that is used to define the disclosing or withholding of information -for an X.500/LDAP[^2] DIT[^3] as it pertains to its userbase. +Within the context of ACIv3, An [ACI](## "Access Control Instruction") is an expressive statement or "policy" that is used to define the disclosing or withholding of information +for an [X.500](## "ITU-T X-Series 500")/[LDAP](Lightweight Directory Access Protocol) [DIT](## "Directory Information Tree") as it pertains to its userbase. In layperson's terms, ACIs are a specific and (largely) non-proprietary form of "LDAP permissions" that govern who can read, write, search, etc. Not all LDAP server implementations support the ACIv3 syntax, but several do. Check your vendor or reference material for compatibility information. -[^1]: Access Control Instruction -[^2]: ITU-T X-Series 500 / Lightweight Directory Access Protocol ([`X.500`](https://www.itu.int/rec/T-REC-X.500) and [RFC4510](https://datatracker.ietf.org/doc/html/rfc4510), et al) -[^3]: Directory Information Tree - ## Implementation Compatibility Notice The ACIv3 syntax, though largely the same across the multiple supporting directory products that have adopted it, does have @@ -71,20 +67,17 @@ a few variations in terms of available keywords and features. Though this is not a comprehensive list, a few of these cases are listed below: - TargetRule scoping, through the `targetscope` keyword -- BindRule DN[^4] roles, through the `roledn` keyword +- BindRule [DN](## "LDAP Distinguished Name") roles, through the `roledn` keyword - Group attribute-based value matching, through the `groupattr` keyword -- LDAP Extended Operation OID[^5] definitions, through the `extop` keyword +- LDAP Extended Operation [OID](## "ASN.1 Object Identifier") definitions, through the `extop` keyword - LDAP Control OID definitions, through the `targetcontrol` keyword - Rights definitions, such as `import` and `export` - Number of supported 'levels' for inheritance value matching This package aims to support *ALL* of the facets of the ACIv3 syntax without exception. Users will need to verify, however, that any ACI definitions generated -- in part or in whole as a result of using this package -- are compatible with their -particular X.500/LDAP DSA[^6] implementation; check the docs and always listen to your vendor! - -[^4]: (LDAP) Distinguished Name -[^5]: (ASN.1) Object Identifier -[^6]: Directory System Agent, i.e.: your LDAP server(s) +particular X.500/LDAP [DSA](## "Directory System Agent; an LDAP server") implementation; check the docs and always listen +to your vendor! # Features @@ -131,8 +124,9 @@ particular X.500/LDAP DSA[^6] implementation; check the docs and always listen t ## Parsing vs. Assembly -This package imports an ANTLR4[^7] parsing subsystem to facilitate the "conversion" of ACI textual definitions into proper type instances. -This functionality is provided by the [`go-antlraci`](https://github.com/JesseCoretta/go-antlraci) package. +This package imports an [ANTLR4](## "ANother Tool for Language Recognition, Version 4") parsing subsystem to facilitate the "conversion" of ACI +textual definitions into proper type instances. This functionality is provided by the [`go-antlraci`](https://github.com/JesseCoretta/go-antlraci) +package. The parser reads the user-provided textual expression, processes the components and generates a proper instance of the package-provided type. @@ -176,8 +170,6 @@ Which technique is "better" depends on the use-case. For individuals writing ACI Then again, the same sentiment may not apply to situations in which there are no individuals, and the process is wholly automated: the "parsing" option may be far more appealing. -[^7]: ANother Tool for Language Recognition, Version 4 (www.antlr.org) - ## Potential Use Cases This package could conceivably be used in any of the following scenarios: @@ -186,9 +178,7 @@ This package could conceivably be used in any of the following scenarios: - For Directory personnel in charge of authoring and/or managing rich documentation - For Directory personnel who desire a means to author and/or manage sets of ACIs in a more programmatic / automated manner, perhaps with the aid of a templating system - For use as an access control framework within an actual (Go-based) Directory System Agent implementation that honors the ACI syntax -- For generalized experimentation within the realm of DSA access control design and even PEN[^8] testing - -[^8]: PENetration Testing +- For generalized experimentation within the realm of DSA access control design ## Limitations @@ -248,7 +238,7 @@ building statements that reference a multi-valued expression: In particular, these sorts of quotation schemes appear in the following scenarios: -- `targetattr` TargetRules for lists of LDAP ATs[^9] +- `targetattr` TargetRules for lists of LDAP [ATs](## "LDAP AttributeTypes") - `target`, `target_to` and `target_from` TargetRule DNs - `userdn` and `groupdn` BindRule DNs - `extop` and `targetcontrol` TargetRule OIDs @@ -257,8 +247,6 @@ Users are advised to honor the quotation scheme recommended by their vendor or p support either of the above schemes with no variance in the end result, but has no official position as to which of these schemes should be honored by the user except that quotation should always be used _in some form_. -[^9]: (LDAP) AttributeTypes - ## Contribution Encouraged The ACIv3 syntax is fairly complex, rendering its innate flexibility akin to a double-edged sword. As such there may be errors, or @@ -289,7 +277,5 @@ By now, it is likely obvious this package aims to provide everything one could p not discriminate ACIs that may be overtly "broad" in their influence or entry-matching potential. One such example of this is careless use of the negated equality operator (`!=`), which (when used improperly) can disclose myriad attribute -values unintentionally. This particular case is well-documented in vendor manuals for supporting directory products (likely for legal CYA[^10] +values unintentionally. This particular case is well-documented in vendor manuals for supporting directory products (likely for legal CYA reasons). Users are advised to LEARN the syntax well enough to know when to take such risks. - -[^10]: Cover Your ~~_REDACTED_~~ **Gluteus Maximus**