Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 18 additions & 3 deletions SimConnect.NET.sln
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{02EA681E
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimConnect.NET.Tests.Net8", "tests\SimConnect.NET.Tests.Net8\SimConnect.NET.Tests.Net8.csproj", "{38DFE777-B0F1-DC77-6E04-6DAEFC6F00DB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimConnect.NET.UnitTests", "tests\SimConnect.NET.UnitTests\SimConnect.NET.UnitTests.csproj", "{A5983127-E3A8-4E4A-9F48-307DAB9B2CF0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -43,15 +45,28 @@ Global
{38DFE777-B0F1-DC77-6E04-6DAEFC6F00DB}.Release|Any CPU.Build.0 = Release|Any CPU
{38DFE777-B0F1-DC77-6E04-6DAEFC6F00DB}.Release|x64.ActiveCfg = Release|Any CPU
{38DFE777-B0F1-DC77-6E04-6DAEFC6F00DB}.Release|x64.Build.0 = Release|Any CPU
{38DFE777-B0F1-DC77-6E04-6DAEFC6F00DB}.Release|x86.ActiveCfg = Release|Any CPU
{38DFE777-B0F1-DC77-6E04-6DAEFC6F00DB}.Release|x86.Build.0 = Release|Any CPU
{38DFE777-B0F1-DC77-6E04-6DAEFC6F00DB}.Release|x86.ActiveCfg = Release|Any CPU
{38DFE777-B0F1-DC77-6E04-6DAEFC6F00DB}.Release|x86.Build.0 = Release|Any CPU
{A5983127-E3A8-4E4A-9F48-307DAB9B2CF0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A5983127-E3A8-4E4A-9F48-307DAB9B2CF0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A5983127-E3A8-4E4A-9F48-307DAB9B2CF0}.Debug|x64.ActiveCfg = Debug|Any CPU
{A5983127-E3A8-4E4A-9F48-307DAB9B2CF0}.Debug|x64.Build.0 = Debug|Any CPU
{A5983127-E3A8-4E4A-9F48-307DAB9B2CF0}.Debug|x86.ActiveCfg = Debug|Any CPU
{A5983127-E3A8-4E4A-9F48-307DAB9B2CF0}.Debug|x86.Build.0 = Debug|Any CPU
{A5983127-E3A8-4E4A-9F48-307DAB9B2CF0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A5983127-E3A8-4E4A-9F48-307DAB9B2CF0}.Release|Any CPU.Build.0 = Release|Any CPU
{A5983127-E3A8-4E4A-9F48-307DAB9B2CF0}.Release|x64.ActiveCfg = Release|Any CPU
{A5983127-E3A8-4E4A-9F48-307DAB9B2CF0}.Release|x64.Build.0 = Release|Any CPU
{A5983127-E3A8-4E4A-9F48-307DAB9B2CF0}.Release|x86.ActiveCfg = Release|Any CPU
{A5983127-E3A8-4E4A-9F48-307DAB9B2CF0}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{4252A45B-8C7E-487B-9670-53935D9CD06A} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
{38DFE777-B0F1-DC77-6E04-6DAEFC6F00DB} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
{38DFE777-B0F1-DC77-6E04-6DAEFC6F00DB} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
{A5983127-E3A8-4E4A-9F48-307DAB9B2CF0} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {D38737E6-D81A-4DDE-9278-DE960E039FEB}
Expand Down
49 changes: 49 additions & 0 deletions src/SimConnect.NET/Facilities/FacilityDataResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// <copyright file="FacilityDataResponse.cs" company="BARS">
// Copyright (c) BARS. All rights reserved.
// </copyright>

using System.Collections.Generic;

namespace SimConnect.NET.Facilities
{
/// <summary>
/// Represents the result of a facility data request. Contains one or more payloads describing the
/// requested facility and any child objects (runways, approaches, etc.).
/// </summary>
public sealed class FacilityDataResponse
{
internal FacilityDataResponse(uint requestId, IReadOnlyList<FacilityDataResult> results)
{
this.RequestId = requestId;
this.Results = results;
}

/// <summary>
/// Gets the client supplied request identifier.
/// </summary>
public uint RequestId { get; }

/// <summary>
/// Gets the collection of data packets returned by SimConnect.
/// </summary>
public IReadOnlyList<FacilityDataResult> Results { get; }

/// <summary>
/// Finds the first payload matching the specified <see cref="SimConnectFacilityDataType"/>.
/// </summary>
/// <param name="dataType">The desired data type.</param>
/// <returns>The payload if present; otherwise <see langword="null"/>.</returns>
public FacilityDataResult? Find(SimConnectFacilityDataType dataType)
{
foreach (var result in this.Results)
{
if (result.DataType == dataType)
{
return result;
}
}
Comment on lines +38 to +44

return null;
}
}
}
86 changes: 86 additions & 0 deletions src/SimConnect.NET/Facilities/FacilityDataResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// <copyright file="FacilityDataResult.cs" company="BARS">
// Copyright (c) BARS. All rights reserved.
// </copyright>

using System;
using System.Runtime.InteropServices;

namespace SimConnect.NET.Facilities
{
/// <summary>
/// Represents a single facility data packet returned by SimConnect.
/// </summary>
public readonly struct FacilityDataResult
{
private readonly byte[] payload;

internal FacilityDataResult(
uint uniqueRequestId,
uint parentUniqueRequestId,
SimConnectFacilityDataType dataType,
bool isListItem,
uint itemIndex,
uint listSize,
byte[] payload)
{
this.UniqueRequestId = uniqueRequestId;
this.ParentUniqueRequestId = parentUniqueRequestId;
this.DataType = dataType;
this.IsListItem = isListItem;
this.ItemIndex = itemIndex;
this.ListSize = listSize;
this.payload = payload ?? Array.Empty<byte>();
}

/// <summary>
/// Gets the unique request identifier assigned by SimConnect.
/// </summary>
public uint UniqueRequestId { get; }

/// <summary>
/// Gets the parent unique request identifier, if any.
/// </summary>
public uint ParentUniqueRequestId { get; }

/// <summary>
/// Gets the facility data type represented by this payload.
/// </summary>
public SimConnectFacilityDataType DataType { get; }

/// <summary>
/// Gets a value indicating whether this payload represents an element of a list.
/// </summary>
public bool IsListItem { get; }

/// <summary>
/// Gets the index of the item within a list, if <see cref="IsListItem"/> is true.
/// </summary>
public uint ItemIndex { get; }

/// <summary>
/// Gets the total number of items in the list, if <see cref="IsListItem"/> is true.
/// </summary>
public uint ListSize { get; }

/// <summary>
/// Gets the raw payload memory returned by SimConnect.
/// </summary>
public ReadOnlyMemory<byte> Payload => this.payload;

/// <summary>
/// Marshals the payload into a managed struct of the specified type.
/// </summary>
/// <typeparam name="T">The target struct type. Must be blittable.</typeparam>
/// <returns>The marshalled struct.</returns>
public T As<T>()
where T : struct
{
if (this.payload.Length < Marshal.SizeOf<T>())
{
throw new InvalidOperationException("Payload is smaller than the requested struct type.");
}

return MemoryMarshal.Read<T>(this.payload.AsSpan());
}
}
}
37 changes: 37 additions & 0 deletions src/SimConnect.NET/Facilities/FacilityDefinition.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// <copyright file="FacilityDefinition.cs" company="BARS">
// Copyright (c) BARS. All rights reserved.
// </copyright>

using System;
using System.Collections.Generic;

namespace SimConnect.NET.Facilities
{
/// <summary>
/// Represents a facility data definition registered with SimConnect.
/// </summary>
public sealed class FacilityDefinition
{
internal FacilityDefinition(uint definitionId, IReadOnlyList<string> fields, Type? structType)
{
this.DefinitionId = definitionId;
this.Fields = fields;
this.StructType = structType;
}

/// <summary>
/// Gets the SimConnect definition identifier.
/// </summary>
public uint DefinitionId { get; }

/// <summary>
/// Gets the list of facility fields that are part of this definition.
/// </summary>
public IReadOnlyList<string> Fields { get; }

/// <summary>
/// Gets the struct type used to generate this definition, if any.
/// </summary>
public Type? StructType { get; }
}
}
35 changes: 35 additions & 0 deletions src/SimConnect.NET/Facilities/FacilityDefinitionBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// <copyright file="FacilityDefinitionBuilder.cs" company="BARS">
// Copyright (c) BARS. All rights reserved.
// </copyright>

using System;
using System.Collections.Generic;

namespace SimConnect.NET.Facilities
{
/// <summary>
/// Fluent builder for <see cref="FacilityDefinition"/> instances.
/// </summary>
public sealed class FacilityDefinitionBuilder
{
private readonly List<string> fields = new();

/// <summary>
/// Gets the configured field list.
/// </summary>
internal IReadOnlyList<string> Fields => this.fields;

/// <summary>
/// Adds a field path to the definition.
/// </summary>
/// <param name="fieldPath">The SimConnect facility field path (for example "Airport.Latitude").</param>
/// <returns>The same builder instance to allow fluent chaining.</returns>
/// <exception cref="ArgumentException">Thrown when <paramref name="fieldPath"/> is null or whitespace.</exception>
public FacilityDefinitionBuilder AddField(string fieldPath)
{
ArgumentException.ThrowIfNullOrWhiteSpace(fieldPath);
this.fields.Add(fieldPath);
return this;
}
}
}
37 changes: 37 additions & 0 deletions src/SimConnect.NET/Facilities/FacilityFieldAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// <copyright file="FacilityFieldAttribute.cs" company="BARS">
// Copyright (c) BARS. All rights reserved.
// </copyright>

using System;

namespace SimConnect.NET.Facilities
{
/// <summary>
/// Annotates a struct field with a SimConnect facility field path for automatic definition creation.
/// </summary>
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public sealed class FacilityFieldAttribute : Attribute
{
/// <summary>
/// Initializes a new instance of the <see cref="FacilityFieldAttribute"/> class.
/// </summary>
/// <param name="path">The SimConnect facility field path.</param>
/// <param name="order">Optional explicit ordering (lower numbers are processed first).</param>
public FacilityFieldAttribute(string path, int order = 0)
{
ArgumentException.ThrowIfNullOrWhiteSpace(path);
this.Path = path;
this.Order = order;
}

/// <summary>
/// Gets the SimConnect facility field path represented by this attribute.
/// </summary>
public string Path { get; }

/// <summary>
/// Gets the optional ordering index. Lower values are processed first.
/// </summary>
public int Order { get; }
}
}
Loading
Loading