Fix JSON serialization of numeric types

This commit is contained in:
Kovid Goyal 2023-01-25 10:37:12 +05:30
parent 623f999a54
commit ecc3e96da8
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C

View File

@ -183,7 +183,7 @@ private:
case DT_NONE: case DT_NONE:
out << "nil"; break; out << "nil"; break;
case DT_BOOL: case DT_BOOL:
out << b ? "true" : "false"; break; out << (b ? "true" : "false"); break;
case DT_INT: case DT_INT:
// this is not really correct since JS has various limits on numeric types, but good enough for us // this is not really correct since JS has various limits on numeric types, but good enough for us
serialize_integer(out, i); break; serialize_integer(out, i); break;
@ -226,22 +226,24 @@ public:
json_val(winrt::hstring const& text) : type(DT_STRING), s(winrt::to_string(text)) {} json_val(winrt::hstring const& text) : type(DT_STRING), s(winrt::to_string(text)) {}
json_val(std::wstring const& text) : type(DT_STRING), s(winrt::to_string(text)) {} json_val(std::wstring const& text) : type(DT_STRING), s(winrt::to_string(text)) {}
json_val(std::string_view text) : type(DT_STRING), s(text) {} json_val(std::string_view text) : type(DT_STRING), s(text) {}
json_val(int32_t num) : type(DT_INT), i(num) {}
json_val(int64_t num) : type(DT_INT), i(num) {}
json_val(std::vector<json_val> &&items) : type(DT_LIST), list(items) {} json_val(std::vector<json_val> &&items) : type(DT_LIST), list(items) {}
json_val(std::map<std::string, json_val> &&m) : type(DT_OBJECT), object(m) {} json_val(std::map<std::string, json_val> &&m) : type(DT_OBJECT), object(m) {}
json_val(std::initializer_list<std::pair<const std::string, json_val>> const& vals) : type(DT_OBJECT), object(vals) { } json_val(std::initializer_list<std::pair<const std::string, json_val>> const& vals) : type(DT_OBJECT), object(vals) { }
json_val(bool x) : type(DT_BOOL), b(x) {}
json_val(double x) : type(DT_FLOAT), f(x) {}
json_val(HRESULT hr) : type(DT_STRING) { static json_val from_bool(bool x) { json_val ans; ans.type = DT_BOOL; ans.b = x; return ans; }
static json_val from_double(double x) { json_val ans; ans.type = DT_FLOAT; ans.f = x; return ans; }
static json_val from_integer(int64_t x) { json_val ans; ans.type = DT_INT; ans.i = x; return ans; }
static json_val from_hresult(HRESULT hr) {
json_val ans; ans.type = DT_STRING;
std::array<char, 16> str; std::array<char, 16> str;
str[0] = '0'; str[1] = 'x'; str[0] = '0'; str[1] = 'x';
if (auto [ptr, ec] = std::to_chars(str.data()+2, str.data() + str.size(), (uint32_t)hr, 16); ec == std::errc()) { if (auto [ptr, ec] = std::to_chars(str.data()+2, str.data() + str.size(), (uint32_t)hr, 16); ec == std::errc()) {
s = std::string(str.data(), ptr - str.data()); ans.s = std::string(str.data(), ptr - str.data());
} else { } else {
throw std::exception(std::make_error_code(ec).message().c_str()); throw std::exception(std::make_error_code(ec).message().c_str());
} }
return ans;
} }
json_val(VoiceInformation const& voice) : type(DT_OBJECT) { json_val(VoiceInformation const& voice) : type(DT_OBJECT) {
@ -298,8 +300,8 @@ public:
{"type", json_val(label)}, {"type", json_val(label)},
{"text", json_val(cue.Text())}, {"text", json_val(cue.Text())},
{"start_time", json_val(cue.StartTime())}, {"start_time", json_val(cue.StartTime())},
{"start_pos_in_text", json_val(cue.StartPositionInInput().Value())}, {"start_pos_in_text", json_val::from_integer(cue.StartPositionInInput().Value())},
{"end_pos_in_text", json_val(cue.EndPositionInInput().Value())}, {"end_pos_in_text", json_val::from_integer(cue.EndPositionInInput().Value())},
}; };
} }
@ -320,8 +322,8 @@ output(id_type cmd_id, std::string_view const &msg_type, json_val const &&msg) {
static void static void
output_error(id_type cmd_id, std::string_view const &msg, std::string_view const &error, int64_t line, HRESULT hr=S_OK) { output_error(id_type cmd_id, std::string_view const &msg, std::string_view const &error, int64_t line, HRESULT hr=S_OK) {
std::map<std::string, json_val> m = {{"msg", json_val(msg)}, {"error", json_val(error)}, {"file", json_val("winspeech.cpp")}, {"line", json_val(line)}}; std::map<std::string, json_val> m = {{"msg", json_val(msg)}, {"error", json_val(error)}, {"file", json_val("winspeech.cpp")}, {"line", json_val::from_integer(line)}};
if (hr != S_OK) m["hr"] = json_val(hr); if (hr != S_OK) m["hr"] = json_val::from_hresult(hr);
output(cmd_id, "error", std::move(m)); output(cmd_id, "error", std::move(m));
} }
@ -831,6 +833,7 @@ class Synthesizer {
stop_current_activity(); stop_current_activity();
current_cmd_id.store(cmd_id); current_cmd_id.store(cmd_id);
} }
output(cmd_id, "synthesizing", {{"ssml", json_val::from_bool(is_ssml)}});
bool ok = false; bool ok = false;
try { try {
if (is_ssml) stream = co_await synth.SynthesizeSsmlToStreamAsync(text); if (is_ssml) stream = co_await synth.SynthesizeSsmlToStreamAsync(text);
@ -931,7 +934,7 @@ handle_stdin_message(winrt::hstring const &&msg) {
auto vol = parse_double(parts[0].data()); auto vol = parse_double(parts[0].data());
sx.volume(vol); sx.volume(vol);
} }
output(cmd_id, "volume", {{"value", json_val(sx.volume())}}); output(cmd_id, "volume", {{"value", json_val::from_double(sx.volume())}});
} }
else throw std::string("Unknown command: ") + winrt::to_string(command); else throw std::string("Unknown command: ") + winrt::to_string(command);
} CATCH_ALL_EXCEPTIONS("Error handling input message", cmd_id); } CATCH_ALL_EXCEPTIONS("Error handling input message", cmd_id);