#pragma once #include "routing/city_roads.hpp" #include "coding/succinct_mapper.hpp" #include "coding/writer.hpp" #include "base/assert.hpp" #include "base/logging.hpp" #include #include #include #include #include "3party/succinct/elias_fano.hpp" namespace routing { struct CityRoadsHeader { template void Serialize(Sink & sink) const { WriteToSink(sink, m_version); WriteToSink(sink, m_endianness); WriteToSink(sink, m_dataSize); } template void Deserialize(Source & src) { m_version = ReadPrimitiveFromSource(src); m_endianness = ReadPrimitiveFromSource(src); m_dataSize = ReadPrimitiveFromSource(src); } uint16_t m_version = 0; // Field |m_endianness| is reserved for endianness of the section. uint16_t m_endianness = 0; uint32_t m_dataSize = 0; }; static_assert(sizeof(CityRoadsHeader) == 8, "Wrong header size of city_roads section."); class CityRoadsSerializer { public: CityRoadsSerializer() = delete; template static void Serialize(Sink & sink, std::vector && cityRoadFeatureIds) { CityRoadsHeader header; auto const startOffset = sink.Pos(); header.Serialize(sink); std::sort(cityRoadFeatureIds.begin(), cityRoadFeatureIds.end()); CHECK(adjacent_find(cityRoadFeatureIds.cbegin(), cityRoadFeatureIds.cend()) == cityRoadFeatureIds.cend(), ("City road feature ids should be unique.")); succinct::elias_fano::elias_fano_builder builder(cityRoadFeatureIds.back() + 1, cityRoadFeatureIds.size()); for (auto fid : cityRoadFeatureIds) builder.push_back(fid); coding::FreezeVisitor visitor(sink); succinct::elias_fano(&builder).map(visitor); auto const endOffset = sink.Pos(); header.m_dataSize = static_cast(endOffset - startOffset - sizeof(CityRoadsHeader)); sink.Seek(startOffset); header.Serialize(sink); sink.Seek(endOffset); LOG(LINFO, ("Serialized", cityRoadFeatureIds.size(), "road feature ids in cities. Size:", endOffset - startOffset, "bytes.")); } template static void Deserialize(Source & src, std::unique_ptr & cityRoadsRegion, succinct::elias_fano & cityRoads) { CityRoadsHeader header; header.Deserialize(src); CHECK_EQUAL(header.m_version, 0, ()); std::vector data(header.m_dataSize); src.Read(data.data(), data.size()); cityRoadsRegion = std::make_unique(std::move(data)); coding::MapVisitor visitor(cityRoadsRegion->ImmutableData()); cityRoads.map(visitor); } }; } // namespace routing