Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /// A generic class that can hold either an enum value of type [T] or a raw [String].
- ///
- /// This class is designed to handle deserialization where a string input
- /// might correspond to a known enum value or be an arbitrary string.
- /// If the input string matches an enum's name, the enum value is stored;
- /// otherwise, the raw string is stored.
- class EnumValueOrString<T extends Enum> {
- final T? _enumValue;
- final String? _stringValue;
- /// Private constructor for internal use, ensuring that exactly one of
- /// [_enumValue] or [_stringValue] is non-null.
- EnumValueOrString._({
- T? enumValue,
- String? stringValue,
- }) : _enumValue = enumValue,
- _stringValue = stringValue {
- assert(
- (enumValue != null && stringValue == null) ||
- (enumValue == null && stringValue != null),
- 'EnumValueOrString must hold either an enum value or a string, not both or neither.',
- );
- }
- /// Creates an [EnumValueOrString] instance holding an enum value.
- factory EnumValueOrString.fromEnum(T value) {
- return EnumValueOrString<T>._(enumValue: value);
- }
- /// Creates an [EnumValueOrString] instance holding a raw string.
- factory EnumValueOrString.fromString(String value) {
- return EnumValueOrString<T>._(stringValue: value);
- }
- /// Deserializes a [rawValue] into an [EnumValueOrString].
- ///
- /// It attempts to match the [rawValue] against the [name] property of
- /// each enum value in [enumValues].
- /// If a match is found, an instance holding the enum value is returned.
- /// Otherwise, an instance holding the original [rawValue] as a string is returned.
- factory EnumValueOrString.deserialize(String rawValue, List<T> enumValues) {
- for (var enumValue in enumValues) {
- if (enumValue.name == rawValue) {
- return EnumValueOrString<T>.fromEnum(enumValue);
- }
- }
- // If no matching enum value is found, store the raw string.
- return EnumValueOrString<T>.fromString(rawValue);
- }
- /// Returns `true` if this instance holds an enum value.
- bool get isEnum => _enumValue != null;
- /// Returns `true` if this instance holds a raw string.
- bool get isString => _stringValue != null;
- /// Returns the enum value held by this instance.
- ///
- /// Throws a [StateError] if this instance holds a string instead of an enum.
- T get enumValue {
- if (_enumValue == null) {
- throw StateError(
- 'This EnumValueOrString instance holds a String, not an Enum.');
- }
- return _enumValue!;
- }
- /// Returns the raw string held by this instance.
- ///
- /// Throws a [StateError] if this instance holds an enum instead of a string.
- String get stringValue {
- if (_stringValue == null) {
- throw StateError(
- 'This EnumValueOrString instance holds an Enum, not a String.');
- }
- return _stringValue!;
- }
- @override
- String toString() {
- if (isEnum) {
- return 'EnumValueOrString.enum(${_enumValue!.name})';
- } else {
- return 'EnumValueOrString.string("$_stringValue")';
- }
- }
- @override
- bool operator ==(Object other) {
- if (identical(this, other)) return true;
- return other is EnumValueOrString<T> &&
- _enumValue == other._enumValue &&
- _stringValue == other._stringValue;
- }
- @override
- int get hashCode => Object.hash(_enumValue, _stringValue);
- }
- /// An example enum to demonstrate the usage of [EnumValueOrString].
- enum MyStatus {
- active,
- inactive,
- pending,
- completed,
- cancelled,
- }
- void main() {
- print('--- Deserialization Examples ---');
- // Case 1: Deserializing a string that matches an enum value.
- final knownStatus =
- EnumValueOrString.deserialize('active', MyStatus.values);
- print('Input: "active"');
- print('Is Enum? ${knownStatus.isEnum}, Is String? ${knownStatus.isString}');
- if (knownStatus.isEnum) {
- print('Value: ${knownStatus.enumValue} (Type: ${knownStatus.enumValue.runtimeType})');
- } else {
- print('Value: ${knownStatus.stringValue} (Type: ${knownStatus.stringValue.runtimeType})');
- }
- print('');
- // Case 2: Deserializing a string that does NOT match any enum value.
- final unknownStatus =
- EnumValueOrString.deserialize('on_hold', MyStatus.values);
- print('Input: "on_hold"');
- print('Is Enum? ${unknownStatus.isEnum}, Is String? ${unknownStatus.isString}');
- if (unknownStatus.isEnum) {
- print('Value: ${unknownStatus.enumValue} (Type: ${unknownStatus.enumValue.runtimeType})');
- } else {
- print('Value: ${unknownStatus.stringValue} (Type: ${unknownStatus.stringValue.runtimeType})');
- }
- print('');
- print('--- Direct Creation Examples ---');
- // Case 3: Creating an instance directly from an enum value.
- final directEnum = EnumValueOrString.fromEnum(MyStatus.completed);
- print('Direct Enum: MyStatus.completed');
- print('Is Enum? ${directEnum.isEnum}, Is String? ${directEnum.isString}');
- print('Value: ${directEnum.enumValue}');
- print('');
- // Case 4: Creating an instance directly from a raw string.
- final directString = EnumValueOrString.fromString('archived_item');
- print('Direct String: "archived_item"');
- print('Is Enum? ${directString.isEnum}, Is String? ${directString.isString}');
- print('Value: ${directString.stringValue}');
- print('');
- print('--- Error Handling Examples ---');
- // Attempting to access stringValue on an enum-holding instance.
- try {
- print('Attempting to access stringValue on knownStatus:');
- print(knownStatus.stringValue);
- } catch (e) {
- print('Caught error: $e');
- }
- print('');
- // Attempting to access enumValue on a string-holding instance.
- try {
- print('Attempting to access enumValue on unknownStatus:');
- print(unknownStatus.enumValue);
- } catch (e) {
- print('Caught error: $e');
- }
- print('');
- print('--- Equality Examples ---');
- final anotherKnownStatus =
- EnumValueOrString.deserialize('active', MyStatus.values);
- final anotherUnknownStatus =
- EnumValueOrString.fromString('on_hold');
- print('knownStatus == anotherKnownStatus: ${knownStatus == anotherKnownStatus}'); // Expected: true
- print('unknownStatus == anotherUnknownStatus: ${unknownStatus == anotherUnknownStatus}'); // Expected: true
- print('knownStatus == unknownStatus: ${knownStatus == unknownStatus}'); // Expected: false
- }
Advertisement
Add Comment
Please, Sign In to add comment