Skip to content

Commit

Permalink
dotnet: support for moved objects
Browse files Browse the repository at this point in the history
  • Loading branch information
CBenoit committed Jan 27, 2022
1 parent 456b6ae commit 5ceacb6
Show file tree
Hide file tree
Showing 61 changed files with 2,478 additions and 29 deletions.
106 changes: 106 additions & 0 deletions feature_tests/dotnet/Lib/Generated/CountedOpaque.cs
@@ -0,0 +1,106 @@
// Automatically generated by Diplomat

#pragma warning disable 0105
using System;
using System.Runtime.InteropServices;

using DiplomatFeatures.Diplomat;
#pragma warning restore 0105

namespace DiplomatFeatures;

#nullable enable

public partial class CountedOpaque: IDisposable
{
private unsafe Raw.CountedOpaque* _inner;

/// <summary>
/// Creates a managed <c>CountedOpaque</c> from a raw handle.
/// </summary>
/// <remarks>
/// Safety: you should not build two managed objects using the same raw handle (may causes use-after-free and double-free).
/// </remarks>
/// <remarks>
/// This constructor assumes the raw struct is allocated on Rust side.
/// If implemented, the custom Drop implementation on Rust side WILL run on destruction.
/// </remarks>
public unsafe CountedOpaque(Raw.CountedOpaque* handle)
{
_inner = handle;
}

/// <returns>
/// A <c>CountedOpaque</c> allocated on Rust side.
/// If a custom Drop implementation is implemented on Rust side, it WILL run on destruction.
/// </returns>
public static CountedOpaque New(Counter counter)
{
unsafe
{
Raw.Counter* counterRaw;
counterRaw = counter.AsFFI();
if (counterRaw == null)
{
throw new ObjectDisposedException("Counter");
}
Raw.CountedOpaque* retVal = Raw.CountedOpaque.New(counterRaw);
return new CountedOpaque(retVal);
}
}

/// <summary>
/// Returns the underlying raw handle.
/// </summary>
public unsafe Raw.CountedOpaque* AsFFI()
{
return _inner;
}

/// <summary>
/// Marks this object as moved into Rust side.
/// </summary>
public void MarkAsMoved()
{
unsafe
{
if (_inner == null)
{
throw new ObjectDisposedException("CountedOpaque");
}
_inner = null;
}
}

/// <summary>
/// Restores unmanaged ressource handle to this object.
/// </summary>
public unsafe void RestoreHandle(Raw.CountedOpaque* handle)
{
_inner = handle;
}

/// <summary>
/// Destroys the underlying object immediately.
/// </summary>
public void Dispose()
{
unsafe
{
if (_inner == null)
{
return;
}

Raw.CountedOpaque.Destroy(_inner);
_inner = null;

GC.SuppressFinalize(this);
}
}

~CountedOpaque()
{
Dispose();
}
}
116 changes: 116 additions & 0 deletions feature_tests/dotnet/Lib/Generated/Counter.cs
@@ -0,0 +1,116 @@
// Automatically generated by Diplomat

#pragma warning disable 0105
using System;
using System.Runtime.InteropServices;

using DiplomatFeatures.Diplomat;
#pragma warning restore 0105

namespace DiplomatFeatures;

#nullable enable

/// <summary>
/// Counts how many distinct `CountedOpaque` objects are instanciated
/// </summary>
public partial class Counter: IDisposable
{
private unsafe Raw.Counter* _inner;

/// <summary>
/// Creates a managed <c>Counter</c> from a raw handle.
/// </summary>
/// <remarks>
/// Safety: you should not build two managed objects using the same raw handle (may causes use-after-free and double-free).
/// </remarks>
/// <remarks>
/// This constructor assumes the raw struct is allocated on Rust side.
/// If implemented, the custom Drop implementation on Rust side WILL run on destruction.
/// </remarks>
public unsafe Counter(Raw.Counter* handle)
{
_inner = handle;
}

/// <returns>
/// A <c>Counter</c> allocated on Rust side.
/// If a custom Drop implementation is implemented on Rust side, it WILL run on destruction.
/// </returns>
public static Counter New()
{
unsafe
{
Raw.Counter* retVal = Raw.Counter.New();
return new Counter(retVal);
}
}

public nuint Count()
{
unsafe
{
if (_inner == null)
{
throw new ObjectDisposedException("Counter");
}
nuint retVal = Raw.Counter.Count(_inner);
return retVal;
}
}

/// <summary>
/// Returns the underlying raw handle.
/// </summary>
public unsafe Raw.Counter* AsFFI()
{
return _inner;
}

/// <summary>
/// Marks this object as moved into Rust side.
/// </summary>
public void MarkAsMoved()
{
unsafe
{
if (_inner == null)
{
throw new ObjectDisposedException("Counter");
}
_inner = null;
}
}

/// <summary>
/// Restores unmanaged ressource handle to this object.
/// </summary>
public unsafe void RestoreHandle(Raw.Counter* handle)
{
_inner = handle;
}

/// <summary>
/// Destroys the underlying object immediately.
/// </summary>
public void Dispose()
{
unsafe
{
if (_inner == null)
{
return;
}

Raw.Counter.Destroy(_inner);
_inner = null;

GC.SuppressFinalize(this);
}
}

~Counter()
{
Dispose();
}
}
17 changes: 17 additions & 0 deletions feature_tests/dotnet/Lib/Generated/DiplomatRuntime.cs
Expand Up @@ -136,3 +136,20 @@ public class DiplomatOpaqueException : Exception
{
public DiplomatOpaqueException() : base("The FFI function failed with an opaque error") { }
}

