[routing] The simplest version of MaxspeedSerializer and tests on it.

This commit is contained in:
Vladimir Byko-Ianko 2018-10-25 17:57:50 +03:00 committed by mpimenov
parent f17783b6e4
commit f9d11319ab
4 changed files with 258 additions and 12 deletions

View file

@ -9,16 +9,16 @@ namespace routing
using namespace measurement_utils;
// SpeedInUnits ------------------------------------------------------------------------------------
bool SpeedInUnits::operator==(SpeedInUnits const & s) const
bool SpeedInUnits::operator==(SpeedInUnits const & rhs) const
{
return m_speed == s.m_speed && m_units == s.m_units;
return m_speed == rhs.m_speed && m_units == rhs.m_units;
}
bool SpeedInUnits::operator<(SpeedInUnits const & s) const
bool SpeedInUnits::operator<(SpeedInUnits const & rhs) const
{
if (m_speed != s.m_speed)
return m_speed < s.m_speed;
return m_units < s.m_units;
if (m_speed != rhs.m_speed)
return m_speed < rhs.m_speed;
return m_units < rhs.m_units;
}
bool SpeedInUnits::IsNumeric() const
@ -26,6 +26,18 @@ bool SpeedInUnits::IsNumeric() const
return m_speed != kNoneMaxSpeed && m_speed != kWalkMaxSpeed && m_speed != kInvalidSpeed;
}
// FeatureMaxspeed ---------------------------------------------------------------------------------
FeatureMaxspeed::FeatureMaxspeed(uint32_t fid, SpeedInUnits const & forward,
SpeedInUnits const & backward /* = SpeedInUnits() */)
: m_featureId(fid), m_forward(forward), m_backward(backward)
{
}
bool FeatureMaxspeed::operator==(FeatureMaxspeed const & rhs) const
{
return m_featureId == rhs.m_featureId && m_forward == rhs.m_forward && m_backward == rhs.m_backward;
}
// MaxspeedConverter -------------------------------------------------------------------------------
MaxspeedConverter::MaxspeedConverter()
{
@ -205,6 +217,14 @@ MaxspeedConverter const & GetMaxspeedConverter()
return inst;
}
std::string DebugPrint(Maxspeed maxspeed)
{
std::ostringstream oss;
oss << "Maxspeed:" << static_cast<int>(maxspeed) << " Decoded:"
<< DebugPrint(GetMaxspeedConverter().MacroToSpeed(maxspeed));
return oss.str();
}
std::string DebugPrint(SpeedInUnits const & speed)
{
std::ostringstream oss;
@ -213,11 +233,12 @@ std::string DebugPrint(SpeedInUnits const & speed)
return oss.str();
}
std::string DebugPrint(Maxspeed maxspeed)
std::string DebugPrint(FeatureMaxspeed const & featureMaxspeed)
{
std::ostringstream oss;
oss << "Maxspeed:" << static_cast<int>(maxspeed) << " Decoded:"
<< DebugPrint(GetMaxspeedConverter().MacroToSpeed(maxspeed));
oss << "FeatureMaxspeed [ m_featureId:" << featureMaxspeed.GetFeatureId()
<< " m_forward:" << DebugPrint(featureMaxspeed.GetForward())
<< " m_backward:" << DebugPrint(featureMaxspeed.GetBackward()) << " ]";
return oss.str();
}
} // namespace routing

View file

@ -165,10 +165,10 @@ struct SpeedInUnits
SpeedInUnits() = default;
SpeedInUnits(uint16_t speed, measurement_utils::Units units) noexcept : m_speed(speed), m_units(units) {}
bool operator==(SpeedInUnits const & s) const;
bool operator==(SpeedInUnits const & rhs) const;
/// \note While comparing speeds are not converted to the same units. So according to
/// this compare operator 80 km per hour is more then 79 mile per hour.
bool operator<(SpeedInUnits const & s) const;
bool operator<(SpeedInUnits const & rhs) const;
bool IsNumeric() const;
bool IsValid() const { return m_speed != kInvalidSpeed; }
@ -177,6 +177,33 @@ struct SpeedInUnits
measurement_utils::Units m_units = measurement_utils::Units::Metric;
};
/// \breif Maxspeed tag value for feature id. |m_forward| and |m_backward| fields reflect the fact
/// that a feature may have different maxspeed tag value for different directions.
/// If |m_backward| is invalid it means that |m_forward| tag contains maxspeed for the both
/// directions.
class FeatureMaxspeed
{
public:
FeatureMaxspeed(uint32_t fid, SpeedInUnits const & forward,
SpeedInUnits const & backward = SpeedInUnits());
/// \note operator==() and operator<() do not correspond to each other.
bool operator==(FeatureMaxspeed const & rhs) const;
bool operator<(FeatureMaxspeed const & rhs) const { return m_featureId < rhs.m_featureId; }
bool IsValid() const { return m_forward.IsValid(); }
bool IsBidirectional() const { return IsValid() && m_backward.IsValid(); }
uint32_t GetFeatureId() const { return m_featureId; }
SpeedInUnits const & GetForward() const { return m_forward; }
SpeedInUnits const & GetBackward() const { return m_backward; }
private:
uint32_t m_featureId = 0;
SpeedInUnits m_forward;
SpeedInUnits m_backward;
};
class MaxspeedConverter
{
friend MaxspeedConverter const & GetMaxspeedConverter();
@ -198,6 +225,7 @@ private:
MaxspeedConverter const & GetMaxspeedConverter();
std::string DebugPrint(SpeedInUnits const & speed);
std::string DebugPrint(Maxspeed maxspeed);
std::string DebugPrint(SpeedInUnits const & speed);
std::string DebugPrint(FeatureMaxspeed const & featureMaxspeed);
} // namespace routing

View file

@ -1,5 +1,97 @@
#pragma once
#include "routing/maxspeed_conversion.hpp"
#include "coding/reader.hpp"
#include "coding/write_to_sink.hpp"
#include "base/assert.hpp"
#include <algorithm>
#include <cstdint>
#include <vector>
namespace routing
{
class MaxspeedSerializer
{
public:
MaxspeedSerializer() = delete;
template <class Sink>
static void Serialize(std::vector<FeatureMaxspeed> const & speeds, Sink & sink)
{
CHECK(std::is_sorted(speeds.cbegin(), speeds.cend()), ());
// @TODO(bykoianko) Now serialization is implemented in the simplest way for research purposes.
// It should be rewrite in a better way using MaxspeedConverter before before the PR is merged.
Header header(static_cast<uint32_t>(speeds.size()));
header.Serialize(sink);
for (auto const & s : speeds)
{
WriteToSink(sink, s.GetFeatureId());
WriteToSink(sink, s.GetForward().m_speed);
WriteToSink(sink, static_cast<uint8_t>(s.GetForward().m_units));
WriteToSink(sink, s.GetBackward().m_speed);
WriteToSink(sink, static_cast<uint8_t>(s.GetBackward().m_units));
}
}
template <class Source>
static void Deserialize(Source & src, std::vector<FeatureMaxspeed> & speeds)
{
Header header;
header.Deserialize(src);
speeds.clear();
for (size_t i = 0; i < header.GetSize(); ++i)
{
auto const fid = ReadPrimitiveFromSource<uint32_t>(src);
SpeedInUnits forward;
forward.m_speed = ReadPrimitiveFromSource<decltype(forward.m_speed)>(src);
forward.m_units = static_cast<measurement_utils::Units>(ReadPrimitiveFromSource<uint8_t>(src));
SpeedInUnits backward;
backward.m_speed = ReadPrimitiveFromSource<decltype(backward.m_speed)>(src);
backward.m_units = static_cast<measurement_utils::Units>(ReadPrimitiveFromSource<uint8_t>(src));
speeds.emplace_back(fid, forward, backward);
}
}
private:
static uint8_t constexpr kLastVersion = 0;
class Header final
{
public:
Header() = default;
explicit Header(uint32_t size) : m_size(size) {}
template <class Sink>
void Serialize(Sink & sink) const
{
WriteToSink(sink, m_version);
WriteToSink(sink, m_reserved);
WriteToSink(sink, m_size);
}
template <class Source>
void Deserialize(Source & src)
{
m_version = ReadPrimitiveFromSource<decltype(m_version)>(src);
m_reserved = ReadPrimitiveFromSource<decltype(m_reserved)>(src);
m_size = ReadPrimitiveFromSource<decltype(m_size)>(src);
}
uint32_t GetSize() const { return m_size; }
private:
uint8_t m_version = kLastVersion;
uint8_t m_reserved = 0;
uint32_t m_size = 0;
};
};
} // namespace routing

View file

