Skip to content

Commit

Permalink
feat: Add support for TomlFieldAttribute (#54) (#55)
Browse files Browse the repository at this point in the history
  • Loading branch information
ting-liang-rocketwerkz authored Mar 3, 2025
1 parent 0f83b66 commit f8e94b2
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 11 deletions.
19 changes: 19 additions & 0 deletions Tomlet/Attributes/TomlFieldAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System;

namespace Tomlet.Attributes;

[AttributeUsage(AttributeTargets.Field)]
public class TomlFieldAttribute : Attribute
{
private readonly string _mapFrom;

public TomlFieldAttribute(string mapFrom)
{
_mapFrom = mapFrom;
}

public string GetMappedString()
{
return _mapFrom;
}
}
14 changes: 9 additions & 5 deletions Tomlet/TomlCompositeDeserializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,10 @@ public static TomlSerializationMethods.Deserialize<object> For(Type type, TomlSe
var fields = type.GetFields(memberFlags);

//Ignore NonSerialized and CompilerGenerated fields.
fields = fields.Where(f => !f.IsNotSerialized && GenericExtensions.GetCustomAttribute<CompilerGeneratedAttribute>(f) == null).ToArray();
var fieldsDict = fields
.Where(f => !f.IsNotSerialized && GenericExtensions.GetCustomAttribute<CompilerGeneratedAttribute>(f) == null)
.Select(f => new KeyValuePair<FieldInfo, TomlFieldAttribute?>(f, GenericExtensions.GetCustomAttribute<TomlFieldAttribute>(f)))
.ToDictionary(tuple => tuple.Key, tuple => tuple.Value);

var props = type.GetProperties(memberFlags);

Expand All @@ -62,7 +65,7 @@ public static TomlSerializationMethods.Deserialize<object> For(Type type, TomlSe
.Select(p => new KeyValuePair<PropertyInfo, TomlPropertyAttribute?>(p, GenericExtensions.GetCustomAttribute<TomlPropertyAttribute>(p)))
.ToDictionary(tuple => tuple.Key, tuple => tuple.Value);

if (fields.Length + propsDict.Count == 0)
if (fieldsDict.Count + propsDict.Count == 0)
return value => CreateInstance(type, value, options, out _);

deserializer = value =>
Expand All @@ -72,12 +75,13 @@ public static TomlSerializationMethods.Deserialize<object> For(Type type, TomlSe

var instance = CreateInstance(type, value, options, out var assignedMembers);

foreach (var field in fields)
foreach (var (field, attribute) in fieldsDict)
{
if (!options.OverrideConstructorValues && assignedMembers.Contains(field.Name))
var name = attribute?.GetMappedString() ?? field.Name;
if (!options.OverrideConstructorValues && assignedMembers.Contains(name))
continue;

if (!table.TryGetValue(field.Name, out var entry))
if (!table.TryGetValue(name, out var entry))
continue; //TODO: Do we want to make this configurable? As in, throw exception if data is missing?

object fieldValue;
Expand Down
12 changes: 6 additions & 6 deletions Tomlet/TomlCompositeSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public static TomlSerializationMethods.Serialize<object> For(Type type, TomlSeri

var fields = type.GetFields(memberFlags);
var fieldAttribs = fields
.ToDictionary(f => f, f => new {inline = GenericExtensions.GetCustomAttribute<TomlInlineCommentAttribute>(f), preceding = GenericExtensions.GetCustomAttribute<TomlPrecedingCommentAttribute>(f), noInline = GenericExtensions.GetCustomAttribute<TomlDoNotInlineObjectAttribute>(f)});
.ToDictionary(f => f, f => new {inline = GenericExtensions.GetCustomAttribute<TomlInlineCommentAttribute>(f), preceding = GenericExtensions.GetCustomAttribute<TomlPrecedingCommentAttribute>(f), field = GenericExtensions.GetCustomAttribute<TomlFieldAttribute>(f), noInline = GenericExtensions.GetCustomAttribute<TomlDoNotInlineObjectAttribute>(f)});
var props = type.GetProperties(memberFlags)
.ToArray();
var propAttribs = props
Expand Down Expand Up @@ -73,21 +73,21 @@ public static TomlSerializationMethods.Serialize<object> For(Type type, TomlSeri
if(tomlValue == null)
continue;

var commentAttribs = fieldAttribs[field];
var thisFieldAttribs = fieldAttribs[field];

if (resultTable.ContainsKey(field.Name))
//Do not overwrite fields if they have the same name as something already in the table
//This fixes serializing types which re-declare a field using the `new` keyword, overwriting a field of the same name
//in its supertype.
continue;

tomlValue.Comments.InlineComment = commentAttribs.inline?.Comment;
tomlValue.Comments.PrecedingComment = commentAttribs.preceding?.Comment;
tomlValue.Comments.InlineComment = thisFieldAttribs.inline?.Comment;
tomlValue.Comments.PrecedingComment = thisFieldAttribs.preceding?.Comment;

if(commentAttribs.noInline != null && tomlValue is TomlTable table)
if(thisFieldAttribs.noInline != null && tomlValue is TomlTable table)
table.ForceNoInline = true;

resultTable.PutValue(field.Name, tomlValue);
resultTable.PutValue(thisFieldAttribs.field?.GetMappedString() ?? field.Name, tomlValue);
}

foreach (var prop in props)
Expand Down

0 comments on commit f8e94b2

Please sign in to comment.