diff --git a/kmip/core/enums.py b/kmip/core/enums.py index dd0d888..d2e9921 100644 --- a/kmip/core/enums.py +++ b/kmip/core/enums.py @@ -18,6 +18,7 @@ import copy import enum +import functools import six @@ -1814,14 +1815,86 @@ def convert_attribute_tag_to_name(value): raise ValueError("Unrecognized attribute tag: {}".format(value)) +def get_bit_mask_from_enumerations(enumerations): + """ + A utility function that computes a bit mask from a collection of + enumeration values. -def is_enum_value(enum_class, potential_value): + Args: + enumerations (list): A list of enumeration values to be combined in a + composite bit mask. + + Returns: + int: The composite bit mask. + """ + return functools.reduce( + lambda x, y: x | y, [z.value for z in enumerations] + ) + + +def get_enumerations_from_bit_mask(enumeration, mask): + """ + A utility function that creates a list of enumeration values from a bit + mask for a specific mask enumeration class. + + Args: + enumeration (class): The enumeration class from which to draw + enumeration values. + mask (int): The bit mask from which to identify enumeration values. + + Returns: + list: A list of enumeration values corresponding to the bit mask. + """ + return [x for x in enumeration if (x.value & mask) == x.value] + + +def is_bit_mask(enumeration, potential_mask): + """ + A utility function that checks if the provided value is a composite bit + mask of enumeration values in the specified enumeration class. + + Args: + enumeration (class): One of the mask enumeration classes found in this + file. These include: + * Cryptographic Usage Mask + * Protection Storage Mask + * Storage Status Mask + potential_mask (int): A potential bit mask composed of enumeration + values belonging to the enumeration class. + + Returns: + True: if the potential mask is a valid bit mask of the mask enumeration + False: otherwise + """ + if not isinstance(potential_mask, six.integer_types): + return False + + mask_enumerations = ( + CryptographicUsageMask, + ProtectionStorageMask, + StorageStatusMask + ) + if enumeration not in mask_enumerations: + return False + + mask = 0 + for value in [e.value for e in enumeration]: + if (value & potential_mask) == value: + mask |= value + + if mask != potential_mask: + return False + + return True + + +def is_enum_value(enumeration, potential_value): """ A utility function that checks if the enumeration class contains the provided value. Args: - enum_class (class): One of the enumeration classes found in this file. + enumeration (class): One of the enumeration classes found in this file. potential_value (int, string): A potential value of the enumeration class. @@ -1830,7 +1903,7 @@ def is_enum_value(enum_class, potential_value): False: otherwise """ try: - enum_class(potential_value) + enumeration(potential_value) except ValueError: return False diff --git a/kmip/tests/unit/core/test_enums.py b/kmip/tests/unit/core/test_enums.py index db67943..c0c9197 100644 --- a/kmip/tests/unit/core/test_enums.py +++ b/kmip/tests/unit/core/test_enums.py @@ -87,6 +87,63 @@ class TestEnumUtilityFunctions(testtools.TestCase): def tearDown(self): super(TestEnumUtilityFunctions, self).tearDown() + def test_get_bit_mask_from_enumerations(self): + self.assertEqual( + 7, + enums.get_bit_mask_from_enumerations( + [ + enums.StorageStatusMask.ARCHIVAL_STORAGE, + enums.StorageStatusMask.DESTROYED_STORAGE, + enums.StorageStatusMask.ONLINE_STORAGE + ] + ) + ) + + def test_get_enumerations_from_bit_mask(self): + expected = [ + enums.StorageStatusMask.ARCHIVAL_STORAGE, + enums.StorageStatusMask.DESTROYED_STORAGE, + enums.StorageStatusMask.ONLINE_STORAGE + ] + observed = enums.get_enumerations_from_bit_mask( + enums.StorageStatusMask, + 7 + ) + + self.assertEqual(len(expected), len(observed)) + for x in expected: + self.assertIn(x, observed) + + def test_is_bit_mask(self): + self.assertTrue( + enums.is_bit_mask( + enums.StorageStatusMask, + enums.StorageStatusMask.ARCHIVAL_STORAGE.value | + enums.StorageStatusMask.ONLINE_STORAGE.value + ) + ) + + self.assertFalse( + enums.is_bit_mask( + enums.StorageStatusMask, + enums.StorageStatusMask.DESTROYED_STORAGE + ) + ) + + self.assertFalse( + enums.is_bit_mask( + enums.WrappingMethod, + enums.WrappingMethod.ENCRYPT.value + ) + ) + + self.assertFalse( + enums.is_bit_mask( + enums.ProtectionStorageMask, + 0x80000000 + ) + ) + def test_is_enum_value(self): result = enums.is_enum_value( enums.CryptographicAlgorithm,