#pragma once #include "Model.h" #include #include namespace timbre_core { enum class ValidationCode : std::uint8_t { Ok = 0, None = 0, TooManyProfiles, TooManyPatterns, TooManySchedules, TooManyHolidays, InvalidProfileId, DuplicateProfileId, InvalidPatternId, DuplicatePatternId, InvalidPhaseCount, InvalidPhaseDuration, PatternTotalTooLarge, InvalidHolidayId, DuplicateHolidayId, InvalidHolidayDate, InvalidScheduleId, DuplicateScheduleId, InvalidMinute, InvalidWeekdayMask, UnknownProfile, UnknownPattern, InvalidActiveProfile }; using ValidationError = ValidationCode; struct ValidationResult { bool valid = true; ValidationCode code = ValidationCode::Ok; ValidationCode error = ValidationCode::Ok; std::size_t index = 0; constexpr ValidationResult() = default; explicit constexpr ValidationResult(ValidationCode resultCode, std::size_t resultIndex = 0) noexcept : valid(resultCode == ValidationCode::Ok), code(resultCode), error(resultCode), index(resultIndex) {} constexpr bool ok() const noexcept { return valid; } constexpr bool isValid() const noexcept { return valid; } constexpr explicit operator bool() const noexcept { return valid; } const char* message() const noexcept; }; class ScheduleValidator { public: static ValidationResult validate(const AppState& state) noexcept; static ValidationResult validateState(const AppState& state) noexcept { return validate(state); } static ValidationResult validateAppState(const AppState& state) noexcept { return validate(state); } static bool valid(const AppState& state) noexcept { return validate(state).valid; } static bool isValid(const AppState& state) noexcept { return valid(state); } static ValidationResult validateProfile(const Profile& profile, std::size_t index = 0) noexcept; static ValidationResult validatePattern(const Pattern& pattern, std::size_t index = 0) noexcept; static ValidationResult validateSchedule(const Schedule& schedule, const AppState& state, std::size_t index = 0) noexcept; static ValidationResult validateHoliday(const Holiday& holiday, std::size_t index = 0) noexcept; static std::uint16_t patternTotalSeconds(const Pattern& pattern) noexcept { return pattern.totalSeconds(); } static bool validPhaseDuration(std::uint8_t value) noexcept { return value <= kMaxPhaseDurationSeconds; } static bool validPatternTotal(std::uint16_t totalSeconds) noexcept { return totalSeconds <= kMaxPatternTotalSeconds; } static bool validWeekdayMask(std::uint8_t value) noexcept { return value != 0 && (value & static_cast(~kAllWeekdaysMask)) == 0; } static bool validMinute(std::uint16_t minute) noexcept { return minute < 1440; } static bool validHolidayDate(std::uint8_t month, std::uint8_t day) noexcept; }; } // namespace timbre_core