Skip to content

Commit

Permalink
Implement Eq and Hash trait methods (#97)
Browse files Browse the repository at this point in the history
* implement Eq and Hash trait methods

Signed-off-by: Chloe McKnight <[email protected]>

* remove operator overrides for Eq impl

Signed-off-by: Chloe McKnight <[email protected]>

* fix colon placement

Signed-off-by: Chloe McKnight <[email protected]>

---------

Signed-off-by: Chloe McKnight <[email protected]>
  • Loading branch information
cmcknight-bb authored Nov 18, 2024
1 parent 4c621e1 commit dca4e88
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 4 deletions.
24 changes: 23 additions & 1 deletion bindgen/templates/ObjectTemplate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,14 @@
{%- if self.include_once_check("ObjectRuntime.cs") %}{% include "ObjectRuntime.cs" %}{% endif %}

{%- call cs::docstring(obj, 0) %}
{{ config.access_modifier() }} interface I{{ type_name }} {
{{ config.access_modifier() }} interface I{{ type_name }}
{%- for tm in obj.uniffi_traits() -%}
{%- match tm -%}
{%- when UniffiTrait::Eq { eq, ne } -%}
: IEquatable<{{type_name}}>
{%- else -%}
{%- endmatch -%}
{%- endfor %} {
{% for meth in obj.methods() -%}
{%- call cs::docstring(meth, 4) %}
{%- call cs::method_throws_annotation(meth.throws_type()) %}
Expand Down Expand Up @@ -63,6 +70,21 @@ override protected bool ReleaseHandle() {
public override string ToString() {
return {{ Type::String.borrow()|lift_fn }}({%- call cs::to_ffi_call_with_prefix("this.GetHandle()", fmt) %});
}
{%- when UniffiTrait::Eq { eq, ne } %}
public bool Equals({{type_name}}? other)
{
if (other is null) return false;
return {{ Type::Boolean.borrow()|lift_fn }}({%- call cs::to_ffi_call_with_prefix("this.GetHandle()", eq) %});
}
public override bool Equals(object? obj)
{
if (obj is null || !(obj is {{type_name}})) return false;
return Equals(obj as {{type_name}});
}
{%- when UniffiTrait::Hash { hash } %}
public override int GetHashCode() {
return (int){{ Type::UInt64.borrow()|lift_fn }}({%- call cs::to_ffi_call_with_prefix("this.GetHandle()", hash) %});
}
{%- else %}
{%- endmatch %}
{%- endfor %}
Expand Down
113 changes: 110 additions & 3 deletions dotnet-tests/UniffiCS.BindingTests/TestTraitMethod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

using System;
using System.Collections.Generic;
using uniffi.trait_methods;

namespace UniffiCS.BindingTests;

public class TestTraitMethods
{
[Fact]
public void TraitMethodsWork()
public void TestDisplay()
{
using (var methods = new TraitMethods("yo"))
{
Expand All @@ -18,11 +20,116 @@ public void TraitMethodsWork()
}

[Fact]
public void TraitMethodsProcMacro()
public void TestEq()
{
using (var methods = new TraitMethods("yo"))
{
// Values are equal if input is the same
Assert.Equal(methods, new TraitMethods("yo"));
Assert.NotEqual(methods, new TraitMethods("yoyo"));

// Values are not referentially equal
Assert.False(methods == new TraitMethods("yo"));
}
}

[Fact]
public void TestEqNull()
{
TraitMethods? t1 = null;
TraitMethods? t2 = null;
Assert.True(Object.Equals(t1, t2));

t1 = new TraitMethods("yo");
Assert.False(Object.Equals(t1, t2));

Assert.False(new TraitMethods("yo") == null);
Assert.True(new TraitMethods("yo") != null);
}

[Fact]
public void TestEqContains()
{
var tm = new TraitMethods("yo");
var list = new List<TraitMethods>
{
tm
};

Assert.Contains(tm, list);
Assert.Contains(new TraitMethods("yo"), list);
Assert.DoesNotContain(null, list);
Assert.DoesNotContain(new TraitMethods("yoyo"), list);
}

[Fact]
public void TestHash()
{
using (var methods = new TraitMethods("yo"))
{
Assert.Equal(methods.GetHashCode(), new TraitMethods("yo").GetHashCode());
Assert.NotEqual(methods.GetHashCode(), new TraitMethods("yoyo").GetHashCode());
}
}
}

public class TestProcMacroTraitMethods
{
[Fact]
public void TestDisplay()
{
using (var methods = new ProcTraitMethods("yo"))
{
Assert.Equal("ProcTraitMethods(yo)", methods.ToString());
}
}
}

[Fact]
public void TestEq()
{
using (var methods = new ProcTraitMethods("yo"))
{
// Values are equal if input is the same
Assert.Equal(methods, new ProcTraitMethods("yo"));
Assert.NotEqual(methods, new ProcTraitMethods("yoyo"));

// Values are not referentially equal
Assert.False(methods == new ProcTraitMethods("yo"));
}
}

[Fact]
public void TestEqNull()
{
ProcTraitMethods? t1 = null;
ProcTraitMethods? t2 = null;
Assert.True(Object.Equals(t1, t2));

Assert.False(new ProcTraitMethods("yo") == null);
}

[Fact]
public void TestEqContains()
{
var tm = new ProcTraitMethods("yo");
var list = new List<ProcTraitMethods>
{
tm
};

Assert.Contains(tm, list);
Assert.Contains(new ProcTraitMethods("yo"), list);
Assert.DoesNotContain(null, list);
Assert.DoesNotContain(new ProcTraitMethods("yoyo"), list);
}

[Fact]
public void TestHash()
{
using (var methods = new ProcTraitMethods("yo"))
{
Assert.Equal(methods.GetHashCode(), new ProcTraitMethods("yo").GetHashCode());
Assert.NotEqual(methods.GetHashCode(), new ProcTraitMethods("yoyo").GetHashCode());
}
}
}

0 comments on commit dca4e88

Please sign in to comment.