Skip to content

Commit

Permalink
feat: Added Trimming/NativeAOT support.
Browse files Browse the repository at this point in the history
  • Loading branch information
HavenDV committed Jan 31, 2024
1 parent 0c32ffe commit 86840aa
Show file tree
Hide file tree
Showing 10 changed files with 151 additions and 50 deletions.
16 changes: 16 additions & 0 deletions QrCodes.sln
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QrCodes.SkiaSharp", "src\li
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QrCodes.System.Drawing", "src\libs\QrCodes.System.Drawing\QrCodes.System.Drawing.csproj", "{F58F57D4-B95E-42BF-9BA3-16A31C9E9831}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "helpers", "helpers", "{1BED4380-A713-44C2-99A8-3664D7744746}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TrimmingHelper", "src\helpers\TrimmingHelper\TrimmingHelper.csproj", "{A868190C-1D50-449B-90EA-CC97C53CECB5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AotHelper", "src\helpers\AotHelper\AotHelper.csproj", "{FF8D0D33-B1E6-4BA7-A6A0-D2BE1A30D5AA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -82,6 +88,14 @@ Global
{F58F57D4-B95E-42BF-9BA3-16A31C9E9831}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F58F57D4-B95E-42BF-9BA3-16A31C9E9831}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F58F57D4-B95E-42BF-9BA3-16A31C9E9831}.Release|Any CPU.Build.0 = Release|Any CPU
{A868190C-1D50-449B-90EA-CC97C53CECB5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A868190C-1D50-449B-90EA-CC97C53CECB5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A868190C-1D50-449B-90EA-CC97C53CECB5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A868190C-1D50-449B-90EA-CC97C53CECB5}.Release|Any CPU.Build.0 = Release|Any CPU
{FF8D0D33-B1E6-4BA7-A6A0-D2BE1A30D5AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FF8D0D33-B1E6-4BA7-A6A0-D2BE1A30D5AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FF8D0D33-B1E6-4BA7-A6A0-D2BE1A30D5AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FF8D0D33-B1E6-4BA7-A6A0-D2BE1A30D5AA}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -96,6 +110,8 @@ Global
{507C686B-CBB2-4559-8FCC-DBFA90B3E987} = {732F539D-3402-4E31-AD43-F3653C9F2F0C}
{DCBD2245-73F4-4644-AD0C-38D8197BABB4} = {928D4422-05CE-4AC2-89B0-31060889AE6A}
{F58F57D4-B95E-42BF-9BA3-16A31C9E9831} = {928D4422-05CE-4AC2-89B0-31060889AE6A}
{A868190C-1D50-449B-90EA-CC97C53CECB5} = {1BED4380-A713-44C2-99A8-3664D7744746}
{FF8D0D33-B1E6-4BA7-A6A0-D2BE1A30D5AA} = {1BED4380-A713-44C2-99A8-3664D7744746}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {1493AEE4-9211-46E9-BFE6-8F629EAC5693}
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ xmlns:qr="clr-namespace:QrCodes.Maui;assembly=QrCodes.Maui"
- https://qrapi.io/
- https://github.com/manuelbl/QrCodeGenerator
- https://qr.io/
- https://github.com/guitarrapc/SkiaSharp.QrCode

### Benchmarks
You can view the reports for each version [here](benchmarks)
Expand Down
35 changes: 35 additions & 0 deletions src/helpers/AotHelper/AotHelper.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>

<PublishTrimmed>true</PublishTrimmed>
<PublishAot>true</PublishAot>
<!-- <TrimMode>partial</TrimMode>-->
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\libs\QrCodes\QrCodes.csproj" />
<ProjectReference Include="..\..\libs\QrCodes.SkiaSharp\QrCodes.SkiaSharp.csproj" />
</ItemGroup>

<ItemGroup>
<!-- <TrimmableAssembly Include="QrCodes" />-->
<!-- <TrimmerRootAssembly Include="QrCodes" />-->
<!-- <TrimmerRootAssembly Include="QrCodes.SkiaSharp" />-->
</ItemGroup>

<PropertyGroup Label="Publish">
<RuntimeIdentifier Condition="$([MSBuild]::IsOSPlatform('windows'))">win-x64</RuntimeIdentifier>
<RuntimeIdentifier Condition="!$([MSBuild]::IsOSPlatform('windows'))">osx-arm64</RuntimeIdentifier>

<SelfContained>true</SelfContained>
</PropertyGroup>

