Skip to content

Commit 2da67c3

Browse files
committed
✨ add support for Uin8List bytes.
1 parent b587116 commit 2da67c3

File tree

6 files changed

+111
-29
lines changed

6 files changed

+111
-29
lines changed

.github/workflows/docs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Deploy Playground
1+
name: Deploy Docs
22

33
on:
44
push:

packages/hyper_storage/lib/src/api/api.dart

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// Use of this source code is governed by a BSD license that can be
33
// found in the LICENSE file.
44

5+
import 'dart:typed_data';
6+
57
import 'package:meta/meta.dart';
68

79
import 'backend.dart';
@@ -549,6 +551,39 @@ abstract interface class StorageOperationsApi {
549551
/// * [ArgumentError] if the key is invalid.
550552
Future<List<String>?> getStringList(String key);
551553

554+
/// Saves a byte array with the given [key].
555+
///
556+
/// This method stores a byte array (Uint8List) in the storage, associating it
557+
/// with the specified key. If a value already exists for this key, it will be
558+
/// replaced.
559+
///
560+
/// Parameters:
561+
/// - [key]: The unique identifier for the byte array.
562+
/// - [bytes]: The byte array to store.
563+
///
564+
/// Returns a [Future] that completes when the byte array has been successfully
565+
/// stored.
566+
///
567+
/// Throws:
568+
/// - [ArgumentError] if the key is invalid.
569+
Future<void> setBytes(String key, Uint8List bytes);
570+
571+
/// Retrieves a byte array by its [key].
572+
///
573+
/// This method fetches a byte array (Uint8List) previously stored using [setBytes].
574+
/// If no value exists for the given key, or the stored value is not a byte array,
575+
/// this method returns `null`.
576+
///
577+
/// Parameters:
578+
/// - [key]: The unique identifier of the byte array to retrieve.
579+
///
580+
/// Returns a [Future] that completes with the stored byte array if found,
581+
/// or `null` if the key doesn't exist or the value is not a byte array.
582+
///
583+
/// Throws:
584+
/// - [ArgumentError] if the key is invalid.
585+
Future<Uint8List?> getBytes(String key);
586+
552587
/// Saves a JSON object (Map) with the given [key].
553588
///
554589
/// This method stores a JSON-serializable map in the storage, associating it

packages/hyper_storage/lib/src/api/backend.dart

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
library;
66

77
import 'dart:convert';
8+
import 'dart:typed_data';
89

910
import 'package:meta/meta.dart';
1011

@@ -136,6 +137,16 @@ abstract class StorageBackend with GenericStorageOperationsMixin implements Stor
136137
@override
137138
Future<void> setDuration(String key, Duration value) => setInt(key, value.inMilliseconds);
138139

140+
@override
141+
Future<void> setBytes(String key, List<int> value) => setString(key, base64Encode(value));
142+
143+
@override
144+
Future<Uint8List?> getBytes(String key) async {
145+
final value = await getString(key);
146+
if (value == null) return null;
147+
return base64Decode(value);
148+
}
149+
139150
@override
140151
Future<void> setEnum<E extends Enum>(String key, E value) => setString(key, value.name);
141152

@@ -159,15 +170,17 @@ abstract class StorageBackend with GenericStorageOperationsMixin implements Stor
159170
/// a storage backend by providing type-aware routing logic.
160171
///
161172
/// Supported types:
162-
/// * [String] - Routes to [getString] / [setString]
163-
/// * [int] - Routes to [getInt] / [setInt]
164-
/// * [double] - Routes to [getDouble] / [setDouble]
165-
/// * [bool] - Routes to [getBool] / [setBool]
166-
/// * [DateTime] - Routes to [getDateTime] / [setDateTime]
167-
/// * [Duration] - Routes to [getDuration] / [setDuration]
168-
/// * [List<String>] - Routes to [getStringList] / [setStringList]
169-
/// * [Map<String, dynamic>] - Routes to [getJson] / [setJson]
170-
/// * [List<Map<String, dynamic>>] - Routes to [getJsonList] / [setJsonList]
173+
/// - [String] - Routes to [getString] / [setString]
174+
/// - [int] - Routes to [getInt] / [setInt]
175+
/// - [double] - Routes to [getDouble] / [setDouble]
176+
/// - [bool] - Routes to [getBool] / [setBool]
177+
/// - [DateTime] - Routes to [getDateTime] / [setDateTime]
178+
/// - [Duration] - Routes to [getDuration] / [setDuration]
179+
/// - [List<String>] - Routes to [getStringList] / [setStringList]
180+
/// - [Map<String, dynamic>] - Routes to [getJson] / [setJson]
181+
/// - [List<Map<String, dynamic>>] - Routes to [getJsonList] / [setJsonList]
182+
/// - [Enum] - Routes to [getEnum] / [setEnum] (requires `enumValues` parameter for `get`)
183+
/// - [Uint8List] - Routes to [getBytes] / [setBytes]
171184
@internal
172185
mixin GenericStorageOperationsMixin implements StorageOperationsApi {
173186
@override
@@ -195,6 +208,7 @@ mixin GenericStorageOperationsMixin implements StorageOperationsApi {
195208
const (List<String>) => await getStringList(key) as E?,
196209
const (Map<String, dynamic>) => await getJson(key) as E?,
197210
const (List<Map<String, dynamic>>) => await getJsonList(key) as E?,
211+
const (Uint8List) => await getBytes(key) as E?,
198212
_ when enumValues != null => await () async {
199213
checkEnumType<E>(enumValues);
200214
return await getEnum(key, enumValues.cast<Enum>()) as E?;
@@ -216,6 +230,7 @@ mixin GenericStorageOperationsMixin implements StorageOperationsApi {
216230
Map<String, dynamic> value => setJson(key, value),
217231
List<Map<String, dynamic>> value => setJsonList(key, value),
218232
Enum value => setString(key, value.name),
233+
Uint8List value => setBytes(key, value),
219234
_ => throw UnsupportedError('Type ${value.runtimeType} is not supported'),
220235
};
221236
}

packages/hyper_storage/lib/src/hyper_storage.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
// found in the LICENSE file.
44

55
import 'dart:async';
6+
import 'dart:convert';
67
import 'dart:math';
8+
import 'dart:typed_data';
79

810
import 'package:meta/meta.dart';
911

@@ -406,7 +408,7 @@ class HyperStorage extends _HyperStorageImpl {
406408
/// - Duration
407409
/// - Enum (requires providing [enumValues])
408410
Stream<E?> stream<E extends Object>(String key, {List<Enum>? enumValues}) async* {
409-
if(enumValues != null) checkEnumType<E>(enumValues);
411+
if (enumValues != null) checkEnumType<E>(enumValues);
410412
final E? itemValue = await get<E>(key, enumValues: enumValues);
411413
yield itemValue;
412414

packages/hyper_storage/lib/src/hyper_storage_container.dart

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import 'dart:async';
66
import 'dart:convert';
7+
import 'dart:typed_data';
78

89
import 'package:meta/meta.dart' show protected;
910

@@ -234,32 +235,27 @@ final class HyperStorageContainer extends StorageContainer with ItemHolderMixin,
234235
}
235236

236237
@override
237-
Future<void> removeAll(Iterable<String> keys) async {
238-
validateKeys(keys);
239-
await backend.removeAll(keys.map(encodeKey));
240-
for (final key in keys) {
241-
notifyKeyListeners(key);
242-
}
243-
notifyListeners();
238+
Future<Uint8List?> getBytes(String key) async {
239+
validateKey(key);
240+
final value = await backend.getString(encodeKey(key));
241+
if (value == null) return null;
242+
return base64Decode(value);
244243
}
245244

246245
@override
247-
Future<void> close() async {
248-
removeAllListeners();
249-
await backend.close();
250-
await super.close();
246+
Future<void> setBytes(String key, Uint8List bytes) {
247+
validateKey(key);
248+
return backend.setString(encodeKey(key), base64Encode(bytes));
251249
}
252250

253251
@override
254-
Future<void> clear() async {
255-
final encodedKeys = await getEncodedKeys();
256-
final decodedKeys = encodedKeys.map(decodeKey).toList();
257-
await backend.removeAll(encodedKeys);
258-
for (final key in decodedKeys) {
252+
Future<void> removeAll(Iterable<String> keys) async {
253+
validateKeys(keys);
254+
await backend.removeAll(keys.map(encodeKey));
255+
for (final key in keys) {
259256
notifyKeyListeners(key);
260257
}
261258
notifyListeners();
262-
removeAllListeners();
263259
}
264260

265261
/// Provides a [Stream] of values for the given [key].
@@ -284,7 +280,7 @@ final class HyperStorageContainer extends StorageContainer with ItemHolderMixin,
284280
/// - Duration
285281
/// - Enum (requires providing [enumValues])
286282
Stream<E?> stream<E extends Object>(String key, {List<Enum>? enumValues}) async* {
287-
if(enumValues != null) checkEnumType<E>(enumValues);
283+
if (enumValues != null) checkEnumType<E>(enumValues);
288284
final E? itemValue = await get<E>(key, enumValues: enumValues);
289285
yield itemValue;
290286

@@ -305,4 +301,23 @@ final class HyperStorageContainer extends StorageContainer with ItemHolderMixin,
305301
// Defensive close call. Almost never reached because the stream is closed on cancel.
306302
await controller.close(); // coverage:ignore-line
307303
}
304+
305+
@override
306+
Future<void> close() async {
307+
removeAllListeners();
308+
await backend.close();
309+
await super.close();
310+
}
311+
312+
@override
313+
Future<void> clear() async {
314+
final encodedKeys = await getEncodedKeys();
315+
final decodedKeys = encodedKeys.map(decodeKey).toList();
316+
await backend.removeAll(encodedKeys);
317+
for (final key in decodedKeys) {
318+
notifyKeyListeners(key);
319+
}
320+
notifyListeners();
321+
removeAllListeners();
322+
}
308323
}

packages/hyper_storage/lib/src/storage_base.dart

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,4 +244,19 @@ abstract class _HyperStorageImpl extends BaseStorage
244244
await backend.setStringList(key, value);
245245
notifyListeners(key);
246246
}
247+
248+
@override
249+
Future<void> setBytes(String key, Uint8List bytes) async {
250+
validateKey(key);
251+
await backend.setString(key, base64Encode(bytes));
252+
notifyListeners(key);
253+
}
254+
255+
@override
256+
Future<Uint8List?> getBytes(String key) async {
257+
validateKey(key);
258+
final String? base64String = await backend.getString(key);
259+
if (base64String == null) return null;
260+
return base64Decode(base64String);
261+
}
247262
}

0 commit comments

Comments
 (0)