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

Avoid overflow exceptions when converting BOOL to bool #645

Merged
merged 1 commit into from
Aug 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions src/Microsoft.Windows.CsWin32/templates/BOOL.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
partial struct BOOL
{
internal unsafe BOOL(bool value) => this.Value = *(sbyte*)&value;
public static unsafe implicit operator bool(BOOL value)
{
sbyte v = checked((sbyte)value.Value);
return *(bool*)&v;
}

internal BOOL(bool value) => this.Value = value ? 1 : 0;
public static implicit operator bool(BOOL value) => value.Value != 0;
public static implicit operator BOOL(bool value) => new BOOL(value);
}
9 changes: 2 additions & 7 deletions src/Microsoft.Windows.CsWin32/templates/BOOLEAN.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
partial struct BOOLEAN
{
internal unsafe BOOLEAN(bool value) => this.Value = *(byte*)&value;
public static unsafe implicit operator bool(BOOLEAN value)
{
byte v = checked((byte)value.Value);
return *(bool*)&v;
}

internal BOOLEAN(bool value) => this.Value = value ? (byte)1 : (byte)0;
public static implicit operator bool(BOOLEAN value) => value.Value != 0;
public static implicit operator BOOLEAN(bool value) => new BOOLEAN(value);
}
51 changes: 39 additions & 12 deletions test/GenerationSandbox.Tests/BoolTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
public class BoolTests
{
[Fact]
public void Bool()
public void Ctor_bool()
{
BOOL b = true;
bool b2 = b;
Expand All @@ -16,26 +16,31 @@ public void Bool()
Assert.False(default(BOOL));
}

[Theory]
[InlineData(3)]
[InlineData(-1)]
public void NotLossyConversionBetweenBoolAndBOOL(int ordinal)
[Fact]
public void Ctor_int()
{
BOOL nativeBool = new BOOL(ordinal);
bool managedBool = nativeBool;
BOOL roundtrippedNativeBool = managedBool;
Assert.Equal(nativeBool, roundtrippedNativeBool);
Assert.Equal(2, new BOOL(2).Value);
}

[Fact]
public void ExplicitCast()
{
Assert.Equal(2, ((BOOL)2).Value);
}

[Theory]
[InlineData(3)]
[InlineData(-1)]
public void NotLossyConversionBetweenBoolAndBOOL_Ctors(int ordinal)
[InlineData(0)]
[InlineData(1)]
[InlineData(0xfffff)]
public void LossyConversionFromBOOLtoBool(int ordinal)
{
BOOL nativeBool = new BOOL(ordinal);
bool managedBool = nativeBool;
BOOL roundtrippedNativeBool = new BOOL(managedBool);
Assert.Equal(nativeBool, roundtrippedNativeBool);
Assert.Equal(ordinal != 0, managedBool);
BOOLEAN roundtrippedNativeBool = managedBool;
Assert.Equal(managedBool ? 1 : 0, roundtrippedNativeBool);
}

[Fact]
Expand All @@ -56,5 +61,27 @@ public void BOOL_OverridesEqualityOperator()
Assert.False(@true != new BOOL(true));
Assert.True(@true != @false);
Assert.False(@true == @false);

var two = new BOOL(2);
Assert.False(two == @true);
Assert.True(two != @true);
}

[Fact]
public void LogicalOperators_And()
{
BOOL @true = true, @false = false;
Assert.False(@false && @false);
Assert.False(@true && @false);
Assert.True(@true && @true);
}

