| 314 | } |
| 315 | |
| 316 | tl::expected<std::chrono::milliseconds, std::string> |
| 317 | parse_duration(std::string_view duration) |
| 318 | { |
| 319 | if (duration.empty()) { |
| 320 | return tl::unexpected("invalid empty duration: \"\""); |
| 321 | } |
| 322 | |
| 323 | uint64_t factor_ms = 0; |
| 324 | size_t suffix_len = 1; |
| 325 | char last_ch = duration.back(); |
| 326 | |
| 327 | // Check for two-character suffix "ms" |
| 328 | if (duration.length() >= 2 && last_ch == 's' |
| 329 | && duration[duration.length() - 2] == 'm') { |
| 330 | factor_ms = 1; |
| 331 | suffix_len = 2; |
| 332 | } else { |
| 333 | // Single-character suffixes |
| 334 | switch (last_ch) { |
| 335 | case 's': |
| 336 | factor_ms = 1000; |
| 337 | break; |
| 338 | case 'm': |
| 339 | factor_ms = 60 * 1000; |
| 340 | break; |
| 341 | case 'h': |
| 342 | factor_ms = 60 * 60 * 1000; |
| 343 | break; |
| 344 | case 'd': |
| 345 | factor_ms = 24 * 60 * 60 * 1000; |
| 346 | break; |
| 347 | default: |
| 348 | return tl::unexpected( |
| 349 | FMT("invalid suffix (supported: ms (millisecond), s (second), m " |
| 350 | "(minute), h (hour), d (day)): \"{}\"", |
| 351 | duration)); |
| 352 | } |
| 353 | } |
| 354 | |
| 355 | TRY_ASSIGN( |
| 356 | auto value, |
| 357 | parse_unsigned(duration.substr(0, duration.length() - suffix_len))); |
| 358 | return std::chrono::milliseconds(factor_ms * value); |
| 359 | } |
| 360 | |
| 361 | tl::expected<int64_t, std::string> |
| 362 | parse_signed(std::string_view value, |
no test coverage detected