1 /* 2 This file is part of Telegram Desktop, 3 the official desktop application for the Telegram messaging service. 4 5 For license and copyright information please follow this link: 6 https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL 7 */ 8 #pragma once 9 10 #include <rpl/event_stream.h> 11 12 namespace Data { 13 14 template <typename FlagsType> 15 using FlagsUnderlying = typename FlagsType::Type; 16 17 template < 18 typename FlagsType, 19 FlagsUnderlying<FlagsType> kEssential = FlagsUnderlying<FlagsType>(-1)> 20 class Flags { 21 public: 22 using Type = FlagsType; 23 using Enum = typename Type::Enum; 24 25 struct Change { 26 using Type = FlagsType; 27 using Enum = typename Type::Enum; 28 ChangeChange29 Change(Type diff, Type value) 30 : diff(diff) 31 , value(value) { 32 } 33 Type diff = 0; 34 Type value = 0; 35 }; 36 37 Flags() = default; Flags(Type value)38 Flags(Type value) : _value(value) { 39 } 40 set(Type which)41 void set(Type which) { 42 if (auto diff = which ^ _value) { 43 _value = which; 44 updated(diff); 45 } 46 } add(Type which)47 void add(Type which) { 48 if (auto diff = which & ~_value) { 49 _value |= which; 50 updated(diff); 51 } 52 } remove(Type which)53 void remove(Type which) { 54 if (auto diff = which & _value) { 55 _value &= ~which; 56 updated(diff); 57 } 58 } current()59 auto current() const { 60 return _value; 61 } changes()62 auto changes() const { 63 return _changes.events(); 64 } value()65 auto value() const { 66 return _changes.events_starting_with({ 67 Type::from_raw(kEssential), 68 _value }); 69 } 70 71 private: updated(Type diff)72 void updated(Type diff) { 73 if ((diff &= Type::from_raw(kEssential))) { 74 _changes.fire({ diff, _value }); 75 } 76 } 77 78 Type _value = 0; 79 rpl::event_stream<Change> _changes; 80 81 }; 82 83 } // namespace Data 84