/* This file is part of Telegram Desktop, the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once #include "lang/lang_tag.h" enum lngtag_count : int; namespace Lang { namespace details { inline constexpr auto kPluralCount = 6; template inline constexpr ushort TagValue(); template using S = std::decay_t()(QString()))>; [[nodiscard]] QString Current(ushort key); [[nodiscard]] rpl::producer Value(ushort key); [[nodiscard]] bool IsNonDefaultPlural(ushort keyBase); template [[nodiscard]] Type ReplaceUnwrapTuple(Type accumulated, const Tuple &tuple) { return accumulated; } template < int Index, typename Type, typename Tuple, typename Tag, typename ...Tags> [[nodiscard]] Type ReplaceUnwrapTuple( Type accumulated, const Tuple &tuple, Tag tag, Tags ...tags) { return ReplaceUnwrapTuple( ReplaceTag::Call( std::move(accumulated), tag, std::get(tuple)), tuple, tags...); } template struct ReplaceUnwrap; template <> struct ReplaceUnwrap<> { template [[nodiscard]] static Type Call(Type accumulated) { return accumulated; } }; template struct ReplaceUnwrap { template [[nodiscard]] static Type Call( Type accumulated, const Value &value, const Values &...values) { return ReplaceUnwrap::template Call( ReplaceTag::Call( std::move(accumulated), TagValue(), value), values...); } }; template struct Producer { template [[nodiscard]] static rpl::producer> Combine(ushort base, P p, Values &...values) { return rpl::combine( Value(base), std::move(values)... ) | rpl::map([p = std::move(p)](auto tuple) { return ReplaceUnwrapTuple<1>(p(std::get<0>(tuple)), tuple, TagValue()...); }); } template [[nodiscard]] static S

Current(ushort base, P p, const Values &...values) { return ReplaceUnwrap::template Call( p(Lang::details::Current(base)), values...); } }; template <> struct Producer<> { template [[nodiscard]] static rpl::producer> Combine(ushort base, P p) { return Value(base) | rpl::map(std::move(p)); } template [[nodiscard]] static S

Current(ushort base, P p) { return p(Lang::details::Current(base)); } }; template struct Producer { template [[nodiscard]] static rpl::producer> Combine( ushort base, P p, lngtag_count type, rpl::producer &count, Values &...values) { return rpl::combine( Value(base), Value(base + 1), Value(base + 2), Value(base + 3), Value(base + 4), Value(base + 5), std::move(count), std::move(values)... ) | rpl::map([base, type, p = std::move(p)](auto tuple) { auto plural = Plural(base, std::get<6>(tuple), type); const auto select = [&] { switch (plural.keyShift) { case 0: return std::get<0>(tuple); case 1: return std::get<1>(tuple); case 2: return std::get<2>(tuple); case 3: return std::get<3>(tuple); case 4: return std::get<4>(tuple); case 5: return std::get<5>(tuple); } Unexpected("Lang shift value in Plural result."); }; return ReplaceUnwrapTuple<7>( ReplaceTag>::Call( p(select()), TagValue(), StartReplacements>::Call( std::move(plural.replacement))), tuple, TagValue()...); }); } template [[nodiscard]] static S

Current( ushort base, P p, lngtag_count type, float64 count, const Values &...values) { auto plural = Plural(base, count, type); return ReplaceUnwrap::template Call( ReplaceTag>::Call( p(Lang::details::Current(base + plural.keyShift)), TagValue(), StartReplacements>::Call( std::move(plural.replacement))), values...); } }; } // namespace details } // namespace Lang