From d3608878291b296e5e43aa9a781be733cceca396 Mon Sep 17 00:00:00 2001 From: Dillon Nys Date: Mon, 5 Feb 2024 08:28:22 -0800 Subject: [PATCH] Initial extension types work --- .../lib/src/exception/cloud_exception.dart | 4 +- .../exception/serialization_exception.dart | 2 +- .../lib/src/serialization/serializer.dart | 65 ++++++++++++++----- 3 files changed, 50 insertions(+), 21 deletions(-) diff --git a/packages/celest_core/lib/src/exception/cloud_exception.dart b/packages/celest_core/lib/src/exception/cloud_exception.dart index 870ec6d8..84e4082f 100644 --- a/packages/celest_core/lib/src/exception/cloud_exception.dart +++ b/packages/celest_core/lib/src/exception/cloud_exception.dart @@ -7,7 +7,7 @@ sealed class CloudException implements CelestException {} /// An exception thrown by a Cloud Function when a request contains invalid /// data or otherwise lead to a recoverable exception. /// {@endtemplate} -final class BadRequestException implements CloudException { +class BadRequestException implements CloudException { /// Creates a [BadRequestException] with the given [message]. /// /// {@macro celest_core_exception_bad_request_exception} @@ -21,7 +21,7 @@ final class BadRequestException implements CloudException { /// An exception thrown by a Cloud Function when an unrecoverable internal error /// occurs. /// {@endtemplate} -final class InternalServerException implements CloudException { +class InternalServerException implements CloudException { /// Creates a [InternalServerException] with the given [message]. /// /// {@macro celest_core_exception_internal_server_exception} diff --git a/packages/celest_core/lib/src/exception/serialization_exception.dart b/packages/celest_core/lib/src/exception/serialization_exception.dart index 2ed31f48..ffb40203 100644 --- a/packages/celest_core/lib/src/exception/serialization_exception.dart +++ b/packages/celest_core/lib/src/exception/serialization_exception.dart @@ -7,7 +7,7 @@ import 'package:celest_core/celest_core.dart'; /// deserialize a value. /// {@endtemplate} final class SerializationException extends FormatException - implements CelestException { + implements BadRequestException, CelestException { /// Creates a [SerializationException] with the given [message]. /// /// {@macro celest_core_exceptions_serialization_exception} diff --git a/packages/celest_core/lib/src/serialization/serializer.dart b/packages/celest_core/lib/src/serialization/serializer.dart index 03206109..edd6e239 100644 --- a/packages/celest_core/lib/src/serialization/serializer.dart +++ b/packages/celest_core/lib/src/serialization/serializer.dart @@ -61,31 +61,34 @@ abstract mixin class Serializers { static final Serializers _instance = Serializers(); /// Serializes [value] to the wire type. - Object? serialize(T value) { - final serializer = expect(); + Object? serialize(T value, [TypeToken? typeToken]) { + final serializer = expect(typeToken); return _isNullable() ? value?.let(serializer.serialize) : serializer.serialize(value); } /// Deserializes [value] to [T]. - T deserialize(Object? value) { - final serializer = expect(); + T deserialize(Object? value, [TypeToken? typeToken]) { + final serializer = expect(typeToken); return _isNullable() ? value?.let(serializer.deserialize) as T : serializer.deserialize(value); } /// Gets the [Serializer] for type [Dart]. - Serializer? get(); + Serializer? get([TypeToken? typeToken]); /// Gets the [Serializer] for type [Dart] and asserts its existence. - Serializer expect(); + Serializer expect([TypeToken? typeToken]); /// Puts a [Serializer] for type [Dart]. /// /// Returns the previously registered [Serializer] if it existed. - Serializer? put(Serializer serializer); + Serializer? put( + Serializer serializer, [ + TypeToken? typeToken, + ]); } final class _Serializers extends Serializers { @@ -102,29 +105,55 @@ final class _Serializers extends Serializers { put(const InternalServerExceptionSerializer()); } - final _serializersByType = {}; + final _serializersByType = , Serializer>{}; @override - Serializer expect() { - final serializer = get(); + Serializer expect([TypeToken? typeToken]) { + typeToken ??= TypeToken(); + final serializer = get(typeToken); if (serializer == null) { throw SerializationException( - 'No serializer found for $Dart. Did you forget to call `celest.init()` ' - "at the start of your Flutter app's `main` function?", + 'No serializer found for $typeToken. Did you forget to call ' + "`celest.init()` at the start of your Flutter app's `main` function?", ); } return serializer; } @override - Serializer? get() => - _serializersByType[Dart] as Serializer?; + Serializer? get([TypeToken? typeToken]) => + _serializersByType[typeToken ?? TypeToken()] as Serializer?; @override - Serializer? put(Serializer serializer) { - final existing = get(); - _serializersByType[Dart] = serializer; - _serializersByType[_Nullable] = serializer; + Serializer? put( + Serializer serializer, [ + TypeToken? typeToken, + ]) { + typeToken ??= TypeToken(); + final existing = get(typeToken); + _serializersByType[typeToken] = serializer; + _serializersByType[typeToken.nullable] = serializer; return existing; } } + +final class TypeToken { + const TypeToken([this._typeName]); + + final String? _typeName; + + String get typeName => _typeName ?? '$T'; + Type get type => T; + + TypeToken get nullable => TypeToken<_Nullable>(_typeName); + + @override + bool operator ==(Object other) => + other is TypeToken && other._typeName == _typeName && other.type == type; + + @override + int get hashCode => Object.hash(_typeName, type); + + @override + String toString() => typeName; +}