Skip to main content

PlayerController

Struct PlayerController 

Source
pub struct PlayerController {
Show 19 fields backend: Arc<Mutex<Box<dyn PlayerBackend>>>, queue: Arc<Mutex<QueueManager>>, jellyfin_client: Arc<Mutex<Option<JellyfinClient>>>, muted: bool, sleep_timer: Arc<Mutex<SleepTimerState>>, autoplay_settings: Arc<Mutex<AutoplaySettings>>, repository: Arc<Mutex<Option<Arc<dyn MediaRepository>>>>, event_emitter: Arc<Mutex<Option<Arc<dyn PlayerEventEmitter>>>>, countdown_cancel: Arc<Mutex<Option<Arc<Mutex<bool>>>>>, playback_reporter: Arc<Mutex<Option<PlaybackReporter>>>, reports: Arc<Mutex<Arc<dyn PlaybackReportSink>>>, position_throttler: Arc<EventThrottler>, end_reason: Arc<Mutex<Option<EndReason>>>, autoplay_episode_count: Arc<Mutex<u32>>, background_audio_base: Arc<Mutex<f64>>, background_audio_active: Arc<Mutex<bool>>, stream_resume: Arc<Mutex<ResumeTracker>>, html5_playing: Arc<Mutex<Option<bool>>>, reported_time: Arc<Mutex<ObservedTime>>,
}
Expand description

Central player controller that coordinates playback

Fields§

§backend: Arc<Mutex<Box<dyn PlayerBackend>>>§queue: Arc<Mutex<QueueManager>>§jellyfin_client: Arc<Mutex<Option<JellyfinClient>>>§muted: bool§sleep_timer: Arc<Mutex<SleepTimerState>>§autoplay_settings: Arc<Mutex<AutoplaySettings>>§repository: Arc<Mutex<Option<Arc<dyn MediaRepository>>>>§event_emitter: Arc<Mutex<Option<Arc<dyn PlayerEventEmitter>>>>§countdown_cancel: Arc<Mutex<Option<Arc<Mutex<bool>>>>>§playback_reporter: Arc<Mutex<Option<PlaybackReporter>>>§reports: Arc<Mutex<Arc<dyn PlaybackReportSink>>>§position_throttler: Arc<EventThrottler>§end_reason: Arc<Mutex<Option<EndReason>>>§autoplay_episode_count: Arc<Mutex<u32>>§background_audio_base: Arc<Mutex<f64>>§background_audio_active: Arc<Mutex<bool>>§stream_resume: Arc<Mutex<ResumeTracker>>§html5_playing: Arc<Mutex<Option<bool>>>§reported_time: Arc<Mutex<ObservedTime>>

Implementations§

Source§

impl PlayerController

Source

pub fn new( backend: Box<dyn PlayerBackend>, playback_reporter: Arc<TokioMutex<Option<PlaybackReporter>>>, position_throttler: Arc<EventThrottler>, ) -> Self

Source

pub fn set_jellyfin_client(&self, client: Option<JellyfinClient>)

Configure the Jellyfin API client for automatic playback reporting

Source

pub fn jellyfin_client(&self) -> Arc<Mutex<Option<JellyfinClient>>>

Get a reference to the Jellyfin client (for remote session control)

Source

pub fn set_repository(&self, repo: Arc<dyn MediaRepository>)

Configure the media repository used for next-episode lookups.

The Android ExoPlayer ended-callback calls on_playback_ended with no repository handle (unlike the Linux HTML5 path, which passes one per call), so the controller needs a repository of its own or episode autoplay silently decides Stop.

Source

pub async fn set_playback_reporter(&self, reporter: Option<PlaybackReporter>)

Configure the playback reporter for dual sync (local DB + server). Called from player_configure_jellyfin on login/restore/reauth.

Source

pub fn playback_reporter(&self) -> Arc<TokioMutex<Option<PlaybackReporter>>>

Get a reference to the playback reporter (for backend position updates) Will be used when position update hooks are added to backends

Source

pub fn position_throttler(&self) -> Arc<EventThrottler>

Get a reference to the position throttler (for backend position updates) Will be used when position update hooks are added to backends

Source

fn set_end_reason(&self, reason: EndReason)

Set the end reason for the next playback end event

Source

fn take_end_reason(&self) -> Option<EndReason>

Get and clear the current end reason

Source

fn peek_end_reason(&self) -> Option<EndReason>

Read the end reason WITHOUT consuming it.

take_end_reason has an owner: on Android the JNI ended-callback consumes the NewTrackLoaded every load sets, and the frontend’s echoed call is the one that sees None and decides. The truncated-stream check runs in both calls and must not disturb that hand-off, so it peeks.

Source

fn note_sleep_timer_stop(end_reason: &Arc<Mutex<Option<EndReason>>>)

Record that playback is being stopped by an expiring sleep timer.

Stopping the backend makes it fire its ended callback (ExoPlayer does on Android), which lands in on_playback_ended. Without an end reason that reads as a natural finish and autoplay advances — defeating the timer. UserStop is the honest label: the stop was user-initiated, just via the timer they set rather than the stop button.

Takes the shared slot rather than &self so the sleep-timer thread — which owns clones, not the controller — records it the same way.

TRACES: UR-023, UR-026 | DR-029

Source

fn increment_autoplay_count(&self) -> bool

Increment autoplay episode counter. Returns true if limit is reached.

Source

fn reset_autoplay_count(&self)

Reset autoplay episode counter (called on manual play actions)

Source

pub fn play_item(&self, item: MediaItem) -> Result<(), PlayerError>

Load and play a single item (also sets the queue to contain only this item)

Source

pub fn set_current_item(&self, item: MediaItem) -> Result<(), PlayerError>

Set the current queue item without loading it into the playback backend.

