fixup! [M120 Migration] Notify media device state to webbrowser
[platform/framework/web/chromium-efl.git] / base / state_transitions.h
1 // Copyright 2020 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef BASE_STATE_TRANSITIONS_H_
6 #define BASE_STATE_TRANSITIONS_H_
7
8 #include <vector>
9
10 #include "base/check_op.h"
11 #include "base/containers/contains.h"
12 #include "base/no_destructor.h"
13
14 namespace base {
15
16 // This class represents a set of state transitions where each state is a value
17 // that supports copy, << and == (e.g. an enum element). It's intended to be
18 // used in DCHECK-enabled builds to check that only valid transitions occur. Its
19 // implementation favours convenience and simplicity over performance. To use it
20 // follow this example:
21
22 // In foo.h
23 // ---------
24 // enum class State {
25 //   kState1,
26 //   kState2,
27 //   kState3,
28 // };
29 //
30 // // This may require exporting the symbol (e.g. CONTENT_EXPORT) if it will be
31 // // used by any other components: one common way this can happen is if the
32 // // enum is logged in tests (e.g. via gtest's EXPECT_* macros).
33 // std::ostream& operator<<(std::ostream& o, const State& s);
34 // ---------
35 //
36 // In foo.cc
37 // ---------
38 // #include "base/no_destructor.h"
39 // #include "base/state_transitions.h"
40 //
41 // std::ostream& operator<<(std::ostream& o, const State& s) {
42 //   return o << static_cast<int>(s);
43 // }
44 //
45 // void DCheckStateTransition(State old_state, State new_state) {
46 // #if DCHECK_IS_ON()
47 //   static const base::NoDestructor<StateTransitions<State>> transitions(
48 //       StateTransitions<State>({
49 //           {kState1, {kState2, kState3}},
50 //           {kState2, {kState3}},
51 //           {kState3, {}},
52 //       }));
53 //   DCHECK_STATE_TRANSITION(transitions, old_state, new_state);
54 // #endif  // DCHECK_IS_ON()
55 // }
56 // ---------
57
58 template <typename State>
59 struct StateTransitions {
60  public:
61   // Represents a state and all of the states that are valid transitions from
62   // it.
63   struct StateTransition {
64     StateTransition(State source, std::vector<State> destinations)
65         : source(std::move(source)), destinations(std::move(destinations)) {}
66
67     const State source;
68     const std::vector<State> destinations;
69   };
70
71   explicit StateTransitions(std::vector<StateTransition> state_transitions)
72       : state_transitions(std::move(state_transitions)) {}
73
74   // Returns a list of states that are valid to transition to from |source|.
75   const std::vector<State>& GetValidTransitions(const State& source) const {
76     for (const StateTransition& state_transition : state_transitions) {
77       if (state_transition.source == source)
78         return state_transition.destinations;
79     }
80     static const base::NoDestructor<std::vector<State>> no_transitions;
81     return *no_transitions;
82   }
83
84   // Tests whether transitioning from |source| to |destination| is valid.
85   bool IsTransitionValid(const State& source, const State& destination) const {
86     return base::Contains(GetValidTransitions(source), destination);
87   }
88
89   const std::vector<StateTransition> state_transitions;
90 };
91
92 // DCHECK if transitioning from |old_state| to |new_state| is not valid
93 // according to |transitions|.
94 #define DCHECK_STATE_TRANSITION(transitions, old_state, new_state)   \
95   DCHECK((transitions)->IsTransitionValid((old_state), (new_state))) \
96       << "Invalid transition: " << old_state << " -> " << new_state
97
98 }  // namespace base
99
100 #endif  // BASE_STATE_TRANSITIONS_H_