Fix loading of binary and canonical constants

This commit is contained in:
Yoshi Askharoun
2024-12-29 15:33:10 -06:00
parent 845f241702
commit 58b82c1e64
2 changed files with 38 additions and 24 deletions
+36 -24
View File
@@ -282,52 +282,64 @@ internal class AsmMarkupLoader
foreach (var constant in Program.Body.OfType<ConstantDirective>()) foreach (var constant in Program.Body.OfType<ConstantDirective>())
{ {
object constantValue, persistData = null; object constantValue, persistData = null;
MarkupConstantPersistMode mode;
var constantTypeSchema = ResolveTypeFromQualifiedName(constant.TypeName); var constantTypeSchema = ResolveTypeFromQualifiedName(constant.TypeName);
if (constant is StringEncodedConstantDirective encodedConstant) if (constant is StringEncodedConstantDirective stringEncodedConstant)
{ {
var parseResult = constantTypeSchema.TypeConverter(encodedConstant.Content, stringTypeSchema, out constantValue); var stringParseResult = constantTypeSchema.TypeConverter(stringEncodedConstant.Content, stringTypeSchema, out constantValue);
if (parseResult.Failed) if (stringParseResult.Failed)
{ {
ReportError($"Failed to create an instance of '{constant.TypeName}' from '{encodedConstant.Content}'", constant); ReportError($"Failed to create an instance of '{constant.TypeName}' from '{stringEncodedConstant.Content}'", constant);
continue; continue;
} }
persistData = encodedConstant.Content; persistData = stringEncodedConstant.Content;
mode = MarkupConstantPersistMode.FromString;
} }
else else if (constant is CanonicalInstanceConstantDirective canonicalInstanceConstant)
{ {
var xmlElem = System.Xml.Linq.XElement.Parse(constant.Constructor); var canonicalName = canonicalInstanceConstant.CanonicalName;
persistData = canonicalName;
mode = MarkupConstantPersistMode.Canonical;
constantValue = constantTypeSchema.ConstructDefault(); constantValue = constantTypeSchema.FindCanonicalInstance(canonicalName);
foreach (var attr in xmlElem.Attributes()) if (constantValue is null)
{ {
var propName = attr.Name.LocalName; var canonicalParseResult = constantTypeSchema.TypeConverter(canonicalName, stringTypeSchema, out constantValue);
var prop = constantTypeSchema.FindProperty(propName); if (canonicalParseResult.Failed)
var propConvertResult = prop.PropertyType.TypeConverter(attr.Value, stringTypeSchema, out var propValue);
if (propConvertResult.Failed)
{ {
ReportError($"Failed to set {constantTypeSchema.Name}.{propName}", constant); ReportError($"Failed to get canonical instance '{canonicalName}' from '{constant.TypeName}'", constant);
continue; continue;
} }
prop.SetValue(ref constantValue, propValue);
} }
} }
else if (constant is BinaryEncodedConstantDirective binaryEncodedConstant)
MarkupConstantPersistMode mode;
if (constantTypeSchema.SupportsBinaryEncoding)
{ {
mode = MarkupConstantPersistMode.Binary; if (!constantTypeSchema.SupportsBinaryEncoding)
{
ReportError($"Constant was binary-encoded, but {constant.TypeName} does not support binary encoding.", constant);
continue;
}
var contentBuffer = binaryEncodedConstant.Content;
ByteCodeWriter binaryConstantWrtier = new();
binaryConstantWrtier.Write(contentBuffer, (uint)contentBuffer.Length);
var binaryConstantReader = binaryConstantWrtier.CreateReader();
constantValue = constantTypeSchema.DecodeBinary(binaryConstantReader);
persistData = constantValue; persistData = constantValue;
mode = MarkupConstantPersistMode.Binary;
} }
else else
{ {
mode = MarkupConstantPersistMode.FromString; ReportError($"Constant of type '{constant.TypeName}' was not encoded in a recognized format.", constant);
if (persistData is null) continue;
throw new Exception($"{constant.Name} cannot be persisted as a string without persist data.");
} }
var constantIndex = (ushort)constantsTable.Add(constantTypeSchema, constantValue, mode, persistData); var constantIndex = (ushort)constantsTable.Add(constantTypeSchema, constantValue, mode, persistData);
+2
View File
@@ -328,6 +328,8 @@ public class Disassembler
return new StringEncodedConstantDirective(constantName, qualifiedTypeName, encodedValue); return new StringEncodedConstantDirective(constantName, qualifiedTypeName, encodedValue);
} }
// TODO: How are canonical instances usually handled? Are they always loaded by
// converting the canonical name as a string to the base type?
// Custom handling for ILayout // Custom handling for ILayout
if (constantValue is Layout.ILayout constantLayout && Layout.PredefinedLayouts.TryConvertToString(constantLayout, out var constantLayoutString)) if (constantValue is Layout.ILayout constantLayout && Layout.PredefinedLayouts.TryConvertToString(constantLayout, out var constantLayoutString))
{ {