public class DiplomatUnmovableObject : Exception
{
private string _objectName;

public string ObjectName
{
get
{
return _objectName;
}
}

public DiplomatUnmovableObject(string objectName, string message) : base($"Can't move this instance of {objectName}: {message}") {
_objectName = objectName;
}
}
34 changes: 34 additions & 0 deletions feature_tests/dotnet/Lib/Generated/ErrorStruct.cs
Expand Up @@ -75,6 +75,40 @@ public ErrorStruct(Raw.ErrorStruct handle)
return _inner;
}

/// <summary>
/// Marks this object as moved into Rust side.
/// </summary>
/// <remarks>
/// Safety: this instance must be allocated on Rust side.
/// </remarks>
/// <exception cref="DiplomatUnmovableObject"></exception>
public void MarkAsMoved()
{
unsafe
{
if (!_isAllocatedByRust)
{
throw new DiplomatUnmovableObject("ErrorStruct", "not allocated by Rust");
}
if (_inner == null)
{
throw new ObjectDisposedException("ErrorStruct");
}
_inner = null;
}
}

/// <summary>
/// Restores unmanaged ressource handle to this object.
/// </summary>
/// <remarks>
/// Safety: the pointee must be allocated on Rust side.
/// </remarks>
public unsafe void RestoreHandle(Raw.ErrorStruct* handle)
{
_inner = handle;
}

/// <summary>
/// Destroys the underlying object immediately.
/// </summary>
Expand Down
23 changes: 23 additions & 0 deletions feature_tests/dotnet/Lib/Generated/Float64Vec.cs
Expand Up @@ -87,6 +87,29 @@ public void SetValue(double[] newSlice)
return _inner;
}

/// <summary>
/// Marks this object as moved into Rust side.
/// </summary>
public void MarkAsMoved()
{
unsafe
{
if (_inner == null)
{
throw new ObjectDisposedException("Float64Vec");
}
_inner = null;
}
}

/// <summary>
/// Restores unmanaged ressource handle to this object.
/// </summary>
public unsafe void RestoreHandle(Raw.Float64Vec* handle)
{
_inner = handle;
}

/// <summary>
/// Destroys the underlying object immediately.
/// </summary>
Expand Down
23 changes: 23 additions & 0 deletions feature_tests/dotnet/Lib/Generated/MyString.cs
Expand Up @@ -116,6 +116,29 @@ public static string MakeUppercase(string v)
return _inner;
}

/// <summary>
/// Marks this object as moved into Rust side.
/// </summary>
public void MarkAsMoved()
{
unsafe
{
if (_inner == null)
{
throw new ObjectDisposedException("MyString");
}
_inner = null;
}
}

/// <summary>
/// Restores unmanaged ressource handle to this object.
/// </summary>
public unsafe void RestoreHandle(Raw.MyString* handle)
{
_inner = handle;
}

/// <summary>
/// Destroys the underlying object immediately.
/// </summary>
Expand Down
34 changes: 34 additions & 0 deletions feature_tests/dotnet/Lib/Generated/MyStruct.cs
Expand Up @@ -178,6 +178,40 @@ public static MyStruct New()
return _inner;
}

/// <summary>
/// Marks this object as moved into Rust side.
/// </summary>
/// <remarks>
/// Safety: this instance must be allocated on Rust side.
/// </remarks>
/// <exception cref="DiplomatUnmovableObject"></exception>
public void MarkAsMoved()
{
unsafe
{
if (!_isAllocatedByRust)
{
throw new DiplomatUnmovableObject("MyStruct", "not allocated by Rust");
}
if (_inner == null)
{
throw new ObjectDisposedException("MyStruct");
}
_inner = null;
}
}

/// <summary>
/// Restores unmanaged ressource handle to this object.
/// </summary>
/// <remarks>
/// Safety: the pointee must be allocated on Rust side.
/// </remarks>
public unsafe void RestoreHandle(Raw.MyStruct* handle)
{
_inner = handle;
}

/// <summary>
/// Destroys the underlying object immediately.
/// </summary>
Expand Down

0 comments on commit 5ceacb6

Please sign in to comment.