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