go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/common/proto/protowalk/doc.go (about) 1 // Copyright 2022 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package protowalk contains routines for efficiently walking proto messages, 16 // focusing on the ability to react to field annotations. 17 // 18 // This package defines an interface (FieldProcessor) which you can 19 // implement to react to any fields you like. 20 // 21 // This package also comes with stock implementations for the following common 22 // field annotations: 23 // - google.api.field_behavior = REQUIRED 24 // - google.api.field_behavior = OUTPUT_ONLY 25 // - deprecated = true 26 // 27 // # How it works 28 // 29 // 1. Register a FieldProcessor using RegisterFieldProcessor. 30 // 31 // A FieldProcessor checks and/or manipulates fields in a proto message. When 32 // registering an implementation, you also provide a `selector` function which 33 // detects fields (e.g. by their type, field options, etc.) that the 34 // FieldProcessor wants to operate on. 35 // 36 // 2. Use the Fields() with one or more FieldProcessor instantances to process 37 // a proto message. 38 // 39 // Fields generates, once per process, a global cache entry keyed on 40 // (msgType, processorType). This entry is a list of fields in `msgType` 41 // which the FieldProcessor's registered `selector` function says it should 42 // operate on, and also indicates for a given field if it should be recursed 43 // for this processor (i.e. if field `M.a` is a message type `A` which has 44 // fields that match this processor). 45 // 46 // Once the cache entries are generated, Fields then generates a 'plan' which is 47 // the combination of _all_ the provided processors' cache entries, such that 48 // Fields() can then walk through all affected fields, once, in order, 49 // generating results from the provided message in an ordered and deterministic 50 // fashion. 51 // 52 // The upshot is that Fields() should be O(CheckableFields), no matter how big 53 // the proto messages are, rather than a naive O(Fields) implementation. 54 // 55 // A Result contains the ProtoPath and a message generated by the 56 // FieldProcessor. The ProtoPath describes the path through the source message 57 // to the affected field, and can either be printed for display, or can be used 58 // to retrieve the actual value. 59 package protowalk