/* 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()))>; QString Current(ushort key); rpl::producer Viewer(ushort key); template Type ReplaceUnwrapTuple(Type accumulated, const Tuple &tuple) { return accumulated; } template 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 static Type Call(Type accumulated) { return accumulated; } }; template struct ReplaceUnwrap { template 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 static rpl::producer> Combine(ushort base, P p, Values &...values) { return rpl::combine( Viewer(base), std::move(values)... ) | rpl::map([p = std::move(p)](auto tuple) { return ReplaceUnwrapTuple<1>(p(std::get<0>(tuple)), tuple, TagValue()...); }); } template static S

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

Current(ushort base, P p) { return p(Lang::details::Current(base)); } }; template struct Producer { template static rpl::producer> Combine( ushort base, P p, lngtag_count type, rpl::producer &count, Values &...values) { return rpl::combine( Viewer(base), Viewer(base + 1), Viewer(base + 2), Viewer(base + 3), Viewer(base + 4), Viewer(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 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