From a95d955c6abca687c6305ea133f7dbacdcfce8ba Mon Sep 17 00:00:00 2001 From: Thomas LAY Date: Fri, 3 Apr 2020 17:13:48 +0200 Subject: [PATCH] Fix library exposure --- bits.go | 16 +++--- decode.go | 104 +++++++++++++++++----------------- encoder.go | 105 ----------------------------------- segment_allowed_vendors.go | 16 +++--- segment_core_string.go | 60 ++++++++++---------- segment_disclosed_vendors.go | 16 +++--- segment_publisher_tc.go | 16 +++--- tcencoder.go | 105 +++++++++++++++++++++++++++++++++++ 8 files changed, 219 insertions(+), 219 deletions(-) delete mode 100644 encoder.go create mode 100644 tcencoder.go diff --git a/bits.go b/bits.go index 920b69d..273f3a9 100644 --- a/bits.go +++ b/bits.go @@ -9,11 +9,11 @@ var ( bytePows = []byte{128, 64, 32, 16, 8, 4, 2, 1} ) -func NewBits(bytes []byte) *Bits { +func newBits(bytes []byte) *Bits { return &Bits{bytes: bytes, position: 0} } -func (b *Bits) ReadBool() bool { +func (b *Bits) readBool() bool { byteIndex := b.position / 8 bitIndex := b.position % 8 b.position++ @@ -21,7 +21,7 @@ func (b *Bits) ReadBool() bool { return (b.bytes[byteIndex] & bytePows[bitIndex]) != 0 } -func (b *Bits) WriteBool(v bool) { +func (b *Bits) writeBool(v bool) { byteIndex := b.position / 8 shift := (byteIndex+1)*8 - b.position - 1 b.position++ @@ -33,10 +33,10 @@ func (b *Bits) WriteBool(v bool) { } } -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,11 +45,11 @@ 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) { +func (b *Bits) writeNumber(v int64, n uint) { startOffset := int(b.position) for i := int(n) - 1; i >= 0; i-- { index := startOffset + i diff --git a/decode.go b/decode.go index b62b8ff..8b6b5f3 100644 --- a/decode.go +++ b/decode.go @@ -12,8 +12,8 @@ func DecodeSegmentType(s string) int { return 0 } - var e = NewTCEncoder(b) - return e.ReadInt(3) + var e = newTCEncoder(b) + return e.readInt(3) } func Decode(s string) (t *TCData, err error) { @@ -62,46 +62,46 @@ func DecodeCoreString(s string) (c *CoreString, err error) { return nil, err } - var e = NewTCEncoder(b) + var e = newTCEncoder(b) c = &CoreString{} - c.Version = e.ReadInt(6) - c.Created = e.ReadTime() - c.LastUpdated = e.ReadTime() - c.CmpId = e.ReadInt(12) - c.CmpVersion = e.ReadInt(12) - c.ConsentScreen = e.ReadInt(6) - c.ConsentLanguage = e.ReadIsoCode() - c.VendorListVersion = e.ReadInt(12) - c.TcfPolicyVersion = e.ReadInt(6) - c.IsServiceSpecific = e.ReadBool() - c.UseNonStandardStacks = e.ReadBool() - c.SpecialFeatureOptIns = e.ReadBitField(12) - c.PurposesConsent = e.ReadBitField(24) - c.PurposesLITransparency = e.ReadBitField(24) - c.PurposeOneTreatment = e.ReadBool() - c.PublisherCC = e.ReadIsoCode() + c.Version = e.readInt(6) + c.Created = e.readTime() + c.LastUpdated = e.readTime() + c.CmpId = e.readInt(12) + c.CmpVersion = e.readInt(12) + c.ConsentScreen = e.readInt(6) + c.ConsentLanguage = e.readIsoCode() + c.VendorListVersion = e.readInt(12) + c.TcfPolicyVersion = e.readInt(6) + c.IsServiceSpecific = e.readBool() + c.UseNonStandardStacks = e.readBool() + c.SpecialFeatureOptIns = e.readBitField(12) + c.PurposesConsent = e.readBitField(24) + c.PurposesLITransparency = e.readBitField(24) + c.PurposeOneTreatment = e.readBool() + c.PublisherCC = e.readIsoCode() - c.MaxVendorId = e.ReadInt(16) - c.IsRangeEncoding = e.ReadBool() + c.MaxVendorId = e.readInt(16) + c.IsRangeEncoding = e.readBool() if c.IsRangeEncoding { - c.NumEntries = e.ReadInt(12) - c.RangeEntries = e.ReadRangeEntries(uint(c.NumEntries)) + c.NumEntries = e.readInt(12) + c.RangeEntries = e.readRangeEntries(uint(c.NumEntries)) } else { - c.VendorsConsent = e.ReadBitField(uint(c.MaxVendorId)) + c.VendorsConsent = e.readBitField(uint(c.MaxVendorId)) } - c.MaxVendorIdLI = e.ReadInt(16) - c.IsRangeEncodingLI = e.ReadBool() + c.MaxVendorIdLI = e.readInt(16) + c.IsRangeEncodingLI = e.readBool() if c.IsRangeEncodingLI { - c.NumEntriesLI = e.ReadInt(12) - c.RangeEntriesLI = e.ReadRangeEntries(uint(c.NumEntriesLI)) + c.NumEntriesLI = e.readInt(12) + c.RangeEntriesLI = e.readRangeEntries(uint(c.NumEntriesLI)) } else { - c.VendorsLITransparency = e.ReadBitField(uint(c.MaxVendorIdLI)) + c.VendorsLITransparency = e.readBitField(uint(c.MaxVendorIdLI)) } - c.NumPubRestrictions = e.ReadInt(12) - c.PubRestrictions = e.ReadPubRestrictions(uint(c.NumPubRestrictions)) + c.NumPubRestrictions = e.readInt(12) + c.PubRestrictions = e.readPubRestrictions(uint(c.NumPubRestrictions)) return c, nil } @@ -118,17 +118,17 @@ func DecodeDisclosedVendors(s string) (d *DisclosedVendors, err error) { return nil, err } - var e = NewTCEncoder(b) + var e = newTCEncoder(b) d = &DisclosedVendors{} - d.SegmentType = e.ReadInt(3) - d.MaxVendorId = e.ReadInt(16) - d.IsRangeEncoding = e.ReadBool() + d.SegmentType = e.readInt(3) + d.MaxVendorId = e.readInt(16) + d.IsRangeEncoding = e.readBool() if d.IsRangeEncoding { - d.NumEntries = e.ReadInt(12) - d.RangeEntries = e.ReadRangeEntries(uint(d.NumEntries)) + d.NumEntries = e.readInt(12) + d.RangeEntries = e.readRangeEntries(uint(d.NumEntries)) } else { - d.DisclosedVendors = e.ReadBitField(uint(d.MaxVendorId)) + d.DisclosedVendors = e.readBitField(uint(d.MaxVendorId)) } if d.SegmentType != 1 { @@ -151,17 +151,17 @@ func DecodeAllowedVendors(s string) (a *AllowedVendors, err error) { return nil, err } - var e = NewTCEncoder(b) + var e = newTCEncoder(b) a = &AllowedVendors{} - a.SegmentType = e.ReadInt(3) - a.MaxVendorId = e.ReadInt(16) - a.IsRangeEncoding = e.ReadBool() + a.SegmentType = e.readInt(3) + a.MaxVendorId = e.readInt(16) + a.IsRangeEncoding = e.readBool() if a.IsRangeEncoding { - a.NumEntries = e.ReadInt(12) - a.RangeEntries = e.ReadRangeEntries(uint(a.NumEntries)) + a.NumEntries = e.readInt(12) + a.RangeEntries = e.readRangeEntries(uint(a.NumEntries)) } else { - a.AllowedVendors = e.ReadBitField(uint(a.MaxVendorId)) + a.AllowedVendors = e.readBitField(uint(a.MaxVendorId)) } if a.SegmentType != 2 { @@ -184,15 +184,15 @@ func DecodePubllisherTC(s string) (p *PublisherTC, err error) { return nil, err } - var e = NewTCEncoder(b) + var e = newTCEncoder(b) p = &PublisherTC{} - p.SegmentType = e.ReadInt(3) - p.PubPurposesConsent = e.ReadBitField(24) - p.PubPurposesLITransparency = e.ReadBitField(24) - p.NumCustomPurposes = e.ReadInt(6) - p.CustomPurposesConsent = e.ReadBitField(uint(p.NumCustomPurposes)) - p.CustomPurposesLITransparency = e.ReadBitField(uint(p.NumCustomPurposes)) + p.SegmentType = e.readInt(3) + p.PubPurposesConsent = e.readBitField(24) + p.PubPurposesLITransparency = e.readBitField(24) + p.NumCustomPurposes = e.readInt(6) + p.CustomPurposesConsent = e.readBitField(uint(p.NumCustomPurposes)) + p.CustomPurposesLITransparency = e.readBitField(uint(p.NumCustomPurposes)) if p.SegmentType != 3 { err = fmt.Errorf("allowed vendors segment type must be 3") diff --git a/encoder.go b/encoder.go deleted file mode 100644 index b3afe6f..0000000 --- a/encoder.go +++ /dev/null @@ -1,105 +0,0 @@ -package iabtcf - -import ( - "time" -) - -const ( - decisecondsPerSecond = 10 - nanosecondsPerDecisecond = int64(time.Millisecond * 100) -) - -type TCEncoder struct { - *Bits -} - -func NewTCEncoder(src []byte) *TCEncoder { - return &TCEncoder{NewBits(src)} -} - -func (r *TCEncoder) ReadTime() time.Time { - var ds = int64(r.ReadInt(36)) - return time.Unix(ds/decisecondsPerSecond, (ds%decisecondsPerSecond)*nanosecondsPerDecisecond).UTC() -} - -func (r *TCEncoder) WriteTime(v time.Time) { - r.WriteNumber(v.UnixNano()/nanosecondsPerDecisecond, 36) -} - -func (r *TCEncoder) ReadIsoCode() string { - var buf = make([]byte, 0, 2) - for i := uint(0); i < 2; i++ { - buf = append(buf, byte(r.ReadInt(6))+'A') - } - return string(buf) -} - -func (r *TCEncoder) WriteIsoCode(v string) { - for _, char := range v { - r.WriteInt(int(byte(char)-'A'), 6) - } -} - -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() { - m[int(i)+1] = true - } - } - return m -} - -func (r *TCEncoder) WriteRangeEntries(entries []*RangeEntry) { - for _, entry := range entries { - if entry.EndVendorID > entry.StartVendorID { - r.WriteBool(true) - r.WriteInt(entry.StartVendorID, 16) - r.WriteInt(entry.EndVendorID, 16) - } else { - r.WriteBool(false) - r.WriteInt(entry.StartVendorID, 16) - } - } -} - -func (r *TCEncoder) ReadRangeEntries(n uint) []*RangeEntry { - var ret = make([]*RangeEntry, 0, n) - for i := uint(0); i < n; i++ { - var isRange = r.ReadBool() - var start, end int - start = r.ReadInt(16) - if isRange { - end = r.ReadInt(16) - } else { - end = start - } - ret = append(ret, &RangeEntry{StartVendorID: start, EndVendorID: end}) - } - return ret -} - -func (r *TCEncoder) WritePubRestrictions(entries []*PubRestriction) { - for _, entry := range entries { - r.WriteInt(entry.PurposeId, 6) - r.WriteInt(entry.RestrictionType, 2) - r.WriteInt(len(entry.RangeEntries), 12) - r.WriteRangeEntries(entry.RangeEntries) - } -} - -func (r *TCEncoder) ReadPubRestrictions(n uint) []*PubRestriction { - var ret = make([]*PubRestriction, 0, n) - for i := uint(0); i < n; i++ { - var purposeId = r.ReadInt(6) - var restrictionType = r.ReadInt(2) - var numEntries = r.ReadInt(12) - var rangeEntries = r.ReadRangeEntries(uint(numEntries)) - ret = append(ret, &PubRestriction{PurposeId: purposeId, - RestrictionType: restrictionType, - NumEntries: numEntries, - RangeEntries: rangeEntries, - }) - } - return ret -} diff --git a/segment_allowed_vendors.go b/segment_allowed_vendors.go index 8fef18f..f8f70da 100644 --- a/segment_allowed_vendors.go +++ b/segment_allowed_vendors.go @@ -44,20 +44,20 @@ func (a *AllowedVendors) Encode() string { bitSize += a.MaxVendorId } - var e = NewTCEncoder(make([]byte, bitSize/8)) + var e = newTCEncoder(make([]byte, bitSize/8)) if bitSize%8 != 0 { - e = NewTCEncoder(make([]byte, bitSize/8+1)) + e = newTCEncoder(make([]byte, bitSize/8+1)) } - e.WriteInt(a.SegmentType, 3) - e.WriteInt(a.MaxVendorId, 16) - e.WriteBool(a.IsRangeEncoding) + e.writeInt(a.SegmentType, 3) + e.writeInt(a.MaxVendorId, 16) + e.writeBool(a.IsRangeEncoding) if a.IsRangeEncoding { - e.WriteInt(len(a.RangeEntries), 12) - e.WriteRangeEntries(a.RangeEntries) + e.writeInt(len(a.RangeEntries), 12) + e.writeRangeEntries(a.RangeEntries) } else { for i := 0; i < a.MaxVendorId; i++ { - e.WriteBool(a.IsVendorAllowed(i + 1)) + e.writeBool(a.IsVendorAllowed(i + 1)) } } diff --git a/segment_core_string.go b/segment_core_string.go index f9888f5..9afae5e 100644 --- a/segment_core_string.go +++ b/segment_core_string.go @@ -133,58 +133,58 @@ func (c *CoreString) Encode() string { bitSize += entriesSize } - var e = NewTCEncoder(make([]byte, bitSize/8)) + var e = newTCEncoder(make([]byte, bitSize/8)) if bitSize%8 != 0 { - e = NewTCEncoder(make([]byte, bitSize/8+1)) + e = newTCEncoder(make([]byte, bitSize/8+1)) } - e.WriteInt(c.Version, 6) - e.WriteTime(c.Created) - e.WriteTime(c.LastUpdated) - e.WriteInt(c.CmpId, 12) - e.WriteInt(c.CmpVersion, 12) - e.WriteInt(c.ConsentScreen, 6) - e.WriteIsoCode(c.ConsentLanguage) - e.WriteInt(c.VendorListVersion, 12) - e.WriteInt(c.TcfPolicyVersion, 6) - e.WriteBool(c.IsServiceSpecific) - e.WriteBool(c.UseNonStandardStacks) + e.writeInt(c.Version, 6) + e.writeTime(c.Created) + e.writeTime(c.LastUpdated) + e.writeInt(c.CmpId, 12) + e.writeInt(c.CmpVersion, 12) + e.writeInt(c.ConsentScreen, 6) + e.writeIsoCode(c.ConsentLanguage) + e.writeInt(c.VendorListVersion, 12) + e.writeInt(c.TcfPolicyVersion, 6) + e.writeBool(c.IsServiceSpecific) + e.writeBool(c.UseNonStandardStacks) for i := 0; i < 12; i++ { - e.WriteBool(c.IsSpecialFeatureAllowed(i + 1)) + e.writeBool(c.IsSpecialFeatureAllowed(i + 1)) } for i := 0; i < 24; i++ { - e.WriteBool(c.IsPurposeAllowed(i + 1)) + e.writeBool(c.IsPurposeAllowed(i + 1)) } for i := 0; i < 24; i++ { - e.WriteBool(c.IsPurposeLIAllowed(i + 1)) + e.writeBool(c.IsPurposeLIAllowed(i + 1)) } - e.WriteBool(c.PurposeOneTreatment) - e.WriteIsoCode(c.PublisherCC) + e.writeBool(c.PurposeOneTreatment) + e.writeIsoCode(c.PublisherCC) - e.WriteInt(c.MaxVendorId, 16) - e.WriteBool(c.IsRangeEncoding) + e.writeInt(c.MaxVendorId, 16) + e.writeBool(c.IsRangeEncoding) if c.IsRangeEncoding { - e.WriteInt(len(c.RangeEntries), 12) - e.WriteRangeEntries(c.RangeEntries) + e.writeInt(len(c.RangeEntries), 12) + e.writeRangeEntries(c.RangeEntries) } else { for i := 0; i < c.MaxVendorId; i++ { - e.WriteBool(c.IsVendorAllowed(i + 1)) + e.writeBool(c.IsVendorAllowed(i + 1)) } } - e.WriteInt(c.MaxVendorIdLI, 16) - e.WriteBool(c.IsRangeEncodingLI) + e.writeInt(c.MaxVendorIdLI, 16) + e.writeBool(c.IsRangeEncodingLI) if c.IsRangeEncodingLI { - e.WriteInt(len(c.RangeEntriesLI), 12) - e.WriteRangeEntries(c.RangeEntriesLI) + e.writeInt(len(c.RangeEntriesLI), 12) + e.writeRangeEntries(c.RangeEntriesLI) } else { for i := 0; i < c.MaxVendorIdLI; i++ { - e.WriteBool(c.IsVendorLIAllowed(i + 1)) + e.writeBool(c.IsVendorLIAllowed(i + 1)) } } - e.WriteInt(len(c.PubRestrictions), 12) - e.WritePubRestrictions(c.PubRestrictions) + e.writeInt(len(c.PubRestrictions), 12) + e.writePubRestrictions(c.PubRestrictions) return base64.RawURLEncoding.EncodeToString(e.bytes) } diff --git a/segment_disclosed_vendors.go b/segment_disclosed_vendors.go index 3d8d0f4..558f52c 100644 --- a/segment_disclosed_vendors.go +++ b/segment_disclosed_vendors.go @@ -44,20 +44,20 @@ func (d *DisclosedVendors) Encode() string { bitSize += d.MaxVendorId } - var e = NewTCEncoder(make([]byte, bitSize/8)) + var e = newTCEncoder(make([]byte, bitSize/8)) if bitSize%8 != 0 { - e = NewTCEncoder(make([]byte, bitSize/8+1)) + e = newTCEncoder(make([]byte, bitSize/8+1)) } - e.WriteInt(d.SegmentType, 3) - e.WriteInt(d.MaxVendorId, 16) - e.WriteBool(d.IsRangeEncoding) + e.writeInt(d.SegmentType, 3) + e.writeInt(d.MaxVendorId, 16) + e.writeBool(d.IsRangeEncoding) if d.IsRangeEncoding { - e.WriteInt(len(d.RangeEntries), 12) - e.WriteRangeEntries(d.RangeEntries) + e.writeInt(len(d.RangeEntries), 12) + e.writeRangeEntries(d.RangeEntries) } else { for i := 0; i < d.MaxVendorId; i++ { - e.WriteBool(d.IsVendorDisclosed(i + 1)) + e.writeBool(d.IsVendorDisclosed(i + 1)) } } diff --git a/segment_publisher_tc.go b/segment_publisher_tc.go index a42a161..1f6d9c7 100644 --- a/segment_publisher_tc.go +++ b/segment_publisher_tc.go @@ -30,24 +30,24 @@ func (p *PublisherTC) IsCustomPurposeLIAllowed(id int) bool { func (p *PublisherTC) Encode() string { bitSize := 57 + (p.NumCustomPurposes * 2) - var e = NewTCEncoder(make([]byte, bitSize/8)) + var e = newTCEncoder(make([]byte, bitSize/8)) if bitSize%8 != 0 { - e = NewTCEncoder(make([]byte, bitSize/8+1)) + e = newTCEncoder(make([]byte, bitSize/8+1)) } - e.WriteInt(p.SegmentType, 3) + e.writeInt(p.SegmentType, 3) for i := 0; i < 24; i++ { - e.WriteBool(p.IsPurposeAllowed(i + 1)) + e.writeBool(p.IsPurposeAllowed(i + 1)) } for i := 0; i < 24; i++ { - e.WriteBool(p.IsPurposeLIAllowed(i + 1)) + e.writeBool(p.IsPurposeLIAllowed(i + 1)) } - e.WriteInt(p.NumCustomPurposes, 6) + e.writeInt(p.NumCustomPurposes, 6) for i := 0; i < p.NumCustomPurposes; i++ { - e.WriteBool(p.IsCustomPurposeAllowed(i + 1)) + e.writeBool(p.IsCustomPurposeAllowed(i + 1)) } for i := 0; i < p.NumCustomPurposes; i++ { - e.WriteBool(p.IsCustomPurposeLIAllowed(i + 1)) + e.writeBool(p.IsCustomPurposeLIAllowed(i + 1)) } return base64.RawURLEncoding.EncodeToString(e.bytes) diff --git a/tcencoder.go b/tcencoder.go new file mode 100644 index 0000000..df54101 --- /dev/null +++ b/tcencoder.go @@ -0,0 +1,105 @@ +package iabtcf + +import ( + "time" +) + +const ( + decisecondsPerSecond = 10 + nanosecondsPerDecisecond = int64(time.Millisecond * 100) +) + +type TCEncoder struct { + *Bits +} + +func newTCEncoder(src []byte) *TCEncoder { + return &TCEncoder{newBits(src)} +} + +func (r *TCEncoder) readTime() time.Time { + var ds = int64(r.readInt(36)) + return time.Unix(ds/decisecondsPerSecond, (ds%decisecondsPerSecond)*nanosecondsPerDecisecond).UTC() +} + +func (r *TCEncoder) writeTime(v time.Time) { + r.writeNumber(v.UnixNano()/nanosecondsPerDecisecond, 36) +} + +func (r *TCEncoder) readIsoCode() string { + var buf = make([]byte, 0, 2) + for i := uint(0); i < 2; i++ { + buf = append(buf, byte(r.readInt(6))+'A') + } + return string(buf) +} + +func (r *TCEncoder) writeIsoCode(v string) { + for _, char := range v { + r.writeInt(int(byte(char)-'A'), 6) + } +} + +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() { + m[int(i)+1] = true + } + } + return m +} + +func (r *TCEncoder) writeRangeEntries(entries []*RangeEntry) { + for _, entry := range entries { + if entry.EndVendorID > entry.StartVendorID { + r.writeBool(true) + r.writeInt(entry.StartVendorID, 16) + r.writeInt(entry.EndVendorID, 16) + } else { + r.writeBool(false) + r.writeInt(entry.StartVendorID, 16) + } + } +} + +func (r *TCEncoder) readRangeEntries(n uint) []*RangeEntry { + var ret = make([]*RangeEntry, 0, n) + for i := uint(0); i < n; i++ { + var isRange = r.readBool() + var start, end int + start = r.readInt(16) + if isRange { + end = r.readInt(16) + } else { + end = start + } + ret = append(ret, &RangeEntry{StartVendorID: start, EndVendorID: end}) + } + return ret +} + +func (r *TCEncoder) writePubRestrictions(entries []*PubRestriction) { + for _, entry := range entries { + r.writeInt(entry.PurposeId, 6) + r.writeInt(entry.RestrictionType, 2) + r.writeInt(len(entry.RangeEntries), 12) + r.writeRangeEntries(entry.RangeEntries) + } +} + +func (r *TCEncoder) readPubRestrictions(n uint) []*PubRestriction { + var ret = make([]*PubRestriction, 0, n) + for i := uint(0); i < n; i++ { + var purposeId = r.readInt(6) + var restrictionType = r.readInt(2) + var numEntries = r.readInt(12) + var rangeEntries = r.readRangeEntries(uint(numEntries)) + ret = append(ret, &PubRestriction{PurposeId: purposeId, + RestrictionType: restrictionType, + NumEntries: numEntries, + RangeEntries: rangeEntries, + }) + } + return ret +}