Repo created
This commit is contained in:
parent
4af19165ec
commit
68073add76
12458 changed files with 12350765 additions and 2 deletions
439
libs/transit/transit_serdes.hpp
Normal file
439
libs/transit/transit_serdes.hpp
Normal file
|
|
@ -0,0 +1,439 @@
|
|||
#pragma once
|
||||
|
||||
#include "transit/experimental/transit_types_experimental.hpp"
|
||||
#include "transit/transit_types.hpp"
|
||||
|
||||
#include "coding/geometry_coding.hpp"
|
||||
#include "coding/point_coding.hpp"
|
||||
#include "coding/read_write_utils.hpp"
|
||||
#include "coding/reader.hpp"
|
||||
#include "coding/varint.hpp"
|
||||
#include "coding/write_to_sink.hpp"
|
||||
|
||||
#include "geometry/point2d.hpp"
|
||||
|
||||
#include "base/assert.hpp"
|
||||
#include "base/newtype.hpp"
|
||||
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "3party/opening_hours/opening_hours.hpp"
|
||||
|
||||
namespace routing
|
||||
{
|
||||
namespace transit
|
||||
{
|
||||
// Note. For the time being double in transit section is used only for saving weight of edges (in seconds).
|
||||
// Let us assume that it takes less than 10^7 seconds (115 days) to get from one station to a neighboring one.
|
||||
double constexpr kMinDoubleAtTransitSection = kInvalidWeight;
|
||||
double constexpr kMaxDoubleAtTransitSection = 10000000.0;
|
||||
uint8_t constexpr kDoubleBits = 32;
|
||||
|
||||
template <typename Sink>
|
||||
class Serializer
|
||||
{
|
||||
public:
|
||||
explicit Serializer(Sink & sink) : m_sink(sink) {}
|
||||
|
||||
template <typename T>
|
||||
std::enable_if_t<(std::is_integral<T>::value || std::is_enum<T>::value) && !std::is_same<T, uint32_t>::value &&
|
||||
!std::is_same<T, uint64_t>::value && !std::is_same<T, int32_t>::value &&
|
||||
!std::is_same<T, int64_t>::value>
|
||||
operator()(T const & t, char const * /* name */ = nullptr)
|
||||
{
|
||||
WriteToSink(m_sink, t);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_same<T, uint32_t>::value || std::is_same<T, uint64_t>::value> operator()(
|
||||
T t, char const * /* name */ = nullptr) const
|
||||
{
|
||||
WriteVarUint(m_sink, t);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_same<T, int32_t>::value || std::is_same<T, int64_t>::value> operator()(
|
||||
T t, char const * name = nullptr) const
|
||||
{
|
||||
WriteVarInt(m_sink, t);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_same<T, double>::value || std::is_same<T, float>::value> operator()(
|
||||
T d, char const * name = nullptr)
|
||||
{
|
||||
CHECK_GREATER_OR_EQUAL(d, kMinDoubleAtTransitSection, ());
|
||||
CHECK_LESS_OR_EQUAL(d, kMaxDoubleAtTransitSection, ());
|
||||
(*this)(DoubleToUint32(d, kMinDoubleAtTransitSection, kMaxDoubleAtTransitSection, kDoubleBits), name);
|
||||
}
|
||||
|
||||
void operator()(std::string const & s, char const * /* name */ = nullptr) { rw::Write(m_sink, s); }
|
||||
|
||||
void operator()(m2::PointD const & p, char const * /* name */ = nullptr)
|
||||
{
|
||||
WriteVarInt(m_sink, PointToInt64Obsolete(p, kPointCoordBits));
|
||||
}
|
||||
|
||||
void operator()(std::vector<m2::PointD> const & vs, char const * /* name */ = nullptr)
|
||||
{
|
||||
WriteVarUint(m_sink, static_cast<uint64_t>(vs.size()));
|
||||
m2::PointU lastEncodedPoint(0, 0);
|
||||
for (auto const & p : vs)
|
||||
{
|
||||
m2::PointU const pointU = PointDToPointU(p, kPointCoordBits);
|
||||
WriteVarUint(m_sink, coding::EncodePointDeltaAsUint(pointU, lastEncodedPoint));
|
||||
lastEncodedPoint = pointU;
|
||||
}
|
||||
}
|
||||
|
||||
void operator()(Edge::WrappedEdgeId const & id, char const * /* name */ = nullptr)
|
||||
{
|
||||
CHECK_GREATER_OR_EQUAL(id.Get(), m_lastWrappedEdgeId.Get(), ());
|
||||
WriteVarUint(m_sink, static_cast<uint64_t>(id.Get() - m_lastWrappedEdgeId.Get()));
|
||||
m_lastWrappedEdgeId = id;
|
||||
}
|
||||
|
||||
void operator()(Stop::WrappedStopId const & id, char const * /* name */ = nullptr)
|
||||
{
|
||||
CHECK_GREATER_OR_EQUAL(id.Get(), m_lastWrappedStopId.Get(), ());
|
||||
WriteVarUint(m_sink, static_cast<uint64_t>(id.Get() - m_lastWrappedStopId.Get()));
|
||||
m_lastWrappedStopId = id;
|
||||
}
|
||||
|
||||
void operator()(FeatureIdentifiers const & id, char const * name = nullptr)
|
||||
{
|
||||
if (id.IsSerializeFeatureIdOnly())
|
||||
(*this)(id.GetFeatureId(), name);
|
||||
else
|
||||
id.Visit(*this);
|
||||
}
|
||||
|
||||
void operator()(::transit::experimental::IdBundle const & id, char const * name = nullptr)
|
||||
{
|
||||
if (id.SerializeFeatureIdOnly())
|
||||
(*this)(id.GetFeatureId(), name);
|
||||
else
|
||||
id.Visit(*this);
|
||||
}
|
||||
|
||||
void operator()(osmoh::OpeningHours const & oh, char const * /* name */ = nullptr) { (*this)(ToString(oh)); }
|
||||
|
||||
void operator()(Edge const & e, char const * /* name */ = nullptr)
|
||||
{
|
||||
(*this)(e.m_stop1Id);
|
||||
(*this)(e.m_stop2Id);
|
||||
(*this)(e.m_weight);
|
||||
(*this)(e.m_lineId);
|
||||
// Note. |Edge::m_flags| is not filled fully after deserialization from json.
|
||||
// So it's necessary to fill it here.
|
||||
EdgeFlags const flags = GetEdgeFlags(e.GetTransfer(), e.GetStop1Id(), e.GetStop2Id(), e.GetShapeIds());
|
||||
(*this)(flags);
|
||||
|
||||
if (flags.m_isShapeIdsEmpty || flags.m_isShapeIdsSame || flags.m_isShapeIdsReversed)
|
||||
return;
|
||||
|
||||
if (flags.m_isShapeIdsSingle)
|
||||
{
|
||||
CHECK_EQUAL(e.GetShapeIds().size(), 1, ());
|
||||
(*this)(e.GetShapeIds()[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
(*this)(e.GetShapeIds());
|
||||
}
|
||||
|
||||
void operator()(EdgeFlags const & f, char const * /* name */ = nullptr) { (*this)(f.GetFlags()); }
|
||||
|
||||
template <typename T>
|
||||
void operator()(std::vector<T> const & vs, char const * /* name */ = nullptr)
|
||||
{
|
||||
WriteVarUint(m_sink, static_cast<uint64_t>(vs.size()));
|
||||
for (auto const & v : vs)
|
||||
(*this)(v);
|
||||
}
|
||||
|
||||
template <class K, class V, class H>
|
||||
void operator()(std::unordered_map<K, V, H> const & container, char const * /* name */ = nullptr)
|
||||
{
|
||||
WriteVarUint(m_sink, static_cast<uint64_t>(container.size()));
|
||||
for (auto const & [key, val] : container)
|
||||
{
|
||||
(*this)(key);
|
||||
(*this)(val);
|
||||
}
|
||||
}
|
||||
|
||||
template <class K, class V, class H>
|
||||
void operator()(std::map<K, V, H> const & container, char const * /* name */ = nullptr)
|
||||
{
|
||||
WriteVarUint(m_sink, static_cast<uint64_t>(container.size()));
|
||||
for (auto const & [key, val] : container)
|
||||
{
|
||||
(*this)(key);
|
||||
(*this)(val);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_class<T>::value> operator()(T const & t, char const * /* name */ = nullptr)
|
||||
{
|
||||
t.Visit(*this);
|
||||
}
|
||||
|
||||
private:
|
||||
Sink & m_sink;
|
||||
Edge::WrappedEdgeId m_lastWrappedEdgeId = {};
|
||||
Stop::WrappedStopId m_lastWrappedStopId = {};
|
||||
};
|
||||
|
||||
template <typename Source>
|
||||
class Deserializer
|
||||
{
|
||||
public:
|
||||
explicit Deserializer(Source & source) : m_source(source) {}
|
||||
|
||||
template <typename T>
|
||||
std::enable_if_t<(std::is_integral<T>::value || std::is_enum<T>::value) && !std::is_same<T, uint32_t>::value &&
|
||||
!std::is_same<T, uint64_t>::value && !std::is_same<T, int32_t>::value &&
|
||||
!std::is_same<T, int64_t>::value>
|
||||
operator()(T & t, char const * name = nullptr)
|
||||
{
|
||||
ReadPrimitiveFromSource(m_source, t);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_same<T, uint32_t>::value || std::is_same<T, uint64_t>::value> operator()(
|
||||
T & t, char const * name = nullptr)
|
||||
{
|
||||
t = ReadVarUint<T>(m_source);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_same<T, int32_t>::value || std::is_same<T, int64_t>::value> operator()(
|
||||
T & t, char const * name = nullptr)
|
||||
{
|
||||
t = ReadVarInt<T>(m_source);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_same<T, double>::value || std::is_same<T, float>::value> operator()(
|
||||
T & d, char const * name = nullptr)
|
||||
{
|
||||
uint32_t ui;
|
||||
(*this)(ui, name);
|
||||
d = Uint32ToDouble(ui, kMinDoubleAtTransitSection, kMaxDoubleAtTransitSection, kDoubleBits);
|
||||
}
|
||||
|
||||
void operator()(std::string & s, char const * /* name */ = nullptr) { rw::Read(m_source, s); }
|
||||
|
||||
void operator()(m2::PointD & p, char const * /* name */ = nullptr)
|
||||
{
|
||||
p = Int64ToPointObsolete(ReadVarInt<int64_t>(m_source), kPointCoordBits);
|
||||
}
|
||||
|
||||
void operator()(Edge::WrappedEdgeId & id, char const * /* name */ = nullptr)
|
||||
{
|
||||
id = m_lastWrappedEdgeId + Edge::WrappedEdgeId(ReadVarUint<uint64_t>(m_source));
|
||||
m_lastWrappedEdgeId = id;
|
||||
}
|
||||
|
||||
void operator()(Stop::WrappedStopId & id, char const * /* name */ = nullptr)
|
||||
{
|
||||
id = m_lastWrappedStopId + Stop::WrappedStopId(ReadVarUint<uint64_t>(m_source));
|
||||
m_lastWrappedStopId = id;
|
||||
}
|
||||
|
||||
void operator()(FeatureIdentifiers & id, char const * name = nullptr)
|
||||
{
|
||||
if (id.IsSerializeFeatureIdOnly())
|
||||
{
|
||||
FeatureId featureId;
|
||||
operator()(featureId, name);
|
||||
id.SetOsmId(kInvalidOsmId);
|
||||
id.SetFeatureId(featureId);
|
||||
return;
|
||||
}
|
||||
|
||||
id.Visit(*this);
|
||||
}
|
||||
|
||||
void operator()(::transit::experimental::IdBundle & idBundle, char const * name = nullptr)
|
||||
{
|
||||
if (idBundle.SerializeFeatureIdOnly())
|
||||
{
|
||||
FeatureId featureId;
|
||||
operator()(featureId, name);
|
||||
idBundle.SetFeatureId(featureId);
|
||||
idBundle.SetOsmId(kInvalidOsmId);
|
||||
return;
|
||||
}
|
||||
|
||||
idBundle.Visit(*this);
|
||||
}
|
||||
|
||||
void operator()(Edge & e, char const * name = nullptr)
|
||||
{
|
||||
(*this)(e.m_stop1Id);
|
||||
(*this)(e.m_stop2Id);
|
||||
(*this)(e.m_weight);
|
||||
(*this)(e.m_lineId);
|
||||
(*this)(e.m_flags);
|
||||
|
||||
e.m_shapeIds.clear();
|
||||
if (e.m_flags.m_isShapeIdsEmpty)
|
||||
return;
|
||||
|
||||
if (e.m_flags.m_isShapeIdsSame)
|
||||
{
|
||||
e.m_shapeIds.emplace_back(e.GetStop1Id(), e.GetStop2Id());
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.m_flags.m_isShapeIdsReversed)
|
||||
{
|
||||
e.m_shapeIds.emplace_back(e.GetStop2Id(), e.GetStop1Id());
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.m_flags.m_isShapeIdsSingle)
|
||||
{
|
||||
e.m_shapeIds.resize(1 /* single shape id */);
|
||||
(*this)(e.m_shapeIds.back());
|
||||
return;
|
||||
}
|
||||
|
||||
(*this)(e.m_shapeIds);
|
||||
}
|
||||
|
||||
void operator()(EdgeFlags & f, char const * /* name */ = nullptr)
|
||||
{
|
||||
uint8_t flags = 0;
|
||||
(*this)(flags);
|
||||
f.SetFlags(flags);
|
||||
}
|
||||
|
||||
void operator()(std::vector<m2::PointD> & vs, char const * /* name */ = nullptr)
|
||||
{
|
||||
auto const size = ReadVarUint<uint64_t>(m_source);
|
||||
m2::PointU lastDecodedPoint(0, 0);
|
||||
vs.resize(size);
|
||||
for (auto & p : vs)
|
||||
{
|
||||
m2::PointU const pointU = coding::DecodePointDeltaFromUint(ReadVarUint<uint64_t>(m_source), lastDecodedPoint);
|
||||
p = PointUToPointD(pointU, kPointCoordBits);
|
||||
lastDecodedPoint = pointU;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void operator()(std::vector<T> & vs, char const * /* name */ = nullptr)
|
||||
{
|
||||
auto const size = ReadVarUint<uint64_t>(m_source);
|
||||
vs.resize(size);
|
||||
for (auto & v : vs)
|
||||
(*this)(v);
|
||||
}
|
||||
|
||||
template <class K, class V, class H>
|
||||
void operator()(std::unordered_map<K, V, H> & container, char const * /* name */ = nullptr)
|
||||
{
|
||||
auto const size = static_cast<size_t>(ReadVarUint<uint64_t>(m_source));
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
K key;
|
||||
V val;
|
||||
|
||||
(*this)(key);
|
||||
(*this)(val);
|
||||
|
||||
container.emplace(key, val);
|
||||
}
|
||||
}
|
||||
|
||||
template <class K, class V, class H>
|
||||
void operator()(std::map<K, V, H> & container, char const * /* name */ = nullptr)
|
||||
{
|
||||
auto const size = static_cast<size_t>(ReadVarUint<uint64_t>(m_source));
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
K key;
|
||||
V val;
|
||||
|
||||
(*this)(key);
|
||||
(*this)(val);
|
||||
|
||||
container.emplace(key, val);
|
||||
}
|
||||
}
|
||||
|
||||
void operator()(osmoh::OpeningHours & oh, char const * /* name */ = nullptr)
|
||||
{
|
||||
std::string ohStr;
|
||||
(*this)(ohStr);
|
||||
oh = osmoh::OpeningHours(ohStr);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_class<T>::value> operator()(T & t, char const * /* name */ = nullptr)
|
||||
{
|
||||
t.Visit(*this);
|
||||
}
|
||||
|
||||
private:
|
||||
Source & m_source;
|
||||
Edge::WrappedEdgeId m_lastWrappedEdgeId = {};
|
||||
Stop::WrappedStopId m_lastWrappedStopId = {};
|
||||
};
|
||||
|
||||
template <typename Sink>
|
||||
class FixedSizeSerializer
|
||||
{
|
||||
public:
|
||||
explicit FixedSizeSerializer(Sink & sink) : m_sink(sink) {}
|
||||
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_integral<T>::value || std::is_enum<T>::value, void> operator()(
|
||||
T const & t, char const * /* name */ = nullptr)
|
||||
{
|
||||
WriteToSink(m_sink, t);
|
||||
}
|
||||
|
||||
void operator()(TransitHeader const & header) { header.Visit(*this); }
|
||||
|
||||
void operator()(::transit::experimental::TransitHeader const & headerExperimental)
|
||||
{
|
||||
headerExperimental.Visit(*this);
|
||||
}
|
||||
|
||||
private:
|
||||
Sink & m_sink;
|
||||
};
|
||||
|
||||
template <typename Source>
|
||||
class FixedSizeDeserializer
|
||||
{
|
||||
public:
|
||||
explicit FixedSizeDeserializer(Source & source) : m_source(source) {}
|
||||
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_integral<T>::value || std::is_enum<T>::value, void> operator()(T & t,
|
||||
char const * name = nullptr)
|
||||
{
|
||||
ReadPrimitiveFromSource(m_source, t);
|
||||
}
|
||||
|
||||
void operator()(TransitHeader & header) { header.Visit(*this); }
|
||||
|
||||
void operator()(::transit::experimental::TransitHeader & headerExperimental) { headerExperimental.Visit(*this); }
|
||||
|
||||
private:
|
||||
Source & m_source;
|
||||
};
|
||||
} // namespace transit
|
||||
} // namespace routing
|
||||
Loading…
Add table
Add a link
Reference in a new issue