Skip to content

Commit d7b907f

Browse files
committed
Add Complex_Test
1 parent 5f3a991 commit d7b907f

File tree

2 files changed

+231
-2
lines changed

2 files changed

+231
-2
lines changed

src/Tests/StructTest/Program.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ private static void Main(string[] args)
3232
//Console.WriteLine();
3333
//ValidationTest.ValidationAllow();
3434

35-
StructTest.Test();
35+
//StructTest.Simple_Test();
36+
StructTest.Complex_Test();
3637

3738
//var config = DefaultConfig.Instance
3839
// .WithArtifactsPath(

src/Tests/StructTest/StructTest.cs

Lines changed: 229 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
using ObjectLayoutInspector;
2+
using System.Diagnostics;
3+
using System.Diagnostics.CodeAnalysis;
4+
using System.Runtime.CompilerServices;
25
using System.Runtime.InteropServices;
36

47
namespace StructTest;
@@ -8,7 +11,7 @@ internal static class StructTest
811

912
#region Constants & Statics
1013

11-
public static void Test()
14+
public static void Simple_Test()
1215
{
1316
var box = new BoxStruct(false, 0, new InnerStruct(100, true));
1417

@@ -63,8 +66,15 @@ public static void Test()
6366

6467
#endregion
6568

69+
public static void Complex_Test()
70+
{
71+
var r = new Result<BaseError>(new BaseError());
72+
TypeLayout.PrintLayout(r.GetType(), true);
73+
}
6674
}
6775

