Skip to main content

TimeRangeBound

Struct TimeRangeBound 

Source
pub struct TimeRangeBound<T> { /* private fields */ }
Expand description

A TimeBound object that is valid for a specified range of time.

The range is given as an argument, as in t1..t2.

The range is always treated as inclusive.

Non-invariant: it is possible for the start to be after the end. In that case, it’s simply never valid: either expired, or too soon, or both.

TimeRangeBound<()> aka TimeRange is sometimes used as a representation of a time range, for example, the return value from TimeBound::bounds.

use web_time_compat::{SystemTime, SystemTimeExt, Duration};
use tor_checkable::{TimeBound, TimeValidityError, timed::TimeRangeBound};

let now = SystemTime::get();
let one_hour = Duration::new(3600, 0);

// This seven is only valid for another hour!
let seven = TimeRangeBound::new(7_u32, ..now+one_hour);

assert_eq!(seven.if_valid_at(&now).unwrap(), 7);

// That consumed the previous seven. Try another one.
let seven = TimeRangeBound::new(7_u32, ..now+one_hour);
assert_eq!(seven.if_valid_at(&(now+2*one_hour)),
           Err(TimeValidityError::Expired(one_hour)));

Implementations§

Source§

impl<T> TimeRangeBound<T>

Source

pub fn new<U>(obj: T, range: U) -> Self

Construct a new TimeRangeBound object from a given object and range.

Note that we do not distinguish between inclusive and exclusive bounds: x..y and x..=y are treated the same here - as an inclusive range.

Use TimeRange::new_range to create a TimeRange aka a TimeRangeBound<()>.

Source

pub fn new_from_start_end( obj: T, start: Option<SystemTime>, end: Option<SystemTime>, ) -> Self

Construct a new TimeRangeBound object from a given object, start time, and end time.

Source

pub fn extend_start_bound(self, d: Duration) -> Self

Adjust this time-range bound to tolerate an initial validity time farther in the past.

Source

pub fn extend_end_bound(self, d: Duration) -> Self

Adjust this time-range bound to tolerate an expiration time farther in the future.

Source

pub fn extend_pre_tolerance(self, d: Duration) -> Self

👎Deprecated:

use extend_start_bound instead

Deprecated alias for extend_start_bound

Source

pub fn extend_tolerance(self, d: Duration) -> Self

👎Deprecated:

use extend_end_bound instead

Deprecated alias for extend_end_bound

Source

pub fn dangerously_map<F, U>(self, f: F) -> TimeRangeBound<U>
where F: FnOnce(T) -> U,

Consume this TimeRangeBound, and return a new one with the same bounds, applying f to its protected value.

The caller must ensure that f does not make any assumptions about the timeliness of the protected value, or leak any of its contents in an inappropriate way.

Source

pub fn dangerously_into_parts(self) -> (T, TimeRange)

Consume this TimeRangeBound, and return its underlying time bounds and object.

The caller takes responsibility for making sure that the bounds are actually checked.

Source

pub fn dangerously_peek(&self) -> &T

Return a reference to the inner object of this TimeRangeBound, without checking the time interval.

The caller takes responsibility for making sure that nothing is actually done with the inner object that would rely on the bounds being correct, until the bounds are (eventually) checked.

Source

pub fn as_ref(&self) -> TimeRangeBound<&T>

Return a TimeRangeBound containing a reference

This can be useful to call methods like .check_valid_at without consuming the inner T.

Source

pub fn as_deref(&self) -> TimeRangeBound<&T::Target>
where T: Deref,

Return a TimeRangeBound containing a reference to T’s Deref

Source

pub fn bounds_start_end(&self) -> (Option<SystemTime>, Option<SystemTime>)

Return the underlying time bounds of this object.

Source

pub fn intersect_bounds(&mut self, bounds: TimeRange)

Narrow the bounds of self to the overlap with bounds

If the bounds conflict (ie, if the intersection is empty), simply yields a TimeRangeBound that is never valid.

(This is unlike tor_basic_utils::rangebounds::RangeBoundsExt::intersect which is implemented for TimeRange via RangeBounds: intersect insists on returning a well-formed range, whereas TimeRangeBound can be empty if start > end.)

Source

pub fn build_intersect<Error, Logic>(logic: Logic) -> Result<Self, Error>
where Logic: FnOnce(&mut TimeRangeBoundBuilder) -> Result<T, Error>,

Process multiple TimeBounds, intersecting their validity ranges

Within logic, TimeBound::unwrap_with can be used, for unwrapping TimeBounds.

Those time bounds are accumulated within the TimeRangeBoundBuilder, and when logic returns, they are applied to its result.

This allows multiple time-bound components of (a Tor protocol element) to be conveniently processed into an overall return value.

The API is intended to prevent accidentally forgetting to check or process one of the time bounds; TimeRangeBoundBuilder is an alternative to manual use of dangerously_* and intersect.

§CORRECTNESS

Everything that needs to be bound to the time range must be returned only as part of the return value from logic.

It is the caller’s responsibility not to smuggle out values whose validity time has not been checked out via mutable captures in logic, global variables, etc.

Likewise, if logic returns Err, this must mean that callers don’t treat the data as valid or successful. I.e. Error must really be an error, and not be used as a way to smuggle out potentially-out-of-time-range data.

