Added API:
Default() Option
FilterPriority(opts ...Option) Option
FilterPriority returns a new Option where an option, opts[i],
is only evaluated if no fundamental options remain after applying all filters
in all prior options, opts[:i].
In order to prevent further options from being evaluated, the Default option
can be used to ensure that some fundamental option remains.
Suppose you have a value tree T, where T1 and T2 are sub-trees within T.
Prior to the addition of FilterPriority, it was impossible to do certain things.
Example 1: You could not make the following compose together nicely.
* Have a set of options OT1 to affect only values under T1.
* Have a set of options OT2 to affect only values under T2.
* Have a set of options OT to affect only T, but not values under T1 and T2.
* Have a set of options O to affect all other values, but no those in T
(and by extension those in T1 and T2).
Solution 1:
FilterPriority(
// Since T1 and T2 do not overlap, they could be placed within the
// same priority level by grouping them in an Options group.
FilterTree(T1, OT1),
FilterTree(T2, OT2),
FilterTree(T, OT),
O,
)
Example 2: You could not make the following compose together nicely.
* Have a set of options O apply on all nodes except those in T1 and T2.
* Instead, we want the default behavior of cmp on T1 and T2.
Solution 2:
FilterPriority(
// Here we show how to group T1 and T2 together to be on the same
// priority level.
Options{
FilterTree(T1, Default()),
FilterTree(T2, Default()),
},
O,
)
Example 3: You have this: type MyStruct struct { *pb.MyMessage; ... }
* Generally, you want to use Comparer(proto.Equal) to ensure
that all proto.Messages within the struct are properly compared.
However, this type has an embedded proto (generally a bad idea),
which causes the MyStruct to satisfy the proto.Message interface
and unintentionally causes Equal to use proto.Equal on MyStruct,
which crashes.
* How can you have Comparer(proto.Equal) apply to all other
proto.Message without applying just to MyStruct?
Solution 3:
FilterPriority(
// Only for MyStruct, use the default behavior of Equal,
// which is to recurse into the structure of MyStruct.
FilterPath(func(p Path) bool {
return p.Last().Type() == reflect.TypeOf(MyStruct{})
}, Default()),
// Use proto.Equal for all other cases of proto.Message.
Comparer(proto.Equal),
)