1 /** 2 License: 3 Boost Software License - Version 1.0 - August 17th, 2003 4 5 Permission is hereby granted, free of charge, to any person or organization 6 obtaining a copy of the software and accompanying documentation covered by 7 this license (the "Software") to use, reproduce, display, distribute, 8 execute, and transmit the Software, and to prepare derivative works of the 9 Software, and to permit third-parties to whom the Software is furnished to 10 do so, all subject to the following: 11 12 The copyright notices in the Software and this entire statement, including 13 the above license grant, this restriction and the following disclaimer, 14 must be included in all copies of the Software, in whole or in part, and 15 all derivative works of the Software, unless such copies or derivative 16 works are solely in the form of machine-executable object code generated by 17 a source language processor. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 22 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 23 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 24 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 DEALINGS IN THE SOFTWARE. 26 27 Authors: 28 aermicioi 29 **/ 30 module aermicioi.aedi_property_reader.sdlang.convertor; 31 32 import aermicioi.aedi_property_reader.core.convertor; 33 import aermicioi.aedi_property_reader.core.inspector; 34 import aermicioi.aedi_property_reader.core.accessor; 35 import aermicioi.aedi_property_reader.sdlang.inspector; 36 import aermicioi.aedi.exception.invalid_cast_exception : InvalidCastException; 37 import aermicioi.aedi_property_reader.sdlang.accessor : SdlangElement; 38 import sdlang.ast; 39 import sdlang; 40 import std.conv; 41 import std.traits; 42 import std.meta; 43 import std.experimental.allocator; 44 45 public { 46 import aermicioi.aedi_property_reader.sdlang.sdlang : accessor; 47 enum SdlangAccessorFactory(From : SdlangElement) = () => new RuntimeFieldAccessor!SdlangElement(accessor()); 48 enum SdlangInspectorFactory(From : SdlangElement) = () => new TaggedInspector!(SdlangElement, Tag)(new SdlangTagInspector); 49 } 50 51 alias SdlangConvertor = ChainedAdvisedConvertor!( 52 AdvisedConvertor!(convert, destruct), 53 AdvisedConvertor!( 54 SdlangAccessorFactory, 55 CompositeSetterFactory, 56 CompositeInspectorFactory, 57 SdlangInspectorFactory 58 ) 59 ).AdvisedConvertorImplementation; 60 61 void convert(To, From : Tag)(in From from, ref To to, RCIAllocator allocator = theAllocator) if (!is(To == enum) && !isNumeric!To && !isSomeChar!To && !isSomeString!To) { 62 try { 63 64 to = (cast() from).expectValue!To; 65 } catch (ValueNotFoundException e) { 66 67 throw new InvalidCastException(text("Could not convert value to requested ", typeid(To), " value", e)); 68 } 69 } 70 71 void convert(To, From : Tag)(in From from, ref To to, RCIAllocator allocator = theAllocator) if (!is(To == enum) && isNumeric!To && isFloatingPoint!To) { 72 try { 73 74 static if (is(typeof((cast() from).expectValue!To))) { 75 76 to = (cast() from).expectValue!To; 77 } else { 78 79 static foreach(Numeric; AliasSeq!(real, double, float)) { 80 foreach (value; (cast() from).values) { 81 if (value.type is typeid(Numeric)) { 82 to = (cast() from).expectValue!Numeric.to!To; 83 return; 84 } 85 } 86 } 87 88 throw new InvalidCastException(text("Could not convert value to requested ", typeid(To), " value")); 89 } 90 } catch (ValueNotFoundException e) { 91 92 throw new InvalidCastException(text("Could not convert value to requested ", typeid(To), " value"), e); 93 } 94 } 95 96 void convert(To, From : Tag)(in From from, ref To to, RCIAllocator allocator = theAllocator) if (!is(To == enum) && isNumeric!To && !isFloatingPoint!To) { 97 try { 98 99 static if (is(typeof((cast() from).expectValue!To))) { 100 101 to = (cast() from).expectValue!To; 102 } else { 103 104 static foreach(Numeric; AliasSeq!(long, int)) { 105 foreach (value; (cast() from).values) { 106 if (value.type is typeid(Numeric)) { 107 to = (cast() from).expectValue!Numeric.to!To; 108 return; 109 } 110 } 111 } 112 113 throw new InvalidCastException(text("Could not convert value to requested ", typeid(To), " value")); 114 } 115 } catch (ValueNotFoundException e) { 116 117 throw new InvalidCastException(text("Could not convert value to requested ", typeid(To), " value"), e); 118 } 119 } 120 121 void convert(To : E[], From : Tag, E)(in From from, ref To to, RCIAllocator allocator = theAllocator) 122 if (!is(To == enum) && !is(To : ubyte[]) && !isSomeString!To) { 123 124 import std.variant; 125 to = allocator.makeArray!E(from.values.length); 126 127 foreach (index, ref value; to) { 128 try { 129 130 value = from.values[index].get!E; 131 } catch (VariantException e) { 132 133 throw new InvalidCastException(text("Could not convert value to requested ", typeid(To), " value ", e)); 134 } 135 } 136 } 137 138 void convert(To, From : Tag)(in From from, ref To to, RCIAllocator allocator = theAllocator) if (!is(To == enum) && isSomeChar!To) { 139 140 try { 141 142 to = (cast() from).expectValue!string.to!To; 143 } catch (ValueNotFoundException e) { 144 145 throw new InvalidCastException(text("Could not convert value to requested ", typeid(To), " value", e)); 146 } 147 } 148 149 void convert(To : T[], From : Tag, T)(in From from, ref To to, RCIAllocator allocator = theAllocator) if (!is(To == enum) && isSomeChar!T) { 150 151 try { 152 153 to = (cast() from).expectValue!string.to!To; 154 } catch (ValueNotFoundException e) { 155 156 throw new InvalidCastException(text("Could not convert value to requested ", typeid(To), " value", e)); 157 } 158 } 159 160 void convert(To, From : Attribute)(in From from, ref To to, RCIAllocator allocator = theAllocator) if (!is(To == enum) && !isNumeric!To && !isSomeChar!To) { 161 import std.variant : VariantException; 162 163 try { 164 to = cast(To) from.value.get!To; 165 166 } catch (VariantException e) { 167 168 throw new InvalidCastException(text("Could not convert value to requested ", typeid(To), " value", e)); 169 } 170 } 171 172 void convert(To : T[], From : Attribute, T)(in From from, ref To to, RCIAllocator allocator = theAllocator) if (!is(To == enum) && isSomeChar!T) { 173 import std.variant : VariantException; 174 175 try { 176 to = cast(To) from.value.get!string.to!To; 177 178 } catch (VariantException e) { 179 180 throw new InvalidCastException(text("Could not convert value to requested ", typeid(To), " value", e)); 181 } 182 } 183 184 void convert(To, From : Attribute)(in From from, ref To to, RCIAllocator allocator = theAllocator) if (!is(To == enum) && !isNumeric!To && isSomeChar!To) { 185 import std.variant : VariantException; 186 187 try { 188 to = cast(To) from.value.get!string.to!To; 189 190 } catch (VariantException e) { 191 192 throw new InvalidCastException(text("Could not convert value to requested ", typeid(To), " value", e)); 193 } 194 } 195 196 void convert(To, From : Attribute)(in From from, ref To to, RCIAllocator allocator = theAllocator) if (!is(To == enum) && isNumeric!To && isFloatingPoint!To) { 197 import std.variant : VariantException; 198 199 try { 200 static foreach (Numeric; AliasSeq!(real, double, float)) { 201 if (from.value.type is typeid(Numeric)) { 202 203 to = cast(To) from.value.get!Numeric.to!To; 204 return; 205 } 206 } 207 208 throw new InvalidCastException(text("Could not convert value to requested ", typeid(To), " value")); 209 } catch (VariantException e) { 210 211 throw new InvalidCastException(text("Could not convert value to requested ", typeid(To), " value", e)); 212 } 213 } 214 215 void convert(To, From : Attribute)(in From from, ref To to, RCIAllocator allocator = theAllocator) if (!is(To == enum) && isNumeric!To && !isFloatingPoint!To) { 216 import std.variant : VariantException; 217 218 try { 219 static foreach (Numeric; AliasSeq!(long, int)) { 220 if (from.value.type is typeid(Numeric)) { 221 222 to = cast(To) from.value.get!Numeric.to!To; 223 return; 224 } 225 } 226 227 throw new InvalidCastException(text("Could not convert value to requested ", typeid(To), " value")); 228 } catch (VariantException e) { 229 230 throw new InvalidCastException(text("Could not convert value to requested ", typeid(To), " value"), e); 231 } 232 } 233 234 void convert(To, From : Tag)(in From from, ref To to, RCIAllocator allocator = theAllocator) if (is(To == enum)) { 235 string temp; 236 from.convert!string(temp, allocator); 237 to = temp.to!To; 238 temp.destruct(allocator); 239 } 240 241 void convert(To, From : Attribute)(in From from, ref To to, RCIAllocator allocator = theAllocator) if (is(To == enum)) { 242 string temp; 243 from.convert!string(temp, allocator); 244 to = temp.to!To; 245 temp.destruct(allocator); 246 } 247 248 void convert(To, From : SdlangElement)(in From from, ref To to, RCIAllocator allocator = theAllocator) { 249 250 final switch (from.kind) { 251 case SdlangElement.Kind.tag: { 252 (cast(const(Tag)) from).convert(to, allocator); 253 return; 254 } 255 256 case SdlangElement.Kind.attribute: { 257 (cast(const(Attribute)) from).convert(to, allocator); 258 return; 259 } 260 } 261 } 262 263 void destruct(To)(ref To to, RCIAllocator allocator = theAllocator) { 264 265 destroy(to); 266 to = To.init; 267 }