Extend the current environment with additional options to produce a new Env. Note, the extended Env value should not share memory with the original. It is possible, however, that a CustomTypeAdapter or CustomTypeProvider options could provide values which are mutable. To ensure separation of state
(opts ...EnvOption)
| 532 | // TypeProvider are immutable, or that their underlying implementations are based on the |
| 533 | // ref.TypeRegistry which provides a Copy method which will be invoked by this method. |
| 534 | func (e *Env) Extend(opts ...EnvOption) (*Env, error) { |
| 535 | if _, chkErr := e.getCheckerOrError(); chkErr != nil { |
| 536 | return nil, chkErr |
| 537 | } |
| 538 | |
| 539 | prsrOptsCopy := slices.Clone(e.prsrOpts) |
| 540 | chkOptsCopy := slices.Clone(e.chkOpts) |
| 541 | varsCopy := slices.Clone(e.variables) |
| 542 | macsCopy := slices.Clone(e.macros) |
| 543 | progOptsCopy := slices.Clone(e.progOpts) |
| 544 | validatorsCopy := slices.Clone(e.validators) |
| 545 | costOptsCopy := slices.Clone(e.costOptions) |
| 546 | |
| 547 | // Copy the adapter / provider if they appear to be mutable. |
| 548 | adapter := e.adapter |
| 549 | provider := e.provider |
| 550 | adapterReg, isAdapterReg := e.adapter.(*types.Registry) |
| 551 | providerReg, isProviderReg := e.provider.(*types.Registry) |
| 552 | // In most cases the provider and adapter will be a ref.TypeRegistry; |
| 553 | // however, in the rare cases where they are not, they are assumed to |
| 554 | // be immutable. Since it is possible to set the TypeProvider separately |
| 555 | // from the TypeAdapter, the possible configurations which could use a |
| 556 | // TypeRegistry as the base implementation are captured below. |
| 557 | if isAdapterReg && isProviderReg { |
| 558 | reg := providerReg.Copy() |
| 559 | provider = reg |
| 560 | // If the adapter and provider are the same object, set the adapter |
| 561 | // to the same ref.TypeRegistry as the provider. |
| 562 | if adapterReg == providerReg { |
| 563 | adapter = reg |
| 564 | } else { |
| 565 | // Otherwise, make a copy of the adapter. |
| 566 | adapter = adapterReg.Copy() |
| 567 | } |
| 568 | } else if isProviderReg { |
| 569 | provider = providerReg.Copy() |
| 570 | } else if isAdapterReg { |
| 571 | adapter = adapterReg.Copy() |
| 572 | } |
| 573 | |
| 574 | ext := &Env{ |
| 575 | parent: e, |
| 576 | Container: e.Container, |
| 577 | variables: varsCopy, |
| 578 | functions: e.functions, |
| 579 | macros: macsCopy, |
| 580 | contextProto: e.contextProto, |
| 581 | progOpts: progOptsCopy, |
| 582 | adapter: adapter, |
| 583 | features: e.features, |
| 584 | limits: e.limits, |
| 585 | appliedFeatures: e.appliedFeatures, |
| 586 | libraries: e.libraries, |
| 587 | validators: validatorsCopy, |
| 588 | provider: provider, |
| 589 | chkOpts: chkOptsCopy, |
| 590 | prsrOpts: prsrOptsCopy, |
| 591 | costOptions: costOptsCopy, |