annotate CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/include/kj/one-of.h @ 69:33d812a61356

planemo upload commit 2e9511a184a1ca667c7be0c6321a36dc4e3d116d
author jpayne
date Tue, 18 Mar 2025 17:55:14 -0400
parents
children
rev   line source
jpayne@69 1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
jpayne@69 2 // Licensed under the MIT License:
jpayne@69 3 //
jpayne@69 4 // Permission is hereby granted, free of charge, to any person obtaining a copy
jpayne@69 5 // of this software and associated documentation files (the "Software"), to deal
jpayne@69 6 // in the Software without restriction, including without limitation the rights
jpayne@69 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
jpayne@69 8 // copies of the Software, and to permit persons to whom the Software is
jpayne@69 9 // furnished to do so, subject to the following conditions:
jpayne@69 10 //
jpayne@69 11 // The above copyright notice and this permission notice shall be included in
jpayne@69 12 // all copies or substantial portions of the Software.
jpayne@69 13 //
jpayne@69 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
jpayne@69 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
jpayne@69 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
jpayne@69 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
jpayne@69 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
jpayne@69 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
jpayne@69 20 // THE SOFTWARE.
jpayne@69 21
jpayne@69 22 #pragma once
jpayne@69 23
jpayne@69 24 #include "common.h"
jpayne@69 25
jpayne@69 26 KJ_BEGIN_HEADER
jpayne@69 27
jpayne@69 28 namespace kj {
jpayne@69 29
jpayne@69 30 namespace _ { // private
jpayne@69 31
jpayne@69 32 template <uint i, template<uint> class Fail, typename Key, typename... Variants>
jpayne@69 33 struct TypeIndex_;
jpayne@69 34 template <uint i, template<uint> class Fail, typename Key, typename First, typename... Rest>
jpayne@69 35 struct TypeIndex_<i, Fail, Key, First, Rest...> {
jpayne@69 36 static constexpr uint value = TypeIndex_<i + 1, Fail, Key, Rest...>::value;
jpayne@69 37 };
jpayne@69 38 template <uint i, template<uint> class Fail, typename Key, typename... Rest>
jpayne@69 39 struct TypeIndex_<i, Fail, Key, Key, Rest...> { static constexpr uint value = i; };
jpayne@69 40 template <uint i, template<uint> class Fail, typename Key>
jpayne@69 41 struct TypeIndex_<i, Fail, Key>: public Fail<i> {};
jpayne@69 42
jpayne@69 43 template <uint i>
jpayne@69 44 struct OneOfFailError_ {
jpayne@69 45 static_assert(i == -1, "type does not match any in OneOf");
jpayne@69 46 };
jpayne@69 47 template <uint i>
jpayne@69 48 struct OneOfFailZero_ {
jpayne@69 49 static constexpr int value = 0;
jpayne@69 50 };
jpayne@69 51
jpayne@69 52 template <uint i>
jpayne@69 53 struct SuccessIfNotZero {
jpayne@69 54 typedef int Success;
jpayne@69 55 };
jpayne@69 56 template <>
jpayne@69 57 struct SuccessIfNotZero<0> {};
jpayne@69 58
jpayne@69 59 enum class Variants0 {};
jpayne@69 60 enum class Variants1 { _variant0 };
jpayne@69 61 enum class Variants2 { _variant0, _variant1 };
jpayne@69 62 enum class Variants3 { _variant0, _variant1, _variant2 };
jpayne@69 63 enum class Variants4 { _variant0, _variant1, _variant2, _variant3 };
jpayne@69 64 enum class Variants5 { _variant0, _variant1, _variant2, _variant3, _variant4 };
jpayne@69 65 enum class Variants6 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5 };
jpayne@69 66 enum class Variants7 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6 };
jpayne@69 67 enum class Variants8 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 68 _variant7 };
jpayne@69 69 enum class Variants9 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 70 _variant7, _variant8 };
jpayne@69 71 enum class Variants10 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 72 _variant7, _variant8, _variant9 };
jpayne@69 73 enum class Variants11 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 74 _variant7, _variant8, _variant9, _variant10 };
jpayne@69 75 enum class Variants12 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 76 _variant7, _variant8, _variant9, _variant10, _variant11 };
jpayne@69 77 enum class Variants13 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 78 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12 };
jpayne@69 79 enum class Variants14 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 80 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 81 _variant13 };
jpayne@69 82 enum class Variants15 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 83 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 84 _variant13, _variant14 };
jpayne@69 85 enum class Variants16 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 86 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 87 _variant13, _variant14, _variant15 };
jpayne@69 88 enum class Variants17 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 89 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 90 _variant13, _variant14, _variant15, _variant16 };
jpayne@69 91 enum class Variants18 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 92 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 93 _variant13, _variant14, _variant15, _variant16, _variant17 };
jpayne@69 94 enum class Variants19 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 95 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 96 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18 };
jpayne@69 97 enum class Variants20 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 98 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 99 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
jpayne@69 100 _variant19 };
jpayne@69 101 enum class Variants21 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 102 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 103 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
jpayne@69 104 _variant19, _variant20 };
jpayne@69 105 enum class Variants22 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 106 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 107 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
jpayne@69 108 _variant19, _variant20, _variant21 };
jpayne@69 109 enum class Variants23 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 110 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 111 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
jpayne@69 112 _variant19, _variant20, _variant21, _variant22 };
jpayne@69 113 enum class Variants24 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 114 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 115 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
jpayne@69 116 _variant19, _variant20, _variant21, _variant22, _variant23 };
jpayne@69 117 enum class Variants25 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 118 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 119 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
jpayne@69 120 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24 };
jpayne@69 121 enum class Variants26 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 122 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 123 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
jpayne@69 124 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
jpayne@69 125 _variant25 };
jpayne@69 126 enum class Variants27 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 127 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 128 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
jpayne@69 129 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
jpayne@69 130 _variant25, _variant26 };
jpayne@69 131 enum class Variants28 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 132 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 133 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
jpayne@69 134 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
jpayne@69 135 _variant25, _variant26, _variant27 };
jpayne@69 136 enum class Variants29 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 137 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 138 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
jpayne@69 139 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
jpayne@69 140 _variant25, _variant26, _variant27, _variant28 };
jpayne@69 141 enum class Variants30 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 142 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 143 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
jpayne@69 144 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
jpayne@69 145 _variant25, _variant26, _variant27, _variant28, _variant29 };
jpayne@69 146 enum class Variants31 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 147 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 148 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
jpayne@69 149 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
jpayne@69 150 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30 };
jpayne@69 151 enum class Variants32 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 152 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 153 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
jpayne@69 154 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
jpayne@69 155 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
jpayne@69 156 _variant31 };
jpayne@69 157 enum class Variants33 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 158 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 159 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
jpayne@69 160 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
jpayne@69 161 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
jpayne@69 162 _variant31, _variant32 };
jpayne@69 163 enum class Variants34 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 164 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 165 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
jpayne@69 166 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
jpayne@69 167 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
jpayne@69 168 _variant31, _variant32, _variant33 };
jpayne@69 169 enum class Variants35 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 170 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 171 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
jpayne@69 172 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
jpayne@69 173 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
jpayne@69 174 _variant31, _variant32, _variant33, _variant34 };
jpayne@69 175 enum class Variants36 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 176 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 177 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
jpayne@69 178 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
jpayne@69 179 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
jpayne@69 180 _variant31, _variant32, _variant33, _variant34, _variant35 };
jpayne@69 181 enum class Variants37 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 182 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 183 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
jpayne@69 184 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
jpayne@69 185 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
jpayne@69 186 _variant31, _variant32, _variant33, _variant34, _variant35, _variant36 };
jpayne@69 187 enum class Variants38 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 188 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 189 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
jpayne@69 190 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
jpayne@69 191 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
jpayne@69 192 _variant31, _variant32, _variant33, _variant34, _variant35, _variant36,
jpayne@69 193 _variant37 };
jpayne@69 194 enum class Variants39 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 195 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 196 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
jpayne@69 197 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
jpayne@69 198 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
jpayne@69 199 _variant31, _variant32, _variant33, _variant34, _variant35, _variant36,
jpayne@69 200 _variant37, _variant38 };
jpayne@69 201 enum class Variants40 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 202 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 203 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
jpayne@69 204 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
jpayne@69 205 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
jpayne@69 206 _variant31, _variant32, _variant33, _variant34, _variant35, _variant36,
jpayne@69 207 _variant37, _variant38, _variant39 };
jpayne@69 208 enum class Variants41 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 209 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 210 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
jpayne@69 211 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
jpayne@69 212 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
jpayne@69 213 _variant31, _variant32, _variant33, _variant34, _variant35, _variant36,
jpayne@69 214 _variant37, _variant38, _variant39, _variant40 };
jpayne@69 215 enum class Variants42 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 216 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 217 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
jpayne@69 218 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
jpayne@69 219 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
jpayne@69 220 _variant31, _variant32, _variant33, _variant34, _variant35, _variant36,
jpayne@69 221 _variant37, _variant38, _variant39, _variant40, _variant41 };
jpayne@69 222 enum class Variants43 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 223 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 224 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
jpayne@69 225 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
jpayne@69 226 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
jpayne@69 227 _variant31, _variant32, _variant33, _variant34, _variant35, _variant36,
jpayne@69 228 _variant37, _variant38, _variant39, _variant40, _variant41, _variant42 };
jpayne@69 229 enum class Variants44 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 230 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 231 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
jpayne@69 232 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
jpayne@69 233 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
jpayne@69 234 _variant31, _variant32, _variant33, _variant34, _variant35, _variant36,
jpayne@69 235 _variant37, _variant38, _variant39, _variant40, _variant41, _variant42,
jpayne@69 236 _variant43 };
jpayne@69 237 enum class Variants45 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 238 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 239 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
jpayne@69 240 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
jpayne@69 241 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
jpayne@69 242 _variant31, _variant32, _variant33, _variant34, _variant35, _variant36,
jpayne@69 243 _variant37, _variant38, _variant39, _variant40, _variant41, _variant42,
jpayne@69 244 _variant43, _variant44 };
jpayne@69 245 enum class Variants46 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 246 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 247 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
jpayne@69 248 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
jpayne@69 249 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
jpayne@69 250 _variant31, _variant32, _variant33, _variant34, _variant35, _variant36,
jpayne@69 251 _variant37, _variant38, _variant39, _variant40, _variant41, _variant42,
jpayne@69 252 _variant43, _variant44, _variant45 };
jpayne@69 253 enum class Variants47 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 254 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 255 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
jpayne@69 256 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
jpayne@69 257 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
jpayne@69 258 _variant31, _variant32, _variant33, _variant34, _variant35, _variant36,
jpayne@69 259 _variant37, _variant38, _variant39, _variant40, _variant41, _variant42,
jpayne@69 260 _variant43, _variant44, _variant45, _variant46 };
jpayne@69 261 enum class Variants48 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 262 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 263 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
jpayne@69 264 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
jpayne@69 265 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
jpayne@69 266 _variant31, _variant32, _variant33, _variant34, _variant35, _variant36,
jpayne@69 267 _variant37, _variant38, _variant39, _variant40, _variant41, _variant42,
jpayne@69 268 _variant43, _variant44, _variant45, _variant46, _variant47 };
jpayne@69 269 enum class Variants49 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 270 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 271 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
jpayne@69 272 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
jpayne@69 273 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
jpayne@69 274 _variant31, _variant32, _variant33, _variant34, _variant35, _variant36,
jpayne@69 275 _variant37, _variant38, _variant39, _variant40, _variant41, _variant42,
jpayne@69 276 _variant43, _variant44, _variant45, _variant46, _variant47, _variant48 };
jpayne@69 277 enum class Variants50 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
jpayne@69 278 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
jpayne@69 279 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
jpayne@69 280 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
jpayne@69 281 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
jpayne@69 282 _variant31, _variant32, _variant33, _variant34, _variant35, _variant36,
jpayne@69 283 _variant37, _variant38, _variant39, _variant40, _variant41, _variant42,
jpayne@69 284 _variant43, _variant44, _variant45, _variant46, _variant47, _variant48,
jpayne@69 285 _variant49 };
jpayne@69 286
jpayne@69 287 template <uint i> struct Variants_;
jpayne@69 288 template <> struct Variants_<0> { typedef Variants0 Type; };
jpayne@69 289 template <> struct Variants_<1> { typedef Variants1 Type; };
jpayne@69 290 template <> struct Variants_<2> { typedef Variants2 Type; };
jpayne@69 291 template <> struct Variants_<3> { typedef Variants3 Type; };
jpayne@69 292 template <> struct Variants_<4> { typedef Variants4 Type; };
jpayne@69 293 template <> struct Variants_<5> { typedef Variants5 Type; };
jpayne@69 294 template <> struct Variants_<6> { typedef Variants6 Type; };
jpayne@69 295 template <> struct Variants_<7> { typedef Variants7 Type; };
jpayne@69 296 template <> struct Variants_<8> { typedef Variants8 Type; };
jpayne@69 297 template <> struct Variants_<9> { typedef Variants9 Type; };
jpayne@69 298 template <> struct Variants_<10> { typedef Variants10 Type; };
jpayne@69 299 template <> struct Variants_<11> { typedef Variants11 Type; };
jpayne@69 300 template <> struct Variants_<12> { typedef Variants12 Type; };
jpayne@69 301 template <> struct Variants_<13> { typedef Variants13 Type; };
jpayne@69 302 template <> struct Variants_<14> { typedef Variants14 Type; };
jpayne@69 303 template <> struct Variants_<15> { typedef Variants15 Type; };
jpayne@69 304 template <> struct Variants_<16> { typedef Variants16 Type; };
jpayne@69 305 template <> struct Variants_<17> { typedef Variants17 Type; };
jpayne@69 306 template <> struct Variants_<18> { typedef Variants18 Type; };
jpayne@69 307 template <> struct Variants_<19> { typedef Variants19 Type; };
jpayne@69 308 template <> struct Variants_<20> { typedef Variants20 Type; };
jpayne@69 309 template <> struct Variants_<21> { typedef Variants21 Type; };
jpayne@69 310 template <> struct Variants_<22> { typedef Variants22 Type; };
jpayne@69 311 template <> struct Variants_<23> { typedef Variants23 Type; };
jpayne@69 312 template <> struct Variants_<24> { typedef Variants24 Type; };
jpayne@69 313 template <> struct Variants_<25> { typedef Variants25 Type; };
jpayne@69 314 template <> struct Variants_<26> { typedef Variants26 Type; };
jpayne@69 315 template <> struct Variants_<27> { typedef Variants27 Type; };
jpayne@69 316 template <> struct Variants_<28> { typedef Variants28 Type; };
jpayne@69 317 template <> struct Variants_<29> { typedef Variants29 Type; };
jpayne@69 318 template <> struct Variants_<30> { typedef Variants30 Type; };
jpayne@69 319 template <> struct Variants_<31> { typedef Variants31 Type; };
jpayne@69 320 template <> struct Variants_<32> { typedef Variants32 Type; };
jpayne@69 321 template <> struct Variants_<33> { typedef Variants33 Type; };
jpayne@69 322 template <> struct Variants_<34> { typedef Variants34 Type; };
jpayne@69 323 template <> struct Variants_<35> { typedef Variants35 Type; };
jpayne@69 324 template <> struct Variants_<36> { typedef Variants36 Type; };
jpayne@69 325 template <> struct Variants_<37> { typedef Variants37 Type; };
jpayne@69 326 template <> struct Variants_<38> { typedef Variants38 Type; };
jpayne@69 327 template <> struct Variants_<39> { typedef Variants39 Type; };
jpayne@69 328 template <> struct Variants_<40> { typedef Variants40 Type; };
jpayne@69 329 template <> struct Variants_<41> { typedef Variants41 Type; };
jpayne@69 330 template <> struct Variants_<42> { typedef Variants42 Type; };
jpayne@69 331 template <> struct Variants_<43> { typedef Variants43 Type; };
jpayne@69 332 template <> struct Variants_<44> { typedef Variants44 Type; };
jpayne@69 333 template <> struct Variants_<45> { typedef Variants45 Type; };
jpayne@69 334 template <> struct Variants_<46> { typedef Variants46 Type; };
jpayne@69 335 template <> struct Variants_<47> { typedef Variants47 Type; };
jpayne@69 336 template <> struct Variants_<48> { typedef Variants48 Type; };
jpayne@69 337 template <> struct Variants_<49> { typedef Variants49 Type; };
jpayne@69 338 template <> struct Variants_<50> { typedef Variants50 Type; };
jpayne@69 339
jpayne@69 340 template <uint i>
jpayne@69 341 using Variants = typename Variants_<i>::Type;
jpayne@69 342
jpayne@69 343 } // namespace _ (private)
jpayne@69 344
jpayne@69 345 template <typename... Variants>
jpayne@69 346 class OneOf {
jpayne@69 347 template <typename Key>
jpayne@69 348 static inline constexpr uint typeIndex() {
jpayne@69 349 return _::TypeIndex_<1, _::OneOfFailError_, Key, Variants...>::value;
jpayne@69 350 }
jpayne@69 351 // Get the 1-based index of Key within the type list Types, or static_assert with a nice error.
jpayne@69 352
jpayne@69 353 template <typename Key>
jpayne@69 354 static inline constexpr uint typeIndexOrZero() {
jpayne@69 355 return _::TypeIndex_<1, _::OneOfFailZero_, Key, Variants...>::value;
jpayne@69 356 }
jpayne@69 357
jpayne@69 358 template <uint i, typename... OtherVariants>
jpayne@69 359 struct HasAll;
jpayne@69 360 // Has a member type called "Success" if and only if all of `OtherVariants` are types that
jpayne@69 361 // appear in `Variants`. Used with SFINAE to enable subset constructors.
jpayne@69 362
jpayne@69 363 public:
jpayne@69 364 inline OneOf(): tag(0) {}
jpayne@69 365
jpayne@69 366 OneOf(const OneOf& other) { copyFrom(other); }
jpayne@69 367 OneOf(OneOf& other) { copyFrom(other); }
jpayne@69 368 OneOf(OneOf&& other) { moveFrom(other); }
jpayne@69 369 // Copy/move from same OneOf type.
jpayne@69 370
jpayne@69 371 template <typename... OtherVariants, typename = typename HasAll<1, OtherVariants...>::Success>
jpayne@69 372 OneOf(const OneOf<OtherVariants...>& other) { copyFromSubset(other); }
jpayne@69 373 template <typename... OtherVariants, typename = typename HasAll<1, OtherVariants...>::Success>
jpayne@69 374 OneOf(OneOf<OtherVariants...>& other) { copyFromSubset(other); }
jpayne@69 375 template <typename... OtherVariants, typename = typename HasAll<1, OtherVariants...>::Success>
jpayne@69 376 OneOf(OneOf<OtherVariants...>&& other) { moveFromSubset(other); }
jpayne@69 377 // Copy/move from OneOf that contains a subset of the types we do.
jpayne@69 378
jpayne@69 379 template <typename T, typename = typename HasAll<0, Decay<T>>::Success>
jpayne@69 380 OneOf(T&& other): tag(typeIndex<Decay<T>>()) {
jpayne@69 381 ctor(*reinterpret_cast<Decay<T>*>(space), kj::fwd<T>(other));
jpayne@69 382 }
jpayne@69 383 // Copy/move from a value that matches one of the individual types in the OneOf.
jpayne@69 384
jpayne@69 385 ~OneOf() { destroy(); }
jpayne@69 386
jpayne@69 387 OneOf& operator=(const OneOf& other) { if (tag != 0) destroy(); copyFrom(other); return *this; }
jpayne@69 388 OneOf& operator=(OneOf&& other) { if (tag != 0) destroy(); moveFrom(other); return *this; }
jpayne@69 389
jpayne@69 390 inline bool operator==(decltype(nullptr)) const { return tag == 0; }
jpayne@69 391 inline bool operator!=(decltype(nullptr)) const { return tag != 0; }
jpayne@69 392
jpayne@69 393 template <typename T>
jpayne@69 394 bool is() const {
jpayne@69 395 return tag == typeIndex<T>();
jpayne@69 396 }
jpayne@69 397
jpayne@69 398 template <typename T>
jpayne@69 399 T& get() & {
jpayne@69 400 KJ_IREQUIRE(is<T>(), "Must check OneOf::is<T>() before calling get<T>().");
jpayne@69 401 return *reinterpret_cast<T*>(space);
jpayne@69 402 }
jpayne@69 403 template <typename T>
jpayne@69 404 T&& get() && {
jpayne@69 405 KJ_IREQUIRE(is<T>(), "Must check OneOf::is<T>() before calling get<T>().");
jpayne@69 406 return kj::mv(*reinterpret_cast<T*>(space));
jpayne@69 407 }
jpayne@69 408 template <typename T>
jpayne@69 409 const T& get() const& {
jpayne@69 410 KJ_IREQUIRE(is<T>(), "Must check OneOf::is<T>() before calling get<T>().");
jpayne@69 411 return *reinterpret_cast<const T*>(space);
jpayne@69 412 }
jpayne@69 413 template <typename T>
jpayne@69 414 const T&& get() const&& {
jpayne@69 415 KJ_IREQUIRE(is<T>(), "Must check OneOf::is<T>() before calling get<T>().");
jpayne@69 416 return kj::mv(*reinterpret_cast<const T*>(space));
jpayne@69 417 }
jpayne@69 418
jpayne@69 419 template <typename T, typename... Params>
jpayne@69 420 T& init(Params&&... params) {
jpayne@69 421 if (tag != 0) destroy();
jpayne@69 422 ctor(*reinterpret_cast<T*>(space), kj::fwd<Params>(params)...);
jpayne@69 423 tag = typeIndex<T>();
jpayne@69 424 return *reinterpret_cast<T*>(space);
jpayne@69 425 }
jpayne@69 426
jpayne@69 427 template <typename T>
jpayne@69 428 Maybe<T&> tryGet() {
jpayne@69 429 if (is<T>()) {
jpayne@69 430 return *reinterpret_cast<T*>(space);
jpayne@69 431 } else {
jpayne@69 432 return nullptr;
jpayne@69 433 }
jpayne@69 434 }
jpayne@69 435 template <typename T>
jpayne@69 436 Maybe<const T&> tryGet() const {
jpayne@69 437 if (is<T>()) {
jpayne@69 438 return *reinterpret_cast<const T*>(space);
jpayne@69 439 } else {
jpayne@69 440 return nullptr;
jpayne@69 441 }
jpayne@69 442 }
jpayne@69 443
jpayne@69 444 template <uint i>
jpayne@69 445 KJ_NORETURN(void allHandled());
jpayne@69 446 // After a series of if/else blocks handling each variant of the OneOf, have the final else
jpayne@69 447 // block call allHandled<n>() where n is the number of variants. This will fail to compile
jpayne@69 448 // if new variants are added in the future.
jpayne@69 449
jpayne@69 450 typedef _::Variants<sizeof...(Variants)> Tag;
jpayne@69 451
jpayne@69 452 Tag which() const {
jpayne@69 453 KJ_IREQUIRE(tag != 0, "Can't KJ_SWITCH_ONEOF() on uninitialized value.");
jpayne@69 454 return static_cast<Tag>(tag - 1);
jpayne@69 455 }
jpayne@69 456
jpayne@69 457 template <typename T>
jpayne@69 458 static constexpr Tag tagFor() {
jpayne@69 459 return static_cast<Tag>(typeIndex<T>() - 1);
jpayne@69 460 }
jpayne@69 461
jpayne@69 462 OneOf* _switchSubject() & { return this; }
jpayne@69 463 const OneOf* _switchSubject() const& { return this; }
jpayne@69 464 _::NullableValue<OneOf> _switchSubject() && { return kj::mv(*this); }
jpayne@69 465
jpayne@69 466 private:
jpayne@69 467 uint tag;
jpayne@69 468
jpayne@69 469 static inline constexpr size_t maxSize(size_t a) {
jpayne@69 470 return a;
jpayne@69 471 }
jpayne@69 472 template <typename... Rest>
jpayne@69 473 static inline constexpr size_t maxSize(size_t a, size_t b, Rest... rest) {
jpayne@69 474 return maxSize(kj::max(a, b), rest...);
jpayne@69 475 }
jpayne@69 476 // Returns the maximum of all the parameters.
jpayne@69 477 // TODO(someday): Generalize the above template and make it common. I tried, but C++ decided to
jpayne@69 478 // be difficult so I cut my losses.
jpayne@69 479
jpayne@69 480 static constexpr auto spaceSize = maxSize(sizeof(Variants)...);
jpayne@69 481 // TODO(msvc): This constant could just as well go directly inside space's bracket's, where it's
jpayne@69 482 // used, but MSVC suffers a parse error on `...`.
jpayne@69 483
jpayne@69 484 union {
jpayne@69 485 byte space[spaceSize];
jpayne@69 486
jpayne@69 487 void* forceAligned;
jpayne@69 488 // TODO(someday): Use C++11 alignas() once we require GCC 4.8 / Clang 3.3.
jpayne@69 489 };
jpayne@69 490
jpayne@69 491 template <typename... T>
jpayne@69 492 inline void doAll(T... t) {}
jpayne@69 493
jpayne@69 494 template <typename T>
jpayne@69 495 inline bool destroyVariant() {
jpayne@69 496 if (tag == typeIndex<T>()) {
jpayne@69 497 tag = 0;
jpayne@69 498 dtor(*reinterpret_cast<T*>(space));
jpayne@69 499 }
jpayne@69 500 return false;
jpayne@69 501 }
jpayne@69 502 void destroy() {
jpayne@69 503 doAll(destroyVariant<Variants>()...);
jpayne@69 504 }
jpayne@69 505
jpayne@69 506 template <typename T>
jpayne@69 507 inline bool copyVariantFrom(const OneOf& other) {
jpayne@69 508 if (other.is<T>()) {
jpayne@69 509 ctor(*reinterpret_cast<T*>(space), other.get<T>());
jpayne@69 510 }
jpayne@69 511 return false;
jpayne@69 512 }
jpayne@69 513 void copyFrom(const OneOf& other) {
jpayne@69 514 // Initialize as a copy of `other`. Expects that `this` starts out uninitialized, so the tag
jpayne@69 515 // is invalid.
jpayne@69 516 tag = other.tag;
jpayne@69 517 doAll(copyVariantFrom<Variants>(other)...);
jpayne@69 518 }
jpayne@69 519
jpayne@69 520 template <typename T>
jpayne@69 521 inline bool copyVariantFrom(OneOf& other) {
jpayne@69 522 if (other.is<T>()) {
jpayne@69 523 ctor(*reinterpret_cast<T*>(space), other.get<T>());
jpayne@69 524 }
jpayne@69 525 return false;
jpayne@69 526 }
jpayne@69 527 void copyFrom(OneOf& other) {
jpayne@69 528 // Initialize as a copy of `other`. Expects that `this` starts out uninitialized, so the tag
jpayne@69 529 // is invalid.
jpayne@69 530 tag = other.tag;
jpayne@69 531 doAll(copyVariantFrom<Variants>(other)...);
jpayne@69 532 }
jpayne@69 533
jpayne@69 534 template <typename T>
jpayne@69 535 inline bool moveVariantFrom(OneOf& other) {
jpayne@69 536 if (other.is<T>()) {
jpayne@69 537 ctor(*reinterpret_cast<T*>(space), kj::mv(other.get<T>()));
jpayne@69 538 }
jpayne@69 539 return false;
jpayne@69 540 }
jpayne@69 541 void moveFrom(OneOf& other) {
jpayne@69 542 // Initialize as a copy of `other`. Expects that `this` starts out uninitialized, so the tag
jpayne@69 543 // is invalid.
jpayne@69 544 tag = other.tag;
jpayne@69 545 doAll(moveVariantFrom<Variants>(other)...);
jpayne@69 546 }
jpayne@69 547
jpayne@69 548 template <typename T, typename... OtherVariants>
jpayne@69 549 inline bool copySubsetVariantFrom(const OneOf<OtherVariants...>& other) {
jpayne@69 550 if (other.template is<T>()) {
jpayne@69 551 tag = typeIndex<Decay<T>>();
jpayne@69 552 ctor(*reinterpret_cast<T*>(space), other.template get<T>());
jpayne@69 553 }
jpayne@69 554 return false;
jpayne@69 555 }
jpayne@69 556 template <typename... OtherVariants>
jpayne@69 557 void copyFromSubset(const OneOf<OtherVariants...>& other) {
jpayne@69 558 doAll(copySubsetVariantFrom<OtherVariants>(other)...);
jpayne@69 559 }
jpayne@69 560
jpayne@69 561 template <typename T, typename... OtherVariants>
jpayne@69 562 inline bool copySubsetVariantFrom(OneOf<OtherVariants...>& other) {
jpayne@69 563 if (other.template is<T>()) {
jpayne@69 564 tag = typeIndex<Decay<T>>();
jpayne@69 565 ctor(*reinterpret_cast<T*>(space), other.template get<T>());
jpayne@69 566 }
jpayne@69 567 return false;
jpayne@69 568 }
jpayne@69 569 template <typename... OtherVariants>
jpayne@69 570 void copyFromSubset(OneOf<OtherVariants...>& other) {
jpayne@69 571 doAll(copySubsetVariantFrom<OtherVariants>(other)...);
jpayne@69 572 }
jpayne@69 573
jpayne@69 574 template <typename T, typename... OtherVariants>
jpayne@69 575 inline bool moveSubsetVariantFrom(OneOf<OtherVariants...>& other) {
jpayne@69 576 if (other.template is<T>()) {
jpayne@69 577 tag = typeIndex<Decay<T>>();
jpayne@69 578 ctor(*reinterpret_cast<T*>(space), kj::mv(other.template get<T>()));
jpayne@69 579 }
jpayne@69 580 return false;
jpayne@69 581 }
jpayne@69 582 template <typename... OtherVariants>
jpayne@69 583 void moveFromSubset(OneOf<OtherVariants...>& other) {
jpayne@69 584 doAll(moveSubsetVariantFrom<OtherVariants>(other)...);
jpayne@69 585 }
jpayne@69 586 };
jpayne@69 587
jpayne@69 588 template <typename... Variants>
jpayne@69 589 template <uint i, typename First, typename... Rest>
jpayne@69 590 struct OneOf<Variants...>::HasAll<i, First, Rest...>
jpayne@69 591 : public HasAll<typeIndexOrZero<First>(), Rest...> {};
jpayne@69 592 template <typename... Variants>
jpayne@69 593 template <uint i>
jpayne@69 594 struct OneOf<Variants...>::HasAll<i>: public _::SuccessIfNotZero<i> {};
jpayne@69 595
jpayne@69 596 template <typename... Variants>
jpayne@69 597 template <uint i>
jpayne@69 598 void OneOf<Variants...>::allHandled() {
jpayne@69 599 // After a series of if/else blocks handling each variant of the OneOf, have the final else
jpayne@69 600 // block call allHandled<n>() where n is the number of variants. This will fail to compile
jpayne@69 601 // if new variants are added in the future.
jpayne@69 602
jpayne@69 603 static_assert(i == sizeof...(Variants), "new OneOf variants need to be handled here");
jpayne@69 604 KJ_UNREACHABLE;
jpayne@69 605 }
jpayne@69 606
jpayne@69 607 #if KJ_CPP_STD > 201402L
jpayne@69 608 #define KJ_SWITCH_ONEOF(value) \
jpayne@69 609 switch (auto _kj_switch_subject = (value)._switchSubject(); _kj_switch_subject->which())
jpayne@69 610 #else
jpayne@69 611 #define KJ_SWITCH_ONEOF(value) \
jpayne@69 612 /* Without C++17, we can only support one switch per containing block. Deal with it. */ \
jpayne@69 613 auto _kj_switch_subject = (value)._switchSubject(); \
jpayne@69 614 switch (_kj_switch_subject->which())
jpayne@69 615 #endif
jpayne@69 616 #if !_MSC_VER || defined(__clang__)
jpayne@69 617 #define KJ_CASE_ONEOF(name, ...) \
jpayne@69 618 break; \
jpayne@69 619 case ::kj::Decay<decltype(*_kj_switch_subject)>::template tagFor<__VA_ARGS__>(): \
jpayne@69 620 for (auto& name = _kj_switch_subject->template get<__VA_ARGS__>(), *_kj_switch_done = &name; \
jpayne@69 621 _kj_switch_done; _kj_switch_done = nullptr)
jpayne@69 622 #else
jpayne@69 623 // TODO(msvc): The latest MSVC which ships with VS2019 now ICEs on the implementation above. It
jpayne@69 624 // appears we can hack around the problem by moving the `->template get<>()` syntax to an outer
jpayne@69 625 // `if`. (This unfortunately allows wonky syntax like `KJ_CASE_ONEOF(a, B) { } else { }`.)
jpayne@69 626 // https://developercommunity.visualstudio.com/content/problem/1143733/internal-compiler-error-on-v1670.html
jpayne@69 627 #define KJ_CASE_ONEOF(name, ...) \
jpayne@69 628 break; \
jpayne@69 629 case ::kj::Decay<decltype(*_kj_switch_subject)>::template tagFor<__VA_ARGS__>(): \
jpayne@69 630 if (auto* _kj_switch_done = &_kj_switch_subject->template get<__VA_ARGS__>()) \
jpayne@69 631 for (auto& name = *_kj_switch_done; _kj_switch_done; _kj_switch_done = nullptr)
jpayne@69 632 #endif
jpayne@69 633 #define KJ_CASE_ONEOF_DEFAULT break; default:
jpayne@69 634 // Allows switching over a OneOf.
jpayne@69 635 //
jpayne@69 636 // Example:
jpayne@69 637 //
jpayne@69 638 // kj::OneOf<int, float, const char*> variant;
jpayne@69 639 // KJ_SWITCH_ONEOF(variant) {
jpayne@69 640 // KJ_CASE_ONEOF(i, int) {
jpayne@69 641 // doSomethingWithInt(i);
jpayne@69 642 // }
jpayne@69 643 // KJ_CASE_ONEOF(s, const char*) {
jpayne@69 644 // doSomethingWithString(s);
jpayne@69 645 // }
jpayne@69 646 // KJ_CASE_ONEOF_DEFAULT {
jpayne@69 647 // doSomethingElse();
jpayne@69 648 // }
jpayne@69 649 // }
jpayne@69 650 //
jpayne@69 651 // Notes:
jpayne@69 652 // - If you don't handle all possible types and don't include a default branch, you'll get a
jpayne@69 653 // compiler warning, just like a regular switch() over an enum where one of the enum values is
jpayne@69 654 // missing.
jpayne@69 655 // - There's no need for a `break` statement in a KJ_CASE_ONEOF; it is implied.
jpayne@69 656 // - Under C++11 and C++14, only one KJ_SWITCH_ONEOF() can appear in a block. Wrap the switch in
jpayne@69 657 // a pair of braces if you need a second switch in the same block. If C++17 is enabled, this is
jpayne@69 658 // not an issue.
jpayne@69 659 //
jpayne@69 660 // Implementation notes:
jpayne@69 661 // - The use of __VA_ARGS__ is to account for template types that have commas separating type
jpayne@69 662 // parameters, since macros don't recognize <> as grouping.
jpayne@69 663 // - _kj_switch_done is really used as a boolean flag to prevent the for() loop from actually
jpayne@69 664 // looping, but it's defined as a pointer since that's all we can define in this context.
jpayne@69 665
jpayne@69 666 } // namespace kj
jpayne@69 667
jpayne@69 668 KJ_END_HEADER