Skip to content

Commit ab4aea0

Browse files
committed
feat: Add HtKVStorageService and exceptions
- Define abstract service contract - Add custom storage exceptions
1 parent b4aea33 commit ab4aea0

File tree

1 file changed

+196
-19
lines changed

1 file changed

+196
-19
lines changed

lib/src/ht_kv_storage_service.dart

Lines changed: 196 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,179 @@
1+
// ignore_for_file: lines_longer_than_80_chars
2+
3+
/// {@template storage_exception}
4+
/// Base class for all key-value storage related exceptions.
5+
/// {@endtemplate}
6+
abstract class StorageException implements Exception {
7+
/// {@macro storage_exception}
8+
const StorageException({this.message, this.cause});
9+
10+
/// Optional original exception that caused this storage exception.
11+
final Object? cause;
12+
13+
/// Optional message describing the error.
14+
final String? message;
15+
16+
@override
17+
String toString() {
18+
var result = runtimeType.toString();
19+
if (message != null) {
20+
result += ': $message';
21+
}
22+
if (cause != null) {
23+
result += '\nCaused by: $cause';
24+
}
25+
return result;
26+
}
27+
}
28+
29+
/// {@template storage_initialization_exception}
30+
/// Exception thrown when a storage operation fails during initialization.
31+
/// {@endtemplate}
32+
class StorageInitializationException extends StorageException {
33+
/// {@macro storage_initialization_exception}
34+
const StorageInitializationException({super.message, super.cause});
35+
}
36+
37+
/// {@template storage_write_exception}
38+
/// Exception thrown when a write operation fails.
39+
/// {@endtemplate}
40+
class StorageWriteException extends StorageException {
41+
/// {@macro storage_write_exception}
42+
const StorageWriteException(
43+
this.key,
44+
this.value, {
45+
super.message = 'Failed to write value for key.',
46+
super.cause,
47+
});
48+
49+
/// The key associated with the failed write operation.
50+
final String key;
51+
52+
/// The value that failed to be written.
53+
final dynamic value;
54+
55+
@override
56+
String toString() {
57+
var result = 'StorageWriteException: $message Key: "$key"';
58+
if (cause != null) {
59+
result += '\nCaused by: $cause';
60+
}
61+
return result;
62+
}
63+
}
64+
65+
/// {@template storage_read_exception}
66+
/// Exception thrown when a read operation fails for reasons other than
67+
/// key not found or type mismatch.
68+
/// {@endtemplate}
69+
class StorageReadException extends StorageException {
70+
/// {@macro storage_read_exception}
71+
const StorageReadException(
72+
this.key, {
73+
super.message = 'Failed to read value for key.',
74+
super.cause,
75+
});
76+
77+
/// The key associated with the failed read operation.
78+
final String key;
79+
80+
@override
81+
String toString() {
82+
var result = 'StorageReadException: $message Key: "$key"';
83+
if (cause != null) {
84+
result += '\nCaused by: $cause';
85+
}
86+
return result;
87+
}
88+
}
89+
90+
/// {@template storage_delete_exception}
91+
/// Exception thrown when a delete operation fails.
92+
/// {@endtemplate}
93+
class StorageDeleteException extends StorageException {
94+
/// {@macro storage_delete_exception}
95+
const StorageDeleteException(
96+
this.key, {
97+
super.message = 'Failed to delete value for key.',
98+
super.cause,
99+
});
100+
101+
/// The key associated with the failed delete operation.
102+
final String key;
103+
104+
@override
105+
String toString() {
106+
var result = 'StorageDeleteException: $message Key: "$key"';
107+
if (cause != null) {
108+
result += '\nCaused by: $cause';
109+
}
110+
return result;
111+
}
112+
}
113+
114+
/// {@template storage_clear_exception}
115+
/// Exception thrown when the clear operation fails.
116+
/// {@endtemplate}
117+
class StorageClearException extends StorageException {
118+
/// {@macro storage_clear_exception}
119+
const StorageClearException({
120+
super.message = 'Failed to clear storage.',
121+
super.cause,
122+
});
123+
}
124+
125+
/// {@template storage_key_not_found_exception}
126+
/// Exception thrown when attempting to read or delete a key that does not exist.
127+
///
128+
/// Note: `read*` methods might return null instead of throwing this,
129+
/// depending on the implementation contract.
130+
/// {@endtemplate}
131+
class StorageKeyNotFoundException extends StorageException {
132+
/// {@macro storage_key_not_found_exception}
133+
const StorageKeyNotFoundException(
134+
this.key, {
135+
super.message = 'Key not found in storage.',
136+
}) : super(cause: null);
137+
138+
/// The key that was not found.
139+
final String key; // Typically not caused by another exception
140+
141+
@override
142+
String toString() {
143+
return 'StorageKeyNotFoundException: $message Key: "$key"';
144+
}
145+
}
146+
147+
/// {@template storage_type_mismatch_exception}
148+
/// Exception thrown when the data retrieved from storage does not match
149+
/// the expected type.
150+
/// {@endtemplate}
151+
class StorageTypeMismatchException extends StorageException {
152+
/// {@macro storage_type_mismatch_exception}
153+
const StorageTypeMismatchException(
154+
this.key,
155+
this.expectedType,
156+
this.actualType, {
157+
super.message = 'Type mismatch for key.',
158+
}) : super(cause: null);
159+
160+
/// The key associated with the type mismatch.
161+
final String key;
162+
163+
/// The type that was expected.
164+
final Type expectedType;
165+
166+
/// The actual type found in storage.
167+
final Type actualType; // Typically not caused by another exception
168+
169+
@override
170+
String toString() {
171+
return 'StorageTypeMismatchException: $message Key: "$key", Expected: $expectedType, Found: $actualType';
172+
}
173+
}
174+
175+
// endregion
176+
1177
/// {@template key_value_storage_service}
2178
/// Defines the contract for a generic key-value storage service.
3179
///
@@ -9,61 +185,62 @@
9185
abstract class HtKVStorageService {
10186
/// Writes a string value associated with the given [key].
11187
///
12-
/// Throws an exception if the write operation fails.
188+
/// Throws a [StorageWriteException] if the write operation fails.
13189
Future<void> writeString({required String key, required String value});
14190

15191
/// Reads the string value associated with the given [key].
16192
///
17-
/// Returns `null` if the key is not found or if the stored value
18-
/// is not a string.
19-
/// Throws an exception if the read operation fails.
193+
/// Returns `null` if the key is not found.
194+
/// Throws a [StorageReadException] if the read operation fails for other reasons.
195+
/// Throws a [StorageTypeMismatchException] if the stored value is not a string.
20196
Future<String?> readString({required String key});
21197

22198
/// Writes a boolean value associated with the given [key].
23199
///
24-
/// Throws an exception if the write operation fails.
200+
/// Throws a [StorageWriteException] if the write operation fails.
25201
Future<void> writeBool({required String key, required bool value});
26202

27203
/// Reads the boolean value associated with the given [key].
28204
///
29-
/// Returns [defaultValue] (defaulting to `false`) if the key is not found
30-
/// or if the stored value is not a boolean.
31-
/// Throws an exception if the read operation fails.
205+
/// Returns [defaultValue] (defaulting to `false`) if the key is not found.
206+
/// Throws a [StorageReadException] if the read operation fails for other reasons.
207+
/// Throws a [StorageTypeMismatchException] if the stored value is not a boolean.
32208
Future<bool> readBool({required String key, bool defaultValue = false});
33209

34210
/// Writes an integer value associated with the given [key].
35211
///
36-
/// Throws an exception if the write operation fails.
212+
/// Throws a [StorageWriteException] if the write operation fails.
37213
Future<void> writeInt({required String key, required int value});
38214

39215
/// Reads the integer value associated with the given [key].
40216
///
41-
/// Returns `null` if the key is not found or if the stored value
42-
/// is not an integer.
43-
/// Throws an exception if the read operation fails.
217+
/// Returns `null` if the key is not found.
218+
/// Throws a [StorageReadException] if the read operation fails for other reasons.
219+
/// Throws a [StorageTypeMismatchException] if the stored value is not an integer.
44220
Future<int?> readInt({required String key});
45221

46222
/// Writes a double value associated with the given [key].
47223
///
48-
/// Throws an exception if the write operation fails.
224+
/// Throws a [StorageWriteException] if the write operation fails.
49225
Future<void> writeDouble({required String key, required double value});
50226

51227
/// Reads the double value associated with the given [key].
52228
///
53-
/// Returns `null` if the key is not found or if the stored value
54-
/// is not a double.
55-
/// Throws an exception if the read operation fails.
229+
/// Returns `null` if the key is not found.
230+
/// Throws a [StorageReadException] if the read operation fails for other reasons.
231+
/// Throws a [StorageTypeMismatchException] if the stored value is not a double.
56232
Future<double?> readDouble({required String key});
57233

58234
/// Deletes the value associated with the given [key].
59235
///
60-
/// If the key does not exist, this operation does nothing.
61-
/// Throws an exception if the delete operation fails.
236+
/// If the key does not exist, this operation should ideally complete without
237+
/// throwing an error, but implementations might throw [StorageKeyNotFoundException].
238+
/// Throws a [StorageDeleteException] if the delete operation fails for other reasons.
62239
Future<void> delete({required String key});
63240

64241
/// Deletes all key-value pairs from the storage.
65242
///
66243
/// Use with caution, as this operation is irreversible.
67-
/// Throws an exception if the clear operation fails.
244+
/// Throws a [StorageClearException] if the clear operation fails.
68245
Future<void> clearAll();
69246
}

0 commit comments

Comments
 (0)