mirror of
https://github.com/sebastiandine/Card-Collection-Manager-3.git
synced 2026-08-29 01:08:49 +00:00
major: initial release
* initial development * pipeline * pipeline * pipeline * pipeline * pipeline * pipeline * pipeline * pipeline * pipeline * pipeline * pipeline * pipeline * pipeline * pipeline * ci/cd * ci/cd * ci/cd * ci/cd * ci/cd * ci/cd * ci/cd * pokemon * pokemon * pokemon * pokemon * pokemon * pokemon * improvements * improvements * ci/cd * ci/cd * improvements * improvements * improvements * improvements * improvements * improvements * improvements * improvements * improvements --------- Co-authored-by: sdine <sdine@sdine.com>
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
// Pure functions for filename munging. Ported from the original `util/fs.rs` so
|
||||
// that file naming on disk stays identical between the two codebases.
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace ccm {
|
||||
|
||||
// Replace problematic characters so the result is safe to use as a filename
|
||||
// component. Mirrors `format_text_for_fs` in Rust (drops apostrophes/commas,
|
||||
// strips spaces, replaces `:` with `-`, `&` with `And`, `|` with `Or`,
|
||||
// flattens accented vowels). Pure; safe at any call site.
|
||||
std::string formatTextForFs(std::string_view text);
|
||||
|
||||
// Parse the trailing 1- or 2-digit numeric index from a filename. Examples:
|
||||
// "Image1.png" -> 1
|
||||
// "Image22.jpeg" -> 22
|
||||
// Returns 0 on parse failure, matching the optimistic Rust behavior.
|
||||
std::uint8_t parseIndexFromFilename(std::string_view filename) noexcept;
|
||||
|
||||
} // namespace ccm
|
||||
@@ -0,0 +1,150 @@
|
||||
#pragma once
|
||||
|
||||
// A minimal Result<T, E> type used as a sum-type for fallible operations.
|
||||
// Mirrors the Rust `Result<T, &str>` style used in the original codebase.
|
||||
//
|
||||
// We intentionally do not depend on tl::expected or std::expected so this
|
||||
// header stays buildable on every toolchain in our matrix (clang 14+, GCC 11+).
|
||||
|
||||
#include <new>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace ccm {
|
||||
|
||||
template <typename T, typename E = std::string>
|
||||
class Result {
|
||||
public:
|
||||
using value_type = T;
|
||||
using error_type = E;
|
||||
|
||||
static Result ok(T value) { return Result(OkTag{}, std::move(value)); }
|
||||
static Result err(E error) { return Result(ErrTag{}, std::move(error)); }
|
||||
|
||||
Result(const Result& other) : has_value_(other.has_value_) {
|
||||
if (has_value_) {
|
||||
::new (static_cast<void*>(&value_)) T(other.value_);
|
||||
} else {
|
||||
::new (static_cast<void*>(&error_)) E(other.error_);
|
||||
}
|
||||
}
|
||||
|
||||
Result(Result&& other) noexcept : has_value_(other.has_value_) {
|
||||
if (has_value_) {
|
||||
::new (static_cast<void*>(&value_)) T(std::move(other.value_));
|
||||
} else {
|
||||
::new (static_cast<void*>(&error_)) E(std::move(other.error_));
|
||||
}
|
||||
}
|
||||
|
||||
Result& operator=(const Result& other) {
|
||||
if (this == &other) return *this;
|
||||
destroy();
|
||||
has_value_ = other.has_value_;
|
||||
if (has_value_) {
|
||||
::new (static_cast<void*>(&value_)) T(other.value_);
|
||||
} else {
|
||||
::new (static_cast<void*>(&error_)) E(other.error_);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Result& operator=(Result&& other) noexcept {
|
||||
if (this == &other) return *this;
|
||||
destroy();
|
||||
has_value_ = other.has_value_;
|
||||
if (has_value_) {
|
||||
::new (static_cast<void*>(&value_)) T(std::move(other.value_));
|
||||
} else {
|
||||
::new (static_cast<void*>(&error_)) E(std::move(other.error_));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
~Result() { destroy(); }
|
||||
|
||||
[[nodiscard]] bool isOk() const noexcept { return has_value_; }
|
||||
[[nodiscard]] bool isErr() const noexcept { return !has_value_; }
|
||||
explicit operator bool() const noexcept { return has_value_; }
|
||||
|
||||
const T& value() const& {
|
||||
if (!has_value_) throw std::logic_error("Result::value() on err");
|
||||
return value_;
|
||||
}
|
||||
T& value() & {
|
||||
if (!has_value_) throw std::logic_error("Result::value() on err");
|
||||
return value_;
|
||||
}
|
||||
T&& value() && {
|
||||
if (!has_value_) throw std::logic_error("Result::value() on err");
|
||||
return std::move(value_);
|
||||
}
|
||||
|
||||
const E& error() const& {
|
||||
if (has_value_) throw std::logic_error("Result::error() on ok");
|
||||
return error_;
|
||||
}
|
||||
E&& error() && {
|
||||
if (has_value_) throw std::logic_error("Result::error() on ok");
|
||||
return std::move(error_);
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
T valueOr(U&& fallback) const& {
|
||||
return has_value_ ? value_ : static_cast<T>(std::forward<U>(fallback));
|
||||
}
|
||||
|
||||
private:
|
||||
struct OkTag {};
|
||||
struct ErrTag {};
|
||||
|
||||
Result(OkTag, T value) : has_value_(true) {
|
||||
::new (static_cast<void*>(&value_)) T(std::move(value));
|
||||
}
|
||||
Result(ErrTag, E error) : has_value_(false) {
|
||||
::new (static_cast<void*>(&error_)) E(std::move(error));
|
||||
}
|
||||
|
||||
void destroy() noexcept {
|
||||
if (has_value_) {
|
||||
value_.~T();
|
||||
} else {
|
||||
error_.~E();
|
||||
}
|
||||
}
|
||||
|
||||
bool has_value_;
|
||||
union {
|
||||
T value_;
|
||||
E error_;
|
||||
};
|
||||
};
|
||||
|
||||
// Specialization for void-returning fallible operations.
|
||||
template <typename E>
|
||||
class Result<void, E> {
|
||||
public:
|
||||
using value_type = void;
|
||||
using error_type = E;
|
||||
|
||||
static Result ok() { return Result(true, E{}); }
|
||||
static Result err(E error) { return Result(false, std::move(error)); }
|
||||
|
||||
[[nodiscard]] bool isOk() const noexcept { return has_value_; }
|
||||
[[nodiscard]] bool isErr() const noexcept { return !has_value_; }
|
||||
explicit operator bool() const noexcept { return has_value_; }
|
||||
|
||||
const E& error() const& {
|
||||
if (has_value_) throw std::logic_error("Result::error() on ok");
|
||||
return error_;
|
||||
}
|
||||
|
||||
private:
|
||||
Result(bool ok, E error) : has_value_(ok), error_(std::move(error)) {}
|
||||
bool has_value_;
|
||||
E error_;
|
||||
};
|
||||
|
||||
} // namespace ccm
|
||||
Reference in New Issue
Block a user