refactor: Replace MayFail by Result

This commit is contained in:
PapaTutuWawa 2022-11-19 22:26:02 +01:00
parent 2e3472d88f
commit 300a52f9fe
8 changed files with 38 additions and 51 deletions

View File

@ -25,12 +25,12 @@ export 'package:moxxmpp/src/presence.dart';
export 'package:moxxmpp/src/reconnect.dart'; export 'package:moxxmpp/src/reconnect.dart';
export 'package:moxxmpp/src/rfcs/rfc_2782.dart'; export 'package:moxxmpp/src/rfcs/rfc_2782.dart';
export 'package:moxxmpp/src/rfcs/rfc_4790.dart'; export 'package:moxxmpp/src/rfcs/rfc_4790.dart';
export 'package:moxxmpp/src/roster.dart'; export 'package:moxxmpp/src/roster/errors.dart';
export 'package:moxxmpp/src/roster/roster.dart';
export 'package:moxxmpp/src/settings.dart'; export 'package:moxxmpp/src/settings.dart';
export 'package:moxxmpp/src/socket.dart'; export 'package:moxxmpp/src/socket.dart';
export 'package:moxxmpp/src/stanza.dart'; export 'package:moxxmpp/src/stanza.dart';
export 'package:moxxmpp/src/stringxml.dart'; export 'package:moxxmpp/src/stringxml.dart';
export 'package:moxxmpp/src/types/error.dart';
export 'package:moxxmpp/src/types/result.dart'; export 'package:moxxmpp/src/types/result.dart';
export 'package:moxxmpp/src/xeps/staging/extensible_file_thumbnails.dart'; export 'package:moxxmpp/src/xeps/staging/extensible_file_thumbnails.dart';
export 'package:moxxmpp/src/xeps/staging/file_upload_notification.dart'; export 'package:moxxmpp/src/xeps/staging/file_upload_notification.dart';
@ -61,7 +61,8 @@ export 'package:moxxmpp/src/xeps/xep_0333.dart';
export 'package:moxxmpp/src/xeps/xep_0334.dart'; export 'package:moxxmpp/src/xeps/xep_0334.dart';
export 'package:moxxmpp/src/xeps/xep_0352.dart'; export 'package:moxxmpp/src/xeps/xep_0352.dart';
export 'package:moxxmpp/src/xeps/xep_0359.dart'; export 'package:moxxmpp/src/xeps/xep_0359.dart';
export 'package:moxxmpp/src/xeps/xep_0363.dart'; export 'package:moxxmpp/src/xeps/xep_0363/errors.dart';
export 'package:moxxmpp/src/xeps/xep_0363/xep_0363.dart';
export 'package:moxxmpp/src/xeps/xep_0380.dart'; export 'package:moxxmpp/src/xeps/xep_0380.dart';
export 'package:moxxmpp/src/xeps/xep_0384/crypto.dart'; export 'package:moxxmpp/src/xeps/xep_0384/crypto.dart';
export 'package:moxxmpp/src/xeps/xep_0384/errors.dart'; export 'package:moxxmpp/src/xeps/xep_0384/errors.dart';

View File

@ -15,7 +15,7 @@ import 'package:moxxmpp/src/negotiators/namespaces.dart';
import 'package:moxxmpp/src/negotiators/negotiator.dart'; import 'package:moxxmpp/src/negotiators/negotiator.dart';
import 'package:moxxmpp/src/presence.dart'; import 'package:moxxmpp/src/presence.dart';
import 'package:moxxmpp/src/reconnect.dart'; import 'package:moxxmpp/src/reconnect.dart';
import 'package:moxxmpp/src/roster.dart'; import 'package:moxxmpp/src/roster/roster.dart';
import 'package:moxxmpp/src/routing.dart'; import 'package:moxxmpp/src/routing.dart';
import 'package:moxxmpp/src/settings.dart'; import 'package:moxxmpp/src/settings.dart';
import 'package:moxxmpp/src/socket.dart'; import 'package:moxxmpp/src/socket.dart';

View File

@ -0,0 +1,7 @@
abstract class RosterError {}
/// Returned when the server's response did not contain a <query /> element
class NoQueryError extends RosterError {}
/// Unspecified error
class UnknownError extends RosterError {}

View File

@ -7,16 +7,12 @@ import 'package:moxxmpp/src/managers/namespaces.dart';
import 'package:moxxmpp/src/namespaces.dart'; import 'package:moxxmpp/src/namespaces.dart';
import 'package:moxxmpp/src/negotiators/namespaces.dart'; import 'package:moxxmpp/src/negotiators/namespaces.dart';
import 'package:moxxmpp/src/negotiators/negotiator.dart'; import 'package:moxxmpp/src/negotiators/negotiator.dart';
import 'package:moxxmpp/src/roster/errors.dart';
import 'package:moxxmpp/src/stanza.dart'; import 'package:moxxmpp/src/stanza.dart';
import 'package:moxxmpp/src/stringxml.dart'; import 'package:moxxmpp/src/stringxml.dart';
import 'package:moxxmpp/src/types/error.dart';
import 'package:moxxmpp/src/types/result.dart'; import 'package:moxxmpp/src/types/result.dart';
const rosterErrorNoQuery = 1;
const rosterErrorNonResult = 2;
class XmppRosterItem { class XmppRosterItem {
XmppRosterItem({ required this.jid, required this.subscription, this.ask, this.name, this.groups = const [] }); XmppRosterItem({ required this.jid, required this.subscription, this.ask, this.name, this.groups = const [] });
final String jid; final String jid;
final String? name; final String? name;
@ -32,14 +28,12 @@ enum RosterRemovalResult {
} }
class RosterRequestResult { class RosterRequestResult {
RosterRequestResult({ required this.items, this.ver }); RosterRequestResult({ required this.items, this.ver });
List<XmppRosterItem> items; List<XmppRosterItem> items;
String? ver; String? ver;
} }
class RosterPushEvent extends XmppEvent { class RosterPushEvent extends XmppEvent {
RosterPushEvent({ required this.item, this.ver }); RosterPushEvent({ required this.item, this.ver });
final XmppRosterItem item; final XmppRosterItem item;
final String? ver; final String? ver;
@ -149,7 +143,7 @@ class RosterManager extends XmppManagerBase {
/// Shared code between requesting rosters without and with roster versioning, if /// Shared code between requesting rosters without and with roster versioning, if
/// the server deems a regular roster response more efficient than n roster pushes. /// the server deems a regular roster response more efficient than n roster pushes.
Future<MayFail<RosterRequestResult>> _handleRosterResponse(XMLNode? query) async { Future<Result<RosterRequestResult, RosterError>> _handleRosterResponse(XMLNode? query) async {
final List<XmppRosterItem> items; final List<XmppRosterItem> items;
if (query != null) { if (query != null) {
items = query.children.map((item) => XmppRosterItem( items = query.children.map((item) => XmppRosterItem(
@ -167,7 +161,7 @@ class RosterManager extends XmppManagerBase {
} }
} else { } else {
logger.warning('Server response to roster request without roster versioning does not contain a <query /> element, while the type is not error. This violates RFC6121'); logger.warning('Server response to roster request without roster versioning does not contain a <query /> element, while the type is not error. This violates RFC6121');
return MayFail.failure(rosterErrorNoQuery); return Result(NoQueryError());
} }
final ver = query.attributes['ver'] as String?; final ver = query.attributes['ver'] as String?;
@ -176,7 +170,7 @@ class RosterManager extends XmppManagerBase {
await commitLastRosterVersion(ver); await commitLastRosterVersion(ver);
} }
return MayFail.success( return Result(
RosterRequestResult( RosterRequestResult(
items: items, items: items,
ver: ver, ver: ver,
@ -186,7 +180,7 @@ class RosterManager extends XmppManagerBase {
} }
/// Requests the roster following RFC 6121 without using roster versioning. /// Requests the roster following RFC 6121 without using roster versioning.
Future<MayFail<RosterRequestResult>> requestRoster() async { Future<Result<RosterRequestResult, RosterError>> requestRoster() async {
final attrs = getAttributes(); final attrs = getAttributes();
final response = await attrs.sendStanza( final response = await attrs.sendStanza(
Stanza.iq( Stanza.iq(
@ -202,7 +196,7 @@ class RosterManager extends XmppManagerBase {
if (response.attributes['type'] != 'result') { if (response.attributes['type'] != 'result') {
logger.warning('Error requesting roster without roster versioning: ${response.toXml()}'); logger.warning('Error requesting roster without roster versioning: ${response.toXml()}');
return MayFail.failure(rosterErrorNonResult); return Result(UnknownError());
} }
final query = response.firstTag('query', xmlns: rosterXmlns); final query = response.firstTag('query', xmlns: rosterXmlns);
@ -211,7 +205,7 @@ class RosterManager extends XmppManagerBase {
/// Requests a series of roster pushes according to RFC6121. Requires that the server /// Requests a series of roster pushes according to RFC6121. Requires that the server
/// advertises urn:xmpp:features:rosterver in the stream features. /// advertises urn:xmpp:features:rosterver in the stream features.
Future<MayFail<RosterRequestResult?>> requestRosterPushes() async { Future<Result<RosterRequestResult?, RosterError>> requestRosterPushes() async {
if (_rosterVersion == null) { if (_rosterVersion == null) {
await loadLastRosterVersion(); await loadLastRosterVersion();
} }
@ -234,7 +228,7 @@ class RosterManager extends XmppManagerBase {
if (result.attributes['type'] != 'result') { if (result.attributes['type'] != 'result') {
logger.warning('Requesting roster pushes failed: ${result.toXml()}'); logger.warning('Requesting roster pushes failed: ${result.toXml()}');
return MayFail.failure(rosterErrorNonResult); return Result(UnknownError());
} }
final query = result.firstTag('query', xmlns: rosterXmlns); final query = result.firstTag('query', xmlns: rosterXmlns);

View File

@ -1,19 +0,0 @@
/// A wrapper class that can be used to indicate that a function may return a valid
/// instance of [T] but may also fail.
/// The way [MayFail] is intended to be used to to have function specific - or application
/// specific - error codes that can be either handled by code or be translated into a
/// localised error message for the user.
class MayFail<T> {
MayFail({ this.result, this.errorCode });
MayFail.success(this.result);
MayFail.failure(this.errorCode);
T? result;
int? errorCode;
bool isError() => result == null && errorCode != null;
T getValue() => result!;
int getErrorCode() => errorCode!;
}

View File

@ -0,0 +1,10 @@
abstract class HttpFileUploadError {}
/// Returned when we don't know what JID to ask for an upload slot
class NoEntityKnownError extends HttpFileUploadError {}
/// Returned when the file we want to upload is too big
class FileTooBigError extends HttpFileUploadError {}
/// Unspecified errors
class UnknownHttpFileUploadError extends HttpFileUploadError {}

View File

@ -7,19 +7,15 @@ import 'package:moxxmpp/src/managers/namespaces.dart';
import 'package:moxxmpp/src/namespaces.dart'; import 'package:moxxmpp/src/namespaces.dart';
import 'package:moxxmpp/src/stanza.dart'; import 'package:moxxmpp/src/stanza.dart';
import 'package:moxxmpp/src/stringxml.dart'; import 'package:moxxmpp/src/stringxml.dart';
import 'package:moxxmpp/src/types/error.dart'; import 'package:moxxmpp/src/types/result.dart';
import 'package:moxxmpp/src/xeps/xep_0030/errors.dart'; import 'package:moxxmpp/src/xeps/xep_0030/errors.dart';
import 'package:moxxmpp/src/xeps/xep_0030/types.dart'; import 'package:moxxmpp/src/xeps/xep_0030/types.dart';
import 'package:moxxmpp/src/xeps/xep_0030/xep_0030.dart'; import 'package:moxxmpp/src/xeps/xep_0030/xep_0030.dart';
import 'package:moxxmpp/src/xeps/xep_0363/errors.dart';
const errorNoUploadServer = 1;
const errorFileTooBig = 2;
const errorGeneric = 3;
const allowedHTTPHeaders = [ 'authorization', 'cookie', 'expires' ]; const allowedHTTPHeaders = [ 'authorization', 'cookie', 'expires' ];
class HttpFileUploadSlot { class HttpFileUploadSlot {
const HttpFileUploadSlot(this.putUrl, this.getUrl, this.headers); const HttpFileUploadSlot(this.putUrl, this.getUrl, this.headers);
final String putUrl; final String putUrl;
final String getUrl; final String getUrl;
@ -45,7 +41,6 @@ Map<String, String> prepareHeaders(Map<String, String> headers) {
} }
class HttpFileUploadManager extends XmppManagerBase { class HttpFileUploadManager extends XmppManagerBase {
HttpFileUploadManager() : _gotSupported = false, _supported = false, super(); HttpFileUploadManager() : _gotSupported = false, _supported = false, super();
JID? _entityJid; JID? _entityJid;
int? _maxUploadSize; int? _maxUploadSize;
@ -119,17 +114,17 @@ class HttpFileUploadManager extends XmppManagerBase {
/// the file's size in octets. [contentType] is optional and refers to the file's /// the file's size in octets. [contentType] is optional and refers to the file's
/// Mime type. /// Mime type.
/// Returns an [HttpFileUploadSlot] if the request was successful; null otherwise. /// Returns an [HttpFileUploadSlot] if the request was successful; null otherwise.
Future<MayFail<HttpFileUploadSlot>> requestUploadSlot(String filename, int filesize, { String? contentType }) async { Future<Result<HttpFileUploadSlot, HttpFileUploadError>> requestUploadSlot(String filename, int filesize, { String? contentType }) async {
if (!(await isSupported())) return MayFail.failure(errorNoUploadServer); if (!(await isSupported())) return Result(NoEntityKnownError());
if (_entityJid == null) { if (_entityJid == null) {
logger.warning('Attempted to request HTTP File Upload slot but no entity is known to send this request to.'); logger.warning('Attempted to request HTTP File Upload slot but no entity is known to send this request to.');
return MayFail.failure(errorNoUploadServer); return Result(NoEntityKnownError());
} }
if (_maxUploadSize != null && filesize > _maxUploadSize!) { if (_maxUploadSize != null && filesize > _maxUploadSize!) {
logger.warning('Attempted to request HTTP File Upload slot for a file that exceeds the filesize limit'); logger.warning('Attempted to request HTTP File Upload slot for a file that exceeds the filesize limit');
return MayFail.failure(errorFileTooBig); return Result(FileTooBigError());
} }
final attrs = getAttributes(); final attrs = getAttributes();
@ -154,7 +149,7 @@ class HttpFileUploadManager extends XmppManagerBase {
if (response.attributes['type']! != 'result') { if (response.attributes['type']! != 'result') {
logger.severe('Failed to request HTTP File Upload slot.'); logger.severe('Failed to request HTTP File Upload slot.');
// TODO(Unknown): Be more precise // TODO(Unknown): Be more precise
return MayFail.failure(errorGeneric); return Result(UnknownHttpFileUploadError());
} }
final slot = response.firstTag('slot', xmlns: httpFileUploadXmlns)!; final slot = response.firstTag('slot', xmlns: httpFileUploadXmlns)!;
@ -169,7 +164,7 @@ class HttpFileUploadManager extends XmppManagerBase {
}), }),
); );
return MayFail.success( return Result(
HttpFileUploadSlot( HttpFileUploadSlot(
putUrl, putUrl,
getUrl, getUrl,

View File

@ -44,7 +44,6 @@ const _doNotEncryptList = [
]; ];
abstract class OmemoManager extends XmppManagerBase { abstract class OmemoManager extends XmppManagerBase {
OmemoManager() : _handlerLock = Lock(), _handlerFutures = {}, super(); OmemoManager() : _handlerLock = Lock(), _handlerFutures = {}, super();
final Lock _handlerLock; final Lock _handlerLock;