/* * Copyright (C) 2023-present ScyllaDB */ /* * SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.0 */ #pragma once #include #include namespace utils { class pretty_printed_data_size { uint64_t _size; public: pretty_printed_data_size(uint64_t size) : _size(size) {} friend fmt::formatter; }; class pretty_printed_throughput { uint64_t _size; std::chrono::duration _duration; public: pretty_printed_throughput(uint64_t size, std::chrono::duration dur) : _size(size), _duration(std::move(dur)) {} friend fmt::formatter; }; } // print data_size using IEC or SI binary prefix annotation with optional "B" // or " bytes" unit postfix. // // usage: // fmt::print("{}", 10'024); // prints "10kB", using SI and add the "B" unit // // postfix by default // fmt::print("{:i}", 42); // prints "42 bytes" // fmt::print("{:ib}", 10'024); // prints "10Ki", IEC unit is used, without // // the " bytes" or "B" unit // fmt::print("{:I}", 1024); // prints "1K", IEC unit is used, but without // // the "iB" postfix. // fmt::print("{:s}", 10); // prints "10 bytes", SI unit is used // fmt::print("{:sb}", 10'000); // prints "10k", SI unit is used, without // // the unit postfix template <> struct fmt::formatter { enum class prefix_type { SI, IEC, IEC_SANS_I, }; prefix_type _prefix = prefix_type::SI; bool _bytes = true; constexpr auto parse(format_parse_context& ctx) { auto it = ctx.begin(); auto end = ctx.end(); if (it != end) { if (*it == 's') { _prefix = prefix_type::SI; ++it; } else if (*it == 'i') { _prefix = prefix_type::IEC; ++it; } else if (*it == 'I') { _prefix = prefix_type::IEC_SANS_I; ++it; } if (*it == 'b') { _bytes = false; ++it; } } if (it != end && *it != '}') { throw fmt::format_error("invalid format specifier"); } return it; } template auto format(utils::pretty_printed_data_size, FormatContext& ctx) const -> decltype(ctx.out()); }; template <> struct fmt::formatter : private fmt::formatter { using size_formatter = fmt::formatter; public: using size_formatter::parse; template auto format(const utils::pretty_printed_throughput&, FormatContext& ctx) const -> decltype(ctx.out()); };