| // Copyright 2022 The LUCI Authors. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| // Package protowalk contains routines for efficiently walking proto messages, |
| // focusing on the ability to react to field annotations. |
| // |
| // This package defines an interface (FieldProcessor) which you can |
| // implement to react to any fields you like. |
| // |
| // This package also comes with stock implementations for the following common |
| // field annotations: |
| // - google.api.field_behavior = REQUIRED |
| // - google.api.field_behavior = OUTPUT_ONLY |
| // - deprecated = true |
| // |
| // # How it works |
| // |
| // 1. Register a FieldProcessor using RegisterFieldProcessor. |
| // |
| // A FieldProcessor checks and/or manipulates fields in a proto message. When |
| // registering an implementation, you also provide a `selector` function which |
| // detects fields (e.g. by their type, field options, etc.) that the |
| // FieldProcessor wants to operate on. |
| // |
| // 2. Use the Fields() with one or more FieldProcessor instantances to process |
| // a proto message. |
| // |
| // Fields generates, once per process, a global cache entry keyed on |
| // (msgType, processorType). This entry is a list of fields in `msgType` |
| // which the FieldProcessor's registered `selector` function says it should |
| // operate on, and also indicates for a given field if it should be recursed |
| // for this processor (i.e. if field `M.a` is a message type `A` which has |
| // fields that match this processor). |
| // |
| // Once the cache entries are generated, Fields then generates a 'plan' which is |
| // the combination of _all_ the provided processors' cache entries, such that |
| // Fields() can then walk through all affected fields, once, in order, |
| // generating results from the provided message in an ordered and deterministic |
| // fashion. |
| // |
| // The upshot is that Fields() should be O(CheckableFields), no matter how big |
| // the proto messages are, rather than a naive O(Fields) implementation. |
| // |
| // A Result contains the ProtoPath and a message generated by the |
| // FieldProcessor. The ProtoPath describes the path through the source message |
| // to the affected field, and can either be printed for display, or can be used |
| // to retrieve the actual value. |
| package protowalk |