1*1fa6dee9SAndroid Build Coastguard Worker// Copyright 2020 Google Inc. All rights reserved. 2*1fa6dee9SAndroid Build Coastguard Worker// 3*1fa6dee9SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*1fa6dee9SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*1fa6dee9SAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*1fa6dee9SAndroid Build Coastguard Worker// 7*1fa6dee9SAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*1fa6dee9SAndroid Build Coastguard Worker// 9*1fa6dee9SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*1fa6dee9SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*1fa6dee9SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*1fa6dee9SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*1fa6dee9SAndroid Build Coastguard Worker// limitations under the License. 14*1fa6dee9SAndroid Build Coastguard Worker 15*1fa6dee9SAndroid Build Coastguard Workerpackage blueprint 16*1fa6dee9SAndroid Build Coastguard Worker 17*1fa6dee9SAndroid Build Coastguard Workerimport ( 18*1fa6dee9SAndroid Build Coastguard Worker "encoding/gob" 19*1fa6dee9SAndroid Build Coastguard Worker "fmt" 20*1fa6dee9SAndroid Build Coastguard Worker 21*1fa6dee9SAndroid Build Coastguard Worker "github.com/google/blueprint/gobtools" 22*1fa6dee9SAndroid Build Coastguard Worker "github.com/google/blueprint/proptools" 23*1fa6dee9SAndroid Build Coastguard Worker) 24*1fa6dee9SAndroid Build Coastguard Worker 25*1fa6dee9SAndroid Build Coastguard Worker// This file implements Providers, modelled after Bazel 26*1fa6dee9SAndroid Build Coastguard Worker// (https://docs.bazel.build/versions/master/skylark/rules.html#providers). 27*1fa6dee9SAndroid Build Coastguard Worker// Each provider can be associated with a mutator, in which case the value for the provider for a 28*1fa6dee9SAndroid Build Coastguard Worker// module can only be set during the mutator call for the module, and the value can only be 29*1fa6dee9SAndroid Build Coastguard Worker// retrieved after the mutator call for the module. For providers not associated with a mutator, the 30*1fa6dee9SAndroid Build Coastguard Worker// value can for the provider for a module can only be set during GenerateBuildActions for the 31*1fa6dee9SAndroid Build Coastguard Worker// module, and the value can only be retrieved after GenerateBuildActions for the module. 32*1fa6dee9SAndroid Build Coastguard Worker// 33*1fa6dee9SAndroid Build Coastguard Worker// Providers are globally registered during init() and given a unique ID. The value of a provider 34*1fa6dee9SAndroid Build Coastguard Worker// for a module is stored in an []any indexed by the ID. If the value of a provider has 35*1fa6dee9SAndroid Build Coastguard Worker// not been set, the value in the []any will be nil. 36*1fa6dee9SAndroid Build Coastguard Worker// 37*1fa6dee9SAndroid Build Coastguard Worker// If the storage used by the provider value arrays becomes too large: 38*1fa6dee9SAndroid Build Coastguard Worker// sizeof([]interface) * number of providers * number of modules that have a provider value set 39*1fa6dee9SAndroid Build Coastguard Worker// then the storage can be replaced with something like a bitwise trie. 40*1fa6dee9SAndroid Build Coastguard Worker// 41*1fa6dee9SAndroid Build Coastguard Worker// The purpose of providers is to provide a serializable checkpoint between modules to enable 42*1fa6dee9SAndroid Build Coastguard Worker// Blueprint to skip parts of the analysis phase when inputs haven't changed. To that end, 43*1fa6dee9SAndroid Build Coastguard Worker// values passed to providers should be treated as immutable by callers to both the getters and 44*1fa6dee9SAndroid Build Coastguard Worker// setters. Go doesn't provide any way to enforce immutability on arbitrary types, so it may be 45*1fa6dee9SAndroid Build Coastguard Worker// necessary for the getters and setters to make deep copies of the values, likely extending 46*1fa6dee9SAndroid Build Coastguard Worker// proptools.CloneProperties to do so. 47*1fa6dee9SAndroid Build Coastguard Worker 48*1fa6dee9SAndroid Build Coastguard Workertype typedProviderKey[K any] struct { 49*1fa6dee9SAndroid Build Coastguard Worker providerKey 50*1fa6dee9SAndroid Build Coastguard Worker} 51*1fa6dee9SAndroid Build Coastguard Worker 52*1fa6dee9SAndroid Build Coastguard Workertype providerKey struct { 53*1fa6dee9SAndroid Build Coastguard Worker id int 54*1fa6dee9SAndroid Build Coastguard Worker typ string 55*1fa6dee9SAndroid Build Coastguard Worker mutator string 56*1fa6dee9SAndroid Build Coastguard Worker} 57*1fa6dee9SAndroid Build Coastguard Worker 58*1fa6dee9SAndroid Build Coastguard Workertype providerKeyGob struct { 59*1fa6dee9SAndroid Build Coastguard Worker Id int 60*1fa6dee9SAndroid Build Coastguard Worker Typ string 61*1fa6dee9SAndroid Build Coastguard Worker Mutator string 62*1fa6dee9SAndroid Build Coastguard Worker} 63*1fa6dee9SAndroid Build Coastguard Worker 64*1fa6dee9SAndroid Build Coastguard Workerfunc (m *providerKey) ToGob() *providerKeyGob { 65*1fa6dee9SAndroid Build Coastguard Worker return &providerKeyGob{ 66*1fa6dee9SAndroid Build Coastguard Worker Id: m.id, 67*1fa6dee9SAndroid Build Coastguard Worker Typ: m.typ, 68*1fa6dee9SAndroid Build Coastguard Worker Mutator: m.mutator, 69*1fa6dee9SAndroid Build Coastguard Worker } 70*1fa6dee9SAndroid Build Coastguard Worker} 71*1fa6dee9SAndroid Build Coastguard Worker 72*1fa6dee9SAndroid Build Coastguard Workerfunc (m *providerKey) FromGob(data *providerKeyGob) { 73*1fa6dee9SAndroid Build Coastguard Worker m.id = data.Id 74*1fa6dee9SAndroid Build Coastguard Worker m.typ = data.Typ 75*1fa6dee9SAndroid Build Coastguard Worker m.mutator = data.Mutator 76*1fa6dee9SAndroid Build Coastguard Worker} 77*1fa6dee9SAndroid Build Coastguard Worker 78*1fa6dee9SAndroid Build Coastguard Workerfunc (m *providerKey) GobEncode() ([]byte, error) { 79*1fa6dee9SAndroid Build Coastguard Worker return gobtools.CustomGobEncode[providerKeyGob](m) 80*1fa6dee9SAndroid Build Coastguard Worker} 81*1fa6dee9SAndroid Build Coastguard Worker 82*1fa6dee9SAndroid Build Coastguard Workerfunc (m *providerKey) GobDecode(data []byte) error { 83*1fa6dee9SAndroid Build Coastguard Worker return gobtools.CustomGobDecode[providerKeyGob](data, m) 84*1fa6dee9SAndroid Build Coastguard Worker} 85*1fa6dee9SAndroid Build Coastguard Worker 86*1fa6dee9SAndroid Build Coastguard Workerfunc (p *providerKey) provider() *providerKey { return p } 87*1fa6dee9SAndroid Build Coastguard Worker 88*1fa6dee9SAndroid Build Coastguard Workertype AnyProviderKey interface { 89*1fa6dee9SAndroid Build Coastguard Worker provider() *providerKey 90*1fa6dee9SAndroid Build Coastguard Worker} 91*1fa6dee9SAndroid Build Coastguard Workertype ProviderKey[K any] struct { 92*1fa6dee9SAndroid Build Coastguard Worker *typedProviderKey[K] 93*1fa6dee9SAndroid Build Coastguard Worker} 94*1fa6dee9SAndroid Build Coastguard Worker 95*1fa6dee9SAndroid Build Coastguard Workervar _ AnyProviderKey = (*providerKey)(nil) 96*1fa6dee9SAndroid Build Coastguard Workervar _ AnyProviderKey = ProviderKey[bool]{} 97*1fa6dee9SAndroid Build Coastguard Worker 98*1fa6dee9SAndroid Build Coastguard Workervar providerRegistry []*providerKey 99*1fa6dee9SAndroid Build Coastguard Worker 100*1fa6dee9SAndroid Build Coastguard Worker// NewProvider returns a ProviderKey for the given type. 101*1fa6dee9SAndroid Build Coastguard Worker// 102*1fa6dee9SAndroid Build Coastguard Worker// The returned ProviderKey can be used to set a value of the ProviderKey's type for a module 103*1fa6dee9SAndroid Build Coastguard Worker// inside GenerateBuildActions for the module, and to get the value from GenerateBuildActions from 104*1fa6dee9SAndroid Build Coastguard Worker// any module later in the build graph. 105*1fa6dee9SAndroid Build Coastguard Workerfunc NewProvider[K any]() ProviderKey[K] { 106*1fa6dee9SAndroid Build Coastguard Worker var defaultValue K 107*1fa6dee9SAndroid Build Coastguard Worker gob.Register(defaultValue) 108*1fa6dee9SAndroid Build Coastguard Worker return NewMutatorProvider[K]("") 109*1fa6dee9SAndroid Build Coastguard Worker} 110*1fa6dee9SAndroid Build Coastguard Worker 111*1fa6dee9SAndroid Build Coastguard Worker// NewMutatorProvider returns a ProviderKey for the given type. 112*1fa6dee9SAndroid Build Coastguard Worker// 113*1fa6dee9SAndroid Build Coastguard Worker// The returned ProviderKey can be used to set a value of the ProviderKey's type for a module inside 114*1fa6dee9SAndroid Build Coastguard Worker// the given mutator for the module, and to get the value from GenerateBuildActions from any 115*1fa6dee9SAndroid Build Coastguard Worker// module later in the build graph in the same mutator, or any module in a later mutator or during 116*1fa6dee9SAndroid Build Coastguard Worker// GenerateBuildActions. 117*1fa6dee9SAndroid Build Coastguard Workerfunc NewMutatorProvider[K any](mutator string) ProviderKey[K] { 118*1fa6dee9SAndroid Build Coastguard Worker checkCalledFromInit() 119*1fa6dee9SAndroid Build Coastguard Worker 120*1fa6dee9SAndroid Build Coastguard Worker typ := fmt.Sprintf("%T", *new(K)) 121*1fa6dee9SAndroid Build Coastguard Worker 122*1fa6dee9SAndroid Build Coastguard Worker provider := ProviderKey[K]{ 123*1fa6dee9SAndroid Build Coastguard Worker typedProviderKey: &typedProviderKey[K]{ 124*1fa6dee9SAndroid Build Coastguard Worker providerKey: providerKey{ 125*1fa6dee9SAndroid Build Coastguard Worker id: len(providerRegistry), 126*1fa6dee9SAndroid Build Coastguard Worker typ: typ, 127*1fa6dee9SAndroid Build Coastguard Worker mutator: mutator, 128*1fa6dee9SAndroid Build Coastguard Worker }, 129*1fa6dee9SAndroid Build Coastguard Worker }, 130*1fa6dee9SAndroid Build Coastguard Worker } 131*1fa6dee9SAndroid Build Coastguard Worker 132*1fa6dee9SAndroid Build Coastguard Worker providerRegistry = append(providerRegistry, &provider.providerKey) 133*1fa6dee9SAndroid Build Coastguard Worker 134*1fa6dee9SAndroid Build Coastguard Worker return provider 135*1fa6dee9SAndroid Build Coastguard Worker} 136*1fa6dee9SAndroid Build Coastguard Worker 137*1fa6dee9SAndroid Build Coastguard Worker// initProviders fills c.providerMutators with the *mutatorInfo associated with each provider ID, 138*1fa6dee9SAndroid Build Coastguard Worker// if any. 139*1fa6dee9SAndroid Build Coastguard Workerfunc (c *Context) initProviders() { 140*1fa6dee9SAndroid Build Coastguard Worker c.providerMutators = make([]*mutatorInfo, len(providerRegistry)) 141*1fa6dee9SAndroid Build Coastguard Worker for _, provider := range providerRegistry { 142*1fa6dee9SAndroid Build Coastguard Worker for _, mutator := range c.mutatorInfo { 143*1fa6dee9SAndroid Build Coastguard Worker if mutator.name == provider.mutator { 144*1fa6dee9SAndroid Build Coastguard Worker c.providerMutators[provider.id] = mutator 145*1fa6dee9SAndroid Build Coastguard Worker } 146*1fa6dee9SAndroid Build Coastguard Worker } 147*1fa6dee9SAndroid Build Coastguard Worker } 148*1fa6dee9SAndroid Build Coastguard Worker} 149*1fa6dee9SAndroid Build Coastguard Worker 150*1fa6dee9SAndroid Build Coastguard Worker// setProvider sets the value for a provider on a moduleInfo. Verifies that it is called during the 151*1fa6dee9SAndroid Build Coastguard Worker// appropriate mutator or GenerateBuildActions pass for the provider, and that the value is of the 152*1fa6dee9SAndroid Build Coastguard Worker// appropriate type. The value should not be modified after being passed to setProvider. 153*1fa6dee9SAndroid Build Coastguard Worker// 154*1fa6dee9SAndroid Build Coastguard Worker// Once Go has generics the value parameter can be typed: 155*1fa6dee9SAndroid Build Coastguard Worker// setProvider(type T)(m *moduleInfo, provider ProviderKey(T), value T) 156*1fa6dee9SAndroid Build Coastguard Workerfunc (c *Context) setProvider(m *moduleInfo, provider *providerKey, value any) { 157*1fa6dee9SAndroid Build Coastguard Worker if provider.mutator == "" { 158*1fa6dee9SAndroid Build Coastguard Worker if !m.startedGenerateBuildActions { 159*1fa6dee9SAndroid Build Coastguard Worker panic(fmt.Sprintf("Can't set value of provider %s before GenerateBuildActions started", 160*1fa6dee9SAndroid Build Coastguard Worker provider.typ)) 161*1fa6dee9SAndroid Build Coastguard Worker } else if m.finishedGenerateBuildActions { 162*1fa6dee9SAndroid Build Coastguard Worker panic(fmt.Sprintf("Can't set value of provider %s after GenerateBuildActions finished", 163*1fa6dee9SAndroid Build Coastguard Worker provider.typ)) 164*1fa6dee9SAndroid Build Coastguard Worker } 165*1fa6dee9SAndroid Build Coastguard Worker } else { 166*1fa6dee9SAndroid Build Coastguard Worker expectedMutator := c.providerMutators[provider.id] 167*1fa6dee9SAndroid Build Coastguard Worker if expectedMutator == nil { 168*1fa6dee9SAndroid Build Coastguard Worker panic(fmt.Sprintf("Can't set value of provider %s associated with unregistered mutator %s", 169*1fa6dee9SAndroid Build Coastguard Worker provider.typ, provider.mutator)) 170*1fa6dee9SAndroid Build Coastguard Worker } else if c.mutatorFinishedForModule(expectedMutator, m) { 171*1fa6dee9SAndroid Build Coastguard Worker panic(fmt.Sprintf("Can't set value of provider %s after mutator %s finished", 172*1fa6dee9SAndroid Build Coastguard Worker provider.typ, provider.mutator)) 173*1fa6dee9SAndroid Build Coastguard Worker } else if !c.mutatorStartedForModule(expectedMutator, m) { 174*1fa6dee9SAndroid Build Coastguard Worker panic(fmt.Sprintf("Can't set value of provider %s before mutator %s started", 175*1fa6dee9SAndroid Build Coastguard Worker provider.typ, provider.mutator)) 176*1fa6dee9SAndroid Build Coastguard Worker } 177*1fa6dee9SAndroid Build Coastguard Worker } 178*1fa6dee9SAndroid Build Coastguard Worker 179*1fa6dee9SAndroid Build Coastguard Worker if m.providers == nil { 180*1fa6dee9SAndroid Build Coastguard Worker m.providers = make([]any, len(providerRegistry)) 181*1fa6dee9SAndroid Build Coastguard Worker } 182*1fa6dee9SAndroid Build Coastguard Worker 183*1fa6dee9SAndroid Build Coastguard Worker if m.providers[provider.id] != nil { 184*1fa6dee9SAndroid Build Coastguard Worker panic(fmt.Sprintf("Value of provider %s is already set", provider.typ)) 185*1fa6dee9SAndroid Build Coastguard Worker } 186*1fa6dee9SAndroid Build Coastguard Worker 187*1fa6dee9SAndroid Build Coastguard Worker m.providers[provider.id] = value 188*1fa6dee9SAndroid Build Coastguard Worker 189*1fa6dee9SAndroid Build Coastguard Worker if m.providerInitialValueHashes == nil { 190*1fa6dee9SAndroid Build Coastguard Worker m.providerInitialValueHashes = make([]uint64, len(providerRegistry)) 191*1fa6dee9SAndroid Build Coastguard Worker } 192*1fa6dee9SAndroid Build Coastguard Worker hash, err := proptools.CalculateHash(value) 193*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 194*1fa6dee9SAndroid Build Coastguard Worker panic(fmt.Sprintf("Can't set value of provider %s: %s", provider.typ, err.Error())) 195*1fa6dee9SAndroid Build Coastguard Worker } 196*1fa6dee9SAndroid Build Coastguard Worker m.providerInitialValueHashes[provider.id] = hash 197*1fa6dee9SAndroid Build Coastguard Worker} 198*1fa6dee9SAndroid Build Coastguard Worker 199*1fa6dee9SAndroid Build Coastguard Worker// provider returns the value, if any, for a given provider for a module. Verifies that it is 200*1fa6dee9SAndroid Build Coastguard Worker// called after the appropriate mutator or GenerateBuildActions pass for the provider on the module. 201*1fa6dee9SAndroid Build Coastguard Worker// If the value for the provider was not set it returns nil. The return value should always be considered read-only. 202*1fa6dee9SAndroid Build Coastguard Worker// 203*1fa6dee9SAndroid Build Coastguard Worker// Once Go has generics the return value can be typed and the type assert by callers can be dropped: 204*1fa6dee9SAndroid Build Coastguard Worker// provider(type T)(m *moduleInfo, provider ProviderKey(T)) T 205*1fa6dee9SAndroid Build Coastguard Workerfunc (c *Context) provider(m *moduleInfo, provider *providerKey) (any, bool) { 206*1fa6dee9SAndroid Build Coastguard Worker if provider.mutator == "" { 207*1fa6dee9SAndroid Build Coastguard Worker if !m.finishedGenerateBuildActions { 208*1fa6dee9SAndroid Build Coastguard Worker panic(fmt.Sprintf("Can't get value of provider %s before GenerateBuildActions finished", 209*1fa6dee9SAndroid Build Coastguard Worker provider.typ)) 210*1fa6dee9SAndroid Build Coastguard Worker } 211*1fa6dee9SAndroid Build Coastguard Worker } else { 212*1fa6dee9SAndroid Build Coastguard Worker expectedMutator := c.providerMutators[provider.id] 213*1fa6dee9SAndroid Build Coastguard Worker if expectedMutator != nil && !c.mutatorFinishedForModule(expectedMutator, m) { 214*1fa6dee9SAndroid Build Coastguard Worker panic(fmt.Sprintf("Can't get value of provider %s before mutator %s finished", 215*1fa6dee9SAndroid Build Coastguard Worker provider.typ, provider.mutator)) 216*1fa6dee9SAndroid Build Coastguard Worker } 217*1fa6dee9SAndroid Build Coastguard Worker } 218*1fa6dee9SAndroid Build Coastguard Worker 219*1fa6dee9SAndroid Build Coastguard Worker if len(m.providers) > provider.id { 220*1fa6dee9SAndroid Build Coastguard Worker if p := m.providers[provider.id]; p != nil { 221*1fa6dee9SAndroid Build Coastguard Worker return p, true 222*1fa6dee9SAndroid Build Coastguard Worker } 223*1fa6dee9SAndroid Build Coastguard Worker } 224*1fa6dee9SAndroid Build Coastguard Worker 225*1fa6dee9SAndroid Build Coastguard Worker return nil, false 226*1fa6dee9SAndroid Build Coastguard Worker} 227*1fa6dee9SAndroid Build Coastguard Worker 228*1fa6dee9SAndroid Build Coastguard Workerfunc (c *Context) mutatorFinishedForModule(mutator *mutatorInfo, m *moduleInfo) bool { 229*1fa6dee9SAndroid Build Coastguard Worker if c.finishedMutators[mutator.index] { 230*1fa6dee9SAndroid Build Coastguard Worker // mutator pass finished for all modules 231*1fa6dee9SAndroid Build Coastguard Worker return true 232*1fa6dee9SAndroid Build Coastguard Worker } 233*1fa6dee9SAndroid Build Coastguard Worker 234*1fa6dee9SAndroid Build Coastguard Worker return m.finishedMutator >= mutator.index 235*1fa6dee9SAndroid Build Coastguard Worker} 236*1fa6dee9SAndroid Build Coastguard Worker 237*1fa6dee9SAndroid Build Coastguard Workerfunc (c *Context) mutatorStartedForModule(mutator *mutatorInfo, m *moduleInfo) bool { 238*1fa6dee9SAndroid Build Coastguard Worker if c.finishedMutators[mutator.index] { 239*1fa6dee9SAndroid Build Coastguard Worker // mutator pass finished for all modules 240*1fa6dee9SAndroid Build Coastguard Worker return true 241*1fa6dee9SAndroid Build Coastguard Worker } 242*1fa6dee9SAndroid Build Coastguard Worker 243*1fa6dee9SAndroid Build Coastguard Worker return m.startedMutator >= mutator.index 244*1fa6dee9SAndroid Build Coastguard Worker} 245*1fa6dee9SAndroid Build Coastguard Worker 246*1fa6dee9SAndroid Build Coastguard Worker// OtherModuleProviderContext is a helper interface that is a subset of ModuleContext, BottomUpMutatorContext, or 247*1fa6dee9SAndroid Build Coastguard Worker// TopDownMutatorContext for use in OtherModuleProvider. 248*1fa6dee9SAndroid Build Coastguard Workertype OtherModuleProviderContext interface { 249*1fa6dee9SAndroid Build Coastguard Worker OtherModuleProvider(m Module, provider AnyProviderKey) (any, bool) 250*1fa6dee9SAndroid Build Coastguard Worker} 251*1fa6dee9SAndroid Build Coastguard Worker 252*1fa6dee9SAndroid Build Coastguard Workervar _ OtherModuleProviderContext = BaseModuleContext(nil) 253*1fa6dee9SAndroid Build Coastguard Workervar _ OtherModuleProviderContext = ModuleContext(nil) 254*1fa6dee9SAndroid Build Coastguard Workervar _ OtherModuleProviderContext = BottomUpMutatorContext(nil) 255*1fa6dee9SAndroid Build Coastguard Workervar _ OtherModuleProviderContext = TopDownMutatorContext(nil) 256*1fa6dee9SAndroid Build Coastguard Worker 257*1fa6dee9SAndroid Build Coastguard Worker// OtherModuleProvider reads the provider for the given module. If the provider has been set the value is 258*1fa6dee9SAndroid Build Coastguard Worker// returned and the boolean is true. If it has not been set the zero value of the provider's type is returned 259*1fa6dee9SAndroid Build Coastguard Worker// and the boolean is false. The value returned may be a deep copy of the value originally passed to SetProvider. 260*1fa6dee9SAndroid Build Coastguard Worker// 261*1fa6dee9SAndroid Build Coastguard Worker// OtherModuleProviderContext is a helper interface that accepts ModuleContext, BottomUpMutatorContext, or 262*1fa6dee9SAndroid Build Coastguard Worker// TopDownMutatorContext. 263*1fa6dee9SAndroid Build Coastguard Workerfunc OtherModuleProvider[K any](ctx OtherModuleProviderContext, module Module, provider ProviderKey[K]) (K, bool) { 264*1fa6dee9SAndroid Build Coastguard Worker value, ok := ctx.OtherModuleProvider(module, provider) 265*1fa6dee9SAndroid Build Coastguard Worker if !ok { 266*1fa6dee9SAndroid Build Coastguard Worker var k K 267*1fa6dee9SAndroid Build Coastguard Worker return k, false 268*1fa6dee9SAndroid Build Coastguard Worker } 269*1fa6dee9SAndroid Build Coastguard Worker return value.(K), ok 270*1fa6dee9SAndroid Build Coastguard Worker} 271*1fa6dee9SAndroid Build Coastguard Worker 272*1fa6dee9SAndroid Build Coastguard Worker// SingletonModuleProviderContext is a helper interface that is a subset of Context and SingletonContext for use in 273*1fa6dee9SAndroid Build Coastguard Worker// SingletonModuleProvider. 274*1fa6dee9SAndroid Build Coastguard Workertype SingletonModuleProviderContext interface { 275*1fa6dee9SAndroid Build Coastguard Worker ModuleProvider(m Module, provider AnyProviderKey) (any, bool) 276*1fa6dee9SAndroid Build Coastguard Worker} 277*1fa6dee9SAndroid Build Coastguard Worker 278*1fa6dee9SAndroid Build Coastguard Workervar _ SingletonModuleProviderContext = &Context{} 279*1fa6dee9SAndroid Build Coastguard Workervar _ SingletonModuleProviderContext = SingletonContext(nil) 280*1fa6dee9SAndroid Build Coastguard Worker 281*1fa6dee9SAndroid Build Coastguard Worker// SingletonModuleProvider reads the provider for the given module. If the provider has been set the value is 282*1fa6dee9SAndroid Build Coastguard Worker// returned and the boolean is true. If it has not been set the zero value of the provider's type is returned 283*1fa6dee9SAndroid Build Coastguard Worker// and the boolean is false. The value returned may be a deep copy of the value originally passed to SetProvider. 284*1fa6dee9SAndroid Build Coastguard Worker// 285*1fa6dee9SAndroid Build Coastguard Worker// SingletonModuleProviderContext is a helper interface that accepts Context or SingletonContext. 286*1fa6dee9SAndroid Build Coastguard Workerfunc SingletonModuleProvider[K any](ctx SingletonModuleProviderContext, module Module, provider ProviderKey[K]) (K, bool) { 287*1fa6dee9SAndroid Build Coastguard Worker value, ok := ctx.ModuleProvider(module, provider) 288*1fa6dee9SAndroid Build Coastguard Worker if !ok { 289*1fa6dee9SAndroid Build Coastguard Worker var k K 290*1fa6dee9SAndroid Build Coastguard Worker return k, false 291*1fa6dee9SAndroid Build Coastguard Worker } 292*1fa6dee9SAndroid Build Coastguard Worker return value.(K), ok 293*1fa6dee9SAndroid Build Coastguard Worker} 294*1fa6dee9SAndroid Build Coastguard Worker 295*1fa6dee9SAndroid Build Coastguard Worker// ModuleProviderContext is a helper interface that is a subset of ModuleContext, BottomUpMutatorContext, or 296*1fa6dee9SAndroid Build Coastguard Worker// TopDownMutatorContext for use in ModuleProvider. 297*1fa6dee9SAndroid Build Coastguard Workertype ModuleProviderContext interface { 298*1fa6dee9SAndroid Build Coastguard Worker Provider(provider AnyProviderKey) (any, bool) 299*1fa6dee9SAndroid Build Coastguard Worker} 300*1fa6dee9SAndroid Build Coastguard Worker 301*1fa6dee9SAndroid Build Coastguard Workervar _ ModuleProviderContext = BaseModuleContext(nil) 302*1fa6dee9SAndroid Build Coastguard Workervar _ ModuleProviderContext = ModuleContext(nil) 303*1fa6dee9SAndroid Build Coastguard Workervar _ ModuleProviderContext = BottomUpMutatorContext(nil) 304*1fa6dee9SAndroid Build Coastguard Workervar _ ModuleProviderContext = TopDownMutatorContext(nil) 305*1fa6dee9SAndroid Build Coastguard Worker 306*1fa6dee9SAndroid Build Coastguard Worker// ModuleProvider reads the provider for the current module. If the provider has been set the value is 307*1fa6dee9SAndroid Build Coastguard Worker// returned and the boolean is true. If it has not been set the zero value of the provider's type is returned 308*1fa6dee9SAndroid Build Coastguard Worker// and the boolean is false. The value returned may be a deep copy of the value originally passed to SetProvider. 309*1fa6dee9SAndroid Build Coastguard Worker// 310*1fa6dee9SAndroid Build Coastguard Worker// ModuleProviderContext is a helper interface that accepts ModuleContext, BottomUpMutatorContext, or 311*1fa6dee9SAndroid Build Coastguard Worker// TopDownMutatorContext. 312*1fa6dee9SAndroid Build Coastguard Workerfunc ModuleProvider[K any](ctx ModuleProviderContext, provider ProviderKey[K]) (K, bool) { 313*1fa6dee9SAndroid Build Coastguard Worker value, ok := ctx.Provider(provider) 314*1fa6dee9SAndroid Build Coastguard Worker if !ok { 315*1fa6dee9SAndroid Build Coastguard Worker var k K 316*1fa6dee9SAndroid Build Coastguard Worker return k, false 317*1fa6dee9SAndroid Build Coastguard Worker } 318*1fa6dee9SAndroid Build Coastguard Worker return value.(K), ok 319*1fa6dee9SAndroid Build Coastguard Worker} 320*1fa6dee9SAndroid Build Coastguard Worker 321*1fa6dee9SAndroid Build Coastguard Worker// SetProviderContext is a helper interface that is a subset of ModuleContext, BottomUpMutatorContext, or 322*1fa6dee9SAndroid Build Coastguard Worker// TopDownMutatorContext for use in SetProvider. 323*1fa6dee9SAndroid Build Coastguard Workertype SetProviderContext interface { 324*1fa6dee9SAndroid Build Coastguard Worker SetProvider(provider AnyProviderKey, value any) 325*1fa6dee9SAndroid Build Coastguard Worker} 326*1fa6dee9SAndroid Build Coastguard Worker 327*1fa6dee9SAndroid Build Coastguard Workervar _ SetProviderContext = BaseModuleContext(nil) 328*1fa6dee9SAndroid Build Coastguard Workervar _ SetProviderContext = ModuleContext(nil) 329*1fa6dee9SAndroid Build Coastguard Workervar _ SetProviderContext = BottomUpMutatorContext(nil) 330*1fa6dee9SAndroid Build Coastguard Workervar _ SetProviderContext = TopDownMutatorContext(nil) 331*1fa6dee9SAndroid Build Coastguard Worker 332*1fa6dee9SAndroid Build Coastguard Worker// SetProvider sets the value for a provider for the current module. It panics if not called 333*1fa6dee9SAndroid Build Coastguard Worker// during the appropriate mutator or GenerateBuildActions pass for the provider, if the value 334*1fa6dee9SAndroid Build Coastguard Worker// is not of the appropriate type, or if the value has already been set. The value should not 335*1fa6dee9SAndroid Build Coastguard Worker// be modified after being passed to SetProvider. 336*1fa6dee9SAndroid Build Coastguard Worker// 337*1fa6dee9SAndroid Build Coastguard Worker// SetProviderContext is a helper interface that accepts ModuleContext, BottomUpMutatorContext, or 338*1fa6dee9SAndroid Build Coastguard Worker// TopDownMutatorContext. 339*1fa6dee9SAndroid Build Coastguard Workerfunc SetProvider[K any](ctx SetProviderContext, provider ProviderKey[K], value K) { 340*1fa6dee9SAndroid Build Coastguard Worker ctx.SetProvider(provider, value) 341*1fa6dee9SAndroid Build Coastguard Worker} 342