Codec: StandardResolverAllowPrivate's formatter for an id-path type is no claim

It writes the [Key] layout plus non-public keyed members, and registration now refuses any of those that
reaches an object list, so no element id can be dropped. The comparison is made lazily, only after an
ahead resolver returned a non-standard formatter, and an exception from it reads as not equal.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Meta Vens 2026-10-15 01:23:40 +02:00
commit 908d9ac29d
2 changed files with 80 additions and 1 deletions

View file

@ -83,8 +83,12 @@ public static class CultDocumentMessagePackSerialization
{
var generic = GetFormatterMethod.MakeGenericMethod(type);
// A resolver that hands back MessagePack's own formatter for the type writes its [Key] layout: that is no claim, and the
// composite stops there, so no later resolver is asked.
// composite stops there, so no later resolver is asked. StandardResolverAllowPrivate's formatter writes the same layout
// plus non-public [Key] members, and registration refuses a non-public member on the way to an object list, so it
// claims nothing either.
var standard = generic.Invoke(StandardResolver.Instance, null);
var allowPrivateAsked = false;
object? allowPrivate = null;
foreach (var resolver in ahead)
{
var formatter = generic.Invoke(resolver, null);
@ -92,6 +96,21 @@ public static class CultDocumentMessagePackSerialization
continue;
if (ReferenceEquals(formatter, standard))
break;
if (!allowPrivateAsked)
{
allowPrivateAsked = true;
try
{
allowPrivate = generic.Invoke(StandardResolverAllowPrivate.Instance, null);
}
catch (Exception)
{
allowPrivate = null;
}
}
if (allowPrivate != null && ReferenceEquals(formatter, allowPrivate))
break;
return $"Cult document {documentType.Name}: formatter resolver {resolver.GetType().FullName} formats {type.Name}, which is on the path to a list whose elements carry ids, so its element ids would never reach disk. A resolver may not claim such a type; write it by its [Key] layout or keep it out of the document's lists.";
}
}