@ -1,11 +1,16 @@
#include "testing/testing.hpp"
#include "routing/maxspeed_conversion.hpp"
#include "routing/maxspeed_serialization.hpp"
#include "coding/reader.hpp"
#include "coding/writer.hpp"
#include "platform/measurement_utils.hpp"
#include <cstdint>
#include <limits>
#include <vector>
namespace
{
@ -13,6 +18,23 @@ using namespace measurement_utils;
using namespace routing;
using namespace std;
void TestMaxspeedSerialization(std::vector<FeatureMaxspeed> const & speed)
{
vector<char> buffer;
MemWriter<vector<char> > w(buffer);
MaxspeedSerializer::Serialize(speed, w);
size_t const sz = buffer.size();
MemReader r(buffer.data(), sz);
ReaderSource<MemReader> src(r);
std::vector<FeatureMaxspeed> result;
MaxspeedSerializer::Deserialize(src, result);
TEST_EQUAL(speed, result, ());
}
UNIT_TEST(MaxspeedConverter)
{
auto const & conv = GetMaxspeedConverter();
@ -51,4 +73,87 @@ UNIT_TEST(MaxspeedConverter)
TEST(conv.IsValidMacro(1), ()); // static_cast<uint8_t>(None) == 1
TEST(!conv.IsValidMacro(9), ()); // A value which is undefined in Maxspeed enum class.
}
UNIT_TEST(MaxspeedSerializer_Smoke)
{
TestMaxspeedSerialization({});
}
UNIT_TEST(MaxspeedSerializer_OneForwardMetric)
{
TestMaxspeedSerialization(
{FeatureMaxspeed(0 /* feature id */, SpeedInUnits(20 /* speed */, Units::Metric))});
}
UNIT_TEST(MaxspeedSerializer_OneNone)
{
TestMaxspeedSerialization(
{FeatureMaxspeed(0 /* feature id */, SpeedInUnits(kNoneMaxSpeed, Units::Metric))});
}
UNIT_TEST(MaxspeedSerializer_OneWalk)
{
TestMaxspeedSerialization(
{FeatureMaxspeed(0 /* feature id */, SpeedInUnits(kWalkMaxSpeed, Units::Metric))});
}
UNIT_TEST(MaxspeedSerializer_OneBidirectionalMetric_1)
{
TestMaxspeedSerialization(
{FeatureMaxspeed(0 /* feature id */, SpeedInUnits(20 /* speed */, Units::Metric),
SpeedInUnits(40 /* speed */, Units::Metric))});
}
UNIT_TEST(MaxspeedSerializer_OneBidirectionalMetric_2)
{
TestMaxspeedSerialization(
{FeatureMaxspeed(0 /* feature id */, SpeedInUnits(10 /* speed */, Units::Metric),
SpeedInUnits(kWalkMaxSpeed, Units::Metric))});
}
UNIT_TEST(MaxspeedSerializer_OneBidirectionalImperial)
{
TestMaxspeedSerialization(
{FeatureMaxspeed(0 /* feature id */, SpeedInUnits(30 /* speed */, Units::Imperial),
SpeedInUnits(50 /* speed */, Units::Imperial))});
}
UNIT_TEST(MaxspeedSerializer_BigMetric)
{
std::vector<FeatureMaxspeed> const maxspeeds = {
FeatureMaxspeed(0 /* feature id */, SpeedInUnits(20 /* speed */, Units::Metric)),
FeatureMaxspeed(1 /* feature id */, SpeedInUnits(60 /* speed */, Units::Metric)),
FeatureMaxspeed(4 /* feature id */, SpeedInUnits(90 /* speed */, Units::Metric)),
FeatureMaxspeed(5 /* feature id */, SpeedInUnits(5 /* speed */, Units::Metric)),
FeatureMaxspeed(7 /* feature id */, SpeedInUnits(70 /* speed */, Units::Metric),
SpeedInUnits(90 /* speed */, Units::Metric)),
FeatureMaxspeed(8 /* feature id */, SpeedInUnits(100 /* speed */, Units::Metric)),
FeatureMaxspeed(9 /* feature id */, SpeedInUnits(60 /* speed */, Units::Metric)),
FeatureMaxspeed(10 /* feature id */, SpeedInUnits(kNoneMaxSpeed, Units::Metric)),
FeatureMaxspeed(11 /* feature id */, SpeedInUnits(40 /* speed */, Units::Metric),
SpeedInUnits(50 /* speed */, Units::Metric)),
FeatureMaxspeed(12 /* feature id */, SpeedInUnits(40 /* speed */, Units::Metric),
SpeedInUnits(60 /* speed */, Units::Metric)),
};
TestMaxspeedSerialization(maxspeeds);
}
UNIT_TEST(MaxspeedSerializer_BigImperial)
{
std::vector<FeatureMaxspeed> const maxspeeds = {
FeatureMaxspeed(0 /* feature id */, SpeedInUnits(30 /* speed */, Units::Imperial)),
FeatureMaxspeed(1 /* feature id */, SpeedInUnits(5 /* speed */, Units::Imperial)),
FeatureMaxspeed(4 /* feature id */, SpeedInUnits(1 /* speed */, Units::Imperial)),
FeatureMaxspeed(5 /* feature id */, SpeedInUnits(5 /* speed */, Units::Imperial)),
FeatureMaxspeed(7 /* feature id */, SpeedInUnits(30 /* speed */, Units::Imperial),
SpeedInUnits(50 /* speed */, Units::Imperial)),
FeatureMaxspeed(8 /* feature id */, SpeedInUnits(70 /* speed */, Units::Imperial)),
FeatureMaxspeed(9 /* feature id */, SpeedInUnits(50 /* speed */, Units::Imperial)),
FeatureMaxspeed(10 /* feature id */, SpeedInUnits(40 /* speed */, Units::Imperial),
SpeedInUnits(50 /* speed */, Units::Metric)),
FeatureMaxspeed(11 /* feature id */, SpeedInUnits(30 /* speed */, Units::Imperial),
SpeedInUnits(50 /* speed */, Units::Metric)),
};
TestMaxspeedSerialization(maxspeeds);
}
} // namespace