diff --git a/au/BUILD.bazel b/au/BUILD.bazel index c17a37ca..c45e4021 100644 --- a/au/BUILD.bazel +++ b/au/BUILD.bazel @@ -160,6 +160,8 @@ cc_library( includes = ["code"], deps = [ ":units", + ":prefix", + ":quantity", ], ) diff --git a/au/code/au/CMakeLists.txt b/au/code/au/CMakeLists.txt index 35492412..807fda6f 100644 --- a/au/code/au/CMakeLists.txt +++ b/au/code/au/CMakeLists.txt @@ -37,6 +37,7 @@ header_only_library( HEADERS chrono_interop.hh DEPS + prefix quantity units GTEST_SRCS diff --git a/au/code/au/chrono_interop.hh b/au/code/au/chrono_interop.hh index 03c44816..3a4a0b98 100644 --- a/au/code/au/chrono_interop.hh +++ b/au/code/au/chrono_interop.hh @@ -17,7 +17,10 @@ #include #include +#include "au/prefix.hh" #include "au/quantity.hh" +#include "au/units/hours.hh" +#include "au/units/minutes.hh" #include "au/units/seconds.hh" namespace au { @@ -34,6 +37,40 @@ struct CorrespondingQuantity> { static constexpr ChronoDuration construct_from_value(Rep x) { return ChronoDuration{x}; } }; +// Define special mappings for widely used chrono types. +template +struct SpecialCorrespondingQuantity { + using Unit = AuUnit; + using Rep = decltype(ChronoType{}.count()); + + static constexpr Rep extract_value(ChronoType d) { return d.count(); } + static constexpr ChronoType construct_from_value(Rep x) { return ChronoType{x}; } +}; + +template <> +struct CorrespondingQuantity + : SpecialCorrespondingQuantity> {}; + +template <> +struct CorrespondingQuantity + : SpecialCorrespondingQuantity> {}; + +template <> +struct CorrespondingQuantity + : SpecialCorrespondingQuantity> {}; + +template <> +struct CorrespondingQuantity + : SpecialCorrespondingQuantity {}; + +template <> +struct CorrespondingQuantity + : SpecialCorrespondingQuantity {}; + +template <> +struct CorrespondingQuantity + : SpecialCorrespondingQuantity {}; + // Convert any Au duration quantity to an equivalent `std::chrono::duration`. template constexpr auto as_chrono_duration(Quantity dt) { diff --git a/au/code/au/chrono_interop_test.cc b/au/code/au/chrono_interop_test.cc index ab6d482c..2d3ac275 100644 --- a/au/code/au/chrono_interop_test.cc +++ b/au/code/au/chrono_interop_test.cc @@ -14,13 +14,26 @@ #include "au/chrono_interop.hh" +#include + #include "au/prefix.hh" #include "au/testing.hh" +#include "gmock/gmock.h" #include "gtest/gtest.h" +using ::testing::StrEq; + using namespace std::chrono_literals; namespace au { +namespace { +template +std::string stream_to_string(const T &t) { + std::ostringstream oss; + oss << t; + return oss.str(); +} +} // namespace TEST(DurationQuantity, InterconvertsWithExactlyEquivalentChronoDuration) { constexpr QuantityD from_chrono = std::chrono::duration{1.23}; @@ -36,6 +49,36 @@ TEST(DurationQuantity, InterconvertsWithIndirectlyEquivalentChronoDuration) { EXPECT_THAT(from_chrono, SameTypeAndValue(seconds(1.234))); } +TEST(DurationQuantity, EquivalentOfChronoNanosecondsHasNsLabel) { + constexpr auto from_chrono_ns = as_quantity(std::chrono::nanoseconds{123}); + EXPECT_THAT(stream_to_string(from_chrono_ns), StrEq("123 ns")); +} + +TEST(DurationQuantity, EquivalentOfChronoMicrosecondsHasUsLabel) { + constexpr auto from_chrono_us = as_quantity(std::chrono::microseconds{123}); + EXPECT_THAT(stream_to_string(from_chrono_us), StrEq("123 us")); +} + +TEST(DurationQuantity, EquivalentOfChronoMillisecondsHasMsLabel) { + constexpr auto from_chrono_ms = as_quantity(std::chrono::milliseconds{123}); + EXPECT_THAT(stream_to_string(from_chrono_ms), StrEq("123 ms")); +} + +TEST(DurationQuantity, EquivalentOfChronoSecondsHasSLabel) { + constexpr auto from_chrono_s = as_quantity(std::chrono::seconds{123}); + EXPECT_THAT(stream_to_string(from_chrono_s), StrEq("123 s")); +} + +TEST(DurationQuantity, EquivalentOfChronoMinutesHasMinLabel) { + constexpr auto from_chrono_min = as_quantity(std::chrono::minutes{123}); + EXPECT_THAT(stream_to_string(from_chrono_min), StrEq("123 min")); +} + +TEST(DurationQuantity, EquivalentOfChronoHoursHasHLabel) { + constexpr auto from_chrono_h = as_quantity(std::chrono::hours{123}); + EXPECT_THAT(stream_to_string(from_chrono_h), StrEq("123 h")); +} + TEST(AsChronoDuration, ProducesExpectedResults) { constexpr auto original = milli(seconds)(12.3f); constexpr auto result = as_chrono_duration(original);