Open Andrepuel opened 1 year ago
I was thinking about this a lot. The problem becomes that if struct is used, then basic types have to be explicitly wrapped when interfacing with such bindings. I'm not sure if this is acceptable. E.g.
// UDL
[Custom]
typedef string Url;
// C#
struct URL {
// pseudo
String Value;
}
void VisitURL(URL url);
Uri uri = ..;
VisitURL(URL(uri.AbsolutePath));
What is your use case?
I have some types that I want to be opaque but I don't want to deal with pay the cost of heap. For example, UUID. For my scenario, I consider it dangerous that my function accept any string. I would like my functions to accept only the type UUID that I have provided. It is like the difference between pub struct Handle(i64);
and pub struct Handle(pub i64);
.
I've checked the behavior of Python, Kotlin e Swift generator and all of them are using the "typedef" behavior. So I think the the current C# behavior is more aligned with the others generators.
It is just bugging my mind that the original project did choose rust new-type to exemplify what is generated as a type-alias in the bindgen.
For now, I've chosen to implement UUID et al using a struct with a single attribute that the end user should not access directly.
I see, I think understand now. In Rust code, custom type is declared as an opaque type alias. In foreign bindings, the same custom type is declared as a transparent type alias. I agree that it would be useful to create an opaque type alias in bindings. This issue could also be created in uniffi-rs.
For C#, using an opaque type alias as a struct would be very useful actually. External types can't be implemented right now due to the current using A = B
custom type implementation. It seems like implementing custom type as a struct wrapper would solve both these issues. When writing the current implementation I was very unsure what would be the "right" use case for custom types, so I just copied what Kotlin/Swift/ does.
Would a struct with a single private attribute be the desirable way of implementing this feature?
public struct A {
private A _this;
}
I guess that would work, but there should be a getter to get the underlying value. As I understand your use case is a Handle, in which case its convenient for you to keep the underlying value private. But for other types of values it might be necessary to have access to underlying value. Though I can't think of any case for that. Url
comes to mind, but that could be represented as C# Uri
without any type alias.
In uniffi documentation, it uses the following example for custom type:
Which, in Rust, is a new type.
On the generate C# code,
alias
is used. This does not create a new type. This type may not be named outside of the module. Perhaps custom types should use C# Record with one positional argument that matches the UDL typedef.