Created
October 11, 2021 13:23
-
-
Save rianjs/ce46d0be1e88f66bf5a57954357c3dae to your computer and use it in GitHub Desktop.
Creating semantic bitmasks using enums
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public bool HasPermission(long userPermissions, Permission desiredAction) | |
{ | |
if (userPermissions < 1) | |
{ | |
return false; | |
} | |
var asLong = (long)desiredAction; | |
var hasPermission = userPermissions & asLong; | |
return hasPermission != 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public enum PermissionMask : long | |
{ | |
Read = 1L, | |
Edit = Read << 1, | |
Create = Edit << 1, | |
Delete = Create << 1, | |
} | |
public void DisplayMasks() | |
{ | |
WriteLine($"{PermissionMask.Read}:\tBinary:{Convert.ToString((long)PermissionMask.Read, 2).PadLeft(8, '0')}\tLong:{(long)PermissionMask.Read:N0}"); | |
WriteLine($"{PermissionMask.Edit}:\tBinary:{Convert.ToString((long)PermissionMask.Edit, 2).PadLeft(8, '0')}\tLong:{(long)PermissionMask.Edit:N0}"); | |
WriteLine($"{PermissionMask.Create}:\tBinary:{Convert.ToString((long)PermissionMask.Create, 2).PadLeft(8, '0')}\tLong:{(long)PermissionMask.Create:N0}"); | |
WriteLine($"{PermissionMask.Delete}:\tBinary:{Convert.ToString((long)PermissionMask.Delete, 2).PadLeft(8, '0')}\tLong:{(long)PermissionMask.Delete:N0}"); | |
// Read: Binary:00000001 Long:1 | |
// Edit: Binary:00000010 Long:2 | |
// Create: Binary:00000100 Long:4 | |
// Delete: Binary:00001000 Long:8 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static IEnumerable<ITestCaseData> HasPermissionTestCases() | |
{ | |
yield return new TestCaseData(0L, Permission.Edit) | |
.Returns(false) | |
.SetName("Can't edit with zero permissions"); | |
yield return new TestCaseData(-1L, Permission.Edit) | |
.Returns(false) | |
.SetName("Can't edit with permissions < 0"); | |
var enumerablePermissions = Enum.GetValues(typeof(Permission)).Cast<Permission>(); | |
//Tautologies | |
foreach (var permission in enumerablePermissions) | |
{ | |
yield return new TestCaseData((long)permission, permission) | |
.Returns(true) | |
.SetName($"Permission.{permission} allows Permission.{permission}"); | |
} | |
//Contradictions | |
foreach (var outer in enumerablePermissions) //If I have Permission.Foo | |
{ | |
foreach (var inner in enumerablePermissions.Where(p => p != outer)) //I can't do Permission.Bar | |
{ | |
yield return new TestCaseData((long)outer, inner) | |
.Returns(false) | |
.SetName($"Permission.{outer} doesn't allow for Permission.{inner}"); | |
} | |
} | |
//Some combinations | |
var allowed = enumerablePermissions.Take(2).ToList(); | |
var aggregation = allowed | |
.Cast<long>() | |
.Aggregate((a, b) => a | b); | |
foreach (var permission in enumerablePermissions) | |
{ | |
var returns = allowed.Contains(permission); | |
yield return new TestCaseData(aggregation, permission) | |
.Returns(returns) | |
.SetName($"Permissions {string.Join(",", allowed)} against Permission.{permission} = {returns}"); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment