[−][src]Struct dogear::Builder
A tree builder builds a bookmark tree structure from a flat list of items and parent-child associations.
Tree structure
In a well-formed tree:
- Each item exists in exactly one folder. Two different folder's
children
should never reference the same item. - Each folder contains existing children. A folder's
children
should never reference tombstones, or items that don't exist in the tree at all. - Each item has a
parentid
that agrees with its parent'schildren
. In other words, if item B'sparentid
is A, then A'schildren
should contain B.
Because of Reasons, things are (a lot) messier in practice.
Structure inconsistencies
Sync stores structure in two places: a parentid
property on each item,
which points to its parent's GUID, and a list of ordered children
on the
item's parent. They're duplicated because, historically, Sync clients didn't
stage incoming records. Instead, they applied records one at a time,
directly to the live local tree. This meant that, if a client saw a child
before its parent, it would first use the parentid
to decide where to keep
the child, then fix up parents and positions using the parent's children
.
This is also why moving an item into a different folder uploads records for
the item, old folder, and new folder. The item has a new parentid
, and the
folders have new children
. Similarly, deleting an item uploads a tombstone
for the item, and a record for the item's old parent.
Unfortunately, bugs (bug 1258127) and missing features (bug 1253051) in older clients sometimes caused them to upload invalid or incomplete changes. For example, a client might have:
- Uploaded a moved child, but not its parents. This means the child now
appears in multiple parents. In the most extreme case, an item might be
referenced in two different sets of
children
, and have a third, completely unrelatedparentid
. - Deleted a child, and tracked the deletion, but didn't flag the parent for reupload. The parent folder now has a tombstone child.
- Tracked and uploaded items that shouldn't exist on the server at all, like the left pane or reading list roots (bug 1309255).
- Missed new folders created during a sync, creating holes in the tree.
Newer clients shouldn't do this, but we might still have inconsistent records on the server that will confuse older clients. Additionally, Firefox for iOS includes a much stricter bookmarks engine that refuses to sync if it detects inconsistencies.
Divergences
To work around this, the builder lets the structure diverge. This allows:
- Items with multiple parents.
- Items with missing
parentid
s. - Folders with
children
whoseparentid
s don't match the folder. - Items whose
parentid
s don't mention the item in theirchildren
. - Items with
parentid
s that point to nonexistent or deleted folders. - Folders with nonexistent
children
. - Non-syncable items, like custom roots.
- Any combination of these.
Resolving divergences
Building a tree using std::convert::TryInto<Tree>::try_into
resolves
divergences using these rules:
- User content roots should always be children of the Places root. If they appear in other parents, we move them.
- Items that appear in multiple
children
, and items with mismatchedparentid
s, use the chronologically newer parent, based on the parent's last modified time. We always prefer parents bychildren
overparentid,
becausechildren
also gives us the item's position. - Items that aren't mentioned in any parent's
children
, but have aparentid
that references an existing folder in the tree, are reparented to the end of that folder, after the folder'schildren
. - Items that reference a nonexistent or non-folder
parentid
, or don't have aparentid
at all, are reparented to the default folder. - If the default folder isn't set, or doesn't exist, items from rule 4 are reparented to the root instead.
The result is a well-formed tree structure that can be merged. The merger detects if the structure diverged, and flags affected items for reupload.
Methods
impl Builder
[src]
pub fn reparent_orphans_to(&mut self, guid: &Guid) -> &mut Builder
[src]
Sets the default folder for reparented orphans. If not set, doesn't exist, or not a folder, orphans will be reparented to the root.
pub fn item(&mut self, item: Item) -> Result<ItemBuilder>
[src]
Inserts an item
into the tree. Returns an error if the item already
exists.
pub fn parent_for(&mut self, child_guid: &Guid) -> ParentBuilder
[src]
Sets parents for a child_guid
. Depending on where the parent comes
from, child_guid
may not need to exist in the tree.
pub fn deletion(&mut self, guid: Guid) -> &mut Builder
[src]
Notes a tombstone for a deleted item, marking it as deleted in the tree.
pub fn into_tree(self) -> Result<Tree>
[src]
Equivalent to using our implementation ofTryInto<Tree>::try_into
, but
provided both for convenience when updating from previous versions of
dogear
, and for cases where a type hint would otherwise be needed to
clarify the target type of the conversion.
Trait Implementations
Auto Trait Implementations
impl Sync for Builder
impl Send for Builder
impl Unpin for Builder
impl RefUnwindSafe for Builder
impl UnwindSafe for Builder
Blanket Implementations
impl<T> From<T> for T
[src]
impl<T, U> Into<U> for T where
U: From<T>,
[src]
U: From<T>,
impl<T, U> TryFrom<U> for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T, U> TryInto<U> for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,
type Error = <U as TryFrom<T>>::Error
The type returned in the event of a conversion error.
fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>
[src]
impl<T> BorrowMut<T> for T where
T: ?Sized,
[src]
T: ?Sized,
fn borrow_mut(&mut self) -> &mut T
[src]
impl<T> Borrow<T> for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,