§Example
use humantime::parse_rfc3339;
use tor_checkable::{TimeBound as _, TimeRangeBound};

// Fake document.  A real document would involve signature verification too.
struct Data {}
struct FakeDoc { data: Data, sig: TimeRangeBound<()>, }
impl FakeDoc {
    fn parse(_dummy: &str) -> TimeRangeBound<Self> {
        let t = |s| parse_rfc3339(s).unwrap();
        let sig = TimeRangeBound::new((), ..=t("2001-01-01T00:00:01Z"));
        let doc = FakeDoc { data: Data {}, sig };
        TimeRangeBound::new(doc, ..=t("2000-01-01T00:00:01Z"))
    }
}

// Demo usage of TimeBoundRangeBuilder, in verification function
fn parse_verify(input: &str) -> Result<TimeRangeBound<Data>, ()> {
    let parsed = FakeDoc::parse(input); // real parser would be fallible
    TimeRangeBound::build_intersect(move |times| {
        let FakeDoc { data, sig } = parsed.unwrap_with(times);
        let _: () = sig.unwrap_with(times); // would verify signature too
        Ok(data)
    })
}

assert_eq!(
    parse_verify("dummy").unwrap().bounds().end(),
    Some(parse_rfc3339("2000-01-01T00:00:01Z").unwrap()),
);
Source§

impl TimeRangeBound<()>

Source

pub fn new_range<U>(range: U) -> Self

Create a new TimeRange from a std::ops::RangeBounds

Source

pub fn apply_to<T>(self, t: T) -> TimeRangeBound<T>

Applies this TimeRange to a value, protecting it

Source

pub fn start(&self) -> Option<SystemTime>

Get the start of the validity period

None means there is no start: the object has been valid forever.

Provided only for TimeRange; to call on a general TimeRangeBound<T>, write .bounds().start().

Source

pub fn end(&self) -> Option<SystemTime>

Get the end of the validity period

None means there is no end: the object will been valid forever. This is normally a mistake.

Provided only for TimeRange; to call on a general TimeRangeBound<T>, write .bounds().end().

Trait Implementations§

Source§

impl<T: Clone> Clone for TimeRangeBound<T>

Source§

fn clone(&self) -> TimeRangeBound<T>

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<T: Debug> Debug for TimeRangeBound<T>

Source§

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

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

impl<T> RangeBounds<SystemTime> for TimeRangeBound<T>

Source§

fn start_bound(&self) -> Bound<&SystemTime>

Start index bound. Read more
Source§

fn end_bound(&self) -> Bound<&SystemTime>

End index bound. Read more
1.35.0 (const: unstable) · Source§

fn contains<U>(&self, item: &U) -> bool
where T: PartialOrd<U>, U: PartialOrd<T> + ?Sized,

Returns true if item is contained in the range. Read more
Source§

fn is_empty(&self) -> bool
where T: PartialOrd,

🔬This is a nightly-only experimental API. (range_bounds_is_empty)
Returns true if the range contains no items. One-sided ranges (RangeFrom, etc) always return false. Read more
Source§

impl<T> TimeBound for TimeRangeBound<T>

Source§

type Inner = T

The inner, wrapped type, which is being protected by this TimeBound implementation
Source§

fn bounds(&self) -> TimeRange

Get the bounds, in the form of a TimeRangeBound<()> Read more
Source§

fn check_valid_at(&self, t: &SystemTime) -> Result<(), TimeValidityError>

Check whether this object is valid at a given time. Read more
Source§

fn dangerously_assume_timely(self) -> T

Return the underlying object without checking whether it’s valid.
Source§

fn if_valid_at(self, t: &SystemTime) -> Result<Self::Inner, TimeValidityError>

Unwrap this TimeBound object if it is valid at a given time.
Source§

fn if_valid_now(self) -> Result<Self::Inner, TimeValidityError>

Unwrap this TimeBound object if it is valid now.
Source§

fn unwrap_with(self, builder: &mut TimeRangeBoundBuilder) -> Self::Inner

Gain access to the Inner, handling the timeout with a TimeRangeBoundBuilder Read more
Source§

fn check_valid_at_opt( self, t: Option<SystemTime>, ) -> Result<Self::Inner, TimeValidityError>

👎Deprecated:

use check_valid_at

Unwrap this object if it is valid at the provided time t. If no time is provided, check the object at the current time. Read more

Auto Trait Implementations§

§

impl<T> Freeze for TimeRangeBound<T>
where T: Freeze,

§

impl<T> RefUnwindSafe for TimeRangeBound<T>
where T: RefUnwindSafe,

§

impl<T> Send for TimeRangeBound<T>
where T: Send,

§

impl<T> Sync for TimeRangeBound<T>
where T: Sync,

§

impl<T> Unpin for TimeRangeBound<T>
where T: Unpin,

§

impl<T> UnsafeUnpin for TimeRangeBound<T>
where T: UnsafeUnpin,

§

impl<T> UnwindSafe for TimeRangeBound<T>
where T: UnwindSafe,

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<'a, T, E> AsTaggedExplicit<'a, E> for T
where T: 'a,

Source§

fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self, E>

Source§

impl<'a, T, E> AsTaggedImplicit<'a, E> for T
where T: 'a,

Source§

fn implicit( self, class: Class, constructed: bool, tag: u32, ) -> TaggedParser<'a, Implicit, Self, E>

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

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
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, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

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