1 /******************************************************************************* 2 3 Helper function for formatting a SmartUnion's active member to a string. 4 5 This function is not placed in the SmartUnion class itself so as to avoid 6 spreading the dependency on ocean.text.convert.Formatter throughout the 7 codebase. 8 9 Copyright: 10 Copyright (c) 2018 dunnhumby Germany GmbH. 11 All rights reserved. 12 13 License: 14 Boost Software License Version 1.0. See LICENSE_BOOST.txt for details. 15 Alternatively, this file may be distributed under the terms of the Tango 16 3-Clause BSD License (see LICENSE_BSD.txt for details). 17 18 *******************************************************************************/ 19 20 module ocean.text.formatter.SmartUnion; 21 22 import ocean.meta.types.Qualifiers; 23 import ocean.core.SmartUnion; 24 import ocean.core.Verify; 25 import ocean.text.convert.Formatter; 26 27 /******************************************************************************* 28 29 Gets a wrapper struct with a toString method to format the provided smart 30 union. 31 32 Params: 33 SU = type of smart union to get formatting wrapper for 34 smart_union = smart union to get formatting wrapper for 35 include_name = flag to toggle formatting of the name of the active union 36 member. If true, format output will look like 37 "<activename>: value". If false, format output will look like 38 "value" 39 40 *******************************************************************************/ 41 42 public SmartUnionFormatter!(SU) asActiveField ( SU ) ( SU smart_union, 43 bool include_name = false ) 44 { 45 return SmartUnionFormatter!(SU)(smart_union, include_name); 46 } 47 48 /// 49 unittest 50 { 51 union U 52 { 53 int i; 54 cstring s; 55 } 56 57 SmartUnion!(U) su; 58 59 // format from ocean.text.convert.Formatter 60 format("union active member: {}", asActiveField(su)); 61 } 62 63 /******************************************************************************* 64 65 Struct that wraps a smart union with a toString method, for Formatter 66 compatibility. 67 68 Params: 69 SU = type of smart union to format 70 71 *******************************************************************************/ 72 73 private struct SmartUnionFormatter ( SU ) 74 { 75 import ocean.meta.types.Templates : TemplateInstanceArgs; 76 77 static assert(is(TemplateInstanceArgs!(SmartUnion, SU))); 78 79 alias typeof(this) This; 80 81 /// Smart union to format. 82 private SU smart_union; 83 84 /// Flag to toggle formatting of the name of the active union member. If 85 /// true, format output will look like "<activename>: value". If false, 86 /// format output will look like "value". 87 private bool include_name; 88 89 /// Formatting sink delegate, passed to toString and used by 90 /// formatUnionMember. 91 static private FormatterSink sink; 92 93 /*************************************************************************** 94 95 Formats the smart union as a string to the provided sink delegate 96 (suitable for use with ocean.text.convert.Formatter). The formatted text 97 depends on whether a field of the union is active or not and whether 98 the `include_name` member is true or false: 99 * No union field active; `include_name` is: 100 - true: "<none>". 101 - false: "". 102 * Union field active; `include_name` is: 103 - true: "<name>: value". 104 - false: "value". 105 106 Params: 107 sink = formatter sink delegate to use 108 109 ***************************************************************************/ 110 111 public void toString ( scope FormatterSink sink ) 112 { 113 if ( this.smart_union.active ) 114 { 115 if ( this.include_name ) 116 sformat(sink, "<{}>: ", this.smart_union.active_name); 117 118 This.sink = sink; 119 scope ( exit ) This.sink = null; 120 121 callWithActive!(formatUnionMember)(this.smart_union); 122 } 123 else 124 { 125 if ( this.include_name ) 126 sformat(sink, "<{}>", this.smart_union.active_name); 127 } 128 } 129 130 /*************************************************************************** 131 132 Formats the specified argument with the static sink delegate. 133 134 Note: this function has to be public, so that it can be accessed by the 135 callWithActive function in ocean.core.SmartUnion. It is not intended to 136 be called by users. 137 138 Params: 139 T = type of union member to format 140 union_member = union member to format 141 142 ***************************************************************************/ 143 144 // FIXME_IN_D2: `package ocean.core` 145 static public void formatUnionMember ( T ) ( T union_member ) 146 { 147 verify(This.sink !is null); 148 sformat(sink, "{}", union_member); 149 } 150 } 151 152 version (unittest) 153 { 154 import ocean.core.Test; 155 } 156 157 unittest 158 { 159 union U 160 { 161 int i; 162 cstring s; 163 } 164 165 SmartUnion!(U) su; 166 167 // Inactive union. 168 test!("==")(format("{}", asActiveField(su)), ""); 169 170 // Inactive union, plus name formatting. 171 test!("==")(format("{}", asActiveField(su, true)), "<none>"); 172 173 // i active. 174 su.i = 23; 175 test!("==")(format("{}", asActiveField(su)), "23"); 176 177 // s active. 178 su.s = "hello"; 179 test!("==")(format("{}", asActiveField(su)), "hello"); 180 181 // s active, plus name formatting. 182 test!("==")(format("{}", asActiveField(su, true)), "<s>: hello"); 183 }