pub struct Selection { /* private fields */ }Expand description
A resolved, ordered, immutable snapshot of the issues a bulk operation acts on.
Built by Selection::resolve. The store is read; nothing is written, and
there is no method on this type that can write — that is the property
contract §3 needs, and it is structural rather than a promise.
Implementations§
Source§impl Selection
impl Selection
Sourcepub fn resolve(
store: &Store,
selectors: &[String],
query: Option<&str>,
source: SelectionSource,
scope: SelectionScope,
) -> Result<Self>
pub fn resolve( store: &Store, selectors: &[String], query: Option<&str>, source: SelectionSource, scope: SelectionScope, ) -> Result<Self>
Resolve a selection from explicit selectors and/or a query.
Resolution order, and why: explicit selectors first, then the query’s issues, then de-duplication. A user who typed both means the union, and taking the union in that order means the explicit ones lead — which is what a dry run should show first.
Ambiguity and not-found are the existing diagnostics, propagated
unwrapped (contract §2). The first version wrapped the selector failure in
a fresh NotFound, and the user saw not found: not found: issue matching … — the same doubled prefix a relationship message had. One message, from
one place.
Sourcepub fn from_issues(
issues: impl IntoIterator<Item = Issue>,
source: SelectionSource,
scope: SelectionScope,
) -> Self
pub fn from_issues( issues: impl IntoIterator<Item = Issue>, source: SelectionSource, scope: SelectionScope, ) -> Self
A snapshot from issues the caller already has, with no store involved.
Two callers need this and neither is a test: the TUI multi-select (WP07)
resolves a selection from the board’s cards rather than from typed
selectors, and a caller previewing a large in-memory set has no store to
resolve against. Both want the same guarantee — a value that cannot grow
— which is what makes this a constructor on the type rather than a pub
field.
The order is preserved rather than sorted: a board’s column order is what a user sees, and a selection’s order is presentation (the fingerprint is the order-insensitive part, and is the thing an apply is authorized for).
Numbers are de-duplicated, because a board can list the same issue twice and a plan that writes it twice is the failure the data-model calls “the plan never double-writes an issue unintentionally”.
Sourcepub fn into_issues(self) -> Vec<Issue>
pub fn into_issues(self) -> Vec<Issue>
Take the snapshot, so a later stage owns it rather than borrowing.
pub fn source(&self) -> SelectionSource
pub fn query(&self) -> Option<&str>
pub fn scope(&self) -> SelectionScope
Sourcepub fn selectors(&self) -> &[String]
pub fn selectors(&self) -> &[String]
The selectors after de-duplication, in the order they resolved.
Sourcepub fn duplicates(&self) -> &[String]
pub fn duplicates(&self) -> &[String]
Selectors that named an issue an earlier selector had already named.
Reported rather than silently dropped: a user who typed 12 12 alpha and
sees “3 issues” would otherwise have no way to know the third selector was
ignored. The plan renders this (WP02 T009).
pub fn len(&self) -> usize
pub fn is_empty(&self) -> bool
Sourcepub fn fingerprint(&self) -> Vec<u32>
pub fn fingerprint(&self) -> Vec<u32>
A stable identity for this selection, so an apply can refuse a plan that was confirmed against a different snapshot (contract §4: “apply requires the exact confirmed plan”).
Built from the numbers, not from a hash of the issue contents: a user may edit a selected issue between preview and apply, and the plan still applies to those issues — the values were validated at preview time and re-validated at apply time, so a content hash would refuse a legitimate apply for the wrong reason. Membership is what has to match.
Sourcepub fn matches_fingerprint(&self, fingerprint: &[u32]) -> bool
pub fn matches_fingerprint(&self, fingerprint: &[u32]) -> bool
Whether this selection matches a fingerprint, ignoring order.
Order-insensitive on purpose. A selection’s order is presentation; its membership is what an apply is authorized for, and rejecting an apply because the board came back in a different order would be a refusal with no user-visible cause.
Trait Implementations§
impl Eq for Selection
impl StructuralPartialEq for Selection
Auto Trait Implementations§
impl Freeze for Selection
impl RefUnwindSafe for Selection
impl Send for Selection
impl Sync for Selection
impl Unpin for Selection
impl UnsafeUnpin for Selection
impl UnwindSafe for Selection
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more