<Target Name="ProduceAotWarnings" AfterTargets="Build">
<CallTarget Targets="Publish"/>
</Target>

</Project>
12 changes: 12 additions & 0 deletions src/helpers/AotHelper/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using QrCodes;
using QrCodes.Renderers;

Console.WriteLine("Build, rebuild or publish this app to see aot warnings.");

var qr = QrCodeGenerator.Generate("Hello World!", ErrorCorrectionLevel.Medium);

Console.WriteLine(AsciiRenderer.Render(qr, 1));

var bytes = new SkiaSharpRenderer().RenderToBytes(qr);

File.WriteAllBytes("qr.png", bytes);
1 change: 1 addition & 0 deletions src/helpers/TrimmingHelper/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Console.WriteLine("Build, rebuild or publish this app to see trimming warnings.");
38 changes: 38 additions & 0 deletions src/helpers/TrimmingHelper/TrimmingHelper.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>

<PublishTrimmed>true</PublishTrimmed>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\libs\QrCodes\QrCodes.csproj" />
<ProjectReference Include="..\..\libs\QrCodes.ImageSharp\QrCodes.ImageSharp.csproj" />
<ProjectReference Include="..\..\libs\QrCodes.SkiaSharp\QrCodes.SkiaSharp.csproj" />
<ProjectReference Include="..\..\libs\QrCodes.System.Drawing\QrCodes.System.Drawing.csproj" />
<ProjectReference Include="..\..\libs\QrCodes.Maui\QrCodes.Maui.csproj" />
</ItemGroup>

<ItemGroup>
<TrimmerRootAssembly Include="QrCodes" />
<TrimmerRootAssembly Include="QrCodes.ImageSharp" />
<TrimmerRootAssembly Include="QrCodes.SkiaSharp" />
<TrimmerRootAssembly Include="QrCodes.System.Drawing" />
<TrimmerRootAssembly Include="QrCodes.Maui" />
</ItemGroup>

<PropertyGroup Label="Publish">
<RuntimeIdentifier Condition="$([MSBuild]::IsOSPlatform('windows'))">win-x64</RuntimeIdentifier>
<RuntimeIdentifier Condition="!$([MSBuild]::IsOSPlatform('windows'))">osx-arm64</RuntimeIdentifier>

<SelfContained>true</SelfContained>
</PropertyGroup>

<Target Name="ProduceTrimmingWarnings" AfterTargets="Build">
<CallTarget Targets="Publish"/>
</Target>

</Project>
10 changes: 9 additions & 1 deletion src/libs/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
</ItemGroup>

<PropertyGroup Label="Nuget">
<Version>1.0.2</Version>
<Version>1.0.3</Version>
<Description>Modern cross-platform QR code generation, rendering and serialization.</Description>
<PackageTags>qr;qrcode;qrcoder;cross-platform;logo;modern;net8</PackageTags>
<GeneratePackageOnBuild Condition=" '$(Configuration)' == 'Release' ">true</GeneratePackageOnBuild>
Expand Down Expand Up @@ -48,4 +48,12 @@
<AnalysisMode>All</AnalysisMode>
</PropertyGroup>

<PropertyGroup Label="Trimmable" Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net6.0'))">
<IsAotCompatible>true</IsAotCompatible>
<EnableTrimAnalyzer>true</EnableTrimAnalyzer>
<IsTrimmable>true</IsTrimmable>
<SuppressTrimAnalysisWarnings>false</SuppressTrimAnalysisWarnings>
<TrimmerSingleWarn>false</TrimmerSingleWarn>
</PropertyGroup>

</Project>
2 changes: 1 addition & 1 deletion src/libs/QrCodes.Maui/EnumExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public IList ProvideValue(IServiceProvider serviceProvider)
}

