diff --git a/bits.go b/bits.go index 8881227..07a955e 100644 --- a/bits.go +++ b/bits.go @@ -1,42 +1,42 @@ package iabtcfv2 type Bits struct { - position uint - bytes []byte + Position uint + Bytes []byte } var ( bytePows = []byte{128, 64, 32, 16, 8, 4, 2, 1} ) -func newBits(bytes []byte) *Bits { - return &Bits{bytes: bytes, position: 0} +func NewBits(bytes []byte) *Bits { + return &Bits{Bytes: bytes, Position: 0} } -func (b *Bits) readBool() bool { - byteIndex := b.position / 8 - bitIndex := b.position % 8 - b.position++ +func (b *Bits) ReadBool() bool { + byteIndex := b.Position / 8 + bitIndex := b.Position % 8 + b.Position++ - return (b.bytes[byteIndex] & bytePows[bitIndex]) != 0 + return (b.Bytes[byteIndex] & bytePows[bitIndex]) != 0 } -func (b *Bits) writeBool(v bool) { - byteIndex := b.position / 8 - shift := (byteIndex+1)*8 - b.position - 1 - b.position++ +func (b *Bits) WriteBool(v bool) { + byteIndex := b.Position / 8 + shift := (byteIndex+1)*8 - b.Position - 1 + b.Position++ if v { - b.bytes[byteIndex] |= 1 << uint(shift) + b.Bytes[byteIndex] |= 1 << uint(shift) } else { - b.bytes[byteIndex] &^= 1 << uint(shift) + b.Bytes[byteIndex] &^= 1 << uint(shift) } } -func (b *Bits) readInt(n uint) int { +func (b *Bits) ReadInt(n uint) int { v := 0 for i, shift := uint(0), n-1; i < n; i++ { - if b.readBool() { + if b.ReadBool() { v += 1 << uint(shift) } shift-- @@ -45,19 +45,19 @@ func (b *Bits) readInt(n uint) int { return v } -func (b *Bits) writeInt(v int, n uint) { - b.writeNumber(int64(v), n) +func (b *Bits) WriteInt(v int, n uint) { + b.WriteNumber(int64(v), n) } -func (b *Bits) writeNumber(v int64, n uint) { - startOffset := int(b.position) +func (b *Bits) WriteNumber(v int64, n uint) { + startOffset := int(b.Position) for i := int(n) - 1; i >= 0; i-- { index := startOffset + i byteIndex := index / 8 shift := (byteIndex+1)*8 - index - 1 - b.bytes[byteIndex] |= byte(v%2) << uint(shift) + b.Bytes[byteIndex] |= byte(v%2) << uint(shift) v /= 2 } - b.position += n + b.Position += n } diff --git a/decode.go b/decode.go index a0ad66c..0c97b6b 100644 --- a/decode.go +++ b/decode.go @@ -28,8 +28,8 @@ func GetVersion(s string) (version TcfVersion, err error) { return TcfVersionUndefined, err } - var e = newTCEncoder(b) - return TcfVersion(e.readInt(bitsVersion)), nil + var e = NewTCEncoder(b) + return TcfVersion(e.ReadInt(bitsVersion)), nil } // Decodes a segment value and returns the SegmentType @@ -49,8 +49,8 @@ func GetSegmentType(segment string) (segmentType SegmentType, err error) { return SegmentTypeUndefined, err } - var e = newTCEncoder(b) - return SegmentType(e.readInt(bitsSegmentType)), nil + var e = NewTCEncoder(b) + return SegmentType(e.ReadInt(bitsSegmentType)), nil } // Decode a TC String and returns it as a TCData structure @@ -123,43 +123,43 @@ func DecodeCoreString(coreString string) (c *CoreString, err error) { return nil, err } - var e = newTCEncoder(b) + var e = NewTCEncoder(b) c = &CoreString{} - c.Version = e.readInt(bitsVersion) - c.Created = e.readTime() - c.LastUpdated = e.readTime() - c.CmpId = e.readInt(bitsCmpId) - c.CmpVersion = e.readInt(bitsCmpVersion) - c.ConsentScreen = e.readInt(bitsConsentScreen) - c.ConsentLanguage = e.readChars(bitsConsentLanguage) - c.VendorListVersion = e.readInt(bitsVendorListVersion) - c.TcfPolicyVersion = e.readInt(bitsTcfPolicyVersion) - c.IsServiceSpecific = e.readBool() - c.UseNonStandardTexts = e.readBool() - c.SpecialFeatureOptIns = e.readBitField(bitsSpecialFeatureOptIns) - c.PurposesConsent = e.readBitField(bitsPurposesConsent) - c.PurposesLITransparency = e.readBitField(bitsPurposesLITransparency) - c.PurposeOneTreatment = e.readBool() - c.PublisherCC = e.readChars(bitsPublisherCC) - - c.MaxVendorId = e.readInt(bitsMaxVendorId) - c.IsRangeEncoding = e.readBool() + c.Version = e.ReadInt(bitsVersion) + c.Created = e.ReadTime() + c.LastUpdated = e.ReadTime() + c.CmpId = e.ReadInt(bitsCmpId) + c.CmpVersion = e.ReadInt(bitsCmpVersion) + c.ConsentScreen = e.ReadInt(bitsConsentScreen) + c.ConsentLanguage = e.ReadChars(bitsConsentLanguage) + c.VendorListVersion = e.ReadInt(bitsVendorListVersion) + c.TcfPolicyVersion = e.ReadInt(bitsTcfPolicyVersion) + c.IsServiceSpecific = e.ReadBool() + c.UseNonStandardTexts = e.ReadBool() + c.SpecialFeatureOptIns = e.ReadBitField(bitsSpecialFeatureOptIns) + c.PurposesConsent = e.ReadBitField(bitsPurposesConsent) + c.PurposesLITransparency = e.ReadBitField(bitsPurposesLITransparency) + c.PurposeOneTreatment = e.ReadBool() + c.PublisherCC = e.ReadChars(bitsPublisherCC) + + c.MaxVendorId = e.ReadInt(bitsMaxVendorId) + c.IsRangeEncoding = e.ReadBool() if c.IsRangeEncoding { - c.NumEntries, c.RangeEntries = e.readRangeEntries() + c.NumEntries, c.RangeEntries = e.ReadRangeEntries() } else { - c.VendorsConsent = e.readBitField(uint(c.MaxVendorId)) + c.VendorsConsent = e.ReadBitField(uint(c.MaxVendorId)) } - c.MaxVendorIdLI = e.readInt(bitsMaxVendorId) - c.IsRangeEncodingLI = e.readBool() + c.MaxVendorIdLI = e.ReadInt(bitsMaxVendorId) + c.IsRangeEncodingLI = e.ReadBool() if c.IsRangeEncodingLI { - c.NumEntriesLI, c.RangeEntriesLI = e.readRangeEntries() + c.NumEntriesLI, c.RangeEntriesLI = e.ReadRangeEntries() } else { - c.VendorsLITransparency = e.readBitField(uint(c.MaxVendorIdLI)) + c.VendorsLITransparency = e.ReadBitField(uint(c.MaxVendorIdLI)) } - c.NumPubRestrictions, c.PubRestrictions = e.readPubRestrictions() + c.NumPubRestrictions, c.PubRestrictions = e.ReadPubRestrictions() return c, nil } @@ -177,16 +177,16 @@ func DecodeDisclosedVendors(disclosedVendors string) (d *DisclosedVendors, err e return nil, err } - var e = newTCEncoder(b) + var e = NewTCEncoder(b) d = &DisclosedVendors{} - d.SegmentType = e.readInt(bitsSegmentType) - d.MaxVendorId = e.readInt(bitsMaxVendorId) - d.IsRangeEncoding = e.readBool() + d.SegmentType = e.ReadInt(bitsSegmentType) + d.MaxVendorId = e.ReadInt(bitsMaxVendorId) + d.IsRangeEncoding = e.ReadBool() if d.IsRangeEncoding { - d.NumEntries, d.RangeEntries = e.readRangeEntries() + d.NumEntries, d.RangeEntries = e.ReadRangeEntries() } else { - d.DisclosedVendors = e.readBitField(uint(d.MaxVendorId)) + d.DisclosedVendors = e.ReadBitField(uint(d.MaxVendorId)) } if d.SegmentType != int(SegmentTypeDisclosedVendors) { @@ -210,15 +210,15 @@ func DecodePublisherTC(publisherTC string) (p *PublisherTC, err error) { return nil, err } - var e = newTCEncoder(b) + var e = NewTCEncoder(b) p = &PublisherTC{} - p.SegmentType = e.readInt(bitsSegmentType) - p.PubPurposesConsent = e.readBitField(bitsPubPurposesConsent) - p.PubPurposesLITransparency = e.readBitField(bitsPubPurposesLITransparency) - p.NumCustomPurposes = e.readInt(bitsNumCustomPurposes) - p.CustomPurposesConsent = e.readBitField(uint(p.NumCustomPurposes)) - p.CustomPurposesLITransparency = e.readBitField(uint(p.NumCustomPurposes)) + p.SegmentType = e.ReadInt(bitsSegmentType) + p.PubPurposesConsent = e.ReadBitField(bitsPubPurposesConsent) + p.PubPurposesLITransparency = e.ReadBitField(bitsPubPurposesLITransparency) + p.NumCustomPurposes = e.ReadInt(bitsNumCustomPurposes) + p.CustomPurposesConsent = e.ReadBitField(uint(p.NumCustomPurposes)) + p.CustomPurposesLITransparency = e.ReadBitField(uint(p.NumCustomPurposes)) if p.SegmentType != int(SegmentTypePublisherTC) { return nil, fmt.Errorf("publisher TC segment type must be %d", SegmentTypePublisherTC) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..e69de29 diff --git a/segment_core_string.go b/segment_core_string.go index caf33bc..c77ab89 100644 --- a/segment_core_string.go +++ b/segment_core_string.go @@ -323,41 +323,41 @@ func (c *CoreString) Encode() string { bitSize += restriction.getBitSize() } - e := newTCEncoderFromSize(bitSize) - e.writeInt(c.Version, bitsVersion) - e.writeTime(c.Created) - e.writeTime(c.LastUpdated) - e.writeInt(c.CmpId, bitsCmpId) - e.writeInt(c.CmpVersion, bitsCmpVersion) - e.writeInt(c.ConsentScreen, bitsConsentScreen) - e.writeChars(c.ConsentLanguage, bitsConsentLanguage) - e.writeInt(c.VendorListVersion, bitsVendorListVersion) - e.writeInt(c.TcfPolicyVersion, bitsTcfPolicyVersion) - e.writeBool(c.IsServiceSpecific) - e.writeBool(c.UseNonStandardTexts) - e.writeBools(c.IsSpecialFeatureAllowed, bitsSpecialFeatureOptIns) - e.writeBools(c.IsPurposeAllowed, bitsPurposesConsent) - e.writeBools(c.IsPurposeLIAllowed, bitsPurposesLITransparency) - e.writeBool(c.PurposeOneTreatment) - e.writeChars(c.PublisherCC, bitsPublisherCC) - - e.writeInt(c.MaxVendorId, bitsMaxVendorId) - e.writeBool(c.IsRangeEncoding) + e := NewTCEncoderFromSize(bitSize) + e.WriteInt(c.Version, bitsVersion) + e.WriteTime(c.Created) + e.WriteTime(c.LastUpdated) + e.WriteInt(c.CmpId, bitsCmpId) + e.WriteInt(c.CmpVersion, bitsCmpVersion) + e.WriteInt(c.ConsentScreen, bitsConsentScreen) + e.WriteChars(c.ConsentLanguage, bitsConsentLanguage) + e.WriteInt(c.VendorListVersion, bitsVendorListVersion) + e.WriteInt(c.TcfPolicyVersion, bitsTcfPolicyVersion) + e.WriteBool(c.IsServiceSpecific) + e.WriteBool(c.UseNonStandardTexts) + e.WriteBools(c.IsSpecialFeatureAllowed, bitsSpecialFeatureOptIns) + e.WriteBools(c.IsPurposeAllowed, bitsPurposesConsent) + e.WriteBools(c.IsPurposeLIAllowed, bitsPurposesLITransparency) + e.WriteBool(c.PurposeOneTreatment) + e.WriteChars(c.PublisherCC, bitsPublisherCC) + + e.WriteInt(c.MaxVendorId, bitsMaxVendorId) + e.WriteBool(c.IsRangeEncoding) if c.IsRangeEncoding { - e.writeRangeEntries(c.RangeEntries) + e.WriteRangeEntries(c.RangeEntries) } else { - e.writeBools(c.IsVendorAllowed, c.MaxVendorId) + e.WriteBools(c.IsVendorAllowed, c.MaxVendorId) } - e.writeInt(c.MaxVendorIdLI, bitsMaxVendorId) - e.writeBool(c.IsRangeEncodingLI) + e.WriteInt(c.MaxVendorIdLI, bitsMaxVendorId) + e.WriteBool(c.IsRangeEncodingLI) if c.IsRangeEncodingLI { - e.writeRangeEntries(c.RangeEntriesLI) + e.WriteRangeEntries(c.RangeEntriesLI) } else { - e.writeBools(c.IsVendorLIAllowed, c.MaxVendorIdLI) + e.WriteBools(c.IsVendorLIAllowed, c.MaxVendorIdLI) } - e.writePubRestrictions(c.PubRestrictions) + e.WritePubRestrictions(c.PubRestrictions) - return base64.RawURLEncoding.EncodeToString(e.bytes) + return base64.RawURLEncoding.EncodeToString(e.Bytes) } diff --git a/segment_disclosed_vendors.go b/segment_disclosed_vendors.go index 65dc6c1..795428f 100644 --- a/segment_disclosed_vendors.go +++ b/segment_disclosed_vendors.go @@ -50,15 +50,15 @@ func (d *DisclosedVendors) Encode() string { bitSize += d.MaxVendorId } - e := newTCEncoderFromSize(bitSize) - e.writeInt(d.SegmentType, bitsSegmentType) - e.writeInt(d.MaxVendorId, bitsMaxVendorId) - e.writeBool(d.IsRangeEncoding) + e := NewTCEncoderFromSize(bitSize) + e.WriteInt(d.SegmentType, bitsSegmentType) + e.WriteInt(d.MaxVendorId, bitsMaxVendorId) + e.WriteBool(d.IsRangeEncoding) if d.IsRangeEncoding { - e.writeRangeEntries(d.RangeEntries) + e.WriteRangeEntries(d.RangeEntries) } else { - e.writeBools(d.IsVendorDisclosed, d.MaxVendorId) + e.WriteBools(d.IsVendorDisclosed, d.MaxVendorId) } - return base64.RawURLEncoding.EncodeToString(e.bytes) + return base64.RawURLEncoding.EncodeToString(e.Bytes) } diff --git a/segment_publisher_tc.go b/segment_publisher_tc.go index b9f5706..6eb864a 100644 --- a/segment_publisher_tc.go +++ b/segment_publisher_tc.go @@ -43,13 +43,13 @@ func (p *PublisherTC) Encode() string { bitSize += bitsNumCustomPurposes bitSize += p.NumCustomPurposes * 2 - e := newTCEncoderFromSize(bitSize) - e.writeInt(p.SegmentType, bitsSegmentType) - e.writeBools(p.IsPurposeAllowed, bitsPubPurposesConsent) - e.writeBools(p.IsPurposeLIAllowed, bitsPubPurposesLITransparency) - e.writeInt(p.NumCustomPurposes, bitsNumCustomPurposes) - e.writeBools(p.IsCustomPurposeAllowed, p.NumCustomPurposes) - e.writeBools(p.IsCustomPurposeLIAllowed, p.NumCustomPurposes) - - return base64.RawURLEncoding.EncodeToString(e.bytes) + e := NewTCEncoderFromSize(bitSize) + e.WriteInt(p.SegmentType, bitsSegmentType) + e.WriteBools(p.IsPurposeAllowed, bitsPubPurposesConsent) + e.WriteBools(p.IsPurposeLIAllowed, bitsPubPurposesLITransparency) + e.WriteInt(p.NumCustomPurposes, bitsNumCustomPurposes) + e.WriteBools(p.IsCustomPurposeAllowed, p.NumCustomPurposes) + e.WriteBools(p.IsCustomPurposeLIAllowed, p.NumCustomPurposes) + + return base64.RawURLEncoding.EncodeToString(e.Bytes) } diff --git a/tcencoder.go b/tcencoder.go index 928c93f..eab46af 100644 --- a/tcencoder.go +++ b/tcencoder.go @@ -13,80 +13,80 @@ type TCEncoder struct { *Bits } -func newTCEncoder(src []byte) *TCEncoder { - return &TCEncoder{newBits(src)} +func NewTCEncoder(src []byte) *TCEncoder { + return &TCEncoder{NewBits(src)} } -func newTCEncoderFromSize(bitSize int) *TCEncoder { +func NewTCEncoderFromSize(bitSize int) *TCEncoder { if bitSize%8 != 0 { - return newTCEncoder(make([]byte, bitSize/8+1)) + return NewTCEncoder(make([]byte, bitSize/8+1)) } - return newTCEncoder(make([]byte, bitSize/8)) + return NewTCEncoder(make([]byte, bitSize/8)) } -func (r *TCEncoder) readTime() time.Time { - var ds = int64(r.readInt(bitsTime)) +func (r *TCEncoder) ReadTime() time.Time { + var ds = int64(r.ReadInt(bitsTime)) return time.Unix(ds/decisecondsPerSecond, (ds%decisecondsPerSecond)*nanosecondsPerDecisecond).UTC() } -func (r *TCEncoder) writeTime(v time.Time) { - r.writeNumber(v.UnixNano()/nanosecondsPerDecisecond, bitsTime) +func (r *TCEncoder) WriteTime(v time.Time) { + r.WriteNumber(v.UnixNano()/nanosecondsPerDecisecond, bitsTime) } -func (r *TCEncoder) readChars(n uint) string { +func (r *TCEncoder) ReadChars(n uint) string { var buf = make([]byte, 0, n/bitsChar) for i := uint(0); i < n/bitsChar; i++ { - buf = append(buf, byte(r.readInt(bitsChar))+'A') + buf = append(buf, byte(r.ReadInt(bitsChar))+'A') } return string(buf) } -func (r *TCEncoder) writeChars(v string, n uint) { +func (r *TCEncoder) WriteChars(v string, n uint) { for i := uint(0); i < n/bitsChar; i++ { char := v[i] - r.writeInt(int(byte(char)-'A'), bitsChar) + r.WriteInt(int(byte(char)-'A'), bitsChar) } } -func (r *TCEncoder) readBitField(n uint) map[int]bool { +func (r *TCEncoder) ReadBitField(n uint) map[int]bool { var m = make(map[int]bool) for i := uint(0); i < n; i++ { - if r.readBool() { + if r.ReadBool() { m[int(i)+1] = true } } return m } -func (b *Bits) writeBools(getBool func(int) bool, n int) { +func (b *Bits) WriteBools(getBool func(int) bool, n int) { for i := 1; i <= n; i++ { - b.writeBool(getBool(i)) + b.WriteBool(getBool(i)) } } -func (r *TCEncoder) writeRangeEntries(entries []*RangeEntry) { - r.writeInt(len(entries), bitsNumEntries) +func (r *TCEncoder) WriteRangeEntries(entries []*RangeEntry) { + r.WriteInt(len(entries), bitsNumEntries) for _, entry := range entries { if entry.EndVendorID > entry.StartVendorID { - r.writeBool(true) - r.writeInt(entry.StartVendorID, bitsVendorId) - r.writeInt(entry.EndVendorID, bitsVendorId) + r.WriteBool(true) + r.WriteInt(entry.StartVendorID, bitsVendorId) + r.WriteInt(entry.EndVendorID, bitsVendorId) } else { - r.writeBool(false) - r.writeInt(entry.StartVendorID, bitsVendorId) + r.WriteBool(false) + r.WriteInt(entry.StartVendorID, bitsVendorId) } } } -func (r *TCEncoder) readRangeEntries() (int, []*RangeEntry) { - n := r.readInt(bitsNumEntries) +func (r *TCEncoder) ReadRangeEntries() (int, []*RangeEntry) { + n := r.ReadInt(bitsNumEntries) var ret = make([]*RangeEntry, 0, n) for i := uint(0); i < uint(n); i++ { - var isRange = r.readBool() + var isRange = r.ReadBool() var start, end int - start = r.readInt(bitsVendorId) + start = r.ReadInt(bitsVendorId) if isRange { - end = r.readInt(bitsVendorId) + end = r.ReadInt(bitsVendorId) } else { end = start } @@ -95,22 +95,22 @@ func (r *TCEncoder) readRangeEntries() (int, []*RangeEntry) { return n, ret } -func (r *TCEncoder) writePubRestrictions(entries []*PubRestriction) { - r.writeInt(len(entries), bitsNumPubRestrictions) +func (r *TCEncoder) WritePubRestrictions(entries []*PubRestriction) { + r.WriteInt(len(entries), bitsNumPubRestrictions) for _, entry := range entries { - r.writeInt(entry.PurposeId, bitsPubRestrictionsEntryPurposeId) - r.writeInt(int(entry.RestrictionType), bitsPubRestrictionsEntryRestrictionType) - r.writeRangeEntries(entry.RangeEntries) + r.WriteInt(entry.PurposeId, bitsPubRestrictionsEntryPurposeId) + r.WriteInt(int(entry.RestrictionType), bitsPubRestrictionsEntryRestrictionType) + r.WriteRangeEntries(entry.RangeEntries) } } -func (r *TCEncoder) readPubRestrictions() (int, []*PubRestriction) { - n := r.readInt(bitsNumPubRestrictions) +func (r *TCEncoder) ReadPubRestrictions() (int, []*PubRestriction) { + n := r.ReadInt(bitsNumPubRestrictions) var ret = make([]*PubRestriction, 0, n) for i := uint(0); i < uint(n); i++ { - var purposeId = r.readInt(bitsPubRestrictionsEntryPurposeId) - var restrictionType = r.readInt(bitsPubRestrictionsEntryRestrictionType) - numEntries, rangeEntries := r.readRangeEntries() + var purposeId = r.ReadInt(bitsPubRestrictionsEntryPurposeId) + var restrictionType = r.ReadInt(bitsPubRestrictionsEntryRestrictionType) + numEntries, rangeEntries := r.ReadRangeEntries() ret = append(ret, &PubRestriction{PurposeId: purposeId, RestrictionType: RestrictionType(restrictionType), NumEntries: numEntries,