Skip to main content

ShapeProfile

Struct ShapeProfile 

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

A complete egress shaping configuration for one session.

Constructed only through ShapeProfile::try_new, which validates the combination — an invalid profile cannot reach a session, so there is no runtime your config was rejected path to miss.

Not #[non_exhaustive]: the fields are private, so the attribute would add nothing a caller could observe.

§Reading one from a file

Under the non-default serde feature this type serializes and deserializes, and the two directions are not symmetric. Serializing is a derive over the private fields, which is safe because writing a profile out cannot make an invalid one. Deserializing goes #[serde(try_from = "ShapeProfileSpec")], through a public-field mirror whose TryFrom calls ShapeProfile::try_new.

The detour is the whole point. A derived Deserialize would reach these private fields directly and bypass every one of the seven validations below — including ShapeError::UnknownBucket, where a file naming a bucket that does not exist would parse, arm, report shaping and shape nothing. Routing through the mirror means there is no deserialization path that skips the constructor, and no consumer has to remember to convert.

Implementations§

Source§

impl ShapeProfile

Source

pub fn try_new( buckets: Vec<BucketConfig>, classes: Vec<ClassRule>, queue: QueueConfig, discipline: Discipline, ) -> Result<Self, ShapeError>

Validate a profile and build it, or say exactly what is wrong.

The seven rejections, in the order they are checked:

  1. ShapeError::EmptyQueue — a queue that can hold nothing.
  2. ShapeError::NoClasses — a profile with no class rules at all, which is a shaping profile that shapes nothing.
  3. ShapeError::DuplicateClassName — class names index the statistics, so duplicates make them unattributable.
  4. ShapeError::UnknownBucket — a class naming a bucket that is not in buckets; the silently-inert class this constructor exists to prevent.
  5. ShapeError::EgressSideInMatcher — a matcher keyed on an egress side, which no hook site ever sees.
  6. ShapeError::ZeroWeight — a zero weight under Discipline::WeightedRoundRobin, which is a class that can never be scheduled.
  7. ShapeError::InertMatcher — a matcher key naming an empty set of values, which is a class that can never claim a unit.

The second is checked outside the loop below, and that is the point of it: every other class rule is checked inside a for class in &classes, and a loop over nothing runs no checks at all. A profile with no classes was therefore the one shape that could pass every rule here by not being subject to any of them.

Duplicate bucket names are not an error: two identical entries resolve to the same bucket and the first one wins, which is what a caller who wrote the name twice meant. Only class names index anything.

§What this constructor cannot see, and why the line is there

Every check above is a property of the configuration alone. What it deliberately does not attempt is anything that depends on the draft or on the traffic, and there are two such faults; both are reported during the run instead, because a rejection here has to be right for every session the profile could be used in.

A key the wire does not carry on this draft is Impairment{ShapeRuleUnmatchable}try_new has no draft. And a BucketConfig::burst_bytes smaller than the objects a class actually sees is Impairment{ShapeBurstBelowUnit}try_new has the burst but not the object sizes, and the sizes are what decide. The second is worth the attention because its silent form is so plausible: a burst below one object makes every unit leave at its max_hold clamp, at a throughput with no relation to the rate that was configured, and before the report existed the only signal was the one an ordinary rate-limited class produces.

Source

pub fn buckets(&self) -> &[BucketConfig]

The configured buckets, in the order they were given.

Source

pub fn classes(&self) -> &[ClassRule]

The configured class rules, in the order they were given — which is also the order the statistics snapshot reports them in, and the order Discipline::Fifo tie-breaks on.

Source

pub fn queue(&self) -> &QueueConfig

The per-stream queue policy.

Source

pub fn discipline(&self) -> Discipline

How classes competing for one bucket are arbitrated.

Trait Implementations§

Source§

impl Clone for ShapeProfile

Source§

fn clone(&self) -> ShapeProfile

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 ShapeProfile

Source§

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

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

impl PartialEq for ShapeProfile

Source§

fn eq(&self, other: &ShapeProfile) -> 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 ShapeProfile

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<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> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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> 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, 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, <T as TryFrom<U>>::Error>

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<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