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.yaml.accessor; 31 32 import dyaml; 33 import aermicioi.aedi_property_reader.core.accessor; 34 import aermicioi.aedi.exception.not_found_exception : NotFoundException; 35 import std.exception; 36 import std.experimental.logger; 37 import aermicioi.aedi_property_reader.core.traits : n; 38 39 /** 40 An accessor allowing access to child yaml nodes of a parent yaml node by their name 41 **/ 42 class YamlNodePropertyAccessor : PropertyAccessor!(Node, Node) { 43 44 /** 45 Get a property out of component 46 47 Params: 48 component = a component which has some properties identified by property. 49 Throws: 50 NotFoundException in case when no requested property is available. 51 InvalidArgumentException in case when passed arguments are somehow invalid for use. 52 Returns: 53 FieldType accessed property. 54 **/ 55 Node access(Node component, in string property) const { 56 57 if (this.has(component, property)) { 58 return component[property]; 59 } 60 61 throw new NotFoundException("yaml tag " ~ component.tag ~ " doesn't have child " ~ property); 62 } 63 64 /** 65 Check if requested property is present in component. 66 67 Check if requested property is present in component. 68 The method could have allocation side effects due to the fact that 69 it is not restricted in calling access method of the accessor. 70 71 Params: 72 component = component which is supposed to have property 73 property = speculated property that is to be tested if it is present in component 74 Returns: 75 true if property is in component 76 **/ 77 bool has(in Node component, in string property) const nothrow { 78 try { 79 return component.isMapping && component.containsKey(property); 80 } catch (Exception e) { 81 82 debug(trace) error("Failed to check property ", property, " existence due to ", e).n; 83 } 84 85 return false; 86 } 87 88 /** 89 Identify the type of supported component. 90 91 Identify the type of supported component. It returns type info of component 92 if it is supported by accessor, otherwise it will return typeid(void) denoting that 93 the type isn't supported by accessor. The accessor is not limited to returning the type 94 info of passed component, it can actually return type info of super type or any type 95 given the returned type is implicitly convertible or castable to ComponentType. 96 97 Params: 98 component = the component for which accessor should identify the underlying type 99 100 Returns: 101 TypeInfo type information about passed component, or typeid(void) if component is not supported. 102 **/ 103 TypeInfo componentType(Node component) const nothrow { 104 return typeid(Node); 105 } 106 } 107 108 /** 109 An accessor allowing access to child yaml nodes of a parent yaml node by their index 110 **/ 111 class YamlIntegerIndexAccessor : PropertyAccessor!(Node, Node) { 112 113 /** 114 Get a property out of component 115 116 Params: 117 component = a component which has some properties identified by property. 118 Throws: 119 NotFoundException in case when no requested property is available. 120 InvalidArgumentException in case when passed arguments are somehow invalid for use. 121 Returns: 122 FieldType accessed property. 123 **/ 124 Node access(Node component, in string property) const { 125 126 if (this.has(component, property)) { 127 import std.conv : to; 128 129 return component[property.to!size_t]; 130 } 131 132 throw new NotFoundException("yaml tag " ~ component.tag ~ " doesn't have child on index " ~ property); 133 } 134 135 /** 136 Check if requested property is present in component. 137 138 Check if requested property is present in component. 139 The method could have allocation side effects due to the fact that 140 it is not restricted in calling access method of the accessor. 141 142 Params: 143 component = component which is supposed to have property 144 property = speculated property that is to be tested if it is present in component 145 Returns: 146 true if property is in component 147 **/ 148 bool has(in Node component, in string property) const nothrow { 149 try { 150 import std.string; 151 import std.conv; 152 153 return property.isNumeric && component.isSequence && (property.to!size_t < component.length); 154 } catch (Exception e) { 155 156 debug(trace) error("Failed to check property ", property, " existence due to ", e).n; 157 } 158 159 return false; 160 } 161 162 /** 163 Identify the type of supported component. 164 165 Identify the type of supported component. It returns type info of component 166 if it is supported by accessor, otherwise it will return typeid(void) denoting that 167 the type isn't supported by accessor. The accessor is not limited to returning the type 168 info of passed component, it can actually return type info of super type or any type 169 given the returned type is implicitly convertible or castable to ComponentType. 170 171 Params: 172 component = the component for which accessor should identify the underlying type 173 174 Returns: 175 TypeInfo type information about passed component, or typeid(void) if component is not supported. 176 **/ 177 TypeInfo componentType(Node component) const nothrow { 178 return typeid(Node); 179 } 180 181 }