Skip to main content

SupportedVersions

Struct SupportedVersions 

Source
pub struct SupportedVersions { /* private fields */ }
Expand description

A non-empty, sorted, duplicate-free set of protocol versions.

Construct it with new or from_slice; both return Result because emptiness is the one thing a caller gets wrong by accident and cannot fix afterwards.

§Examples

use protocol_droid::domain::{ProtocolVersion, SupportedVersions};

let ours = SupportedVersions::new([ProtocolVersion::V2024_11_05, ProtocolVersion::V2025_03_26])?;
assert_eq!(ours.latest(), ProtocolVersion::V2025_03_26);
assert!(ours.contains(&ProtocolVersion::V2024_11_05));

// Newest mutually supported wins, which is what the specification requires
// when both sides can speak more than one revision.
let theirs = [ProtocolVersion::V2025_06_18, ProtocolVersion::V2025_03_26];
assert_eq!(ours.best_match(&theirs), Some(ProtocolVersion::V2025_03_26));

Implementations§

Source§

impl SupportedVersions

Source

pub fn all() -> Result<Self, SupportedVersionsError>

Every revision this build has wire types for.

§Errors

Never. It exists so callers do not spell the list out, and the list is known non-empty, so the Result is a formality rather than a branch.

Source

pub fn as_slice(&self) -> &[ProtocolVersion]

The set of every revision this build knows, as a slice.

A convenience for the read-only cases; new and from_slice are the ways to build one that can be held.

Source

pub fn new( versions: impl IntoIterator<Item = ProtocolVersion>, ) -> Result<Self, SupportedVersionsError>

Sorts, deduplicates, and rejects an empty set.

§Errors

SupportedVersionsError::Empty when versions has no members.

§Examples
use protocol_droid::domain::{ProtocolVersion, SupportedVersions};

// Order and duplicates are the caller's problem, not the caller's job.
let set = SupportedVersions::new([
    ProtocolVersion::V2025_03_26,
    ProtocolVersion::V2024_11_05,
    ProtocolVersion::V2025_03_26,
])?;
assert_eq!(set.as_slice(), &[ProtocolVersion::V2024_11_05, ProtocolVersion::V2025_03_26]);
Source

pub fn from_slice( versions: &[ProtocolVersion], ) -> Result<Self, SupportedVersionsError>

new for a slice that is already borrowed.

§Errors

SupportedVersionsError::Empty when versions is empty.

Source

pub fn len(&self) -> usize

How many revisions the peer supports.

At least one, always — that is the invariant.

Source

pub const fn is_empty(&self) -> bool

Always false. Present because len exists and clippy asks.

Source

pub fn latest(&self) -> ProtocolVersion

The newest revision the peer supports.

Infallible rather than Option because the set is non-empty and sorted: the last element is the answer, and there is no path to a set where that element does not exist.

Source

pub fn latest_handshake(&self) -> ProtocolVersion

The newest revision here that still defines a handshake.

Not latest. SEP-2575 removed initialize from 2026-07-28, and that revision is currently the newest the crate knows — so a ceiling taken from latest would be a revision no peer can complete a handshake on, and a server gating its whole life on one can never finish talking to anybody.

Infallible for the same reason latest is: the set is non-empty and sorted, and the earliest-known revision still has a handshake, so the scan has something to return.

Source

pub fn earliest(&self) -> ProtocolVersion

The oldest revision the peer supports.

Source

pub fn contains(&self, version: &ProtocolVersion) -> bool

Whether the peer supports version.

Source

pub fn best_match(&self, offered: &[ProtocolVersion]) -> Option<ProtocolVersion>

The newest revision this set and offered have in common, or None.

Newest-common rather than first-offered: the specification tells a peer to use the latest version it can support, and a client that advertised ["2024-11-05", "2025-06-18"] is not asking for 2024-11-05.

offered is taken as a slice and scanned rather than sorted into a set, because it arrives from the wire, may contain duplicates, and is usually a handful of entries. The cost is one linear pass, and ProtocolVersion is Copy so the comparison is a field compare.

§Why Option when the task said -> ProtocolVersion

There is a real outcome where no revision is shared, and a peer’s offer can be empty. Returning a ProtocolVersion there means returning a value the peer did not offer, which is how a bridge ends up announcing a version it cannot speak. T06 maps None onto JSON-RPC’s UnsupportedProtocolVersion error, which is the answer the wire format already has for exactly this case.

§Examples
use protocol_droid::domain::{ProtocolVersion, SupportedVersions};

let ours = SupportedVersions::new(ProtocolVersion::KNOWN)?;
assert_eq!(
    ours.best_match(&[ProtocolVersion::V2025_06_18, ProtocolVersion::V2024_11_05]),
    Some(ProtocolVersion::V2025_06_18)
);
assert_eq!(ours.best_match(&[ProtocolVersion::Unknown("2027-01-01".parse().unwrap())]), None);
assert_eq!(ours.best_match(&[]), None);
Source

pub fn not_offered_by<'a>( &'a self, offered: &'a [ProtocolVersion], ) -> impl Iterator<Item = ProtocolVersion> + 'a

The revisions in this set that offered does not contain.

The negotiation log wants both directions, and a codec wants to know what it must translate away from, so this is a first-class operation rather than something each caller reassembles.

Trait Implementations§

Source§

impl Clone for SupportedVersions

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for SupportedVersions

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for SupportedVersions

Source§

fn fmt(&self, formatter: &mut Formatter<'_>) -> Result

Joins the versions with commas, oldest first.

Used in negotiation error messages, where the reader wants the list rather than a Debug dump with a name per element.

Source§

impl Eq for SupportedVersions

Source§

impl IntoIterator for SupportedVersions

Source§

type Item = ProtocolVersion

The type of the elements being iterated over.
Source§

type IntoIter = IntoIter<ProtocolVersion>

Which kind of iterator are we turning this into?
Source§

fn into_iter(self) -> Self::IntoIter

Creates an iterator from a value. Read more
Source§

impl PartialEq for SupportedVersions

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for SupportedVersions

Source§

impl TryFrom<&[ProtocolVersion]> for SupportedVersions

Source§

type Error = SupportedVersionsError

The type returned in the event of a conversion error.
Source§

fn try_from(versions: &[ProtocolVersion]) -> Result<Self, Self::Error>

Performs the conversion.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
Source§

impl<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

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

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more