diff options
Diffstat (limited to 'local_ads/campaign_serialization.cpp')
-rw-r--r-- | local_ads/campaign_serialization.cpp | 110 |
1 files changed, 79 insertions, 31 deletions
diff --git a/local_ads/campaign_serialization.cpp b/local_ads/campaign_serialization.cpp index 4b64e1a87d..7c20bf7042 100644 --- a/local_ads/campaign_serialization.cpp +++ b/local_ads/campaign_serialization.cpp @@ -13,8 +13,9 @@ namespace { using namespace local_ads; -auto const kHalfByteShift = 0x4; -auto const kLowerMask = 0xF; +auto const kHalfByteShift = CHAR_BIT / 2; +auto const kHalfByteMaxValue = 15; +auto const kLowerMask = 0x0F; auto const kUpperMask = 0xF0; auto const kMinZoomLevel = 10; auto const kMaxZoomLevel = 17; @@ -61,10 +62,27 @@ std::vector<Integral> ReadData(ByteStream & s, size_t chunksNumber) return result; } + +std::vector<uint8_t> SerializeV1(std::vector<Campaign> const & campaigns) +{ + std::vector<uint8_t> buff; + PushBackByteSink<decltype(buff)> dst(buff); + Write(dst, Version::V1); + Write(dst, campaigns.size()); + for (auto const & c : campaigns) + WriteVarUint(dst, c.m_featureId); + for (auto const & c : campaigns) + WriteVarUint(dst, c.m_iconId); + for (auto const & c : campaigns) + Write(dst, c.m_daysBeforeExpired); + + return buff; +} + std::vector<Campaign> DeserializeV1(std::vector<uint8_t> const & bytes) { ArrayByteSource src(bytes.data()); - CHECK_EQUAL(Read<Version>(src), Version::v1, ()); + CHECK_EQUAL(Read<Version>(src), Version::V1, ()); auto const chunksNumber = Read<uint64_t>(src); auto const featureIds = ReadData<uint32_t>(src, chunksNumber); @@ -88,10 +106,52 @@ uint8_t ZoomIndex(uint8_t zoomValue) { return zoomValue - kMinZoomLevel; } uint8_t ZoomValue(uint8_t zoomIndex) { return zoomIndex + kMinZoomLevel; } +uint8_t PackZoomAndPriority(uint8_t minZoomLevel, uint8_t priority) +{ + ASSERT_GREATER_OR_EQUAL(minZoomLevel, kMinZoomLevel, ("Unsupported zoom level")); + ASSERT_LESS_OR_EQUAL(minZoomLevel, kMaxZoomLevel, ("Unsupported zoom level")); + ASSERT_LESS_OR_EQUAL(priority, kMaxPriority, ("Unsupported priority value")); + + auto const zoomIndex = ZoomIndex(minZoomLevel); + ASSERT_LESS_OR_EQUAL(zoomIndex, kHalfByteMaxValue, ()); + ASSERT_LESS_OR_EQUAL(priority, kHalfByteMaxValue, ()); + + // Pack zoom and priority into single byte. + return (zoomIndex & kLowerMask) | ((priority << kHalfByteShift) & kUpperMask); +} + +uint8_t UnpackZoom(uint8_t src) +{ + return ZoomValue(src & kLowerMask); +} + +uint8_t UnpackPriority(uint8_t src) +{ + return (src >> kHalfByteShift) & kLowerMask; +} + +std::vector<uint8_t> SerializeV2(std::vector<Campaign> const & campaigns) +{ + std::vector<uint8_t> buff; + PushBackByteSink<decltype(buff)> dst(buff); + Write(dst, Version::V2); + Write(dst, campaigns.size()); + for (auto const & c : campaigns) + WriteVarUint(dst, c.m_featureId); + for (auto const & c : campaigns) + WriteVarUint(dst, c.m_iconId); + for (auto const & c : campaigns) + Write(dst, c.m_daysBeforeExpired); + for (auto const & c : campaigns) + Write(dst, PackZoomAndPriority(c.m_minZoomLevel, c.m_priority)); + + return buff; +} + std::vector<Campaign> DeserializeV2(std::vector<uint8_t> const & bytes) { ArrayByteSource src(bytes.data()); - CHECK_EQUAL(Read<Version>(src), Version::v2, ()); + CHECK_EQUAL(Read<Version>(src), Version::V2, ()); auto const chunksNumber = Read<uint64_t>(src); auto const featureIds = ReadData<uint32_t>(src, chunksNumber); @@ -109,8 +169,8 @@ std::vector<Campaign> DeserializeV2(std::vector<uint8_t> const & bytes) for (size_t i = 0; i < chunksNumber; ++i) { campaigns.emplace_back(featureIds[i], icons[i], expirations[i], - ZoomValue(zoomAndPriority[i] & kLowerMask), - (zoomAndPriority[i] >> kHalfByteShift) & kLowerMask); + UnpackZoom(zoomAndPriority[i]), + UnpackPriority(zoomAndPriority[i])); ASSERT_GREATER_OR_EQUAL(campaigns.back().m_minZoomLevel, kMinZoomLevel, ("Unsupported zoom level")); @@ -126,32 +186,19 @@ namespace local_ads { std::vector<uint8_t> Serialize(std::vector<Campaign> const & campaigns, Version const version) { - std::vector<uint8_t> buff; - PushBackByteSink<decltype(buff)> dst(buff); - Write(dst, version); - Write(dst, campaigns.size()); - for (auto const & c : campaigns) - WriteVarUint(dst, c.m_featureId); - for (auto const & c : campaigns) - WriteVarUint(dst, c.m_iconId); - for (auto const & c : campaigns) - Write(dst, c.m_daysBeforeExpired); - for (auto const & c : campaigns) + switch (version) { - ASSERT_GREATER_OR_EQUAL(c.m_minZoomLevel, kMinZoomLevel, ("Unsupported zoom level")); - ASSERT_LESS_OR_EQUAL(c.m_minZoomLevel, kMaxZoomLevel, ("Unsupported zoom level")); - ASSERT_LESS_OR_EQUAL(c.m_priority, kMaxPriority, ("Unsupported priority value")); - - Write(dst, static_cast<uint8_t>((ZoomIndex(c.m_minZoomLevel) & kLowerMask) | - ((c.m_priority << kHalfByteShift) & kUpperMask))); + case Version::V1: return SerializeV1(campaigns); + case Version::V2: return SerializeV2(campaigns); + default: ASSERT(false, ("Unknown version")); } - return buff; + return {}; } std::vector<uint8_t> Serialize(std::vector<Campaign> const & campaigns) { - return Serialize(campaigns, Version::latest); + return Serialize(campaigns, Version::Latest); } std::vector<Campaign> Deserialize(std::vector<uint8_t> const & bytes) @@ -161,9 +208,9 @@ std::vector<Campaign> Deserialize(std::vector<uint8_t> const & bytes) switch (version) { - case Version::v1: return DeserializeV1(bytes); - case Version::v2: return DeserializeV2(bytes); - default: ASSERT(false, ("Unknown version type")); + case Version::V1: return DeserializeV1(bytes); + case Version::V2: return DeserializeV2(bytes); + default: ASSERT(false, ("Unknown version")); } return {}; @@ -175,9 +222,10 @@ std::string DebugPrint(local_ads::Version version) switch (version) { - case Version::unknown: return "Unknown"; - case Version::v1: return "Version 1"; - case Version::v2: return "Version 2"; + case Version::Unknown: return "Unknown"; + case Version::V1: return "Version 1"; + case Version::V2: return "Version 2"; + default: ASSERT(false, ("Unknown version")); } } } // namespace local_ads |