{"id":26391037,"url":"https://github.com/themeldingwars/aero","last_synced_at":"2025-03-17T10:17:46.884Z","repository":{"id":101897894,"uuid":"365640889","full_name":"themeldingwars/Aero","owner":"themeldingwars","description":"Fast span based source generator for serializing packets from annotated classes.","archived":false,"fork":false,"pushed_at":"2025-02-10T12:41:49.000Z","size":217,"stargazers_count":6,"open_issues_count":7,"forks_count":2,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-03-10T19:18:28.033Z","etag":null,"topics":["csharp"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/themeldingwars.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-05-09T01:02:46.000Z","updated_at":"2024-06-02T11:42:26.000Z","dependencies_parsed_at":null,"dependency_job_id":"4da23e13-53ce-4cd8-95d0-d1d26b85b181","html_url":"https://github.com/themeldingwars/Aero","commit_stats":null,"previous_names":[],"tags_count":20,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/themeldingwars%2FAero","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/themeldingwars%2FAero/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/themeldingwars%2FAero/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/themeldingwars%2FAero/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/themeldingwars","download_url":"https://codeload.github.com/themeldingwars/Aero/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244014187,"owners_count":20383716,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["csharp"],"created_at":"2025-03-17T10:17:36.235Z","updated_at":"2025-03-17T10:17:45.619Z","avatar_url":"https://github.com/themeldingwars.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Aero\n## Packet and file serialization code gen\nFor the server we are hoping to have a code gen to create the packet reader and writers for the messages and maybe to also be used on the file formats.\nThe idea is you define the class and annotate the fields and then have the code gen generate the read and write functions, the benfit of this is avoid having to write uguly error prone code over and over again and allows us to make sweeping changes to the readers and writers with out having to re write all those functions.\nPlanning to use .Net 5 Source Generators. \u003chttps://devblogs.microsoft.com/dotnet/introducing-c-source-generators/\u003e\n\nAn other plus from this should be better packet peep inspection, the code gen can also create imgui views for each class with better views on the data and better tracking of reads.\n\nWhy Aero, well she did talk alot so....\n\n# How to install\nInstall the nuget package ``Aero.Gen``\n\n# Generated Functions\nThe following functions will be generated on Aero marked classes\n\n## Unpack:\n``int Unpack(ReadOnlySpan\u003cbyte\u003e data)``\n\nUnpacks the given span into the class, the return value is how many bytes were read from the data span.\u003c/br\u003e\nIf the return int is negative then the unpack failed and that how many bytes were read. (Needs to be compiled with bounds check on)\n```csharp\nvar TestPacket = new TestPacket();\nint readBytes = TestPacket.Unpack(packetData);\n```\n\n## GetPackedSize:\n``int GetPackedSize()``\nCalculate the size in bytes this class will have when packed.\u003c/br\u003e\nThis function will preform much the same logic used for packing but just record the size.\n\n```csharp\nvar TestPacket = new TestPacket();\nint SizeThatWillBePacked = TestPacket.GetPackedSize();\n```\n\n## Pack:\n``int Pack(Span\u003cbyte\u003e buffer)``\nPacks this class into the buffer and returns how many bytes where packed.\nThe given buffer span should be atleast big enough to pack all the fields into.\n\n```csharp\nSpan\u003cbyte\u003e buffer = new byte[10000];\nvar TestPacket = new TestPacket();\nint packedSize = TestPacket.Pack(buffer);\n```\n\n# Supported Types\n* byte\n* char\n* int\n* uint\n* long\n* ulong\n* short\n* ushort\n* float\n* double\n* string\n* Vector2\n* Vector3\n* Vector4\n* Quaternion\n\n# Attributes\n## ``[Aero]``\nMarks a class as one that should have readers, writers and such generated for it.\n\n## ``[AeroBlock]``\nMarks a struct as one that can be serialised and included in an Aero class.\n\nIf a struct isn't marked with this it won't be serialised.\n\n## ``[AeroArray]``\nMarks a field as an array, there are a few variants of this.\n* ``AeroArray(int length)`` : eg ``[AeroArray(2)]`` Will read 2 values of the type of the array this is attached to\n* ``AeroArray(string nameOfFeild)``: like the normal use only will take the length from the named field.\n    * The named field must be a number type, eg, byte, short, int\n    * Should use ``nameof`` eg ``[AeroArray(nameof(ArrayLen))]``\n* ``AeroArray(Type lengthType)`` read a number type of that type and use that for the length of the array\n    * eg. ``AeroArray(typeof(uint))`` Will read a uint and then read that value number of elements.\n* ``AeroArray(int -length)`` : eg ``[AeroArray(-4)]`` If the fixed size is negative then the array will be crated with that number positive but will keep reading untill the end of the data is reached\n  * eg. ``[AeroArray(-4)] public int Test;`` will create an array of ints with a size of 4 and do a ``while(!hasReachedTheEnd)`` for reading\n  * The size given as the arg should be the max size that the array can have, it won't be resized\n  * There will be a ``Get[ArrayName]Count`` getter added that has the number of items that were read for this array.\n\n## ``[AeroIf]``\nA field with this will be conditionally serialised if the logic passes.\n* ``[AeroIf(nameof(TestValue), 1)]``: Equivalent to ``if (TestValue == 1)`` around the read\n* ``[AeroIf(nameof(TestValue), 1, 2)]``: Equivalent to ``if (TestValue == 1 || TestValue == 2)`` around the read\n* ``[AeroIf(nameof(TestValue), Op.NotEqual, 1)]``: Equivalent to ``if (TestValue != 1)`` around the read\n* ``[AeroIf(nameof(TestValue), Op.HasFlag, Flags.Flag1)]``: Equivalent to ``if (TestValue \u0026 Flags.Flag1)`` around the read\n\nMultiple values in the one attribute will be ored as you can see above, to get and logic do like below:\n```csharp\n[AeroIf(nameof(TestValue), 1)]\n[AeroIf(nameof(TestValue), 2)]\npublic int TestInt;\n```\n\nand creates code equivalent to:\n```csharp\nif ((Byte == 0) \u0026\u0026 (Byte == 1))\n{\n\n}\n```\n\nThe ops options are:\n* Equal\n* NotEqual\n* HasFlag\n* DoesntHaveFlag\n\n## ``[AeroString]``\nStrings should be marked with this attribute to be parsed correctly.\n* ``[AeroString(nameof(LenghtField))]``: Similar to the array attribute you can pass the name of a already defined numeric value to be used as the length of the string\n* ``[AeroString(typeof(byte))]``: Marks the string as length prefixed with the given type, eg will read a byte and then that number of chars into the string\n* ``[AeroString(10)]``: Read a fixed size string, in this case will read 10 chars as a string\n* ``[AeroString]``: Defines a null terminated string, will read until it gets a ``0x00`` or it reaches the end of the span.\n\n## ``[AeroSdb]``\n* ``[AeroSdb(\"Table Name\", \"Column Name\")]``: Mark a field as having a value from the sdb table and column given.\n\n# Examples\nHere are some exampls, for more you can see the unit tests in the project.\n\n## Example 1\nA basic example for all that is needed to have basic value types serialised\n\n```csharp\n[Aero]\npublic partial class SimpleTypes\n{\n    public byte   Byte;\n    public char   Char;\n    public int    IntTest;\n    public uint   UintTest;\n    public short  ShortTest;\n    public ushort UshortTest;\n    public long   Long;\n    public ulong  ULong;\n    public float  Float;\n    public double Double;\n}\n```\n\n## Example 2\nA basic example with arrays and some logic\n\n```csharp\n[Aero]\npublic partial class Example2\n{\n    public byte   Byte;\n    public char   Char;\n    \n    // Read 4 ints\n    [AeroArray(4)]\n    public int[] FourInts;\n    \n    // Read an int and uses it to get the length of the array and then reads them\n    [AeroArray(typeof(int))]\n    public int[] VarableIntArray;\n    \n    // If the Byte value is 1 then the value is read, other wise it isn't\n    [AeroIf(nameof(Byte), 1)]\n    public int ShouldBeReadIfByteIs1;\n}\n```\n\n## Example 3\nA basic example of string parsing\n\n```csharp\n[Aero]\npublic partial class Example3\n{\n  [AeroString]\n  public string NulNullTerminatedString;\n  \n  [AeroString(10)]\n  public string FixedSizeString;\n  \n  [AeroString(typeof(byte))]\n  public string ByteLengthPrefixedString;\n  \n  public int StringLength;\n  [AeroString(nameof(StringLength))]\n  public string VarablePrefixedLengthString;\n}\n```\n\n# Views\nTo mark a class as a view add the attribute ``[Aero(AeroGenTypes.View)]`` or ``[Aero(AeroGenTypes.Controller)]`` to it, the true marks it as a view and will genrate the extra data.\n\nFields in the class will get a ``ShadowField`` idx based on the order that they are defined in.\nNullables can be marked as such with the ``[AeroNullable]``\n\nExample:\n```csharp\n[Aero(AeroGenTypes.View)]\npublic partial class SimpleViewWithNullable\n{\n    public int   TestValue;\n    public float TestVlaue2;\n    \n    [AeroNullable] public int TestValueNullable;\n}\n```\n\nThe added functions are:\n* ``GetPackedSize()``\n* ``UnpackChanges(ReadOnlySpan\u003cbyte\u003e data)``\n* ``PackChanges(Span\u003cbyte\u003e buffer, bool clearDirtyAfterSend = true)``\n* ``ShadowFieldIdToName(int id)`` Returns a `string` name for the shadow field with this id\n* ``ShadowFieldIdToType(int id)`` Returns the `Type` for the shadow field with this id\n* ``GetShadowFieldsData()`` Returns an array of `(string, int, Type, bool)` for all the shadowfields in this class, (name, id, Type, nullable)\n\nIf compiled with the Diag Logging enabled then there will also be a function ``GetDiagReadLogs()`` that will return a `List\u003cAeroReadLog\u003e` for each read that was done in the ``Unpack`` or ``UnpackChanges`` functions.\n\nFor each field in a view call a property will be genrated, for non nullables the set on this will mark that value as dirty so a ``PackChanges`` call will only pack what has changed.\nThis is why feilds should be defined as private to ensure only the propetys can be called and those changes can be tracked.\nThese views shouldn't be shared or polled for this reason.\n\n\n# Config\nThe following settings can be used in a .editorconfig file to adjust the generators output (or it should).\n* ``Aero_Enabled``: Enable or disable the generator\n* ``Aero_BoundsCheck``: Enable or disable bounds checking for the unpacker, will return -bytes read if it couldn't read more from the passed buffer\n* ``Aero_DiagLogging``: Enable or disable diagnostic logging from the packer / unpackers\n* ``Aero_LogReadsWrites``: Enable or disable logging the reading or writing done by the packers or unpackers (just the unpackers atm), needs Aero_DiagLogging enabled too.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthemeldingwars%2Faero","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthemeldingwars%2Faero","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthemeldingwars%2Faero/lists"}