1 /*
2 	This file is part of solidity.
3 
4 	solidity is free software: you can redistribute it and/or modify
5 	it under the terms of the GNU General Public License as published by
6 	the Free Software Foundation, either version 3 of the License, or
7 	(at your option) any later version.
8 
9 	solidity is distributed in the hope that it will be useful,
10 	but WITHOUT ANY WARRANTY; without even the implied warranty of
11 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 	GNU General Public License for more details.
13 
14 	You should have received a copy of the GNU General Public License
15 	along with solidity.  If not, see <http://www.gnu.org/licenses/>.
16 */
17 // SPDX-License-Identifier: GPL-3.0
18 #pragma once
19 
20 #include <string>
21 
22 namespace solidity::util
23 {
24 
25 /// Simple generic result that holds a value and an optional error message.
26 /// Results can be implicitly converted to and created from the type of
27 /// the value they hold. The class is mainly designed for a result type of
28 /// bool or pointer type. The idea is that the default constructed value of
29 /// the result type is interpreted as an error value.
30 ///
31 /// Result<bool> check()
32 /// {
33 ///		if (false)
34 ///			return Result<bool>::err("Error message.")
35 ///		return true;
36 /// }
37 ///
38 
39 template <class ResultType>
40 class [[nodiscard]] Result
41 {
42 public:
43 	/// Constructs a result with _value and an empty message.
44 	/// This is meant to be called with valid results. Please use
45 	/// the static err() member function to signal an error.
Result(ResultType _value)46 	Result(ResultType _value): Result(_value, std::string{}) {}
47 
48 	/// Constructs a result with a default-constructed value and an
49 	/// error message.
err(std::string _message)50 	static Result<ResultType> err(std::string _message)
51 	{
52 		return Result{ResultType{}, std::move(_message)};
53 	}
54 
55 	/// @{
56 	/// @name Wrapper functions
57 	/// Wrapper functions that provide implicit conversions to and explicit retrieval of
58 	/// the value this result holds.
59 	operator ResultType const&() const { return m_value; }
get()60 	ResultType const& get() const { return m_value; }
61 	/// @}
62 
63 	/// @returns the error message (can be empty).
message()64 	std::string const& message() const { return m_message; }
65 
66 	/// Merges _other into this using the _merger
67 	/// and appends the error messages. Meant to be called
68 	/// with logical operators like logical_and, etc.
69 	template<typename F>
merge(Result<ResultType> const & _other,F _merger)70 	void merge(Result<ResultType> const& _other, F _merger)
71 	{
72 		m_value = _merger(m_value, _other.get());
73 		m_message += _other.message();
74 	}
75 
76 private:
Result(ResultType _value,std::string _message)77 	explicit Result(ResultType _value, std::string _message):
78 		m_value(std::move(_value)),
79 		m_message(std::move(_message))
80 	{}
81 
82 	ResultType m_value;
83 	std::string m_message;
84 };
85 
86 }
87