#pragma once #include #include #include namespace signal_garden { // General alignment, including non-power-of-two values. This does not allocate. [[nodiscard]] constexpr std::optional align_up(std::size_t value, std::size_t alignment) noexcept { if (alignment == 0) return std::nullopt; const auto remainder = value % alignment; const auto padding = remainder == 0 ? 0 : alignment - remainder; if (value > std::numeric_limits::max() - padding) return std::nullopt; return value + padding; } // Preconditions become checked results at the allocation boundary. [[nodiscard]] constexpr std::optional checked_bytes(std::size_t count, std::size_t stride, std::size_t budget) noexcept { if (stride == 0 || count > budget / stride) return std::nullopt; return count * stride; } } // namespace signal_garden