[Fact]
public void LogicalOperators_Or()
{
BOOL @true = true, @false = false;
Assert.True(@true || @false);
Assert.False(@false || @false);
Assert.True(@true || @true);
}
}
51 changes: 39 additions & 12 deletions test/GenerationSandbox.Tests/BooleanTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
public class BooleanTests
{
[Fact]
public void Boolean()
public void Ctor_Bool()
{
BOOLEAN b = true;
bool b2 = b;
Expand All @@ -16,26 +16,31 @@ public void Boolean()
Assert.False(default(BOOLEAN));
}

[Theory]
[InlineData(3)]
[InlineData(0xff)]
public void NotLossyConversionBetweenBoolAndBOOLEAN(byte ordinal)
[Fact]
public void Ctor_byte()
{
BOOLEAN nativeBool = new BOOLEAN(ordinal);
bool managedBool = nativeBool;
BOOLEAN roundtrippedNativeBool = managedBool;
Assert.Equal(nativeBool, roundtrippedNativeBool);
Assert.Equal(2, new BOOLEAN(2).Value);
}

[Fact]
public void ExplicitCast()
{
Assert.Equal(2, ((BOOLEAN)2).Value);
}

[Theory]
[InlineData(3)]
[InlineData(0xff)]
public void NotLossyConversionBetweenBoolAndBOOLEAN_Ctors(byte ordinal)
[InlineData(0x80)]
[InlineData(0x00)]
[InlineData(0x01)]
public void LossyConversionFromBOOLEANtoBool(byte ordinal)
{
BOOLEAN nativeBool = new BOOLEAN(ordinal);
bool managedBool = nativeBool;
BOOLEAN roundtrippedNativeBool = new BOOLEAN(managedBool);
Assert.Equal(nativeBool, roundtrippedNativeBool);
Assert.Equal(ordinal != 0, managedBool);
BOOLEAN roundtrippedNativeBool = managedBool;
Assert.Equal(managedBool ? 1 : 0, roundtrippedNativeBool);
}

[Fact]
Expand All @@ -56,5 +61,27 @@ public void BOOLEAN_OverridesEqualityOperator()
Assert.False(@true != new BOOLEAN(true));
Assert.True(@true != @false);
Assert.False(@true == @false);

var two = new BOOLEAN(2);
Assert.False(two == @true);
Assert.True(two != @true);
}

[Fact]
public void LogicalOperators_And()
{
BOOLEAN @true = true, @false = false;
Assert.False(@false && @false);
Assert.False(@true && @false);
Assert.True(@true && @true);
}

[Fact]
public void LogicalOperators_Or()
{
BOOLEAN @true = true, @false = false;
Assert.True(@true || @false);
Assert.False(@false || @false);
Assert.True(@true || @true);
}
}
30 changes: 6 additions & 24 deletions test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1632,14 +1632,8 @@ namespace Foundation
public override bool Equals(object obj) => obj is BOOL other && this.Equals(other);

public override int GetHashCode() => this.Value.GetHashCode();
internal unsafe BOOL(bool value) => this.Value = *(sbyte*)&value;
public static unsafe implicit operator bool(BOOL value)

{
sbyte v = checked((sbyte)value.Value);
return *(bool*)&v;
}

internal BOOL(bool value) => this.Value = value ? 1 : 0;
public static implicit operator bool(BOOL value) => value.Value != 0;
public static implicit operator BOOL(bool value) => new BOOL(value);
}
}
Expand Down Expand Up @@ -1904,14 +1898,8 @@ namespace Foundation
public override bool Equals(object obj) => obj is BOOL other && this.Equals(other);

public override int GetHashCode() => this.Value.GetHashCode();
internal unsafe BOOL(bool value) => this.Value = *(sbyte*)&value;
public static unsafe implicit operator bool(BOOL value)

{
sbyte v = checked((sbyte)value.Value);
return *(bool*)&v;
}

internal BOOL(bool value) => this.Value = value ? 1 : 0;
public static implicit operator bool(BOOL value) => value.Value != 0;
public static implicit operator BOOL(bool value) => new BOOL(value);
}
}
Expand Down Expand Up @@ -2231,14 +2219,8 @@ namespace Foundation
public override bool Equals(object obj) => obj is BOOL other && this.Equals(other);

public override int GetHashCode() => this.Value.GetHashCode();
internal unsafe BOOL(bool value) => this.Value = *(sbyte*)&value;
public static unsafe implicit operator bool(BOOL value)

{
sbyte v = checked((sbyte)value.Value);
return *(bool*)&v;
}

internal BOOL(bool value) => this.Value = value ? 1 : 0;
public static implicit operator bool(BOOL value) => value.Value != 0;
public static implicit operator BOOL(bool value) => new BOOL(value);
}
}
Expand Down