[][src]Struct dogear::Builder

pub struct Builder { /* fields omitted */ }

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's children. In other words, if item B's parentid is A, then A's children 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 unrelated parentid.
  • 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 parentids.
  • Folders with children whose parentids don't match the folder.
  • Items whose parentids don't mention the item in their children.
  • Items with parentids 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:

  1. User content roots should always be children of the Places root. If they appear in other parents, we move them.
  2. Items that appear in multiple children, and items with mismatched parentids, use the chronologically newer parent, based on the parent's last modified time. We always prefer parents by children over parentid, because children also gives us the item's position.
  3. Items that aren't mentioned in any parent's children, but have a parentid that references an existing folder in the tree, are reparented to the end of that folder, after the folder's children.
  4. Items that reference a nonexistent or non-folder parentid, or don't have a parentid at all, are reparented to the default folder.
  5. 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

impl Debug for Builder[src]

impl TryFrom<Builder> for Tree[src]

type Error = Error

The type returned in the event of a conversion error.

fn try_from(builder: Builder) -> Result<Tree>[src]

Builds a tree from all stored items and parent-child associations, resolving inconsistencies like orphans, multiple parents, and parent-child disagreements.

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]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> Any for T where
    T: 'static + ?Sized
[src]