Skip to content

Commit

Permalink
Add encode method to convert Sections into GPP String (#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
bsardo authored Nov 14, 2023
2 parents 041527a + b1c7c3f commit 8cca024
Show file tree
Hide file tree
Showing 23 changed files with 1,362 additions and 11 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,8 @@

# Dependency directories (remove the comment below to include it)
# vendor/

release/
.idea/
.vscode/
.DS_Store
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
# go-gpp
Golang support for the IAB's GPP framework
Golang support for the IAB's GPP framework.

Provided the basic *Parse* and *Encode* methods for conversions between IAB-supported
sections and GPP strings, people other than CMPs are not encouraged to generate GPP strings
in production according to the IAB documentation.

For more information, please refer to https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform
73 changes: 73 additions & 0 deletions encode.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package gpp

import (
"errors"
"fmt"
"github.com/prebid/go-gpp/constants"
"github.com/prebid/go-gpp/util"
"sort"
"strings"
)

const (
// the first 6 bits of the header must always evaluate to the integer '3'.
gppType byte = 0x3
gppVersion byte = 0x1
// the range of SectionID must start with 1 and end with the maximum value represented by uint16.
minSectionId constants.SectionID = 1
maxSectionId constants.SectionID = 0xffff
)

var (
sectionIdOutOfRangeErr = errors.New("section ID out of range")
duplicatedSectionErr = errors.New("duplicated sections")
)

func Encode(sections []Section) (string, error) {
bs := util.NewBitStreamForWrite()
builder := strings.Builder{}

bs.WriteByte6(gppType)
bs.WriteByte6(gppVersion)

sort.Slice(sections, func(i, j int) bool {
return sections[i].GetID() < sections[j].GetID()
})

if len(sections) > 0 && (sections[0].GetID() < minSectionId ||
sections[len(sections)-1].GetID() > maxSectionId) {
return "", sectionIdOutOfRangeErr
}
// Generate int range object.
intRange := new(util.IntRange)
// Since the minimum sectionID is 1, the previous one should start with -1, which makes it not continuous.
var prevID constants.SectionID = -1
for _, sec := range sections {
id := sec.GetID()
if id == prevID {
return "", duplicatedSectionErr
}
if prevID+1 == id {
intRange.Range[len(intRange.Range)-1].EndID = uint16(id)
} else {
intRange.Range = append(intRange.Range, util.IRange{StartID: uint16(id), EndID: uint16(id)})
}
prevID = id
}
intRange.Size = uint16(len(intRange.Range))

err := bs.WriteIntRange(intRange)
if err != nil {
return "", fmt.Errorf("write int range error: %v", err)
}

builder.Write(bs.Base64Encode())

for _, sec := range sections {
builder.WriteByte('~')
// By default, GPP is included.
builder.Write(sec.Encode(true))
}

return builder.String(), nil
}
Loading

0 comments on commit 8cca024

Please sign in to comment.