Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide a way to introspect NothingSerialDescriptor #2788

Open
BenWoodworth opened this issue Aug 20, 2024 · 2 comments
Open

Provide a way to introspect NothingSerialDescriptor #2788

BenWoodworth opened this issue Aug 20, 2024 · 2 comments
Labels

Comments

@BenWoodworth
Copy link
Contributor

What is your use-case and why do you need this feature?

I support a format where Nothing in its schema is meaningful, e.g. List<Nothing> is encoded differently than an empty List<Int>. So far I have been getting by with descriptor == NothingSerializer().descriptor, but I'm finding issues with this now that I'm supporting new features of the format in my library.

Basically, if NothingSerialDescriptor is decorated at all, e.g.:

  • NothingSerialDescriptor.nullable
  • SerialDescriptor("renamed", NothingSerialDescriptor) like with serializer delegation
  • Or any other SerialDescriptor delegating its interface to it

Specifically though, it's been useful for serializing list element types right away, like when encodeCollection is called, instead of holding off until the first element is serialized.

In addition to that, I have another feature planned with dynamic element names for serial types that would similarly decorate a serial descriptor by adding an annotation, and that would also be affected by this.

Describe the solution you'd like

It feels like Nothing is a special enough type that formats that could support it should be able to tell it apart from any other StructureKind.OBJECT (which is how it appears now), and making that transparent through decorated/delegated SerialDescriptors would be beneficial.

I don't know the best way to support this, but I have a couple ideas.

Adding another serial kind for Nothing would work, though it feels too late at this point. If it's not though, that feels like a good option.

Otherwise, a solution that would work for me is adding an (internal) annotation that kxs can use to identify a Nothing serial descriptor, even when wrapping serial descriptors. Something like this is what I have in mind:

internal object NothingSerialDescriptor : SerialDescriptor {
    public override val kind: SerialKind = StructureKind.OBJECT
    public override val annotations: List<Annotation> = listOf(NothingSerialKind()) // Added line

    public override val serialName: String = "kotlin.Nothing"
    // ...
}

internal annotation class NothingSerialKind

// In non-internal package:

@ExperimentalSerializationApi
public val SerialDescriptor.isNothing: Boolean
    get() = annotations.any { it is NothingSerialKind }

This way the Nothing-ness is passed down when delegating (assuming the outer descriptor doesn't remove annotations). And I don't think this should be a problem with annotations being experimental since the implementation for isNothing implemented can be changed if needed.

@BenWoodworth
Copy link
Contributor Author

I am curious if this is a proper design concern, or if maybe I'm just approaching this the wrong way. Recommendations welcome, and I'm up for posting a PR if this is a good solution :)

@sandwwraith
Copy link
Member

Are you sure that you want to treat List<Nothing> and List<Nothing?> the same way? To me, the first one is always empty and the second can contain any amount of nulls.
Also, if someone wraps Nothing serial descriptor, they probably do not want it to be treated as a regular Nothing. So, I'm not sure that NothingDescriptor is special enough to have its own kind

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants