in utils/SkiaSharpGenerator/Generate/Generator.cs [174:309]
private void WriteStruct(TextWriter writer, CppClass klass)
{
var cppClassName = klass.GetDisplayName();
if (excludedTypes.Contains(cppClassName) == true)
{
Log?.LogVerbose($" Skipping struct '{cppClassName}' because it was in the exclude list.");
return;
}
Log?.LogVerbose($" {cppClassName}");
typeMappings.TryGetValue(cppClassName, out var map);
var name = map?.CsType ?? CleanName(cppClassName);
writer.WriteLine();
writer.WriteLine($"\t// {cppClassName}");
writer.WriteLine($"\t[StructLayout (LayoutKind.Sequential)]");
var visibility = map?.IsInternal == true ? "internal" : "public";
var isReadonly = map?.IsReadOnly == true ? " readonly" : "";
var equatable = map?.GenerateEquality == true ? $" : IEquatable<{name}>" : "";
writer.WriteLine($"\t{visibility}{isReadonly} unsafe partial struct {name}{equatable} {{");
var allFields = new List<string>();
foreach (var field in klass.Fields)
{
var type = GetType(field.Type);
var cppT = GetCppType(field.Type);
writer.WriteLine($"\t\t// {field}");
var fieldName = field.Name;
var isPrivate = fieldName.StartsWith("_private_", StringComparison.OrdinalIgnoreCase);
if (isPrivate)
fieldName = fieldName[9..];
isPrivate |= fieldName.StartsWith("reserved", StringComparison.OrdinalIgnoreCase);
allFields.Add(fieldName);
var vis = map?.IsInternal == true ? "public" : "private";
var ro = map?.IsReadOnly == true ? " readonly" : "";
writer.WriteLine($"\t\t{vis}{ro} {type} {fieldName};");
if (!isPrivate && (map == null || (map.GenerateProperties && !map.IsInternal)))
{
var propertyName = fieldName;
if (map != null && map.Members.TryGetValue(propertyName, out var fieldMap))
{
if (string.IsNullOrEmpty(fieldMap))
isPrivate = true;
propertyName = fieldMap;
}
else
{
propertyName = CleanName(propertyName);
}
if (!isPrivate)
{
if (fieldName == "value")
fieldName = "this." + fieldName;
if (cppT == "bool")
{
if (map?.IsReadOnly == true)
{
writer.WriteLine($"\t\tpublic readonly bool {propertyName} => {fieldName} > 0;");
}
else
{
writer.WriteLine($"\t\tpublic bool {propertyName} {{");
writer.WriteLine($"\t\t\treadonly get => {fieldName} > 0;");
writer.WriteLine($"\t\t\tset => {fieldName} = value ? (byte)1 : (byte)0;");
writer.WriteLine($"\t\t}}");
}
}
else
{
if (map?.IsReadOnly == true)
{
writer.WriteLine($"\t\tpublic readonly {type} {propertyName} => {fieldName};");
}
else
{
writer.WriteLine($"\t\tpublic {type} {propertyName} {{");
writer.WriteLine($"\t\t\treadonly get => {fieldName};");
writer.WriteLine($"\t\t\tset => {fieldName} = value;");
writer.WriteLine($"\t\t}}");
}
}
}
}
writer.WriteLine();
}
if (map?.GenerateEquality == true)
{
// IEquatable
var equalityFields = new List<string>();
foreach (var f in allFields)
{
equalityFields.Add($"{f} == obj.{f}");
}
writer.WriteLine($"\t\tpublic readonly bool Equals ({name} obj) =>");
writer.WriteLine($"\t\t\t{string.Join(" && ", equalityFields)};");
writer.WriteLine();
// Equals
writer.WriteLine($"\t\tpublic readonly override bool Equals (object obj) =>");
writer.WriteLine($"\t\t\tobj is {name} f && Equals (f);");
writer.WriteLine();
// equality operators
writer.WriteLine($"\t\tpublic static bool operator == ({name} left, {name} right) =>");
writer.WriteLine($"\t\t\tleft.Equals (right);");
writer.WriteLine();
writer.WriteLine($"\t\tpublic static bool operator != ({name} left, {name} right) =>");
writer.WriteLine($"\t\t\t!left.Equals (right);");
writer.WriteLine();
// GetHashCode
writer.WriteLine($"\t\tpublic readonly override int GetHashCode ()");
writer.WriteLine($"\t\t{{");
writer.WriteLine($"\t\t\tvar hash = new HashCode ();");
foreach (var f in allFields)
{
writer.WriteLine($"\t\t\thash.Add ({f});");
}
writer.WriteLine($"\t\t\treturn hash.ToHashCode ();");
writer.WriteLine($"\t\t}}");
writer.WriteLine();
}
writer.WriteLine($"\t}}");
}