github.com/prebid/prebid-server/v2@v2.18.0/openrtb_ext/request_wrapper.go (about)

     1  package openrtb_ext
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  
     7  	"github.com/prebid/openrtb/v20/openrtb2"
     8  	"github.com/prebid/prebid-server/v2/util/jsonutil"
     9  	"github.com/prebid/prebid-server/v2/util/maputil"
    10  	"github.com/prebid/prebid-server/v2/util/ptrutil"
    11  	"github.com/prebid/prebid-server/v2/util/sliceutil"
    12  )
    13  
    14  // RequestWrapper wraps the OpenRTB request to provide a storage location for unmarshalled ext fields, so they
    15  // will not need to be unmarshalled multiple times.
    16  //
    17  // To start with, the wrapper can be created for a request 'req' via:
    18  // reqWrapper := openrtb_ext.RequestWrapper{BidRequest: req}
    19  //
    20  // In order to access an object's ext field, fetch it via:
    21  // userExt, err := reqWrapper.GetUserExt()
    22  // or other Get method as appropriate.
    23  //
    24  // To read or write values, use the Ext objects Get and Set methods. If you need to write to a field that has its own Set
    25  // method, use that to set the value rather than using SetExt() with that change done in the map; when rewritting the
    26  // ext JSON the code will overwrite the the values in the map with the values stored in the seperate fields.
    27  //
    28  // userPrebid := userExt.GetPrebid()
    29  // userExt.SetConsent(consentString)
    30  //
    31  // The GetExt() and SetExt() should only be used to access fields that have not already been resolved in the object.
    32  // Using SetExt() at all is a strong hint that the ext object should be extended to support the new fields being set
    33  // in the map.
    34  //
    35  // NOTE: The RequestWrapper methods (particularly the ones calling (un)Marshal are not thread safe)
    36  type RequestWrapper struct {
    37  	*openrtb2.BidRequest
    38  	impWrappers         []*ImpWrapper
    39  	impWrappersAccessed bool
    40  	userExt             *UserExt
    41  	deviceExt           *DeviceExt
    42  	requestExt          *RequestExt
    43  	appExt              *AppExt
    44  	regExt              *RegExt
    45  	siteExt             *SiteExt
    46  	doohExt             *DOOHExt
    47  	sourceExt           *SourceExt
    48  }
    49  
    50  const (
    51  	jsonEmptyObjectLength               = 2
    52  	consentedProvidersSettingsStringKey = "ConsentedProvidersSettings"
    53  	consentedProvidersSettingsListKey   = "consented_providers_settings"
    54  	consentKey                          = "consent"
    55  	ampKey                              = "amp"
    56  	dsaKey                              = "dsa"
    57  	eidsKey                             = "eids"
    58  	gdprKey                             = "gdpr"
    59  	prebidKey                           = "prebid"
    60  	dataKey                             = "data"
    61  	schainKey                           = "schain"
    62  	us_privacyKey                       = "us_privacy"
    63  	cdepKey                             = "cdep"
    64  )
    65  
    66  // LenImp returns the number of impressions without causing the creation of ImpWrapper objects.
    67  func (rw *RequestWrapper) LenImp() int {
    68  	if rw.impWrappersAccessed {
    69  		return len(rw.impWrappers)
    70  	}
    71  
    72  	return len(rw.Imp)
    73  }
    74  
    75  func (rw *RequestWrapper) GetImp() []*ImpWrapper {
    76  	if rw.impWrappersAccessed {
    77  		return rw.impWrappers
    78  	}
    79  
    80  	// There is minimal difference between nil and empty arrays in Go, but it matters
    81  	// for json encoding. In practice there will always be at least one impression,
    82  	// so this is an optimization for tests with (appropriately) incomplete requests.
    83  	if rw.Imp != nil {
    84  		rw.impWrappers = make([]*ImpWrapper, len(rw.Imp))
    85  		for i := range rw.Imp {
    86  			rw.impWrappers[i] = &ImpWrapper{Imp: &rw.Imp[i]}
    87  		}
    88  	}
    89  
    90  	rw.impWrappersAccessed = true
    91  
    92  	return rw.impWrappers
    93  }
    94  
    95  func (rw *RequestWrapper) SetImp(imps []*ImpWrapper) {
    96  	rw.impWrappers = imps
    97  	rw.impWrappersAccessed = true
    98  }
    99  
   100  func (rw *RequestWrapper) GetUserExt() (*UserExt, error) {
   101  	if rw.userExt != nil {
   102  		return rw.userExt, nil
   103  	}
   104  	rw.userExt = &UserExt{}
   105  	if rw.BidRequest == nil || rw.User == nil || rw.User.Ext == nil {
   106  		return rw.userExt, rw.userExt.unmarshal(json.RawMessage{})
   107  	}
   108  
   109  	return rw.userExt, rw.userExt.unmarshal(rw.User.Ext)
   110  }
   111  
   112  func (rw *RequestWrapper) GetDeviceExt() (*DeviceExt, error) {
   113  	if rw.deviceExt != nil {
   114  		return rw.deviceExt, nil
   115  	}
   116  	rw.deviceExt = &DeviceExt{}
   117  	if rw.BidRequest == nil || rw.Device == nil || rw.Device.Ext == nil {
   118  		return rw.deviceExt, rw.deviceExt.unmarshal(json.RawMessage{})
   119  	}
   120  	return rw.deviceExt, rw.deviceExt.unmarshal(rw.Device.Ext)
   121  }
   122  
   123  func (rw *RequestWrapper) GetRequestExt() (*RequestExt, error) {
   124  	if rw.requestExt != nil {
   125  		return rw.requestExt, nil
   126  	}
   127  	rw.requestExt = &RequestExt{}
   128  	if rw.BidRequest == nil || rw.Ext == nil {
   129  		return rw.requestExt, rw.requestExt.unmarshal(json.RawMessage{})
   130  	}
   131  	return rw.requestExt, rw.requestExt.unmarshal(rw.Ext)
   132  }
   133  
   134  func (rw *RequestWrapper) GetAppExt() (*AppExt, error) {
   135  	if rw.appExt != nil {
   136  		return rw.appExt, nil
   137  	}
   138  	rw.appExt = &AppExt{}
   139  	if rw.BidRequest == nil || rw.App == nil || rw.App.Ext == nil {
   140  		return rw.appExt, rw.appExt.unmarshal(json.RawMessage{})
   141  	}
   142  	return rw.appExt, rw.appExt.unmarshal(rw.App.Ext)
   143  }
   144  
   145  func (rw *RequestWrapper) GetRegExt() (*RegExt, error) {
   146  	if rw.regExt != nil {
   147  		return rw.regExt, nil
   148  	}
   149  	rw.regExt = &RegExt{}
   150  	if rw.BidRequest == nil || rw.Regs == nil || rw.Regs.Ext == nil {
   151  		return rw.regExt, rw.regExt.unmarshal(json.RawMessage{})
   152  	}
   153  	return rw.regExt, rw.regExt.unmarshal(rw.Regs.Ext)
   154  }
   155  
   156  func (rw *RequestWrapper) GetSiteExt() (*SiteExt, error) {
   157  	if rw.siteExt != nil {
   158  		return rw.siteExt, nil
   159  	}
   160  	rw.siteExt = &SiteExt{}
   161  	if rw.BidRequest == nil || rw.Site == nil || rw.Site.Ext == nil {
   162  		return rw.siteExt, rw.siteExt.unmarshal(json.RawMessage{})
   163  	}
   164  	return rw.siteExt, rw.siteExt.unmarshal(rw.Site.Ext)
   165  }
   166  
   167  func (rw *RequestWrapper) GetDOOHExt() (*DOOHExt, error) {
   168  	if rw.doohExt != nil {
   169  		return rw.doohExt, nil
   170  	}
   171  	rw.doohExt = &DOOHExt{}
   172  	if rw.BidRequest == nil || rw.DOOH == nil || rw.DOOH.Ext == nil {
   173  		return rw.doohExt, rw.doohExt.unmarshal(json.RawMessage{})
   174  	}
   175  	return rw.doohExt, rw.doohExt.unmarshal(rw.DOOH.Ext)
   176  }
   177  
   178  func (rw *RequestWrapper) GetSourceExt() (*SourceExt, error) {
   179  	if rw.sourceExt != nil {
   180  		return rw.sourceExt, nil
   181  	}
   182  	rw.sourceExt = &SourceExt{}
   183  	if rw.BidRequest == nil || rw.Source == nil || rw.Source.Ext == nil {
   184  		return rw.sourceExt, rw.sourceExt.unmarshal(json.RawMessage{})
   185  	}
   186  	return rw.sourceExt, rw.sourceExt.unmarshal(rw.Source.Ext)
   187  }
   188  
   189  func (rw *RequestWrapper) RebuildRequest() error {
   190  	if rw.BidRequest == nil {
   191  		return errors.New("Requestwrapper RebuildRequest called on a nil BidRequest")
   192  	}
   193  
   194  	if err := rw.rebuildImp(); err != nil {
   195  		return err
   196  	}
   197  	if err := rw.rebuildUserExt(); err != nil {
   198  		return err
   199  	}
   200  	if err := rw.rebuildDeviceExt(); err != nil {
   201  		return err
   202  	}
   203  	if err := rw.rebuildRequestExt(); err != nil {
   204  		return err
   205  	}
   206  	if err := rw.rebuildAppExt(); err != nil {
   207  		return err
   208  	}
   209  	if err := rw.rebuildRegExt(); err != nil {
   210  		return err
   211  	}
   212  	if err := rw.rebuildSiteExt(); err != nil {
   213  		return err
   214  	}
   215  	if err := rw.rebuildDOOHExt(); err != nil {
   216  		return err
   217  	}
   218  	if err := rw.rebuildSourceExt(); err != nil {
   219  		return err
   220  	}
   221  
   222  	return nil
   223  }
   224  
   225  func (rw *RequestWrapper) rebuildImp() error {
   226  	if !rw.impWrappersAccessed {
   227  		return nil
   228  	}
   229  
   230  	if rw.impWrappers == nil {
   231  		rw.Imp = nil
   232  		return nil
   233  	}
   234  
   235  	rw.Imp = make([]openrtb2.Imp, len(rw.impWrappers))
   236  	for i := range rw.impWrappers {
   237  		if err := rw.impWrappers[i].RebuildImp(); err != nil {
   238  			return err
   239  		}
   240  		rw.Imp[i] = *rw.impWrappers[i].Imp
   241  	}
   242  
   243  	return nil
   244  }
   245  
   246  func (rw *RequestWrapper) rebuildUserExt() error {
   247  	if rw.userExt == nil || !rw.userExt.Dirty() {
   248  		return nil
   249  	}
   250  
   251  	userJson, err := rw.userExt.marshal()
   252  	if err != nil {
   253  		return err
   254  	}
   255  
   256  	if userJson != nil && rw.User == nil {
   257  		rw.User = &openrtb2.User{Ext: userJson}
   258  	} else if rw.User != nil {
   259  		rw.User.Ext = userJson
   260  	}
   261  
   262  	return nil
   263  }
   264  
   265  func (rw *RequestWrapper) rebuildDeviceExt() error {
   266  	if rw.deviceExt == nil || !rw.deviceExt.Dirty() {
   267  		return nil
   268  	}
   269  
   270  	deviceJson, err := rw.deviceExt.marshal()
   271  	if err != nil {
   272  		return err
   273  	}
   274  
   275  	if deviceJson != nil && rw.Device == nil {
   276  		rw.Device = &openrtb2.Device{Ext: deviceJson}
   277  	} else if rw.Device != nil {
   278  		rw.Device.Ext = deviceJson
   279  	}
   280  
   281  	return nil
   282  }
   283  
   284  func (rw *RequestWrapper) rebuildRequestExt() error {
   285  	if rw.requestExt == nil || !rw.requestExt.Dirty() {
   286  		return nil
   287  	}
   288  
   289  	requestJson, err := rw.requestExt.marshal()
   290  	if err != nil {
   291  		return err
   292  	}
   293  
   294  	rw.Ext = requestJson
   295  
   296  	return nil
   297  }
   298  
   299  func (rw *RequestWrapper) rebuildAppExt() error {
   300  	if rw.appExt == nil || !rw.appExt.Dirty() {
   301  		return nil
   302  	}
   303  
   304  	appJson, err := rw.appExt.marshal()
   305  	if err != nil {
   306  		return err
   307  	}
   308  
   309  	if appJson != nil && rw.App == nil {
   310  		rw.App = &openrtb2.App{Ext: appJson}
   311  	} else if rw.App != nil {
   312  		rw.App.Ext = appJson
   313  	}
   314  
   315  	return nil
   316  }
   317  
   318  func (rw *RequestWrapper) rebuildDOOHExt() error {
   319  	if rw.doohExt == nil || !rw.doohExt.Dirty() {
   320  		return nil
   321  	}
   322  
   323  	doohJson, err := rw.doohExt.marshal()
   324  	if err != nil {
   325  		return err
   326  	}
   327  
   328  	if doohJson != nil && rw.DOOH == nil {
   329  		rw.DOOH = &openrtb2.DOOH{Ext: doohJson}
   330  	} else if rw.DOOH != nil {
   331  		rw.DOOH.Ext = doohJson
   332  	}
   333  
   334  	return nil
   335  }
   336  
   337  func (rw *RequestWrapper) rebuildRegExt() error {
   338  	if rw.regExt == nil || !rw.regExt.Dirty() {
   339  		return nil
   340  	}
   341  
   342  	regsJson, err := rw.regExt.marshal()
   343  	if err != nil {
   344  		return err
   345  	}
   346  
   347  	if regsJson != nil && rw.Regs == nil {
   348  		rw.Regs = &openrtb2.Regs{Ext: regsJson}
   349  	} else if rw.Regs != nil {
   350  		rw.Regs.Ext = regsJson
   351  	}
   352  
   353  	return nil
   354  }
   355  
   356  func (rw *RequestWrapper) rebuildSiteExt() error {
   357  	if rw.siteExt == nil || !rw.siteExt.Dirty() {
   358  		return nil
   359  	}
   360  
   361  	siteJson, err := rw.siteExt.marshal()
   362  	if err != nil {
   363  		return err
   364  	}
   365  
   366  	if siteJson != nil && rw.Site == nil {
   367  		rw.Site = &openrtb2.Site{Ext: siteJson}
   368  	} else if rw.Site != nil {
   369  		rw.Site.Ext = siteJson
   370  	}
   371  
   372  	return nil
   373  }
   374  
   375  func (rw *RequestWrapper) rebuildSourceExt() error {
   376  	if rw.sourceExt == nil || !rw.sourceExt.Dirty() {
   377  		return nil
   378  	}
   379  
   380  	sourceJson, err := rw.sourceExt.marshal()
   381  	if err != nil {
   382  		return err
   383  	}
   384  
   385  	if sourceJson != nil && rw.Source == nil {
   386  		rw.Source = &openrtb2.Source{Ext: sourceJson}
   387  	} else if rw.Source != nil {
   388  		rw.Source.Ext = sourceJson
   389  	}
   390  
   391  	return nil
   392  }
   393  
   394  func (rw *RequestWrapper) Clone() *RequestWrapper {
   395  	if rw == nil {
   396  		return nil
   397  	}
   398  	clone := *rw
   399  	newImpWrappers := make([]*ImpWrapper, len(rw.impWrappers))
   400  	for i, iw := range rw.impWrappers {
   401  		newImpWrappers[i] = iw.Clone()
   402  	}
   403  	clone.impWrappers = newImpWrappers
   404  	clone.userExt = rw.userExt.Clone()
   405  	clone.deviceExt = rw.deviceExt.Clone()
   406  	clone.requestExt = rw.requestExt.Clone()
   407  	clone.appExt = rw.appExt.Clone()
   408  	clone.regExt = rw.regExt.Clone()
   409  	clone.siteExt = rw.siteExt.Clone()
   410  	clone.doohExt = rw.doohExt.Clone()
   411  	clone.sourceExt = rw.sourceExt.Clone()
   412  
   413  	return &clone
   414  }
   415  
   416  // ---------------------------------------------------------------
   417  // UserExt provides an interface for request.user.ext
   418  // ---------------------------------------------------------------
   419  
   420  type UserExt struct {
   421  	ext                                map[string]json.RawMessage
   422  	extDirty                           bool
   423  	consent                            *string
   424  	consentDirty                       bool
   425  	prebid                             *ExtUserPrebid
   426  	prebidDirty                        bool
   427  	eids                               *[]openrtb2.EID
   428  	eidsDirty                          bool
   429  	consentedProvidersSettingsIn       *ConsentedProvidersSettingsIn
   430  	consentedProvidersSettingsInDirty  bool
   431  	consentedProvidersSettingsOut      *ConsentedProvidersSettingsOut
   432  	consentedProvidersSettingsOutDirty bool
   433  }
   434  
   435  func (ue *UserExt) unmarshal(extJson json.RawMessage) error {
   436  	if len(ue.ext) != 0 || ue.Dirty() {
   437  		return nil
   438  	}
   439  
   440  	ue.ext = make(map[string]json.RawMessage)
   441  
   442  	if len(extJson) == 0 {
   443  		return nil
   444  	}
   445  
   446  	if err := jsonutil.Unmarshal(extJson, &ue.ext); err != nil {
   447  		return err
   448  	}
   449  
   450  	consentJson, hasConsent := ue.ext[consentKey]
   451  	if hasConsent && consentJson != nil {
   452  		if err := jsonutil.Unmarshal(consentJson, &ue.consent); err != nil {
   453  			return err
   454  		}
   455  	}
   456  
   457  	prebidJson, hasPrebid := ue.ext[prebidKey]
   458  	if hasPrebid {
   459  		ue.prebid = &ExtUserPrebid{}
   460  	}
   461  	if prebidJson != nil {
   462  		if err := jsonutil.Unmarshal(prebidJson, ue.prebid); err != nil {
   463  			return err
   464  		}
   465  	}
   466  
   467  	eidsJson, hasEids := ue.ext[eidsKey]
   468  	if hasEids {
   469  		ue.eids = &[]openrtb2.EID{}
   470  	}
   471  	if eidsJson != nil {
   472  		if err := jsonutil.Unmarshal(eidsJson, ue.eids); err != nil {
   473  			return err
   474  		}
   475  	}
   476  
   477  	consentedProviderSettingsInJson, hasCPSettingsIn := ue.ext[consentedProvidersSettingsStringKey]
   478  	if hasCPSettingsIn {
   479  		ue.consentedProvidersSettingsIn = &ConsentedProvidersSettingsIn{}
   480  	}
   481  	if consentedProviderSettingsInJson != nil {
   482  		if err := jsonutil.Unmarshal(consentedProviderSettingsInJson, ue.consentedProvidersSettingsIn); err != nil {
   483  			return err
   484  		}
   485  	}
   486  
   487  	consentedProviderSettingsOutJson, hasCPSettingsOut := ue.ext[consentedProvidersSettingsListKey]
   488  	if hasCPSettingsOut {
   489  		ue.consentedProvidersSettingsOut = &ConsentedProvidersSettingsOut{}
   490  	}
   491  	if consentedProviderSettingsOutJson != nil {
   492  		if err := jsonutil.Unmarshal(consentedProviderSettingsOutJson, ue.consentedProvidersSettingsOut); err != nil {
   493  			return err
   494  		}
   495  	}
   496  
   497  	return nil
   498  }
   499  
   500  func (ue *UserExt) marshal() (json.RawMessage, error) {
   501  	if ue.consentDirty {
   502  		if ue.consent != nil && len(*ue.consent) > 0 {
   503  			consentJson, err := jsonutil.Marshal(ue.consent)
   504  			if err != nil {
   505  				return nil, err
   506  			}
   507  			ue.ext[consentKey] = json.RawMessage(consentJson)
   508  		} else {
   509  			delete(ue.ext, consentKey)
   510  		}
   511  		ue.consentDirty = false
   512  	}
   513  
   514  	if ue.prebidDirty {
   515  		if ue.prebid != nil {
   516  			prebidJson, err := jsonutil.Marshal(ue.prebid)
   517  			if err != nil {
   518  				return nil, err
   519  			}
   520  			if len(prebidJson) > jsonEmptyObjectLength {
   521  				ue.ext[prebidKey] = json.RawMessage(prebidJson)
   522  			} else {
   523  				delete(ue.ext, prebidKey)
   524  			}
   525  		} else {
   526  			delete(ue.ext, prebidKey)
   527  		}
   528  		ue.prebidDirty = false
   529  	}
   530  
   531  	if ue.consentedProvidersSettingsInDirty {
   532  		if ue.consentedProvidersSettingsIn != nil {
   533  			cpSettingsJson, err := jsonutil.Marshal(ue.consentedProvidersSettingsIn)
   534  			if err != nil {
   535  				return nil, err
   536  			}
   537  			if len(cpSettingsJson) > jsonEmptyObjectLength {
   538  				ue.ext[consentedProvidersSettingsStringKey] = json.RawMessage(cpSettingsJson)
   539  			} else {
   540  				delete(ue.ext, consentedProvidersSettingsStringKey)
   541  			}
   542  		} else {
   543  			delete(ue.ext, consentedProvidersSettingsStringKey)
   544  		}
   545  		ue.consentedProvidersSettingsInDirty = false
   546  	}
   547  
   548  	if ue.consentedProvidersSettingsOutDirty {
   549  		if ue.consentedProvidersSettingsOut != nil {
   550  			cpSettingsJson, err := jsonutil.Marshal(ue.consentedProvidersSettingsOut)
   551  			if err != nil {
   552  				return nil, err
   553  			}
   554  			if len(cpSettingsJson) > jsonEmptyObjectLength {
   555  				ue.ext[consentedProvidersSettingsListKey] = json.RawMessage(cpSettingsJson)
   556  			} else {
   557  				delete(ue.ext, consentedProvidersSettingsListKey)
   558  			}
   559  		} else {
   560  			delete(ue.ext, consentedProvidersSettingsListKey)
   561  		}
   562  		ue.consentedProvidersSettingsOutDirty = false
   563  	}
   564  
   565  	if ue.eidsDirty {
   566  		if ue.eids != nil && len(*ue.eids) > 0 {
   567  			eidsJson, err := jsonutil.Marshal(ue.eids)
   568  			if err != nil {
   569  				return nil, err
   570  			}
   571  			ue.ext[eidsKey] = json.RawMessage(eidsJson)
   572  		} else {
   573  			delete(ue.ext, eidsKey)
   574  		}
   575  		ue.eidsDirty = false
   576  	}
   577  
   578  	ue.extDirty = false
   579  	if len(ue.ext) == 0 {
   580  		return nil, nil
   581  	}
   582  	return jsonutil.Marshal(ue.ext)
   583  }
   584  
   585  func (ue *UserExt) Dirty() bool {
   586  	return ue.extDirty || ue.eidsDirty || ue.prebidDirty || ue.consentDirty || ue.consentedProvidersSettingsInDirty || ue.consentedProvidersSettingsOutDirty
   587  }
   588  
   589  func (ue *UserExt) GetExt() map[string]json.RawMessage {
   590  	ext := make(map[string]json.RawMessage)
   591  	for k, v := range ue.ext {
   592  		ext[k] = v
   593  	}
   594  	return ext
   595  }
   596  
   597  func (ue *UserExt) SetExt(ext map[string]json.RawMessage) {
   598  	ue.ext = ext
   599  	ue.extDirty = true
   600  }
   601  
   602  func (ue *UserExt) GetConsent() *string {
   603  	if ue.consent == nil {
   604  		return nil
   605  	}
   606  	consent := *ue.consent
   607  	return &consent
   608  }
   609  
   610  func (ue *UserExt) SetConsent(consent *string) {
   611  	ue.consent = consent
   612  	ue.consentDirty = true
   613  }
   614  
   615  // GetConsentedProvidersSettingsIn() returns a reference to a copy of ConsentedProvidersSettingsIn, a struct that
   616  // has a string field formatted as a Google's Additional Consent string
   617  func (ue *UserExt) GetConsentedProvidersSettingsIn() *ConsentedProvidersSettingsIn {
   618  	if ue.consentedProvidersSettingsIn == nil {
   619  		return nil
   620  	}
   621  	consentedProvidersSettingsIn := *ue.consentedProvidersSettingsIn
   622  	return &consentedProvidersSettingsIn
   623  }
   624  
   625  // SetConsentedProvidersSettingsIn() sets ConsentedProvidersSettingsIn, a struct that
   626  // has a string field formatted as a Google's Additional Consent string
   627  func (ue *UserExt) SetConsentedProvidersSettingsIn(cpSettings *ConsentedProvidersSettingsIn) {
   628  	ue.consentedProvidersSettingsIn = cpSettings
   629  	ue.consentedProvidersSettingsInDirty = true
   630  }
   631  
   632  // GetConsentedProvidersSettingsOut() returns a reference to a copy of ConsentedProvidersSettingsOut, a struct that
   633  // has an int array field listing Google's Additional Consent string elements
   634  func (ue *UserExt) GetConsentedProvidersSettingsOut() *ConsentedProvidersSettingsOut {
   635  	if ue.consentedProvidersSettingsOut == nil {
   636  		return nil
   637  	}
   638  	consentedProvidersSettingsOut := *ue.consentedProvidersSettingsOut
   639  	return &consentedProvidersSettingsOut
   640  }
   641  
   642  // SetConsentedProvidersSettingsIn() sets ConsentedProvidersSettingsOut, a struct that
   643  // has an int array field listing Google's Additional Consent string elements. This
   644  // function overrides an existing ConsentedProvidersSettingsOut object, if any
   645  func (ue *UserExt) SetConsentedProvidersSettingsOut(cpSettings *ConsentedProvidersSettingsOut) {
   646  	if cpSettings == nil {
   647  		return
   648  	}
   649  
   650  	ue.consentedProvidersSettingsOut = cpSettings
   651  	ue.consentedProvidersSettingsOutDirty = true
   652  }
   653  
   654  func (ue *UserExt) GetPrebid() *ExtUserPrebid {
   655  	if ue.prebid == nil {
   656  		return nil
   657  	}
   658  	prebid := *ue.prebid
   659  	return &prebid
   660  }
   661  
   662  func (ue *UserExt) SetPrebid(prebid *ExtUserPrebid) {
   663  	ue.prebid = prebid
   664  	ue.prebidDirty = true
   665  }
   666  
   667  func (ue *UserExt) GetEid() *[]openrtb2.EID {
   668  	if ue.eids == nil {
   669  		return nil
   670  	}
   671  	eids := *ue.eids
   672  	return &eids
   673  }
   674  
   675  func (ue *UserExt) SetEid(eid *[]openrtb2.EID) {
   676  	ue.eids = eid
   677  	ue.eidsDirty = true
   678  }
   679  
   680  func (ue *UserExt) Clone() *UserExt {
   681  	if ue == nil {
   682  		return nil
   683  	}
   684  	clone := *ue
   685  	clone.ext = maputil.Clone(ue.ext)
   686  
   687  	if ue.consent != nil {
   688  		clonedConsent := *ue.consent
   689  		clone.consent = &clonedConsent
   690  	}
   691  
   692  	if ue.prebid != nil {
   693  		clone.prebid = &ExtUserPrebid{}
   694  		clone.prebid.BuyerUIDs = maputil.Clone(ue.prebid.BuyerUIDs)
   695  	}
   696  
   697  	if ue.eids != nil {
   698  		clonedEids := make([]openrtb2.EID, len(*ue.eids))
   699  		for i, eid := range *ue.eids {
   700  			newEid := eid
   701  			newEid.UIDs = sliceutil.Clone(eid.UIDs)
   702  			clonedEids[i] = newEid
   703  		}
   704  		clone.eids = &clonedEids
   705  	}
   706  
   707  	if ue.consentedProvidersSettingsIn != nil {
   708  		clone.consentedProvidersSettingsIn = &ConsentedProvidersSettingsIn{ConsentedProvidersString: ue.consentedProvidersSettingsIn.ConsentedProvidersString}
   709  	}
   710  	if ue.consentedProvidersSettingsOut != nil {
   711  		clone.consentedProvidersSettingsOut = &ConsentedProvidersSettingsOut{ConsentedProvidersList: sliceutil.Clone(ue.consentedProvidersSettingsOut.ConsentedProvidersList)}
   712  	}
   713  
   714  	return &clone
   715  }
   716  
   717  // ---------------------------------------------------------------
   718  // RequestExt provides an interface for request.ext
   719  // ---------------------------------------------------------------
   720  
   721  type RequestExt struct {
   722  	ext         map[string]json.RawMessage
   723  	extDirty    bool
   724  	prebid      *ExtRequestPrebid
   725  	prebidDirty bool
   726  	schain      *openrtb2.SupplyChain // ORTB 2.4 location
   727  	schainDirty bool
   728  }
   729  
   730  func (re *RequestExt) unmarshal(extJson json.RawMessage) error {
   731  	if len(re.ext) != 0 || re.Dirty() {
   732  		return nil
   733  	}
   734  
   735  	re.ext = make(map[string]json.RawMessage)
   736  
   737  	if len(extJson) == 0 {
   738  		return nil
   739  	}
   740  
   741  	if err := jsonutil.Unmarshal(extJson, &re.ext); err != nil {
   742  		return err
   743  	}
   744  
   745  	prebidJson, hasPrebid := re.ext[prebidKey]
   746  	if hasPrebid {
   747  		re.prebid = &ExtRequestPrebid{}
   748  	}
   749  	if prebidJson != nil {
   750  		if err := jsonutil.Unmarshal(prebidJson, re.prebid); err != nil {
   751  			return err
   752  		}
   753  	}
   754  
   755  	schainJson, hasSChain := re.ext[schainKey]
   756  	if hasSChain {
   757  		re.schain = &openrtb2.SupplyChain{}
   758  	}
   759  	if schainJson != nil {
   760  		if err := jsonutil.Unmarshal(schainJson, re.schain); err != nil {
   761  			return err
   762  		}
   763  	}
   764  
   765  	return nil
   766  }
   767  
   768  func (re *RequestExt) marshal() (json.RawMessage, error) {
   769  	if re.prebidDirty {
   770  		if re.prebid != nil {
   771  			prebidJson, err := jsonutil.Marshal(re.prebid)
   772  			if err != nil {
   773  				return nil, err
   774  			}
   775  			if len(prebidJson) > jsonEmptyObjectLength {
   776  				re.ext[prebidKey] = json.RawMessage(prebidJson)
   777  			} else {
   778  				delete(re.ext, prebidKey)
   779  			}
   780  		} else {
   781  			delete(re.ext, prebidKey)
   782  		}
   783  		re.prebidDirty = false
   784  	}
   785  
   786  	if re.schainDirty {
   787  		if re.schain != nil {
   788  			schainJson, err := jsonutil.Marshal(re.schain)
   789  			if err != nil {
   790  				return nil, err
   791  			}
   792  			if len(schainJson) > jsonEmptyObjectLength {
   793  				re.ext[schainKey] = json.RawMessage(schainJson)
   794  			} else {
   795  				delete(re.ext, schainKey)
   796  			}
   797  		} else {
   798  			delete(re.ext, schainKey)
   799  		}
   800  		re.schainDirty = false
   801  	}
   802  
   803  	re.extDirty = false
   804  	if len(re.ext) == 0 {
   805  		return nil, nil
   806  	}
   807  	return jsonutil.Marshal(re.ext)
   808  }
   809  
   810  func (re *RequestExt) Dirty() bool {
   811  	return re.extDirty || re.prebidDirty || re.schainDirty
   812  }
   813  
   814  func (re *RequestExt) GetExt() map[string]json.RawMessage {
   815  	ext := make(map[string]json.RawMessage)
   816  	for k, v := range re.ext {
   817  		ext[k] = v
   818  	}
   819  	return ext
   820  }
   821  
   822  func (re *RequestExt) SetExt(ext map[string]json.RawMessage) {
   823  	re.ext = ext
   824  	re.extDirty = true
   825  }
   826  
   827  func (re *RequestExt) GetPrebid() *ExtRequestPrebid {
   828  	if re == nil || re.prebid == nil {
   829  		return nil
   830  	}
   831  	prebid := *re.prebid
   832  	return &prebid
   833  }
   834  
   835  func (re *RequestExt) SetPrebid(prebid *ExtRequestPrebid) {
   836  	re.prebid = prebid
   837  	re.prebidDirty = true
   838  }
   839  
   840  // These schain methods on the request.ext are only for ORTB 2.4 backwards compatibility and
   841  // should not be used for any other purposes. To access ORTB 2.5 schains, see source.ext.schain
   842  // or request.ext.prebid.schains.
   843  func (re *RequestExt) GetSChain() *openrtb2.SupplyChain {
   844  	if re.schain == nil {
   845  		return nil
   846  	}
   847  	schain := *re.schain
   848  	return &schain
   849  }
   850  
   851  func (re *RequestExt) SetSChain(schain *openrtb2.SupplyChain) {
   852  	re.schain = schain
   853  	re.schainDirty = true
   854  }
   855  
   856  func (re *RequestExt) Clone() *RequestExt {
   857  	if re == nil {
   858  		return nil
   859  	}
   860  
   861  	clone := *re
   862  	clone.ext = maputil.Clone(re.ext)
   863  
   864  	if re.prebid != nil {
   865  		clone.prebid = re.prebid.Clone()
   866  	}
   867  
   868  	clone.schain = cloneSupplyChain(re.schain)
   869  
   870  	return &clone
   871  }
   872  
   873  // ---------------------------------------------------------------
   874  // DeviceExt provides an interface for request.device.ext
   875  // ---------------------------------------------------------------
   876  // NOTE: openrtb_ext/device.go:ParseDeviceExtATTS() uses ext.atts, as read only, via jsonparser, only for IOS.
   877  // Doesn't seem like we will see any performance savings by parsing atts at this point, and as it is read only,
   878  // we don't need to worry about write conflicts. Note here in case additional uses of atts evolve as things progress.
   879  // ---------------------------------------------------------------
   880  
   881  type DeviceExt struct {
   882  	ext         map[string]json.RawMessage
   883  	extDirty    bool
   884  	prebid      *ExtDevicePrebid
   885  	prebidDirty bool
   886  	cdep        string
   887  	cdepDirty   bool
   888  }
   889  
   890  func (de *DeviceExt) unmarshal(extJson json.RawMessage) error {
   891  	if len(de.ext) != 0 || de.Dirty() {
   892  		return nil
   893  	}
   894  
   895  	de.ext = make(map[string]json.RawMessage)
   896  
   897  	if len(extJson) == 0 {
   898  		return nil
   899  	}
   900  
   901  	if err := jsonutil.Unmarshal(extJson, &de.ext); err != nil {
   902  		return err
   903  	}
   904  
   905  	prebidJson, hasPrebid := de.ext[prebidKey]
   906  	if hasPrebid {
   907  		de.prebid = &ExtDevicePrebid{}
   908  	}
   909  	if prebidJson != nil {
   910  		if err := jsonutil.Unmarshal(prebidJson, de.prebid); err != nil {
   911  			return err
   912  		}
   913  	}
   914  
   915  	cdepJson, hasCDep := de.ext[cdepKey]
   916  	if hasCDep && cdepJson != nil {
   917  		if err := jsonutil.Unmarshal(cdepJson, &de.cdep); err != nil {
   918  			return err
   919  		}
   920  	}
   921  
   922  	return nil
   923  }
   924  
   925  func (de *DeviceExt) marshal() (json.RawMessage, error) {
   926  	if de.prebidDirty {
   927  		if de.prebid != nil {
   928  			prebidJson, err := jsonutil.Marshal(de.prebid)
   929  			if err != nil {
   930  				return nil, err
   931  			}
   932  			if len(prebidJson) > jsonEmptyObjectLength {
   933  				de.ext[prebidKey] = json.RawMessage(prebidJson)
   934  			} else {
   935  				delete(de.ext, prebidKey)
   936  			}
   937  		} else {
   938  			delete(de.ext, prebidKey)
   939  		}
   940  		de.prebidDirty = false
   941  	}
   942  
   943  	if de.cdepDirty {
   944  		if len(de.cdep) > 0 {
   945  			rawjson, err := jsonutil.Marshal(de.cdep)
   946  			if err != nil {
   947  				return nil, err
   948  			}
   949  			de.ext[cdepKey] = rawjson
   950  		} else {
   951  			delete(de.ext, cdepKey)
   952  		}
   953  		de.cdepDirty = false
   954  	}
   955  
   956  	de.extDirty = false
   957  	if len(de.ext) == 0 {
   958  		return nil, nil
   959  	}
   960  	return jsonutil.Marshal(de.ext)
   961  }
   962  
   963  func (de *DeviceExt) Dirty() bool {
   964  	return de.extDirty || de.prebidDirty || de.cdepDirty
   965  }
   966  
   967  func (de *DeviceExt) GetExt() map[string]json.RawMessage {
   968  	ext := make(map[string]json.RawMessage)
   969  	for k, v := range de.ext {
   970  		ext[k] = v
   971  	}
   972  	return ext
   973  }
   974  
   975  func (de *DeviceExt) SetExt(ext map[string]json.RawMessage) {
   976  	de.ext = ext
   977  	de.extDirty = true
   978  }
   979  
   980  func (de *DeviceExt) GetPrebid() *ExtDevicePrebid {
   981  	if de.prebid == nil {
   982  		return nil
   983  	}
   984  	prebid := *de.prebid
   985  	return &prebid
   986  }
   987  
   988  func (de *DeviceExt) SetPrebid(prebid *ExtDevicePrebid) {
   989  	de.prebid = prebid
   990  	de.prebidDirty = true
   991  }
   992  
   993  func (de *DeviceExt) GetCDep() string {
   994  	return de.cdep
   995  }
   996  
   997  func (de *DeviceExt) SetCDep(cdep string) {
   998  	de.cdep = cdep
   999  	de.cdepDirty = true
  1000  }
  1001  
  1002  func (de *DeviceExt) Clone() *DeviceExt {
  1003  	if de == nil {
  1004  		return nil
  1005  	}
  1006  
  1007  	clone := *de
  1008  	clone.ext = maputil.Clone(de.ext)
  1009  
  1010  	if de.prebid != nil {
  1011  		clonedPrebid := *de.prebid
  1012  		if clonedPrebid.Interstitial != nil {
  1013  			clonedInterstitial := *de.prebid.Interstitial
  1014  			clonedPrebid.Interstitial = &clonedInterstitial
  1015  		}
  1016  		clone.prebid = &clonedPrebid
  1017  	}
  1018  
  1019  	return &clone
  1020  }
  1021  
  1022  // ---------------------------------------------------------------
  1023  // AppExt provides an interface for request.app.ext
  1024  // ---------------------------------------------------------------
  1025  
  1026  type AppExt struct {
  1027  	ext         map[string]json.RawMessage
  1028  	extDirty    bool
  1029  	prebid      *ExtAppPrebid
  1030  	prebidDirty bool
  1031  }
  1032  
  1033  func (ae *AppExt) unmarshal(extJson json.RawMessage) error {
  1034  	if len(ae.ext) != 0 || ae.Dirty() {
  1035  		return nil
  1036  	}
  1037  
  1038  	ae.ext = make(map[string]json.RawMessage)
  1039  
  1040  	if len(extJson) == 0 {
  1041  		return nil
  1042  	}
  1043  
  1044  	if err := jsonutil.Unmarshal(extJson, &ae.ext); err != nil {
  1045  		return err
  1046  	}
  1047  
  1048  	prebidJson, hasPrebid := ae.ext[prebidKey]
  1049  	if hasPrebid {
  1050  		ae.prebid = &ExtAppPrebid{}
  1051  	}
  1052  	if prebidJson != nil {
  1053  		if err := jsonutil.Unmarshal(prebidJson, ae.prebid); err != nil {
  1054  			return err
  1055  		}
  1056  	}
  1057  
  1058  	return nil
  1059  }
  1060  
  1061  func (ae *AppExt) marshal() (json.RawMessage, error) {
  1062  	if ae.prebidDirty {
  1063  		if ae.prebid != nil {
  1064  			prebidJson, err := jsonutil.Marshal(ae.prebid)
  1065  			if err != nil {
  1066  				return nil, err
  1067  			}
  1068  			if len(prebidJson) > jsonEmptyObjectLength {
  1069  				ae.ext[prebidKey] = json.RawMessage(prebidJson)
  1070  			} else {
  1071  				delete(ae.ext, prebidKey)
  1072  			}
  1073  		} else {
  1074  			delete(ae.ext, prebidKey)
  1075  		}
  1076  		ae.prebidDirty = false
  1077  	}
  1078  
  1079  	ae.extDirty = false
  1080  	if len(ae.ext) == 0 {
  1081  		return nil, nil
  1082  	}
  1083  	return jsonutil.Marshal(ae.ext)
  1084  }
  1085  
  1086  func (ae *AppExt) Dirty() bool {
  1087  	return ae.extDirty || ae.prebidDirty
  1088  }
  1089  
  1090  func (ae *AppExt) GetExt() map[string]json.RawMessage {
  1091  	ext := make(map[string]json.RawMessage)
  1092  	for k, v := range ae.ext {
  1093  		ext[k] = v
  1094  	}
  1095  	return ext
  1096  }
  1097  
  1098  func (ae *AppExt) SetExt(ext map[string]json.RawMessage) {
  1099  	ae.ext = ext
  1100  	ae.extDirty = true
  1101  }
  1102  
  1103  func (ae *AppExt) GetPrebid() *ExtAppPrebid {
  1104  	if ae.prebid == nil {
  1105  		return nil
  1106  	}
  1107  	prebid := *ae.prebid
  1108  	return &prebid
  1109  }
  1110  
  1111  func (ae *AppExt) SetPrebid(prebid *ExtAppPrebid) {
  1112  	ae.prebid = prebid
  1113  	ae.prebidDirty = true
  1114  }
  1115  
  1116  func (ae *AppExt) Clone() *AppExt {
  1117  	if ae == nil {
  1118  		return nil
  1119  	}
  1120  
  1121  	clone := *ae
  1122  	clone.ext = maputil.Clone(ae.ext)
  1123  
  1124  	clone.prebid = ptrutil.Clone(ae.prebid)
  1125  
  1126  	return &clone
  1127  }
  1128  
  1129  // ---------------------------------------------------------------
  1130  // DOOHExt provides an interface for request.dooh.ext
  1131  // This is currently a placeholder for consistency with others - no useful attributes and getters/setters exist yet
  1132  // ---------------------------------------------------------------
  1133  
  1134  type DOOHExt struct {
  1135  	ext      map[string]json.RawMessage
  1136  	extDirty bool
  1137  }
  1138  
  1139  func (de *DOOHExt) unmarshal(extJson json.RawMessage) error {
  1140  	if len(de.ext) != 0 || de.Dirty() {
  1141  		return nil
  1142  	}
  1143  
  1144  	de.ext = make(map[string]json.RawMessage)
  1145  
  1146  	if len(extJson) == 0 {
  1147  		return nil
  1148  	}
  1149  
  1150  	if err := jsonutil.Unmarshal(extJson, &de.ext); err != nil {
  1151  		return err
  1152  	}
  1153  
  1154  	return nil
  1155  }
  1156  
  1157  func (de *DOOHExt) marshal() (json.RawMessage, error) {
  1158  	de.extDirty = false
  1159  	if len(de.ext) == 0 {
  1160  		return nil, nil
  1161  	}
  1162  	return jsonutil.Marshal(de.ext)
  1163  }
  1164  
  1165  func (de *DOOHExt) Dirty() bool {
  1166  	return de.extDirty
  1167  }
  1168  
  1169  func (de *DOOHExt) GetExt() map[string]json.RawMessage {
  1170  	ext := make(map[string]json.RawMessage)
  1171  	for k, v := range de.ext {
  1172  		ext[k] = v
  1173  	}
  1174  	return ext
  1175  }
  1176  
  1177  func (de *DOOHExt) SetExt(ext map[string]json.RawMessage) {
  1178  	de.ext = ext
  1179  	de.extDirty = true
  1180  }
  1181  
  1182  func (de *DOOHExt) Clone() *DOOHExt {
  1183  	if de == nil {
  1184  		return nil
  1185  	}
  1186  
  1187  	clone := *de
  1188  	clone.ext = maputil.Clone(de.ext)
  1189  
  1190  	return &clone
  1191  }
  1192  
  1193  // ---------------------------------------------------------------
  1194  // RegExt provides an interface for request.regs.ext
  1195  // ---------------------------------------------------------------
  1196  
  1197  type RegExt struct {
  1198  	ext            map[string]json.RawMessage
  1199  	extDirty       bool
  1200  	dsa            *ExtRegsDSA
  1201  	dsaDirty       bool
  1202  	gdpr           *int8
  1203  	gdprDirty      bool
  1204  	usPrivacy      string
  1205  	usPrivacyDirty bool
  1206  }
  1207  
  1208  func (re *RegExt) unmarshal(extJson json.RawMessage) error {
  1209  	if len(re.ext) != 0 || re.Dirty() {
  1210  		return nil
  1211  	}
  1212  
  1213  	re.ext = make(map[string]json.RawMessage)
  1214  
  1215  	if len(extJson) == 0 {
  1216  		return nil
  1217  	}
  1218  
  1219  	if err := jsonutil.Unmarshal(extJson, &re.ext); err != nil {
  1220  		return err
  1221  	}
  1222  
  1223  	dsaJson, hasDSA := re.ext[dsaKey]
  1224  	if hasDSA {
  1225  		re.dsa = &ExtRegsDSA{}
  1226  	}
  1227  	if dsaJson != nil {
  1228  		if err := jsonutil.Unmarshal(dsaJson, re.dsa); err != nil {
  1229  			return err
  1230  		}
  1231  	}
  1232  
  1233  	gdprJson, hasGDPR := re.ext[gdprKey]
  1234  	if hasGDPR && gdprJson != nil {
  1235  		if err := jsonutil.Unmarshal(gdprJson, &re.gdpr); err != nil {
  1236  			return errors.New("gdpr must be an integer")
  1237  		}
  1238  	}
  1239  
  1240  	uspJson, hasUsp := re.ext[us_privacyKey]
  1241  	if hasUsp && uspJson != nil {
  1242  		if err := jsonutil.Unmarshal(uspJson, &re.usPrivacy); err != nil {
  1243  			return err
  1244  		}
  1245  	}
  1246  
  1247  	return nil
  1248  }
  1249  
  1250  func (re *RegExt) marshal() (json.RawMessage, error) {
  1251  	if re.dsaDirty {
  1252  		if re.dsa != nil {
  1253  			rawjson, err := jsonutil.Marshal(re.dsa)
  1254  			if err != nil {
  1255  				return nil, err
  1256  			}
  1257  			re.ext[dsaKey] = rawjson
  1258  		} else {
  1259  			delete(re.ext, dsaKey)
  1260  		}
  1261  		re.dsaDirty = false
  1262  	}
  1263  
  1264  	if re.gdprDirty {
  1265  		if re.gdpr != nil {
  1266  			rawjson, err := jsonutil.Marshal(re.gdpr)
  1267  			if err != nil {
  1268  				return nil, err
  1269  			}
  1270  			re.ext[gdprKey] = rawjson
  1271  		} else {
  1272  			delete(re.ext, gdprKey)
  1273  		}
  1274  		re.gdprDirty = false
  1275  	}
  1276  
  1277  	if re.usPrivacyDirty {
  1278  		if len(re.usPrivacy) > 0 {
  1279  			rawjson, err := jsonutil.Marshal(re.usPrivacy)
  1280  			if err != nil {
  1281  				return nil, err
  1282  			}
  1283  			re.ext[us_privacyKey] = rawjson
  1284  		} else {
  1285  			delete(re.ext, us_privacyKey)
  1286  		}
  1287  		re.usPrivacyDirty = false
  1288  	}
  1289  
  1290  	re.extDirty = false
  1291  	if len(re.ext) == 0 {
  1292  		return nil, nil
  1293  	}
  1294  	return jsonutil.Marshal(re.ext)
  1295  }
  1296  
  1297  func (re *RegExt) Dirty() bool {
  1298  	return re.extDirty || re.dsaDirty || re.gdprDirty || re.usPrivacyDirty
  1299  }
  1300  
  1301  func (re *RegExt) GetExt() map[string]json.RawMessage {
  1302  	ext := make(map[string]json.RawMessage)
  1303  	for k, v := range re.ext {
  1304  		ext[k] = v
  1305  	}
  1306  	return ext
  1307  }
  1308  
  1309  func (re *RegExt) SetExt(ext map[string]json.RawMessage) {
  1310  	re.ext = ext
  1311  	re.extDirty = true
  1312  }
  1313  
  1314  func (re *RegExt) GetDSA() *ExtRegsDSA {
  1315  	if re.dsa == nil {
  1316  		return nil
  1317  	}
  1318  	dsa := *re.dsa
  1319  	return &dsa
  1320  }
  1321  
  1322  func (re *RegExt) SetDSA(dsa *ExtRegsDSA) {
  1323  	re.dsa = dsa
  1324  	re.dsaDirty = true
  1325  }
  1326  
  1327  func (re *RegExt) GetGDPR() *int8 {
  1328  	if re.gdpr == nil {
  1329  		return nil
  1330  	}
  1331  	gdpr := *re.gdpr
  1332  	return &gdpr
  1333  }
  1334  
  1335  func (re *RegExt) SetGDPR(gdpr *int8) {
  1336  	re.gdpr = gdpr
  1337  	re.gdprDirty = true
  1338  }
  1339  
  1340  func (re *RegExt) GetUSPrivacy() string {
  1341  	uSPrivacy := re.usPrivacy
  1342  	return uSPrivacy
  1343  }
  1344  
  1345  func (re *RegExt) SetUSPrivacy(usPrivacy string) {
  1346  	re.usPrivacy = usPrivacy
  1347  	re.usPrivacyDirty = true
  1348  }
  1349  
  1350  func (re *RegExt) Clone() *RegExt {
  1351  	if re == nil {
  1352  		return nil
  1353  	}
  1354  
  1355  	clone := *re
  1356  	clone.ext = maputil.Clone(re.ext)
  1357  
  1358  	clone.gdpr = ptrutil.Clone(re.gdpr)
  1359  
  1360  	return &clone
  1361  }
  1362  
  1363  // ---------------------------------------------------------------
  1364  // SiteExt provides an interface for request.site.ext
  1365  // ---------------------------------------------------------------
  1366  
  1367  type SiteExt struct {
  1368  	ext      map[string]json.RawMessage
  1369  	extDirty bool
  1370  	amp      *int8
  1371  	ampDirty bool
  1372  }
  1373  
  1374  func (se *SiteExt) unmarshal(extJson json.RawMessage) error {
  1375  	if len(se.ext) != 0 || se.Dirty() {
  1376  		return nil
  1377  	}
  1378  
  1379  	se.ext = make(map[string]json.RawMessage)
  1380  
  1381  	if len(extJson) == 0 {
  1382  		return nil
  1383  	}
  1384  
  1385  	if err := jsonutil.Unmarshal(extJson, &se.ext); err != nil {
  1386  		return err
  1387  	}
  1388  
  1389  	ampJson, hasAmp := se.ext[ampKey]
  1390  	if hasAmp && ampJson != nil {
  1391  		if err := jsonutil.Unmarshal(ampJson, &se.amp); err != nil {
  1392  			return errors.New(`request.site.ext.amp must be either 1, 0, or undefined`)
  1393  		}
  1394  	}
  1395  
  1396  	return nil
  1397  }
  1398  
  1399  func (se *SiteExt) marshal() (json.RawMessage, error) {
  1400  	if se.ampDirty {
  1401  		if se.amp != nil {
  1402  			ampJson, err := jsonutil.Marshal(se.amp)
  1403  			if err != nil {
  1404  				return nil, err
  1405  			}
  1406  			se.ext[ampKey] = json.RawMessage(ampJson)
  1407  		} else {
  1408  			delete(se.ext, ampKey)
  1409  		}
  1410  		se.ampDirty = false
  1411  	}
  1412  
  1413  	se.extDirty = false
  1414  	if len(se.ext) == 0 {
  1415  		return nil, nil
  1416  	}
  1417  	return jsonutil.Marshal(se.ext)
  1418  }
  1419  
  1420  func (se *SiteExt) Dirty() bool {
  1421  	return se.extDirty || se.ampDirty
  1422  }
  1423  
  1424  func (se *SiteExt) GetExt() map[string]json.RawMessage {
  1425  	ext := make(map[string]json.RawMessage)
  1426  	for k, v := range se.ext {
  1427  		ext[k] = v
  1428  	}
  1429  	return ext
  1430  }
  1431  
  1432  func (se *SiteExt) SetExt(ext map[string]json.RawMessage) {
  1433  	se.ext = ext
  1434  	se.extDirty = true
  1435  }
  1436  
  1437  func (se *SiteExt) GetAmp() *int8 {
  1438  	return se.amp
  1439  }
  1440  
  1441  func (se *SiteExt) SetAmp(amp *int8) {
  1442  	se.amp = amp
  1443  	se.ampDirty = true
  1444  }
  1445  
  1446  func (se *SiteExt) Clone() *SiteExt {
  1447  	if se == nil {
  1448  		return nil
  1449  	}
  1450  
  1451  	clone := *se
  1452  	clone.ext = maputil.Clone(se.ext)
  1453  	clone.amp = ptrutil.Clone(se.amp)
  1454  
  1455  	return &clone
  1456  }
  1457  
  1458  // ---------------------------------------------------------------
  1459  // SourceExt provides an interface for request.source.ext
  1460  // ---------------------------------------------------------------
  1461  
  1462  type SourceExt struct {
  1463  	ext         map[string]json.RawMessage
  1464  	extDirty    bool
  1465  	schain      *openrtb2.SupplyChain
  1466  	schainDirty bool
  1467  }
  1468  
  1469  func (se *SourceExt) unmarshal(extJson json.RawMessage) error {
  1470  	if len(se.ext) != 0 || se.Dirty() {
  1471  		return nil
  1472  	}
  1473  
  1474  	se.ext = make(map[string]json.RawMessage)
  1475  
  1476  	if len(extJson) == 0 {
  1477  		return nil
  1478  	}
  1479  
  1480  	if err := jsonutil.Unmarshal(extJson, &se.ext); err != nil {
  1481  		return err
  1482  	}
  1483  
  1484  	schainJson, hasSChain := se.ext[schainKey]
  1485  	if hasSChain && schainJson != nil {
  1486  		if err := jsonutil.Unmarshal(schainJson, &se.schain); err != nil {
  1487  			return err
  1488  		}
  1489  	}
  1490  
  1491  	return nil
  1492  }
  1493  
  1494  func (se *SourceExt) marshal() (json.RawMessage, error) {
  1495  	if se.schainDirty {
  1496  		if se.schain != nil {
  1497  			schainJson, err := jsonutil.Marshal(se.schain)
  1498  			if err != nil {
  1499  				return nil, err
  1500  			}
  1501  			if len(schainJson) > jsonEmptyObjectLength {
  1502  				se.ext[schainKey] = json.RawMessage(schainJson)
  1503  			} else {
  1504  				delete(se.ext, schainKey)
  1505  			}
  1506  		} else {
  1507  			delete(se.ext, schainKey)
  1508  		}
  1509  		se.schainDirty = false
  1510  	}
  1511  
  1512  	se.extDirty = false
  1513  	if len(se.ext) == 0 {
  1514  		return nil, nil
  1515  	}
  1516  	return jsonutil.Marshal(se.ext)
  1517  }
  1518  
  1519  func (se *SourceExt) Dirty() bool {
  1520  	return se.extDirty || se.schainDirty
  1521  }
  1522  
  1523  func (se *SourceExt) GetExt() map[string]json.RawMessage {
  1524  	ext := make(map[string]json.RawMessage)
  1525  	for k, v := range se.ext {
  1526  		ext[k] = v
  1527  	}
  1528  	return ext
  1529  }
  1530  
  1531  func (se *SourceExt) SetExt(ext map[string]json.RawMessage) {
  1532  	se.ext = ext
  1533  	se.extDirty = true
  1534  }
  1535  
  1536  func (se *SourceExt) GetSChain() *openrtb2.SupplyChain {
  1537  	if se.schain == nil {
  1538  		return nil
  1539  	}
  1540  	schain := *se.schain
  1541  	return &schain
  1542  }
  1543  
  1544  func (se *SourceExt) SetSChain(schain *openrtb2.SupplyChain) {
  1545  	se.schain = schain
  1546  	se.schainDirty = true
  1547  }
  1548  
  1549  func (se *SourceExt) Clone() *SourceExt {
  1550  	if se == nil {
  1551  		return nil
  1552  	}
  1553  
  1554  	clone := *se
  1555  	clone.ext = maputil.Clone(se.ext)
  1556  
  1557  	clone.schain = cloneSupplyChain(se.schain)
  1558  
  1559  	return &clone
  1560  }
  1561  
  1562  // ImpWrapper wraps an OpenRTB impression object to provide storage for unmarshalled ext fields, so they
  1563  // will not need to be unmarshalled multiple times. It is intended to use the ImpWrapper via the RequestWrapper
  1564  // and follow the same usage conventions.
  1565  type ImpWrapper struct {
  1566  	*openrtb2.Imp
  1567  	impExt *ImpExt
  1568  }
  1569  
  1570  func (w *ImpWrapper) GetImpExt() (*ImpExt, error) {
  1571  	if w.impExt != nil {
  1572  		return w.impExt, nil
  1573  	}
  1574  	w.impExt = &ImpExt{}
  1575  	if w.Imp == nil || w.Ext == nil {
  1576  		return w.impExt, w.impExt.unmarshal(json.RawMessage{})
  1577  	}
  1578  	return w.impExt, w.impExt.unmarshal(w.Ext)
  1579  }
  1580  
  1581  func (w *ImpWrapper) RebuildImp() error {
  1582  	if w.Imp == nil {
  1583  		return errors.New("ImpWrapper RebuildImp called on a nil Imp")
  1584  	}
  1585  
  1586  	if err := w.rebuildImpExt(); err != nil {
  1587  		return err
  1588  	}
  1589  
  1590  	return nil
  1591  }
  1592  
  1593  func (w *ImpWrapper) rebuildImpExt() error {
  1594  	if w.impExt == nil || !w.impExt.Dirty() {
  1595  		return nil
  1596  	}
  1597  
  1598  	impJson, err := w.impExt.marshal()
  1599  	if err != nil {
  1600  		return err
  1601  	}
  1602  
  1603  	w.Ext = impJson
  1604  
  1605  	return nil
  1606  }
  1607  
  1608  func (w *ImpWrapper) Clone() *ImpWrapper {
  1609  	if w == nil {
  1610  		return nil
  1611  	}
  1612  
  1613  	clone := *w
  1614  	clone.impExt = w.impExt.Clone()
  1615  
  1616  	return &clone
  1617  }
  1618  
  1619  // ---------------------------------------------------------------
  1620  // ImpExt provides an interface for imp.ext
  1621  // ---------------------------------------------------------------
  1622  
  1623  type ImpExt struct {
  1624  	ext         map[string]json.RawMessage
  1625  	extDirty    bool
  1626  	prebid      *ExtImpPrebid
  1627  	data        *ExtImpData
  1628  	prebidDirty bool
  1629  	tid         string
  1630  	gpId        string
  1631  	tidDirty    bool
  1632  }
  1633  
  1634  func (e *ImpExt) unmarshal(extJson json.RawMessage) error {
  1635  	if len(e.ext) != 0 || e.Dirty() {
  1636  		return nil
  1637  	}
  1638  
  1639  	e.ext = make(map[string]json.RawMessage)
  1640  
  1641  	if len(extJson) == 0 {
  1642  		return nil
  1643  	}
  1644  
  1645  	if err := jsonutil.Unmarshal(extJson, &e.ext); err != nil {
  1646  		return err
  1647  	}
  1648  
  1649  	prebidJson, hasPrebid := e.ext[prebidKey]
  1650  	if hasPrebid {
  1651  		e.prebid = &ExtImpPrebid{}
  1652  	}
  1653  	if prebidJson != nil {
  1654  		if err := jsonutil.Unmarshal(prebidJson, e.prebid); err != nil {
  1655  			return err
  1656  		}
  1657  	}
  1658  
  1659  	dataJson, hasData := e.ext[dataKey]
  1660  	if hasData {
  1661  		e.data = &ExtImpData{}
  1662  	}
  1663  	if dataJson != nil {
  1664  		if err := jsonutil.Unmarshal(dataJson, e.data); err != nil {
  1665  			return err
  1666  		}
  1667  	}
  1668  
  1669  	tidJson, hasTid := e.ext["tid"]
  1670  	if hasTid && tidJson != nil {
  1671  		if err := jsonutil.Unmarshal(tidJson, &e.tid); err != nil {
  1672  			return err
  1673  		}
  1674  	}
  1675  
  1676  	gpIdJson, hasGpId := e.ext["gpid"]
  1677  	if hasGpId && gpIdJson != nil {
  1678  		if err := jsonutil.Unmarshal(gpIdJson, &e.gpId); err != nil {
  1679  			return err
  1680  		}
  1681  	}
  1682  
  1683  	return nil
  1684  }
  1685  
  1686  func (e *ImpExt) marshal() (json.RawMessage, error) {
  1687  	if e.prebidDirty {
  1688  		if e.prebid != nil {
  1689  			prebidJson, err := jsonutil.Marshal(e.prebid)
  1690  			if err != nil {
  1691  				return nil, err
  1692  			}
  1693  			if len(prebidJson) > jsonEmptyObjectLength {
  1694  				e.ext[prebidKey] = json.RawMessage(prebidJson)
  1695  			} else {
  1696  				delete(e.ext, prebidKey)
  1697  			}
  1698  		} else {
  1699  			delete(e.ext, prebidKey)
  1700  		}
  1701  		e.prebidDirty = false
  1702  	}
  1703  
  1704  	if e.tidDirty {
  1705  		if len(e.tid) > 0 {
  1706  			tidJson, err := jsonutil.Marshal(e.tid)
  1707  			if err != nil {
  1708  				return nil, err
  1709  			}
  1710  			e.ext["tid"] = tidJson
  1711  		} else {
  1712  			delete(e.ext, "tid")
  1713  		}
  1714  		e.tidDirty = false
  1715  	}
  1716  
  1717  	e.extDirty = false
  1718  	if len(e.ext) == 0 {
  1719  		return nil, nil
  1720  	}
  1721  	return jsonutil.Marshal(e.ext)
  1722  }
  1723  
  1724  func (e *ImpExt) Dirty() bool {
  1725  	return e.extDirty || e.prebidDirty || e.tidDirty
  1726  }
  1727  
  1728  func (e *ImpExt) GetExt() map[string]json.RawMessage {
  1729  	ext := make(map[string]json.RawMessage)
  1730  	for k, v := range e.ext {
  1731  		ext[k] = v
  1732  	}
  1733  	return ext
  1734  }
  1735  
  1736  func (e *ImpExt) SetExt(ext map[string]json.RawMessage) {
  1737  	e.ext = ext
  1738  	e.extDirty = true
  1739  }
  1740  
  1741  func (e *ImpExt) GetPrebid() *ExtImpPrebid {
  1742  	if e.prebid == nil {
  1743  		return nil
  1744  	}
  1745  	prebid := *e.prebid
  1746  	return &prebid
  1747  }
  1748  
  1749  func (e *ImpExt) GetOrCreatePrebid() *ExtImpPrebid {
  1750  	if e.prebid == nil {
  1751  		e.prebid = &ExtImpPrebid{}
  1752  	}
  1753  	return e.GetPrebid()
  1754  }
  1755  
  1756  func (e *ImpExt) SetPrebid(prebid *ExtImpPrebid) {
  1757  	e.prebid = prebid
  1758  	e.prebidDirty = true
  1759  }
  1760  
  1761  func (e *ImpExt) GetData() *ExtImpData {
  1762  	if e.data == nil {
  1763  		return nil
  1764  	}
  1765  	data := *e.data
  1766  	return &data
  1767  }
  1768  
  1769  func (e *ImpExt) GetTid() string {
  1770  	tid := e.tid
  1771  	return tid
  1772  }
  1773  
  1774  func (e *ImpExt) SetTid(tid string) {
  1775  	e.tid = tid
  1776  	e.tidDirty = true
  1777  }
  1778  
  1779  func (e *ImpExt) GetGpId() string {
  1780  	gpId := e.gpId
  1781  	return gpId
  1782  }
  1783  
  1784  func CreateImpExtForTesting(ext map[string]json.RawMessage, prebid *ExtImpPrebid) ImpExt {
  1785  	return ImpExt{ext: ext, prebid: prebid}
  1786  }
  1787  
  1788  func (e *ImpExt) Clone() *ImpExt {
  1789  	if e == nil {
  1790  		return nil
  1791  	}
  1792  
  1793  	clone := *e
  1794  	clone.ext = maputil.Clone(e.ext)
  1795  
  1796  	if e.prebid != nil {
  1797  		clonedPrebid := *e.prebid
  1798  		clonedPrebid.StoredRequest = ptrutil.Clone(e.prebid.StoredRequest)
  1799  		clonedPrebid.StoredAuctionResponse = ptrutil.Clone(e.prebid.StoredAuctionResponse)
  1800  		if e.prebid.StoredBidResponse != nil {
  1801  			clonedPrebid.StoredBidResponse = make([]ExtStoredBidResponse, len(e.prebid.StoredBidResponse))
  1802  			for i, sbr := range e.prebid.StoredBidResponse {
  1803  				clonedPrebid.StoredBidResponse[i] = sbr
  1804  				clonedPrebid.StoredBidResponse[i].ReplaceImpId = ptrutil.Clone(sbr.ReplaceImpId)
  1805  			}
  1806  		}
  1807  		clonedPrebid.IsRewardedInventory = ptrutil.Clone(e.prebid.IsRewardedInventory)
  1808  		clonedPrebid.Bidder = maputil.Clone(e.prebid.Bidder)
  1809  		clonedPrebid.Options = ptrutil.Clone(e.prebid.Options)
  1810  		clonedPrebid.Floors = ptrutil.Clone(e.prebid.Floors)
  1811  		clone.prebid = &clonedPrebid
  1812  	}
  1813  
  1814  	return &clone
  1815  }