Add API for (de)serialising FolderPath and EmailIdentifier
Supports (de)serialising via GLib.Variant for use as GLib.Action targets transmission via DBus, etc.
This commit is contained in:
parent
f269e552ae
commit
dd3a7a1bc8
14 changed files with 251 additions and 13 deletions
|
|
@ -1,4 +1,6 @@
|
|||
/* Copyright 2016 Software Freedom Conservancy Inc.
|
||||
/*
|
||||
* Copyright 2016 Software Freedom Conservancy Inc.
|
||||
* Copyright 2018-2019 Michael Gratton <mike@vee.net>.
|
||||
*
|
||||
* This software is licensed under the GNU Lesser General Public License
|
||||
* (version 2.1 or later). See the COPYING file in this distribution.
|
||||
|
|
@ -304,6 +306,20 @@ public abstract class Geary.Account : BaseObject {
|
|||
*/
|
||||
public abstract async void rebuild_async(Cancellable? cancellable = null) throws Error;
|
||||
|
||||
/**
|
||||
* Returns an email identifier from its serialised form.
|
||||
*
|
||||
* This is useful for converting a string representation of a
|
||||
* email id back into an actual instance of an id. This does not
|
||||
* guarantee that the email represented by the id will exist.
|
||||
*
|
||||
* @see EmailIdentifier.to_variant
|
||||
* @throws EngineError.BAD_PARAMETERS when the variant is not the
|
||||
* have the correct type.
|
||||
*/
|
||||
public abstract EmailIdentifier to_email_identifier(GLib.Variant serialised)
|
||||
throws EngineError.BAD_PARAMETERS;
|
||||
|
||||
/**
|
||||
* Lists all the currently-available folders found under the parent path
|
||||
* unless it's null, in which case it lists all the root folders. If the
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
/* Copyright 2016 Software Freedom Conservancy Inc.
|
||||
/*
|
||||
* Copyright 2016 Software Freedom Conservancy Inc.
|
||||
* Copyright 2019 Michael Gratton <mike@vee.net>.
|
||||
*
|
||||
* This software is licensed under the GNU Lesser General Public License
|
||||
* (version 2.1 or later). See the COPYING file in this distribution.
|
||||
* (version 2.1 or later). See the COPYING file in this distribution.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
|
@ -28,6 +30,25 @@ public abstract class Geary.EmailIdentifier : BaseObject, Gee.Hashable<Geary.Ema
|
|||
return unique.hash();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a representation useful for serialisation.
|
||||
*
|
||||
* This can be used to transmit ids as D-Bus method and GLib
|
||||
* Action parameters, and so on.
|
||||
*
|
||||
* @returns a serialised form of this id, that will match the
|
||||
* GVariantType `(*)`
|
||||
* @see Account.to_email_identifier
|
||||
*/
|
||||
public abstract GLib.Variant to_variant();
|
||||
|
||||
/**
|
||||
* Returns a representation useful for debugging.
|
||||
*/
|
||||
public virtual string to_string() {
|
||||
return "[%s]".printf(unique.to_string());
|
||||
}
|
||||
|
||||
public virtual bool equal_to(Geary.EmailIdentifier other) {
|
||||
if (this == other)
|
||||
return true;
|
||||
|
|
@ -111,8 +132,4 @@ public abstract class Geary.EmailIdentifier : BaseObject, Gee.Hashable<Geary.Ema
|
|||
return sorted;
|
||||
}
|
||||
|
||||
public virtual string to_string() {
|
||||
return "[%s]".printf(unique.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
/* Copyright 2016 Software Freedom Conservancy Inc.
|
||||
/*
|
||||
* Copyright 2016 Software Freedom Conservancy Inc.
|
||||
* Copyright 2018-2019 Michael Gratton <mike@vee.net>.
|
||||
*
|
||||
* This software is licensed under the GNU Lesser General Public License
|
||||
* (version 2.1 or later). See the COPYING file in this distribution.
|
||||
|
|
@ -12,11 +14,14 @@
|
|||
*
|
||||
* @see FolderRoot
|
||||
*/
|
||||
|
||||
public class Geary.FolderPath :
|
||||
BaseObject, Gee.Hashable<FolderPath>, Gee.Comparable<FolderPath> {
|
||||
|
||||
|
||||
/** Type of the GLib.Variant used to represent folder paths */
|
||||
public const string VARIANT_TYPE = "as";
|
||||
|
||||
|
||||
// Workaround for Vala issue #659. See children below.
|
||||
private class FolderPathWeakRef {
|
||||
|
||||
|
|
@ -218,7 +223,21 @@ public class Geary.FolderPath :
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a string version of the path using a default separator.
|
||||
* Returns a representation useful for serialisation.
|
||||
*
|
||||
* This can be used to transmit folder paths as D-Bus method and
|
||||
* GLib Action parameters, and so on.
|
||||
*
|
||||
* @returns a serialised form of this path, that will match the
|
||||
* GVariantType specified by {@link VARIANT_TYPE}.
|
||||
* @see FolderRoot.from_folder_path
|
||||
*/
|
||||
public GLib.Variant to_variant() {
|
||||
return new GLib.Variant.strv(as_array());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a representation useful for debugging.
|
||||
*
|
||||
* Do not use this for obtaining an IMAP mailbox name to send to a
|
||||
* server, use {@link
|
||||
|
|
@ -287,6 +306,7 @@ public class Geary.FolderPath :
|
|||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The root of a folder hierarchy.
|
||||
*
|
||||
|
|
@ -314,4 +334,24 @@ public class Geary.FolderRoot : FolderPath {
|
|||
this.default_case_sensitivity = default_case_sensitivity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconstructs a path under this root from a GLib variant.
|
||||
*
|
||||
* @see FolderPath.to_variant
|
||||
*/
|
||||
public FolderPath from_variant(GLib.Variant serialised)
|
||||
throws EngineError {
|
||||
if (serialised.get_type_string() != VARIANT_TYPE) {
|
||||
throw new EngineError.BAD_PARAMETERS(
|
||||
"Invalid serialised id type: %s", serialised.get_type_string()
|
||||
);
|
||||
}
|
||||
|
||||
FolderPath path = this;
|
||||
foreach (string step in serialised.get_strv()) {
|
||||
path = path.get_child(step);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,17 @@
|
|||
/* Copyright 2016 Software Freedom Conservancy Inc.
|
||||
/*
|
||||
* Copyright 2016 Software Freedom Conservancy Inc.
|
||||
* Copyright 2018-2019 Michael Gratton <mike@vee.net>.
|
||||
*
|
||||
* This software is licensed under the GNU Lesser General Public License
|
||||
* (version 2.1 or later). See the COPYING file in this distribution.
|
||||
* (version 2.1 or later). See the COPYING file in this distribution.
|
||||
*/
|
||||
|
||||
private class Geary.ImapDB.EmailIdentifier : Geary.EmailIdentifier {
|
||||
|
||||
|
||||
private const string VARIANT_TYPE = "(yxx)";
|
||||
|
||||
|
||||
public int64 message_id { get; private set; }
|
||||
public Imap.UID? uid { get; private set; }
|
||||
|
||||
|
|
@ -26,6 +33,22 @@ private class Geary.ImapDB.EmailIdentifier : Geary.EmailIdentifier {
|
|||
this.uid = uid;
|
||||
}
|
||||
|
||||
/** Reconstructs an identifier from its variant representation. */
|
||||
public EmailIdentifier.from_variant(GLib.Variant serialised)
|
||||
throws EngineError.BAD_PARAMETERS {
|
||||
if (serialised.get_type_string() != VARIANT_TYPE) {
|
||||
throw new EngineError.BAD_PARAMETERS(
|
||||
"Invalid serialised id type: %s", serialised.get_type_string()
|
||||
);
|
||||
}
|
||||
Imap.UID? uid = null;
|
||||
int64 uid_value = serialised.get_child_value(2).get_int64();
|
||||
if (uid_value >= 0) {
|
||||
uid = new Imap.UID(uid_value);
|
||||
}
|
||||
this(serialised.get_child_value(1).get_int64(), uid);
|
||||
}
|
||||
|
||||
// Used to promote an id created with no_message_id to one that has a
|
||||
// message id. Warning: this causes the hash value to change, so if you
|
||||
// have any EmailIdentifiers in a hashed data structure, this will cause
|
||||
|
|
@ -55,6 +78,17 @@ private class Geary.ImapDB.EmailIdentifier : Geary.EmailIdentifier {
|
|||
return uid.compare_to(other.uid);
|
||||
}
|
||||
|
||||
public override GLib.Variant to_variant() {
|
||||
// Return a tuple to satisfy the API contract, add an 'i' to
|
||||
// inform GenericAccount that it's an IMAP id.
|
||||
int64 uid_value = this.uid != null ? this.uid.value : -1;
|
||||
return new GLib.Variant.tuple(new Variant[] {
|
||||
new GLib.Variant.byte('i'),
|
||||
new GLib.Variant.int64(this.message_id),
|
||||
new GLib.Variant.int64(uid_value)
|
||||
});
|
||||
}
|
||||
|
||||
public override string to_string() {
|
||||
return "[%s/%s]".printf(message_id.to_string(), (uid == null ? "null" : uid.to_string()));
|
||||
}
|
||||
|
|
@ -68,4 +102,5 @@ private class Geary.ImapDB.EmailIdentifier : Geary.EmailIdentifier {
|
|||
|
||||
return uids;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,9 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account {
|
|||
Geary.SpecialFolderType.ARCHIVE,
|
||||
};
|
||||
|
||||
private static GLib.VariantType email_id_type = new GLib.VariantType("(y*)");
|
||||
|
||||
|
||||
/** Service for incoming IMAP connections. */
|
||||
public Imap.ClientService imap { get; private set; }
|
||||
|
||||
|
|
@ -412,6 +415,23 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account {
|
|||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public override EmailIdentifier to_email_identifier(GLib.Variant serialised)
|
||||
throws EngineError.BAD_PARAMETERS {
|
||||
if (serialised.is_of_type(GenericAccount.email_id_type)) {
|
||||
throw new EngineError.BAD_PARAMETERS(
|
||||
"Invalid outer serialised type: (y*)"
|
||||
);
|
||||
}
|
||||
char type = (char) serialised.get_child_value(0).get_byte();
|
||||
if (type == 'i')
|
||||
return new ImapDB.EmailIdentifier.from_variant(serialised);
|
||||
if (type == 's')
|
||||
return new Outbox.EmailIdentifier.from_variant(serialised);
|
||||
|
||||
throw new EngineError.BAD_PARAMETERS("Unknown serialised type: %c", type);
|
||||
}
|
||||
|
||||
public override Gee.Collection<Geary.Folder> list_matching_folders(Geary.FolderPath? parent)
|
||||
throws Error {
|
||||
check_open();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright 2016 Software Freedom Conservancy Inc.
|
||||
* Copyright 2019 Michael Gratton <mike@vee.net>.
|
||||
*
|
||||
* This software is licensed under the GNU Lesser General Public License
|
||||
* (version 2.1 or later). See the COPYING file in this distribution.
|
||||
|
|
@ -17,7 +18,7 @@
|
|||
public class Geary.Imap.FolderRoot : Geary.FolderRoot {
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* The canonical path for the IMAP inbox.
|
||||
*
|
||||
* This specific path object will always be returned when a child
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright 2016 Software Freedom Conservancy Inc.
|
||||
* Copyright 2018-2019 Michael Gratton <mike@vee.net>.
|
||||
*
|
||||
* This software is licensed under the GNU Lesser General Public License
|
||||
* (version 2.1 or later). See the COPYING file in this distribution.
|
||||
|
|
@ -8,14 +9,30 @@
|
|||
private class Geary.Outbox.EmailIdentifier : Geary.EmailIdentifier {
|
||||
|
||||
|
||||
private const string VARIANT_TYPE = "(yxx)";
|
||||
|
||||
public int64 message_id { get; private set; }
|
||||
public int64 ordering { get; private set; }
|
||||
|
||||
|
||||
public EmailIdentifier(int64 message_id, int64 ordering) {
|
||||
base("Outbox.EmailIdentifier:%s".printf(message_id.to_string()));
|
||||
this.message_id = message_id;
|
||||
this.ordering = ordering;
|
||||
}
|
||||
|
||||
internal EmailIdentifier.from_variant(GLib.Variant serialised)
|
||||
throws EngineError.BAD_PARAMETERS {
|
||||
if (serialised.get_type_string() != VARIANT_TYPE) {
|
||||
throw new EngineError.BAD_PARAMETERS(
|
||||
"Invalid serialised id type: %s", serialised.get_type_string()
|
||||
);
|
||||
}
|
||||
GLib.Variant mid = serialised.get_child_value(1);
|
||||
GLib.Variant uid = serialised.get_child_value(2);
|
||||
this(mid.get_int64(), uid.get_int64());
|
||||
}
|
||||
|
||||
public override int natural_sort_comparator(Geary.EmailIdentifier o) {
|
||||
EmailIdentifier? other = o as EmailIdentifier;
|
||||
if (other == null) {
|
||||
|
|
@ -24,4 +41,14 @@ private class Geary.Outbox.EmailIdentifier : Geary.EmailIdentifier {
|
|||
return (int) (ordering - other.ordering).clamp(-1, 1);
|
||||
}
|
||||
|
||||
public override GLib.Variant to_variant() {
|
||||
// Return a tuple to satisfy the API contract, add an 's' to
|
||||
// inform GenericAccount that it's an SMTP id.
|
||||
return new GLib.Variant.tuple(new Variant[] {
|
||||
new GLib.Variant.byte('s'),
|
||||
new GLib.Variant.int64(this.message_id),
|
||||
new GLib.Variant.int64(this.ordering)
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,6 +120,21 @@ public class Geary.MockAccount : Account, MockObject {
|
|||
}
|
||||
}
|
||||
|
||||
public override EmailIdentifier to_email_identifier(GLib.Variant serialised)
|
||||
throws EngineError.BAD_PARAMETERS {
|
||||
try {
|
||||
return object_or_throw_call(
|
||||
"to_email_identifier",
|
||||
{ box_arg(serialised) },
|
||||
new EngineError.BAD_PARAMETERS("Mock error")
|
||||
);
|
||||
} catch (EngineError.BAD_PARAMETERS err) {
|
||||
throw err;
|
||||
} catch (GLib.Error err) {
|
||||
return new MockEmailIdentifer(0);
|
||||
}
|
||||
}
|
||||
|
||||
public override Gee.Collection<Folder> list_folders() throws Error {
|
||||
return object_call<Gee.Collection<Folder>>(
|
||||
"list_folders", {}, Gee.List.empty<Folder>()
|
||||
|
|
|
|||
|
|
@ -21,4 +21,8 @@ public class Geary.MockEmailIdentifer : EmailIdentifier {
|
|||
return (other_mock == null) ? 1 : this.id - other_mock.id;
|
||||
}
|
||||
|
||||
public override GLib.Variant to_variant() {
|
||||
return new GLib.Variant.int32(id);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ public class Geary.FolderPathTest : TestCase {
|
|||
add_test("path_compare", path_compare);
|
||||
add_test("path_compare_normalised", path_compare_normalised);
|
||||
add_test("distinct_roots_compare", distinct_roots_compare);
|
||||
add_test("variant_representation", variant_representation);
|
||||
}
|
||||
|
||||
public override void set_up() {
|
||||
|
|
@ -305,4 +306,12 @@ public class Geary.FolderPathTest : TestCase {
|
|||
|
||||
}
|
||||
|
||||
public void variant_representation() throws GLib.Error {
|
||||
FolderPath orig = this.root.get_child("test");
|
||||
GLib.Variant variant = orig.to_variant();
|
||||
FolderPath copy = this.root.from_variant(variant);
|
||||
|
||||
assert_true(orig.equal_to(copy));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
26
test/engine/imap-db/imap-db-email-identifier-test.vala
Normal file
26
test/engine/imap-db/imap-db-email-identifier-test.vala
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright 2019 Michael Gratton <mike@vee.net>
|
||||
*
|
||||
* This software is licensed under the GNU Lesser General Public License
|
||||
* (version 2.1 or later). See the COPYING file in this distribution.
|
||||
*/
|
||||
|
||||
public class Geary.ImapDB.EmailIdentifierTest : TestCase {
|
||||
|
||||
|
||||
public EmailIdentifierTest() {
|
||||
base("Geary.ImapDB.EmailIdentifierTest");
|
||||
add_test("variant_representation", variant_representation);
|
||||
}
|
||||
|
||||
public void variant_representation() throws GLib.Error {
|
||||
EmailIdentifier orig = new EmailIdentifier(
|
||||
123, new Imap.UID(321)
|
||||
);
|
||||
GLib.Variant variant = orig.to_variant();
|
||||
EmailIdentifier copy = new EmailIdentifier.from_variant(variant);
|
||||
|
||||
assert_true(orig.equal_to(copy));
|
||||
}
|
||||
|
||||
}
|
||||
24
test/engine/outbox/outbox-email-identifier-test.vala
Normal file
24
test/engine/outbox/outbox-email-identifier-test.vala
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright 2019 Michael Gratton <mike@vee.net>
|
||||
*
|
||||
* This software is licensed under the GNU Lesser General Public License
|
||||
* (version 2.1 or later). See the COPYING file in this distribution.
|
||||
*/
|
||||
|
||||
public class Geary.Outbox.EmailIdentifierTest : TestCase {
|
||||
|
||||
|
||||
public EmailIdentifierTest() {
|
||||
base("Geary.Outbox.EmailIdentifierTest");
|
||||
add_test("variant_representation", variant_representation);
|
||||
}
|
||||
|
||||
public void variant_representation() throws GLib.Error {
|
||||
EmailIdentifier orig = new EmailIdentifier(123, 321);
|
||||
GLib.Variant variant = orig.to_variant();
|
||||
EmailIdentifier copy = new EmailIdentifier.from_variant(variant);
|
||||
|
||||
assert_true(orig.equal_to(copy));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -40,9 +40,11 @@ geary_test_engine_sources = [
|
|||
'engine/imap-db/imap-db-account-test.vala',
|
||||
'engine/imap-db/imap-db-attachment-test.vala',
|
||||
'engine/imap-db/imap-db-database-test.vala',
|
||||
'engine/imap-db/imap-db-email-identifier-test.vala',
|
||||
'engine/imap-db/imap-db-folder-test.vala',
|
||||
'engine/imap-engine/account-processor-test.vala',
|
||||
'engine/mime-content-type-test.vala',
|
||||
'engine/outbox/outbox-email-identifier-test.vala',
|
||||
'engine/rfc822-mailbox-address-test.vala',
|
||||
'engine/rfc822-mailbox-addresses-test.vala',
|
||||
'engine/rfc822-message-test.vala',
|
||||
|
|
|
|||
|
|
@ -50,11 +50,13 @@ int main(string[] args) {
|
|||
engine.add_suite(new Geary.ImapDB.AttachmentTest().get_suite());
|
||||
engine.add_suite(new Geary.ImapDB.AttachmentIoTest().get_suite());
|
||||
engine.add_suite(new Geary.ImapDB.DatabaseTest().get_suite());
|
||||
engine.add_suite(new Geary.ImapDB.EmailIdentifierTest().get_suite());
|
||||
engine.add_suite(new Geary.ImapDB.FolderTest().get_suite());
|
||||
engine.add_suite(new Geary.ImapEngine.AccountProcessorTest().get_suite());
|
||||
engine.add_suite(new Geary.Inet.Test().get_suite());
|
||||
engine.add_suite(new Geary.JS.Test().get_suite());
|
||||
engine.add_suite(new Geary.Mime.ContentTypeTest().get_suite());
|
||||
engine.add_suite(new Geary.Outbox.EmailIdentifierTest().get_suite());
|
||||
engine.add_suite(new Geary.RFC822.MailboxAddressTest().get_suite());
|
||||
engine.add_suite(new Geary.RFC822.MailboxAddressesTest().get_suite());
|
||||
engine.add_suite(new Geary.RFC822.MessageTest().get_suite());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue