@@ -20,9 +20,15 @@ Author(s):
2020
2121namespace winrt
2222{
23- // If we don't use winrt, nobody will include the ConversionTrait for winrt::guid .
24- // If nobody includes it, this forward declaration will suffice.
23+ // If we don't use winrt, nobody will include the ConversionTraits for winrt stuff .
24+ // If nobody includes it, these forward declarations will suffice.
2525 struct guid ;
26+ struct hstring ;
27+ namespace Windows ::Foundation
28+ {
29+ template <typename T>
30+ struct IReference ;
31+ }
2632}
2733
2834namespace TerminalApp ::JsonUtils
@@ -45,12 +51,21 @@ namespace TerminalApp::JsonUtils
4551 struct DeduceOptional
4652 {
4753 using Type = typename std::decay<T>::type;
54+ static constexpr bool IsOptional = false ;
4855 };
4956
5057 template <typename TOpt>
5158 struct DeduceOptional <std::optional<TOpt>>
5259 {
5360 using Type = typename std::decay<TOpt>::type;
61+ static constexpr bool IsOptional = true ;
62+ };
63+
64+ template <typename TOpt>
65+ struct DeduceOptional <::winrt::Windows::Foundation::IReference<TOpt>>
66+ {
67+ using Type = typename std::decay<TOpt>::type;
68+ static constexpr bool IsOptional = true ;
5469 };
5570 }
5671
@@ -105,7 +120,9 @@ namespace TerminalApp::JsonUtils
105120 template <typename T>
106121 struct ConversionTrait
107122 {
108- // FromJson, CanConvert are not defined so as to cause a compile error (which forces a specialization)
123+ // Forward-declare these so the linker can pick up specializations from elsewhere!
124+ T FromJson (const Json::Value&);
125+ bool CanConvert (const Json::Value& json);
109126 };
110127
111128 template <>
@@ -136,6 +153,18 @@ namespace TerminalApp::JsonUtils
136153 }
137154 };
138155
156+ #ifdef WINRT_BASE_H
157+ template <>
158+ struct ConversionTrait <winrt::hstring> : public ConversionTrait<std::wstring>
159+ {
160+ // Leverage the wstring converter's validation
161+ winrt::hstring FromJson (const Json::Value& json)
162+ {
163+ return winrt::hstring{ til::u8u16 (Detail::GetStringView (json)) };
164+ }
165+ };
166+ #endif
167+
139168 template <>
140169 struct ConversionTrait <bool >
141170 {
@@ -248,7 +277,7 @@ namespace TerminalApp::JsonUtils
248277 }
249278
250279 const auto string{ Detail::GetStringView (json) };
251- return (string.length () == 7 || string.length () == 3 ) && string.front () == ' #' ;
280+ return (string.length () == 7 || string.length () == 4 ) && string.front () == ' #' ;
252281 }
253282 };
254283
@@ -334,6 +363,18 @@ namespace TerminalApp::JsonUtils
334363 template <typename T, typename Converter>
335364 bool GetValue (const Json::Value& json, T& target, Converter&& conv)
336365 {
366+ if constexpr (Detail::DeduceOptional<T>::IsOptional)
367+ {
368+ // FOR OPTION TYPES
369+ // - If the json object is set to `null`, then
370+ // we'll instead set the target back to the empty optional.
371+ if (json.isNull ())
372+ {
373+ target = T{}; // zero-construct an empty optional
374+ return true ;
375+ }
376+ }
377+
337378 if (json)
338379 {
339380 if (!conv.CanConvert (json))
@@ -347,36 +388,6 @@ namespace TerminalApp::JsonUtils
347388 return false ;
348389 }
349390
350- // Method Description:
351- // - Overload on GetValue that will populate a std::optional with a value converted from json
352- // - If the json value doesn't exist we'll leave the target object unmodified.
353- // - If the json object is set to `null`, then
354- // we'll instead set the target back to nullopt.
355- // Arguments:
356- // - json: the json object to convert
357- // - target: the value to populate with the converted result
358- // Return Value:
359- // - a boolean indicating whether the optional was changed
360- //
361- // GetValue, type-deduced for optional, manual converter
362- template <typename TOpt, typename Converter>
363- bool GetValue (const Json::Value& json, std::optional<TOpt>& target, Converter&& conv)
364- {
365- if (json.isNull ())
366- {
367- target = std::nullopt ;
368- return true ; // null is valid for optionals
369- }
370-
371- std::decay_t <TOpt> local{};
372- if (GetValue (json, local, std::forward<Converter>(conv)))
373- {
374- target = std::move (local);
375- return true ;
376- }
377- return false ;
378- }
379-
380391 // GetValue, forced return type, manual converter
381392 template <typename T, typename Converter>
382393 std::decay_t <T> GetValue (const Json::Value& json, Converter&& conv)
0 commit comments