return Enum
.GetValues(Type)
.GetValuesAsUnderlyingType(Type)
.Cast<object>()
.ToArray();
}
Expand Down
11 changes: 11 additions & 0 deletions src/libs/QrCodes.Maui/ImageSourceExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,17 @@ public static class ImageSourceExtensions
/// <exception cref="InvalidOperationException"></exception>
public static async Task<Stream> ToStreamAsync(this ImageSource imageSource)
{
// if (imageSource is FileImageSource fileImageSource)
// {
// var file = fileImageSource.File;
// if (file is null)
// {
// throw new InvalidOperationException("File is null");
// }
//
// return File.OpenRead(Path.Combine(FileSystem.AppDataDirectory, file));
// }

if (Application.Current?.Handler?.MauiContext is not {} mauiContext)
{
throw new InvalidOperationException("MauiContext is null");
Expand Down
75 changes: 27 additions & 48 deletions src/libs/QrCodes/Payloads/RussiaPaymentOrder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,10 @@ namespace QrCodes.Payloads;
public class RussiaPaymentOrder
{
private readonly CharacterSets characterSet;
private readonly MandatoryFields mFields;
private readonly OptionalFields oFields;
private readonly MandatoryFields mFields = new();
private readonly OptionalFields oFields = new();
private string separator = "|";

private RussiaPaymentOrder()
{
mFields = new MandatoryFields();
oFields = new OptionalFields();
}

/// <summary>
/// Generates a RussiaPaymentOrder payload
/// </summary>
Expand All @@ -48,7 +42,7 @@ public RussiaPaymentOrder(
string BIC,
string correspAcc,
OptionalFields? optionalFields = null,
CharacterSets characterSet = CharacterSets.utf_8) : this()
CharacterSets characterSet = CharacterSets.utf_8)
{
this.characterSet = characterSet;
mFields.Name = ValidateInput(name, "Name", @"^.{1,160}$");
Expand Down Expand Up @@ -142,25 +136,21 @@ private string DetermineSeparator()
/// <returns>A List of strings</returns>
private List<string> GetOptionalFieldsAsList()
{
#if NETSTANDARD1_3
return oFields.GetType().GetRuntimeProperties()
.Where(field => field.GetValue(oFields) != null)
.Select(field => {
var objValue = field.GetValue(oFields, null);
var value = field.PropertyType.Equals(typeof(DateTime?)) ? ((DateTime)objValue).ToString("dd.MM.yyyy") : objValue.ToString();
return $"{field.Name}={value}";
})
.ToList();
#else
return oFields.GetType().GetProperties()
.Where(field => field.GetValue(oFields, null) != null)
.Select(field => {
var objValue = field.GetValue(oFields, null);
var value = field.PropertyType == typeof(DateTime?) ? ((DateTime)objValue).ToString("dd.MM.yyyy") : objValue.ToString();
return $"{field.Name}={value}";
})
.ToList();
#endif
// return oFields.GetType().GetProperties()
// .Where(field => field.GetValue(oFields, null) != null)
// .Select(field => {
// var objValue = field.GetValue(oFields, null);
// var value = field.PropertyType == typeof(DateTime?) ? ((DateTime)objValue).ToString("dd.MM.yyyy") : objValue.ToString();
// return $"{field.Name}={value}";
// })
// .ToList();
return new Dictionary<string, string>
{
// TODO: implement other
[nameof(OptionalFields.Category)] = oFields.Category,
}
.Select(static pair => $"{pair.Key}={pair.Value}")
.ToList();
}


Expand All @@ -170,25 +160,14 @@ private List<string> GetOptionalFieldsAsList()
/// <returns>A List of strings</returns>
private List<string> GetMandatoryFieldsAsList()
{
#if NETSTANDARD1_3
return mFields.GetType().GetRuntimeFields()
.Where(field => field.GetValue(mFields) != null)
.Select(field => {
var objValue = field.GetValue(mFields);
var value = field.FieldType.Equals(typeof(DateTime?)) ? ((DateTime)objValue).ToString("dd.MM.yyyy") : objValue.ToString();
return $"{field.Name}={value}";
})
.ToList();
#else
return mFields.GetType().GetFields()
.Where(field => field.GetValue(mFields) != null)
.Select(field => {
var objValue = field.GetValue(mFields);
var value = field.FieldType == typeof(DateTime?) ? ((DateTime)objValue).ToString("dd.MM.yyyy") : objValue.ToString();
return $"{field.Name}={value}";
})
.ToList();
#endif
return
[
$"{nameof(MandatoryFields.Name)}={mFields.Name}",
$"{nameof(MandatoryFields.PersonalAcc)}={mFields.PersonalAcc}",
$"{nameof(MandatoryFields.BankName)}={mFields.BankName}",
$"{nameof(MandatoryFields.BIC)}={mFields.BIC}",
$"{nameof(MandatoryFields.CorrespAcc)}={mFields.CorrespAcc}"
];
}

/// <summary>
Expand Down Expand Up @@ -238,7 +217,7 @@ private static string ValidateInput(
return input;
}

private class MandatoryFields
internal class MandatoryFields
{
public string Name;
public string PersonalAcc;
Expand Down

0 comments on commit 86840aa

Please sign in to comment.