pub enum PairCodeRejection {
BadRequest,
Forbidden,
RateOverlimit,
FeatureNotAvailable,
InternalServerError,
Unknown(i32),
}Expand description
How the server refused a pair-code request, as a matchable status.
The five named variants are the complete set WA Web’s own response parser
accepts (WASmaxInMdIqMixinErrors.parseIqMixinErrors, reached from
WASmaxInMdCompanionHelloResponseError); anything else makes its RPC throw
“unknown error”. They exist so a consumer can branch on the refusal instead
of matching the formatted message, which is not a stable surface.
Both stages report through this, though they were read off companion_hello
and the companion_finish parser is narrower — WASmaxInMdCompanionFinishErrors
admits only bad-request and internal-server-error, and WA Web shows its
generic failure for anything else. A code outside that pair is still
classified here rather than discarded: what a consumer does about a refusal
follows from the code, which is one namespace across both requests, and
answering “nothing was refused” to a refusal we can read would be worse than
naming it.
The numbers are the code attribute, and each is the enum’s whole wire form
— code() is what Serialize emits and what From<i32> reads
back. WA Web pairs each code with a literal text
(429/rate-overlimit, 452/feature-not-available, …) and rejects a
response whose two disagree, so construct these through
from_server rather than from a code alone: it is the
only constructor that sees both attributes, and the only one that can decline
to classify.
WA Web branches on exactly two of them (DevicePhoneNumberCodeScreen, on
CompanionHelloError.type.name): RateOverlimit
becomes “too many attempts, try again later” and
FeatureNotAvailable becomes “not available to
you yet, link with QR code instead”. The rest share a generic “try again or
link with the QR code”. In every case it resets the linking flow and waits
for the person to act — it never retries on its own, and never reads the
backoff hint, so treat that value as the server’s advice rather than a
schedule WA Web is known to follow.
Variants§
BadRequest
The request was malformed — or throttled for this phone number: the
server reuses bad-request for its per-number pair-code limit rather
than answering rate-overlimit. So this is not reliably a permanent
failure; see PairCodeRejection::is_throttled.
Forbidden
RateOverlimit
The connection is asking for codes too fast. The server states the rate is too high; the only correct response is to slow down.
FeatureNotAvailable
Phone-number linking is not enabled for this account. Retrying will not change that — WA Web sends the user to the QR code instead.
InternalServerError
Unknown(i32)
A code outside the set WA Web accepts. Its own RPC would raise
“unknown error” here; we keep the number so a consumer can log it and a
server-side addition is visible rather than silently reshaped.
Implementations§
Source§impl PairCodeRejection
impl PairCodeRejection
Sourcepub fn is_throttled(self) -> bool
pub fn is_throttled(self) -> bool
Whether this refusal is the server rate-limiting the request.
True for RateOverlimit and
BadRequest, because the server throttles pair-code
requests per phone number under bad-request instead of
rate-overlimit. That makes the predicate deliberately wider than the
literal 429: a bad-request may equally be genuinely invalid content,
and the two are indistinguishable on the wire. Treat a true here as
“back off, then retry at most a bounded number of times” — not as proof
the request would ever succeed.
Sourcepub fn text(self) -> Option<&'static str>
pub fn text(self) -> Option<&'static str>
The text WA Web pairs with this code; None for
Unknown, which has no expected pairing.
Sourcepub fn from_server(code: u16, text: &str) -> Option<PairCodeRejection>
pub fn from_server(code: u16, text: &str) -> Option<PairCodeRejection>
Classify a server <error> from both of its attributes, or None when
the two disagree and no classification is honest.
WA Web asserts the pair (literal(attrInt, …, "code", 429) beside
literal(attrString, …, "text", "rate-overlimit")) and drops to its
generic error path when they disagree, so a changed pairing must not keep
reading as the named arm.
None rather than Unknown(code) for that case, because Unknown could
not carry it: the wire form of this enum is code(), so
Unknown(429) serializes to 429 and rehydrates as
RateOverlimit — a consumer that persisted or
forwarded the value would get the demotion silently undone and apply
throttling anyway. There is no in-band value that both records the code
and refuses to alias the arm it came from. The code is not lost: the
caller still has the error’s own rendering, which names it.
An absent text is not a contradiction, and the code alone decides.
Deliberately laxer than WA Web, which would reject it: refusing to
classify a bare 429 would also clear
is_throttled, turning the one refusal a consumer
most needs to act on back into a silent one. A missing attribute is not
evidence that the code means something else.
Trait Implementations§
Source§impl Clone for PairCodeRejection
impl Clone for PairCodeRejection
Source§fn clone(&self) -> PairCodeRejection
fn clone(&self) -> PairCodeRejection
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreimpl Copy for PairCodeRejection
Source§impl Debug for PairCodeRejection
impl Debug for PairCodeRejection
Source§impl<'de> Deserialize<'de> for PairCodeRejection
impl<'de> Deserialize<'de> for PairCodeRejection
Source§fn deserialize<D>(
deserializer: D,
) -> Result<PairCodeRejection, <D as Deserializer<'de>>::Error>where
D: Deserializer<'de>,
fn deserialize<D>(
deserializer: D,
) -> Result<PairCodeRejection, <D as Deserializer<'de>>::Error>where
D: Deserializer<'de>,
Source§impl Display for PairCodeRejection
impl Display for PairCodeRejection
impl Eq for PairCodeRejection
Source§impl From<i32> for PairCodeRejection
impl From<i32> for PairCodeRejection
Source§fn from(code: i32) -> PairCodeRejection
fn from(code: i32) -> PairCodeRejection
Source§impl PartialEq for PairCodeRejection
impl PartialEq for PairCodeRejection
Source§impl Serialize for PairCodeRejection
impl Serialize for PairCodeRejection
Source§fn serialize<S>(
&self,
serializer: S,
) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>where
S: Serializer,
fn serialize<S>(
&self,
serializer: S,
) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>where
S: Serializer,
impl StructuralPartialEq for PairCodeRejection
Auto Trait Implementations§
impl Freeze for PairCodeRejection
impl RefUnwindSafe for PairCodeRejection
impl Send for PairCodeRejection
impl Sync for PairCodeRejection
impl Unpin for PairCodeRejection
impl UnsafeUnpin for PairCodeRejection
impl UnwindSafe for PairCodeRejection
Blanket Implementations§
Source§impl<T> AggregateExpressionMethods for T
impl<T> AggregateExpressionMethods for T
Source§fn aggregate_distinct(self) -> Self::Outputwhere
Self: DistinctDsl,
fn aggregate_distinct(self) -> Self::Outputwhere
Self: DistinctDsl,
DISTINCT modifier for aggregate functions Read moreSource§fn aggregate_all(self) -> Self::Outputwhere
Self: AllDsl,
fn aggregate_all(self) -> Self::Outputwhere
Self: AllDsl,
ALL modifier for aggregate functions Read moreSource§fn aggregate_filter<P>(self, f: P) -> Self::Output
fn aggregate_filter<P>(self, f: P) -> Self::Output
Source§fn aggregate_order<O>(self, o: O) -> Self::Outputwhere
Self: OrderAggregateDsl<O>,
fn aggregate_order<O>(self, o: O) -> Self::Outputwhere
Self: OrderAggregateDsl<O>,
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,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
impl<T> ErasedDestructor for Twhere
T: 'static,
Source§impl<T> IntoSql for T
impl<T> IntoSql for T
Source§fn into_sql<T>(self) -> Self::Expression
fn into_sql<T>(self) -> Self::Expression
self to an expression for Diesel’s query builder. Read moreSource§fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expression
fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expression
&self to an expression for Diesel’s query builder. Read moreimpl<T> MaybeSend for T
impl<T> MaybeSendSync for T
impl<T> Spawnable for Twhere
T: Send + 'static,
Source§impl<T> ToCompactString for Twhere
T: Display,
impl<T> ToCompactString for Twhere
T: Display,
Source§fn try_to_compact_string(&self) -> Result<CompactString, ToCompactStringError>
fn try_to_compact_string(&self) -> Result<CompactString, ToCompactStringError>
ToCompactString::to_compact_string() Read moreSource§fn to_compact_string(&self) -> CompactString
fn to_compact_string(&self) -> CompactString
CompactString. Read more