// Copyright (c) 2025 GeWuYou
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System.Diagnostics.Contracts;
namespace GFramework.Core.Functional;
///
/// 表示一个无值的操作结果,仅包含成功或失败状态
///
public readonly struct Result : IEquatable
{
private readonly Exception? _exception;
private readonly bool _isSuccess;
///
/// 私有构造函数,用于创建 Result 实例
///
/// 是否为成功状态
/// 失败时的异常信息
private Result(bool isSuccess, Exception? exception)
{
_isSuccess = isSuccess;
_exception = exception;
}
///
/// 判断结果是否为成功状态
///
[Pure]
public bool IsSuccess => _isSuccess;
///
/// 判断结果是否为失败状态
///
[Pure]
public bool IsFailure => !_isSuccess;
///
/// 获取失败时的异常信息,若为成功状态则抛出 InvalidOperationException
///
[Pure]
public Exception Error => IsFailure
? _exception!
: throw new InvalidOperationException("Cannot access Error on a successful Result.");
///
/// 创建成功结果
///
/// 成功结果
[Pure]
public static Result Success() => new(true, null);
///
/// 创建失败结果
///
/// 失败的异常
/// 失败结果
[Pure]
public static Result Failure(Exception ex)
{
ArgumentNullException.ThrowIfNull(ex);
return new(false, ex);
}
///
/// 根据错误消息创建失败结果
///
/// 错误消息
/// 失败结果
[Pure]
public static Result Failure(string message)
{
ArgumentException.ThrowIfNullOrWhiteSpace(message);
return new(false, new Exception(message));
}
///
/// 根据成功或失败状态分别执行不同的处理逻辑
///
/// 返回值类型
/// 成功时执行的函数
/// 失败时执行的函数
/// 处理后的结果
public R Match(Func onSuccess, Func onFailure) =>
IsSuccess ? onSuccess() : onFailure(_exception!);
///
/// 将当前无值的 Result 提升为带值的 Result
///
/// 值的类型
/// 成功时关联的值
/// 带值的 Result
[Pure]
public Result ToResult(A value) =>
IsSuccess ? Result.Success(value) : Result.Failure(_exception!);
///
/// 判断当前 Result 是否与另一个 Result 相等
///
/// 另一个 Result
/// 若相等返回 true,否则返回 false
[Pure]
public bool Equals(Result other)
{
// 比较状态和异常信息
return _isSuccess == other._isSuccess &&
(!IsFailure || (_exception?.GetType() == other._exception?.GetType() &&
_exception?.Message == other._exception?.Message));
}
///
/// 判断当前对象是否与另一个对象相等
///
/// 另一个对象
/// 若相等返回 true,否则返回 false
[Pure]
public override bool Equals(object? obj) => obj is Result other && Equals(other);
///
/// 获取当前 Result 的哈希码
///
/// 哈希码
[Pure]
public override int GetHashCode()
{
// 根据状态和异常信息生成哈希码
return IsSuccess
? HashCode.Combine(true)
: HashCode.Combine(false, _exception?.GetType(), _exception?.Message);
}
///
/// 判断两个 Result 是否相等
///
/// 第一个 Result
/// 第二个 Result
/// 若相等返回 true,否则返回 false
[Pure]
public static bool operator ==(Result a, Result b) => a.Equals(b);
///
/// 判断两个 Result 是否不相等
///
/// 第一个 Result
/// 第二个 Result
/// 若不相等返回 true,否则返回 false
[Pure]
public static bool operator !=(Result a, Result b) => !a.Equals(b);
///
/// 返回当前 Result 的字符串表示
///
/// Result 的字符串表示
[Pure]
public override string ToString() =>
IsSuccess ? "Success" : $"Fail({_exception?.Message ?? "Unknown"})";
}