1/*
2
3Copyright (C) 2016-2017 Apple Inc. All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions
7are met:
81. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
102. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13
14THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
15EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
25*/
26
27#pragma once
28
29#include "Exception.h"
30#include <wtf/CrossThreadCopier.h>
31#include <wtf/Expected.h>
32
33namespace WebCore {
34
35template<typename ReturnType> class ExceptionOr {
36public:
37 ExceptionOr(Exception&&);
38 ExceptionOr(ReturnType&&);
39 template<typename OtherType> ExceptionOr(const OtherType&, typename std::enable_if<std::is_scalar<OtherType>::value && std::is_convertible<OtherType, ReturnType>::value>::type* = nullptr);
40
41 bool hasException() const;
42 const Exception& exception() const;
43 Exception&& releaseException();
44 const ReturnType& returnValue() const;
45 ReturnType&& releaseReturnValue();
46
47private:
48 Expected<ReturnType, Exception> m_value;
49};
50
51template<typename ReturnReferenceType> class ExceptionOr<ReturnReferenceType&> {
52public:
53 ExceptionOr(Exception&&);
54 ExceptionOr(ReturnReferenceType&);
55
56 bool hasException() const;
57 const Exception& exception() const;
58 Exception&& releaseException();
59 const ReturnReferenceType& returnValue() const;
60 ReturnReferenceType& releaseReturnValue();
61
62private:
63 ExceptionOr<ReturnReferenceType*> m_value;
64};
65
66template<> class ExceptionOr<void> {
67public:
68 ExceptionOr(Exception&&);
69 ExceptionOr() = default;
70
71 bool hasException() const;
72 const Exception& exception() const;
73 Exception&& releaseException();
74
75private:
76 Expected<void, Exception> m_value;
77};
78
79ExceptionOr<void> isolatedCopy(ExceptionOr<void>&&);
80
81template<typename ReturnType> inline ExceptionOr<ReturnType>::ExceptionOr(Exception&& exception)
82 : m_value(makeUnexpected(WTFMove(exception)))
83{
84}
85
86template<typename ReturnType> inline ExceptionOr<ReturnType>::ExceptionOr(ReturnType&& returnValue)
87 : m_value(WTFMove(returnValue))
88{
89}
90
91template<typename ReturnType> template<typename OtherType> inline ExceptionOr<ReturnType>::ExceptionOr(const OtherType& returnValue, typename std::enable_if<std::is_scalar<OtherType>::value && std::is_convertible<OtherType, ReturnType>::value>::type*)
92 : m_value(static_cast<ReturnType>(returnValue))
93{
94}
95
96template<typename ReturnType> inline bool ExceptionOr<ReturnType>::hasException() const
97{
98 return !m_value.has_value();
99}
100
101template<typename ReturnType> inline const Exception& ExceptionOr<ReturnType>::exception() const
102{
103 return m_value.error();
104}
105
106template<typename ReturnType> inline Exception&& ExceptionOr<ReturnType>::releaseException()
107{
108 return WTFMove(m_value.error());
109}
110
111template<typename ReturnType> inline const ReturnType& ExceptionOr<ReturnType>::returnValue() const
112{
113 return m_value.value();
114}
115
116template<typename ReturnType> inline ReturnType&& ExceptionOr<ReturnType>::releaseReturnValue()
117{
118 return WTFMove(m_value.value());
119}
120
121template<typename ReturnReferenceType> inline ExceptionOr<ReturnReferenceType&>::ExceptionOr(Exception&& exception)
122 : m_value(WTFMove(exception))
123{
124}
125
126template<typename ReturnReferenceType> inline ExceptionOr<ReturnReferenceType&>::ExceptionOr(ReturnReferenceType& returnValue)
127 : m_value(&returnValue)
128{
129}
130
131template<typename ReturnReferenceType> inline bool ExceptionOr<ReturnReferenceType&>::hasException() const
132{
133 return m_value.hasException();
134}
135
136template<typename ReturnReferenceType> inline const Exception& ExceptionOr<ReturnReferenceType&>::exception() const
137{
138 return m_value.exception();
139}
140
141template<typename ReturnReferenceType> inline Exception&& ExceptionOr<ReturnReferenceType&>::releaseException()
142{
143 return m_value.releaseException();
144}
145
146template<typename ReturnReferenceType> inline const ReturnReferenceType& ExceptionOr<ReturnReferenceType&>::returnValue() const
147{
148 return *m_value.returnValue();
149}
150
151template<typename ReturnReferenceType> inline ReturnReferenceType& ExceptionOr<ReturnReferenceType&>::releaseReturnValue()
152{
153 return *m_value.releaseReturnValue();
154}
155
156inline ExceptionOr<void>::ExceptionOr(Exception&& exception)
157 : m_value(makeUnexpected(WTFMove(exception)))
158{
159}
160
161inline bool ExceptionOr<void>::hasException() const
162{
163 return !m_value.has_value();
164}
165
166inline const Exception& ExceptionOr<void>::exception() const
167{
168 return m_value.error();
169}
170
171inline Exception&& ExceptionOr<void>::releaseException()
172{
173 return WTFMove(m_value.error());
174}
175
176inline ExceptionOr<void> isolatedCopy(ExceptionOr<void>&& value)
177{
178 if (value.hasException())
179 return isolatedCopy(value.releaseException());
180 return { };
181}
182
183}
184
185namespace WTF {
186template<typename T> struct CrossThreadCopierBase<false, false, WebCore::ExceptionOr<T> > {
187 typedef WebCore::ExceptionOr<T> Type;
188 static Type copy(const Type& source)
189 {
190 if (source.hasException())
191 return crossThreadCopy(source.exception());
192 return crossThreadCopy(source.returnValue());
193 }
194};
195}
196