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 Alexandru Ermicioi 29 **/ 30 module aermicioi.aedi_property_reader.convertor.type_guesser; 31 32 /** 33 Interface for components that are able to guess the D type of serialized component. 34 **/ 35 @safe interface TypeGuesser(SerializedType) { 36 37 public { 38 39 /** 40 Guess the D type of serialized based on information available in it. 41 42 Params: 43 serialized = the component for which guesser will attempt to guess the type. 44 45 Returns: 46 TypeInfo guessed type 47 **/ 48 TypeInfo guess(SerializedType serialized) const; 49 } 50 } 51 52 /** 53 A guesser that simply doesn't guess anything and just returns the SerializedType 54 **/ 55 @safe class SimpleTypeGuesser(SerializedType) : TypeGuesser!SerializedType { 56 57 public { 58 59 /** 60 Guess the D type of serialized based on information available in it. 61 62 Params: 63 serialized = the component for which guesser will attempt to guess the type. 64 65 Returns: 66 TypeInfo guessed type 67 **/ 68 TypeInfo guess(SerializedType serialized) const { 69 return typeid(SerializedType); 70 } 71 } 72 } 73 74 /** 75 Guesser based on std.conv.to family of functions. 76 77 Guesser based on std.conv.to family of functions. It will attempt to convert sequentially 78 to all ConvertableTypes until one succeeds, for which the typeinfo will be returned. 79 **/ 80 @safe class StdConvTypeGuesser(SerializedType, ConvertableTypes...) : TypeGuesser!SerializedType { 81 82 public { 83 84 /** 85 Guess the D type of serialized based on eager attempts to convert serialized to one of ConvertableTypes. 86 87 Params: 88 serialized = the component for which guesser will attempt to guess the type. 89 90 Returns: 91 TypeInfo guessed type for which std.conv.to didn't fail. 92 **/ 93 TypeInfo guess(SerializedType serialized) const { 94 import std.conv : to, ConvException; 95 96 foreach (ConvertableType; ConvertableTypes) { 97 try { 98 cast(void) serialized.to!ConvertableType; 99 return typeid(ConvertableType); 100 } catch (ConvException ex) { 101 102 } 103 } 104 105 bugfix: return typeid(SerializedType); // Well without this magical label flow analysis thinks that code won't reach up to this point, which is untrue. 106 } 107 } 108 } 109 110 /** 111 A type guesser that will attempt to downcast passed object to a Type from Types list and 112 use particular type guesser on it. 113 **/ 114 class DelegatingObjectTypeGuesser(Types...) : TypeGuesser!Object { 115 import std.meta : staticMap; 116 import aermicioi.aedi_property_reader.convertor.placeholder; 117 118 staticMap!(TypeGuesser, Types) guessers; 119 120 public { 121 122 /** 123 Constructor for delegating object type guesser 124 125 Params: 126 guessers = a list of guessers for this type guesser. 127 **/ 128 this(typeof(this.guessers) guessers) 129 in { 130 import std.conv : text; 131 static foreach (guesser; guessers) { 132 assert(guesser !is null, text("Expected a guesser of type ", typeid(guesser), " not null")); 133 } 134 } 135 do { 136 this.guessers = guessers; 137 } 138 139 /** 140 Guess the D type of serialized based on eager attempts to convert serialized to one of ConvertableTypes. 141 142 Params: 143 serialized = the component for which guesser will attempt to guess the type. 144 145 Returns: 146 TypeInfo guessed type for which std.conv.to didn't fail. 147 **/ 148 TypeInfo guess(Object serialized) const { 149 static foreach (index, Type; Types) { 150 if (serialized.identify is typeid(Type)) { 151 152 return guessers[index].guess(serialized.unwrap!Type); 153 } 154 } 155 156 return typeid(Object); 157 } 158 } 159 } 160 161 /** 162 Alias for StdConvTypeGuesser with serialized type as string. 163 **/ 164 alias StringStdConvTypeGuesser(ConvertableTypes...) = StdConvTypeGuesser!(string, ConvertableTypes); 165 166 /** 167 Alias for StringStdConvTypeGuesser with scalar types as convertable types. 168 **/ 169 alias StringToScalarConvTypeGuesser = StringStdConvTypeGuesser!( 170 bool, 171 long, 172 double, 173 char, 174 bool[], 175 long[], 176 double[], 177 string[] 178 );