Used on platforms where video is rendered outside the native backend (Linux WebKitGTK HTML5

Source

pub fn load_and_play(&self, item: &MediaItem) -> Result<(), PlayerError>

Load and play an item without modifying the queue Use this when the queue is already set up and you just want to play a specific item from it

Source

pub fn play_queue( &self, items: Vec<MediaItem>, start_index: usize, ) -> Result<(), PlayerError>

Set the queue and start playing from the specified index

Source

pub fn play_queue_from( &self, items: Vec<MediaItem>, start_index: usize, start_position: Option<f64>, ) -> Result<(), PlayerError>

Set the queue and start playing from the specified index, optionally resuming the starting track at start_position (seconds).

The seek happens immediately after load so the backend never audibly starts at 0 and there’s no race against a fixed delay. Used when taking over playback from a remote session.

Source

pub fn set_queue( &self, items: Vec<MediaItem>, start_index: usize, ) -> Result<(), PlayerError>

Replace the queue without starting local playback.

Used when we’re controlling a remote session: the tracks play on the remote device, but we keep the local queue in sync so the UI reflects what’s playing and a later transfer-to-local has the queue to resume.

Source

pub fn is_html5_active(&self) -> bool

True while webview-rendered media (HTML5 <video>/<audio>) is the real player, so transport must be routed to it rather than the native backend.

TRACES: UR-005 | DR-097

Source

pub fn html5_is_playing(&self) -> bool

Whether the webview element last reported itself as playing. Meaningless unless Self::is_html5_active is true.

TRACES: UR-005 | DR-097

Source

fn emit_html5_control(&self, action: &str)

Send a transport intent to the webview element that is rendering media.

Source

pub fn play(&self) -> Result<(), PlayerError>

Play/resume playback

Source

pub fn pause(&self) -> Result<(), PlayerError>

Pause playback

Source

pub fn toggle_playback(&self) -> Result<(), PlayerError>

Toggle play/pause.

The decision is made HERE, from authoritative state — the reported webview state for HTML5-rendered media, or the native backend’s state otherwise. The frontend must never decide this from the DOM (see DR-097).

TRACES: UR-005 | DR-097

Source

pub fn stop(&self) -> Result<(), PlayerError>

Stop playback

Source

fn report_stopped_at(&self, jellyfin_id: String, position: f64)

Tell Jellyfin playback stopped at position, unless that position is zero.

Jellyfin stores the reported position as the resume point, so a zero is not a harmless no-op — it is an instruction to forget where the viewer was. And it is never information: nobody watched zero seconds of anything, so every zero this app ever sent came from asking a player that was not rendering the media (webview video, or a handoff whose first tick had not landed). On a device trace, 14 of 14 stop reports in 35 minutes were zeroes, one of them 40s after the frontend had correctly reported 15:22 for the same episode.

TRACES: UR-025, UR-005 | DR-179 | UT-178

Source

pub fn next(&self) -> Result<(), PlayerError>

Skip to next track

Note: load_and_play sets EndReason::NewTrackLoaded to prevent autoplay from triggering when the current track’s EndFile event fires

Source

pub fn previous(&self) -> Result<(), PlayerError>

Skip to previous track

Note: load_and_play sets EndReason::NewTrackLoaded to prevent autoplay from triggering when the current track’s EndFile event fires

Source

pub fn seek(&self, position: f64) -> Result<(), PlayerError>

Seek to a position in seconds, on the player’s own timeline.

During a background-audio handoff that timeline is relative to the handoff point, so this is not the call a lockscreen scrub or a UI seek wants — use seek_absolute, which speaks the episode’s timeline and is what every caller outside the player itself means.

Source

pub async fn seek_absolute(&self, position: f64) -> Result<(), String>

Seek to an absolute position on the item’s own timeline.

This is the boundary every outside seek comes through — the UI, the lockscreen scrubber, a headset gesture — because all of them are looking at the whole episode, not at whatever fragment of it the player happens to be streaming.

Outside a background-audio handoff the two timelines are the same and this is an ordinary seek. Inside one they differ by the handoff base, and the stream cannot be seeked at all: /Audio/{id}/universal is a chunked transcode with no length, so ExoPlayer either refuses or clamps — and a clamped seek lands at stream zero, which is the handoff point. That is the “jumps back to where I locked the screen” symptom. Honouring the seek means re-opening the URL at the new position, which is exactly what the truncation recovery already does, so it shares resume_stream_at.

TRACES: UR-040, UR-005 | DR-159 | UT-155

Source

pub fn set_volume(&self, volume: f32) -> Result<(), PlayerError>

Set volume (0.0 - 1.0)

Source

pub fn set_audio_track(&self, stream_index: i32) -> Result<(), PlayerError>

Set the active audio track by stream index

Source

pub fn set_subtitle_track( &self, stream_index: Option<i32>, ) -> Result<(), PlayerError>

Set the active subtitle track by stream index (None to disable subtitles)

Source

pub fn state(&self) -> PlayerState

Get current state

Source

pub fn position(&self) -> f64

Get current position

Source

pub fn absolute_position(&self) -> f64

The position on the item’s own timeline, whatever is rendering it.

This is what every outbound position must be taken from — the resume point sent to Jellyfin, the point the video reloads at when a handoff ends, the truncation comparison. position() alone answers for exactly one of the three ways this app plays media, and reads 0 for the other two:

  • Webview <video>/<audio>: nothing is loaded into the native backend, so its position is a permanent 0. The element’s own reports are the only reading there is.
  • Background-audio handoff: the audio-only stream’s zero is the handoff point, and the base is added at the native tick boundary (DR-159) — so before the first tick lands, nothing has applied it. Flooring at the base is exact rather than approximate: the stream cannot physically be behind its own starting point.
  • Native playback: the backend is authoritative and both other terms are zero, so the max is its own value.

Returning to the foreground during that pre-first-tick window is what restarted an episode from 0:00 and wiped its server-side resume point.

TRACES: UR-040, UR-005, UR-025 | DR-178 | UT-176, UT-177

Source

pub fn observed_duration(&self) -> Option<f64>

The duration last reported by webview-rendered media, if any.

TRACES: UR-005 | DR-178 | UT-177

Source

fn clear_reported_time(&self)

Forget what webview-rendered media reported.

Called wherever that element stops being the player — it was torn down, a handoff took over, or a different item is loading. A stale position outliving its element would be reported against whatever plays next.

TRACES: UR-005 | DR-178 | UT-177

Source

pub fn set_report_sink(&self, sink: Arc<dyn PlaybackReportSink>)

Replace the sink playback reports go to. Tests capture; production wires the PlaybackReporter at construction and never swaps it.

TRACES: UR-025 | DR-179

Source

fn report(&self, operation: PlaybackOperation)

Send a playback report. Fire-and-forget by contract, so callers can do this while holding nothing and waiting for nothing.

TRACES: UR-025 | DR-179

Source

fn current_jellyfin_id(&self) -> Option<String>

The Jellyfin id of whatever is currently queued, if it has one.

Source

pub fn duration(&self) -> Option<f64>

Get duration.

Falls back to what webview-rendered media reported for the same reason absolute_position does: on that path nothing is loaded into the native backend, so its duration is None and the element’s report is the only one there is.

TRACES: UR-005 | DR-178

Source

pub fn queue(&self) -> Arc<Mutex<QueueManager>>

Get queue reference

Source

pub fn current_is_audio_episode(&self) -> bool

True when the current item is a TV episode being played in audio-only (background) mode — i.e. an item_type == "Episode" item loaded as MediaType::Audio. Used to decide whether the backend must drive the next-episode advance itself (the frontend is suspended in the background).

Only called from the Android autoplay dispatch (#[cfg(android)]), but compiled and unit-tested on the host, hence allow(dead_code) off-Android.

Source

pub fn clear_queue(&self)

Clear the queue entirely (used when playback genuinely stops, e.g. the sleep timer fires or the queue ends with repeat off). Pair with emit_queue_changed so the frontend hides the mini player.

Source

pub fn toggle_shuffle(&self)

Toggle shuffle

Source

pub fn cycle_repeat(&self)

Cycle repeat mode

Source

pub fn is_shuffle(&self) -> bool

Check if shuffle is enabled

Source

pub fn repeat_mode(&self) -> RepeatMode

Get repeat mode

Source

pub fn volume(&self) -> f32

Get current volume (0.0 - 1.0)

Source

pub fn muted(&self) -> bool

Check if muted

Source

pub fn set_audio_settings( &mut self, settings: &AudioSettings, ) -> Result<(), PlayerError>

Set audio settings (crossfade, gapless, normalization)

Source

pub fn audio_settings(&self) -> AudioSettings

Get current audio settings

Source

pub fn set_event_emitter(&self, emitter: Arc<dyn PlayerEventEmitter>)

Set the event emitter for notifications

Source

pub fn event_emitter(&self) -> Option<Arc<dyn PlayerEventEmitter>>

Get the event emitter

Source

pub fn sleep_timer_state(&self) -> SleepTimerState

Get sleep timer state

Source

pub fn set_sleep_timer(&self, mode: SleepTimerMode)

Set sleep timer mode (in-memory only, not persisted)

Source

pub fn cancel_sleep_timer(&self)

Cancel sleep timer

Source

fn start_timer_thread(&self)

Start background timer thread for sleep timer countdown updates

Source

fn emit_sleep_timer_changed(&self)

Emit sleep timer changed event to frontend

Source

pub fn emit_queue_changed(&self)

Emit queue changed event to frontend

Source

pub fn report_html5_state(&self, state: String, media_id: Option<String>)

Report an HTML5

Re-emits a StateChanged event identical to what MpvBackend/ExoPlayer would emit, so playerEvents.ts needs no HTML5-specific branch.

Source

pub fn report_html5_position(&self, position: f64, duration: f64)

Report an HTML5

Re-emits a PositionUpdate event mirroring the native backends’ periodic position updates (the adapter is expected to throttle to ~250ms like MPV).

Source

fn report_progress_throttled(&self, position: f64)

Send a throttled progress report to Jellyfin.

Progress is what makes a position survive anything other than a clean exit — a crash, a swipe-away, a battery death — and lets another device resume mid-episode. Webview-rendered media reported none: the frontend service writes progress to the local DB only, and Rust had no position for it to report. A device trace covering 35 minutes of playback hit /Sessions/Playing/Progress exactly zero times.

The throttler is the one the controller already owned for this purpose (30s per item), so ticks arriving four times a second cost one request per half-minute.

TRACES: UR-005, UR-025 | DR-179 | UT-180

Source

pub fn report_html5_media_loaded(&self, duration: f64)

Report that the HTML5

Source

pub fn autoplay_settings(&self) -> AutoplaySettings

Get autoplay settings

Source

pub fn set_autoplay_settings(&self, settings: AutoplaySettings)

Set autoplay settings (in-memory only, persistence handled by command layer)

Source

pub fn cancel_autoplay_countdown(&self)

Cancel active autoplay countdown

Source

pub async fn on_playback_ended(&self) -> Result<AutoplayDecision, String>

Handle playback ended event - decides what to do next

Only triggers autoplay if the track finished naturally (EndReason::Finished or None). If EndReason is NewTrackLoaded, UserStop, UserSkip, or Error, returns Stop without autoplay.

Source

fn report_completion(&self, item: &MediaItem)

Report an item that just finished as stopped at its runtime, so Jellyfin marks it played.

Jellyfin decides “watched” from the PlaybackStopped report and its position — no report, no completion, however much of the episode was actually heard. In the foreground the frontend sends one when the <video> ends. In background audio-only mode there is nobody: the webview is suspended and its element was torn down at the handoff, while the backend drove the advance to the next episode and said nothing about the one that ended. An episode listened to end-to-end on the lockscreen therefore never counted, and (before DR-179) was often reset to 0 by the stop report that followed.

Scoped to the audio-only handoff — the case the frontend provably cannot report — so foreground playback keeps its single existing report rather than gaining a second one. Music tracks ending natively remain unreported; that is the same gap through a different door and wants its own change.

TRACES: UR-040, UR-025 | DR-179 | UT-179

Source

pub fn set_background_audio_base(&self, seconds: f64)

Record the base offset of a background-audio handoff (the position the video was handed off at, which is the audio stream’s zero).

TRACES: UR-040 | DR-052

Source

pub fn enter_background_audio(&self, position: f64)

Enter a background-audio handoff at position (the video’s position, and therefore the audio stream’s zero).

Hands transport authority to the native audio player: the webview <video> is about to be torn down, so its last reports — including the pause the teardown itself fires — must not keep it looking like the player. Without this the lockscreen pause emitted a ControlCommand at a dead element and the audio played straight through it.

TRACES: UR-040, UR-005 | DR-052, DR-097

Source

pub fn exit_background_audio(&self) -> f64

Leave a background-audio handoff, returning the base offset to add to the native player’s relative position.

The webview <video> becomes the player again once it reloads, so its reports are honoured from here on.

TRACES: UR-040, UR-005 | DR-052, DR-097

Source

pub fn is_background_audio_active(&self) -> bool

True while the native audio player owns playback via a background-audio handoff.

TRACES: UR-040 | DR-052

Source

pub fn take_background_audio_base(&self) -> f64

Read and clear the background-audio base offset.

TRACES: UR-040 | DR-052

Source

pub async fn auto_advance_to_next_episode( &self, next_episode: MediaItem, countdown_seconds: u32, )

Perform the auto-advance for a ShowNextEpisodePopup decision.

Single place both end-of-playback dispatchers agree on: the Android JNI callback (nativeOnPlaybackEnded) and the frontend-invoked command (player_on_playback_ended). They used to each carry their own copy of this branch, and the command’s copy was missing the background-audio case entirely — so an audio-only episode ending while backgrounded only ever started a countdown that nothing could act on.

TRACES: UR-040, UR-023 | DR-052

Source

fn is_audio_only_video(item: &MediaItem) -> bool

A video item played through the native audio path — i.e. the background audio-only handoff, the only place a length-less progressive transcode is used. Jellyfin’s item-type taxonomy stays in Rust (CLAUDE.md).

Source

fn claim_stream_resume(&self) -> Option<(f64, u32)>

Claim a resume attempt for the current stream, returning the absolute position to re-open at and the 1-based attempt number. None when the current item cannot meaningfully be re-requested, or when retrying at this position has stopped helping.

Only Remote sources qualify. A downloaded file cannot fail because of the network, so re-opening one would paper over a real read error; a DirectUrl is a plugin’s endpoint with no Jellyfin item behind it.

The player’s position is relative to the stream’s own zero (the handoff URL’s StartTimeTicks), so the base is added back to get an absolute one. It is zero for everything else, where positions are already absolute.

TRACES: UR-040, UR-004 | DR-129 | UT-117

Source

fn truncated_stream_resume_position(&self) -> Option<f64>

The absolute position to re-open the current stream at, when the reported end was really a dropped connection — None when the end looks genuine, when this is not an audio-only handoff, or when retrying has stopped helping.

TRACES: UR-040 | DR-129 | UT-117

Source

pub fn recoverable_error_resume(&self) -> Option<(f64, u64)>

Where to re-open the current stream after a recoverable playback error, plus how many seconds to wait first.

The media was decoding fine a moment ago, so a mid-playback failure on a server stream is the network — and stopping the player (the previous behaviour, via the frontend’s error handler) turns a hiccup into “playback just died”. Applies to every streamed item, not only the audio-only handoff: music and video reach here instead of the truncation path because their streams declare a length, so a cut connection surfaces as an error rather than a phantom end.

The wait grows with the attempt number so a short outage has time to clear, and the shared budget stops the retries when it doesn’t.

Called from the Android error callback, which decides in-process, and from player_recover_stream, which is how the same decision reaches the backends whose event thread has no controller to call — MPV is built before the controller exists, so on Linux the error is emitted, echoed by the frontend, and decided here.

TRACES: UR-040, UR-004 | DR-129, DR-130 | UT-117

Source

pub async fn resume_stream_at(&self, position: f64) -> Result<(), String>

Re-open the current stream at position after the network cut it short.

Single place every dispatcher agrees on, for the same reason auto_advance_to_next_episode is: the Android JNI callbacks and the frontend-invoked command must not disagree about what a failed stream means. None of them emits PlaybackEnded for this, so nothing downstream clears the queue or tears the session down — from the outside this is a buffering hiccup, which is what it actually was.

Reloads the item in place rather than through play_item, which replaces the queue with a single item: recovering a track that way would throw away the rest of the album, turning a network blip into lost state.

Two shapes of stream, two ways back to position:

  • The audio-only handoff’s /Audio/{id}/universal transcode is chunked with no length, so it cannot be seeked. Its URL is rewritten to start at the position instead — edited, not rebuilt from the repository, since it already carries the user’s audio track and media source and recovering from a network failure must not itself need a network round-trip.
  • Everything else (a static file with byte ranges, an HLS playlist) declares its whole timeline, so re-preparing the URL it already has and seeking lands in the right place — and leaves any transcode session behind it alone.

TRACES: UR-040, UR-004 | DR-129 | UT-117

Source

pub async fn advance_to_next_episode_audio_only( &self, next_episode_id: &str, ) -> Result<(), String>

Advance to the next episode while playing audio-only in the background.

The normal autoplay-next path navigates the frontend to /player/<id>, which is unavailable when the app is backgrounded and the WebView is suspended. This drives the advance entirely in the backend: build the next episode’s audio-only stream URL and load it into the native audio player, so playback continues without any frontend involvement (UR-040).

next_episode_id is the Jellyfin item ID of the episode to play next.

Reached through auto_advance_to_next_episode, which gates it on current_is_audio_episode() — only ever true after a background-audio handoff (Android), but compiled and unit-tested on every platform. TRACES: UR-040, UR-023 | DR-052

Source

pub async fn on_video_playback_ended( &self, item_id: &str, repo: Arc<dyn MediaRepository>, ) -> Result<AutoplayDecision, String>

Handle video playback ended from HTML5 video element.

HTML5 video plays independently of the Rust backend, so the backend queue has no knowledge of the video item. This method bypasses the queue lookup and end_reason check, using the provided Jellyfin item ID to look up the item and check for next episodes.

Source

async fn is_episode_item(&self, item: &MediaItem) -> bool

Check if a media item is an episode (has Jellyfin ID to query).

An explicit item_type == "Episode" wins so that a TV episode handed off to the audio path for background playback (UR-040) is still recognised as an episode — otherwise autoplay would fall through to the queue-based audio path, find nothing next, and stop at the episode boundary. When the type is unknown we fall back to the historical heuristic (video == episode).

Source

async fn fetch_next_episode_for_item( &self, item_id: &str, repo: &Arc<dyn MediaRepository>, ) -> Result<Option<(MediaItem, MediaItem)>, String>

Fetch next episode for a series by looking up the season’s episodes sorted by index number and picking the one after the current episode.

This is deterministic and doesn’t depend on Jellyfin’s “Next Up” API (which relies on watch history that may not be updated yet due to the async nature of playback progress reporting).

Source

pub fn start_autoplay_countdown( &self, _next_item: MediaItem, countdown_seconds: u32, )

Start autoplay countdown thread

Trait Implementations§

Source§

impl Default for PlayerController

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

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

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

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

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

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.

§

impl<T> NoneValue for T
where T: Default,

§

type NoneType = T

§

fn null_value() -> T

The none-equivalent value.
§

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

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: 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
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: 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> Same for T

Source§

type Output = T

Should always be Self
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.
§

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

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

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
§

fn with_current_subscriber(self) -> WithDispatch<Self>

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