76+
#region Simple Structs
77+
6878
[StructLayout(LayoutKind.Sequential)]
6979
public readonly record struct BoxStruct
7080
{
@@ -93,3 +103,221 @@ public InnerStruct(int intField, bool boolField)
93103
_boolField = boolField;
94104
}
95105
}
106+
107+
#endregion
108+
109+
#region Complex
110+
111+
//[StructLayout(LayoutKind.Auto, Pack = 1)]
112+
[StructLayout(LayoutKind.Sequential, Pack = 1)]
113+
[SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "<Pending>")]
114+
public readonly record struct Result<TError>
115+
where TError : struct
116+
{
117+
118+
#region Constants & Statics
119+
120+
/// <summary>
121+
/// No errors, just return.
122+
/// </summary>
123+
private static readonly Result<TError> Ok = new(true);
124+
125+
#endregion
126+
127+
/// <summary>
128+
/// Gets the error.
129+
/// </summary>
130+
internal readonly TError _error;
131+
132+
internal readonly bool _hasError;
133+
134+
#pragma warning disable IDE0060 // Remove unused parameter
135+
private Result(bool isOk)
136+
#pragma warning restore IDE0060 // Remove unused parameter
137+
{
138+
// just use for Ok
139+
_hasError = false;
140+
}
141+
142+
/// <summary>
143+
/// Initializes a new instance of the <see cref="Result{TError}"/> with default <typeparamref name="TError"/>.
144+
/// </summary>
145+
public Result() : this(new TError())
146+
{
147+
}
148+
149+
/// <summary>
150+
/// Initializes a new instance of the <see cref="Result{TData, TError}"/> with error.
151+
/// The result is failed.
152+
/// </summary>
153+
/// <param name="error">The error.</param>
154+
public Result(in TError error)
155+
{
156+
_error = error;
157+
_hasError = true;
158+
}
159+
160+
#region Methods
161+
162+
[UnscopedRef]
163+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
164+
internal ref readonly TError UnwrapErrorWithoutCheck()
165+
{
166+
Debug.Assert(_hasError, $"{nameof(_hasError)} is true");
167+
return ref _error;
168+
}
169+
170+
/// <summary>
171+
/// Determines whether this instance is error.
172+
/// </summary>
173+
/// <returns>
174+
/// <c>true</c> if this instance is error; otherwise <c>false</c>.
175+
/// </returns>
176+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
177+
public readonly bool IsError()
178+
{
179+
return _hasError;
180+
}
181+
182+
/// <summary>
183+
/// Determines whether this instance is error.
184+
/// </summary>
185+
/// <returns>
186+
/// <c>true</c> if this instance is error, and error must not be null; otherwise, <c>false</c>.
187+
/// </returns>
188+
[SuppressMessage(
189+
"Critical Code Smell",
190+
"S3874:\"out\" and \"ref\" parameters should not be used",
191+
Justification = "<Pending>")]
192+
public readonly bool IsError([NotNullWhen(true)] out TError? error)
193+
{
194+
error = null;
195+
196+
if (_hasError)
197+
{
198+
error = _error;
199+
return true;
200+
}
201+
202+
return false;
203+
}
204+
205+
#endregion
206+
207+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
208+
public static implicit operator Result<TError>(in TError error) => new(in error);
209+
}
210+
211+
//[StructLayout(LayoutKind.Auto, Pack = 1)]
212+
[StructLayout(LayoutKind.Sequential, Pack = 1)]
213+
public readonly record struct BaseError(BaseErrorCode Code, string? Reason = null/*, Exception? Exception = null*/)
214+
//: IBaseError<BaseError, BaseErrorCode>
215+
{
216+
public BaseError() : this(BaseErrorCode.Failed)
217+
{
218+
}
219+
220+
#region IBaseError implementations
221+
222+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
223+
public static Result<BaseError> Result(BaseErrorCode code, string? reason = null, Exception? exception = null)
224+
{
225+
return new BaseError(code, reason/*, exception*/);
226+
}
227+
228+
#endregion
229+
230+
#region IError implementations
231+
232+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
233+
public static Result<BaseError> Result()
234+
{
235+
return new BaseError();
236+
}
237+
238+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
239+
public static Result<BaseError> Result(BaseErrorCode code)
240+
{
241+
return new BaseError(code);
242+
}
243+
244+
#endregion
245+
246+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
247+
public static implicit operator BaseError(BaseErrorCode errorCode) => new(errorCode);
248+
}
249+
250+
public interface IError<TError, TCode>
251+
where TError : struct
252+
{
253+
254+
#region Constants & Statics
255+
256+
/// <summary>
257+
/// Create a default result.
258+
/// </summary>
259+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
260+
public static abstract Result<TError> Result();
261+
262+
/// <summary>
263+
/// Create a result with the specified code.
264+
/// </summary>
265+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
266+
public static abstract Result<TError> Result(TCode code);
267+
268+
#endregion
269+
270+
#region Properties
271+
272+
/// <summary>
273+
/// Gets the error code.
274+
/// </summary>
275+
public TCode Code { get; }
276+
277+
#endregion
278+
279+
}
280+
281+
public interface IBaseError<TError, TCode> : IError<TError, TCode>
282+
where TError : struct
283+
{
284+
285+
#region Constants & Statics
286+
287+
/// <summary>
288+
/// Create a result with the specified code, reason and exception.
289+
/// </summary>
290+
/// <param name="code">The code.</param>
291+
/// <param name="reason">The reason.</param>
292+
/// <param name="exception">The exception.</param>
293+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
294+
public static abstract Result<TError> Result(TCode code, string? reason = null, Exception? exception = null);
295+
296+
#endregion
297+
298+
#region Properties
299+
300+
/// <summary>
301+
/// Gets the exception.
302+
/// </summary>
303+
public Exception? Exception { get; }
304+
305+
/// <summary>
306+
/// Gets the reason.
307+
/// </summary>
308+
public string? Reason { get; }
309+
310+
#endregion
311+
312+
}
313+
314+
public enum BaseErrorCode
315+
{
316+
Failure = 0,
317+
318+
Failed = 10,
319+
320+
NotFound = 99
321+
}
322+
323+
#endregion

0 commit comments

Comments
 (0)