55// better json error messages, see https://json.nlohmann.me/api/macros/json_diagnostics/
66#define JSON_DIAGNOSTICS 1 // NOLINT(cppcoreguidelines-macro-usage)
77#endif
8-
98#include < nlohmann/json.hpp>
109
10+ #include < core/helper/types.hpp>
11+
1112#include " ./expected.hpp"
1213#include " ./windows.hpp"
1314
@@ -49,6 +50,12 @@ NLOHMANN_JSON_NAMESPACE_END
4950
5051namespace json {
5152
53+ enum class ParseError : u8 {
54+ OpenError,
55+ ReadError,
56+ FormatError,
57+ };
58+
5259 template <typename T>
5360 [[nodiscard]] helper::expected<T, std::string> try_parse_json (const std::string& content) noexcept {
5461
@@ -68,22 +75,43 @@ namespace json {
6875 }
6976
7077 template <typename T>
71- [[nodiscard]] helper::expected<T, std::string> try_parse_json_file (const std::filesystem::path& file) noexcept {
78+ [[nodiscard]] helper::expected<T, std::pair<std::string, ParseError>> try_parse_json_file (
79+ const std::filesystem::path& file
80+ ) noexcept {
7281
7382 if (not std::filesystem::exists (file)) {
74- return helper::unexpected<std::string>{ fmt::format (" File '{}' doesn't exist" , file.string ()) };
83+ return helper::unexpected<std::pair<std::string, ParseError>>{ std::make_pair<std::string, ParseError>(
84+ fmt::format (" File '{}' doesn't exist" , file.string ()), ParseError::OpenError
85+ ) };
7586 }
7687
7788 std::ifstream file_stream{ file };
7889
7990 if (not file_stream.is_open ()) {
80- return helper::unexpected<std::string>{ fmt::format (" File '{}' couldn't be opened!" , file.string ()) };
91+ return helper::unexpected<std::pair<std::string, ParseError>>{ std::make_pair<std::string, ParseError>(
92+ fmt::format (" File '{}' couldn't be opened!" , file.string ()), ParseError::OpenError
93+ ) };
8194 }
8295
8396 std::stringstream result;
8497 result << file_stream.rdbuf ();
8598
86- return try_parse_json<T>(result.str ());
99+ file_stream.close ();
100+
101+ if (file_stream.fail ()) {
102+ return helper::unexpected<std::pair<std::string, ParseError>>{ std::make_pair<std::string, ParseError>(
103+ fmt::format (" Couldn't read from file '{}'" , file.string ()), ParseError::ReadError
104+ ) };
105+ }
106+
107+ auto parse_result = try_parse_json<T>(result.str ());
108+ if (not parse_result.has_value ()) {
109+ return helper::unexpected<std::pair<std::string, ParseError>>{
110+ std::make_pair<std::string, ParseError>(std::move (parse_result.error ()), ParseError::FormatError)
111+ };
112+ }
113+
114+ return parse_result.value ();
87115 }
88116
89117 template <typename T>
0 commit comments