Skip to main content

mesh_llm_api_server/
node.rs

1use crate::events::EventListener;
2use crate::{
3    ChatRequest, ClientBuilder, InviteToken, MeshApiError, MeshClient, Model, OwnerKeypair,
4    RequestId, ResponsesRequest, Status,
5};
6pub use mesh_llm_node::models::{CapabilityLevel, ModelCapabilities, ModelKind, ModelSource};
7use mesh_llm_node::serving::ServingController;
8use std::path::PathBuf;
9use std::sync::Arc;
10use std::time::Duration;
11use tokio::sync::Mutex;
12
13#[derive(Clone, Debug, Default)]
14pub enum DevicePolicy {
15    #[default]
16    Auto,
17    Cpu,
18    Gpu {
19        device_ids: Vec<String>,
20    },
21}
22
23#[derive(Clone, Debug, Default)]
24pub struct DownloadOptions;
25
26#[derive(Clone, Debug, Default)]
27pub struct DeleteModelOptions {
28    pub force: bool,
29}
30
31#[derive(Clone, Debug, Default)]
32pub struct LoadModelOptions {
33    pub device_policy: DevicePolicy,
34    pub profile: String,
35}
36
37#[derive(Clone, Debug)]
38pub struct UnloadModelOptions {
39    pub drain_timeout: Duration,
40    pub force: bool,
41}
42
43impl Default for UnloadModelOptions {
44    fn default() -> Self {
45        Self {
46            drain_timeout: Duration::from_secs(30),
47            force: false,
48        }
49    }
50}
51
52#[derive(Clone, Debug)]
53pub enum UnloadTarget {
54    Model(String),
55    Instance(String),
56}
57
58#[derive(Clone, Debug, Default)]
59pub struct CleanupPolicy {
60    pub remove_all: bool,
61}
62
63#[derive(Clone, Debug, Default)]
64pub struct PrunePolicy {
65    pub remove_all: bool,
66}
67
68#[derive(Clone, Debug)]
69pub struct ModelSearchQuery {
70    pub query: String,
71    pub limit: Option<usize>,
72}
73
74#[derive(Clone, Debug)]
75pub struct ModelSummary {
76    pub id: String,
77    pub name: String,
78    pub size_label: Option<String>,
79    pub description: Option<String>,
80    pub capabilities: ModelCapabilities,
81}
82
83#[derive(Clone, Debug)]
84pub struct ModelDetails {
85    pub id: String,
86    pub name: String,
87    pub source: ModelSource,
88    pub kind: ModelKind,
89    pub model_ref: String,
90    pub download_ref: String,
91    pub path: Option<PathBuf>,
92    pub size_bytes: Option<u64>,
93    pub size_label: Option<String>,
94    pub description: Option<String>,
95    pub draft: Option<String>,
96    pub installed: bool,
97    pub capabilities: ModelCapabilities,
98}
99
100#[derive(Clone, Debug)]
101pub struct InstalledModel {
102    pub model_ref: String,
103    pub path: PathBuf,
104    pub size_bytes: Option<u64>,
105    pub capabilities: ModelCapabilities,
106}
107
108#[derive(Clone, Debug, Default)]
109pub struct ModelCacheStatus {
110    pub cache_dir: Option<PathBuf>,
111}
112
113#[derive(Clone, Debug)]
114pub struct DownloadId(pub String);
115
116#[derive(Clone, Debug)]
117pub struct DownloadedModel {
118    pub model_ref: String,
119    pub paths: Vec<PathBuf>,
120    pub primary_path: Option<PathBuf>,
121    pub details: Option<ModelDetails>,
122}
123
124#[derive(Clone, Debug, Default)]
125pub struct DeleteModelResult {
126    pub deleted_paths: Vec<PathBuf>,
127    pub reclaimed_bytes: u64,
128}
129
130#[derive(Clone, Debug, Default)]
131pub struct CleanupResult {
132    pub deleted_paths: Vec<PathBuf>,
133    pub reclaimed_bytes: u64,
134    pub skipped_paths: Vec<PathBuf>,
135}
136
137#[derive(Clone, Debug, Default)]
138pub struct PruneResult {
139    pub deleted_paths: Vec<PathBuf>,
140    pub reclaimed_bytes: u64,
141}
142
143#[derive(Clone, Debug)]
144pub struct ServedModel {
145    pub model_ref: String,
146    pub profile: String,
147    pub model_id: String,
148    pub instance_id: Option<String>,
149    pub state: ServingModelState,
150    pub backend: Option<String>,
151    pub capabilities: ModelCapabilities,
152    pub context_length: Option<u32>,
153    pub error: Option<String>,
154}
155
156#[derive(Clone, Debug, Default)]
157pub enum ServingModelState {
158    Loading,
159    #[default]
160    Ready,
161    Failed,
162    Unloading,
163    Stopped,
164    Unknown(String),
165}
166
167#[derive(Clone, Debug, Default)]
168pub struct ServingStatus {
169    pub enabled: bool,
170    pub models: Vec<ServedModel>,
171}
172
173#[derive(Clone, Debug)]
174pub struct MeshNodeConfig {
175    pub owner_keypair: OwnerKeypair,
176    pub invite_token: InviteToken,
177    pub user_agent: String,
178    pub connect_timeout: Duration,
179    pub cache_dir: Option<PathBuf>,
180    pub runtime_dir: Option<PathBuf>,
181    pub serving_enabled: bool,
182    pub device_policy: DevicePolicy,
183}
184
185pub struct MeshNodeBuilder {
186    owner_keypair: Option<OwnerKeypair>,
187    invite_token: Option<InviteToken>,
188    user_agent: String,
189    connect_timeout: Duration,
190    cache_dir: Option<PathBuf>,
191    runtime_dir: Option<PathBuf>,
192    serving_enabled: bool,
193    device_policy: DevicePolicy,
194    serving_controller: Option<Arc<dyn ServingController>>,
195}
196
197impl MeshNodeBuilder {
198    pub fn identity(mut self, identity: OwnerKeypair) -> Self {
199        self.owner_keypair = Some(identity);
200        self
201    }
202
203    pub fn join(mut self, token: InviteToken) -> Self {
204        self.invite_token = Some(token);
205        self
206    }
207
208    pub fn user_agent(mut self, user_agent: impl Into<String>) -> Self {
209        self.user_agent = user_agent.into();
210        self
211    }
212
213    pub fn connect_timeout(mut self, timeout: Duration) -> Self {
214        self.connect_timeout = timeout;
215        self
216    }
217
218    pub fn cache_dir(mut self, path: impl Into<PathBuf>) -> Self {
219        self.cache_dir = Some(path.into());
220        self
221    }
222
223    pub fn runtime_dir(mut self, path: impl Into<PathBuf>) -> Self {
224        self.runtime_dir = Some(path.into());
225        self
226    }
227
228    pub fn serving_enabled(mut self, enabled: bool) -> Self {
229        self.serving_enabled = enabled;
230        self
231    }
232
233    pub fn device_policy(mut self, policy: DevicePolicy) -> Self {
234        self.device_policy = policy;
235        self
236    }
237
238    pub fn serving_controller(mut self, controller: Arc<dyn ServingController>) -> Self {
239        self.serving_enabled = true;
240        self.serving_controller = Some(controller);
241        self
242    }
243
244    pub fn build(self) -> Result<MeshNode, MeshApiError> {
245        let owner_keypair = self.owner_keypair.ok_or(MeshApiError::InvalidConfig {
246            message: "MeshNode identity is required",
247        })?;
248        let invite_token = self.invite_token.ok_or(MeshApiError::InvalidConfig {
249            message: "MeshNode join token is required",
250        })?;
251        let client = ClientBuilder::new(owner_keypair.clone(), invite_token.clone())
252            .with_user_agent(self.user_agent.clone())
253            .with_connect_timeout(self.connect_timeout)
254            .build()?;
255        let config = MeshNodeConfig {
256            owner_keypair,
257            invite_token,
258            user_agent: self.user_agent,
259            connect_timeout: self.connect_timeout,
260            cache_dir: self.cache_dir,
261            runtime_dir: self.runtime_dir,
262            serving_enabled: self.serving_enabled,
263            device_policy: self.device_policy,
264        };
265
266        Ok(MeshNode {
267            inner: Arc::new(MeshNodeInner {
268                client: Mutex::new(client),
269                config,
270                serving_controller: self.serving_controller,
271            }),
272        })
273    }
274}
275
276impl Default for MeshNodeBuilder {
277    fn default() -> Self {
278        Self {
279            owner_keypair: None,
280            invite_token: None,
281            user_agent: format!("mesh-llm-api-server/{}", env!("CARGO_PKG_VERSION")),
282            connect_timeout: Duration::from_secs(30),
283            cache_dir: None,
284            runtime_dir: None,
285            serving_enabled: false,
286            device_policy: DevicePolicy::Auto,
287            serving_controller: None,
288        }
289    }
290}
291
292struct MeshNodeInner {
293    client: Mutex<MeshClient>,
294    config: MeshNodeConfig,
295    serving_controller: Option<Arc<dyn ServingController>>,
296}
297
298#[derive(Clone)]
299pub struct MeshNode {
300    inner: Arc<MeshNodeInner>,
301}
302
303impl MeshNode {
304    pub fn builder() -> MeshNodeBuilder {
305        MeshNodeBuilder::default()
306    }
307
308    pub async fn start(&self) -> Result<(), MeshApiError> {
309        self.inner.client.lock().await.join().await
310    }
311
312    pub async fn stop(&self) -> Result<(), MeshApiError> {
313        self.inner.client.lock().await.disconnect().await;
314        Ok(())
315    }
316
317    pub async fn reconnect(&self) -> Result<(), MeshApiError> {
318        self.inner.client.lock().await.reconnect().await
319    }
320
321    pub fn inference(&self) -> MeshInference {
322        MeshInference {
323            inner: self.inner.clone(),
324        }
325    }
326
327    pub fn models(&self) -> MeshModels {
328        MeshModels {
329            inner: self.inner.clone(),
330        }
331    }
332
333    pub fn serving(&self) -> MeshServing {
334        MeshServing {
335            inner: self.inner.clone(),
336        }
337    }
338
339    pub fn status(&self) -> MeshStatusApi {
340        MeshStatusApi {
341            inner: self.inner.clone(),
342        }
343    }
344
345    pub fn events(&self) -> MeshEvents {
346        MeshEvents {
347            inner: self.inner.clone(),
348        }
349    }
350}
351
352#[derive(Clone)]
353pub struct MeshInference {
354    inner: Arc<MeshNodeInner>,
355}
356
357impl MeshInference {
358    pub async fn list_models(&self) -> Result<Vec<Model>, MeshApiError> {
359        self.inner.client.lock().await.list_models().await
360    }
361
362    pub async fn chat(
363        &self,
364        request: ChatRequest,
365        listener: Arc<dyn EventListener>,
366    ) -> Result<RequestId, MeshApiError> {
367        Ok(self.inner.client.lock().await.chat(request, listener))
368    }
369
370    pub async fn responses(
371        &self,
372        request: ResponsesRequest,
373        listener: Arc<dyn EventListener>,
374    ) -> Result<RequestId, MeshApiError> {
375        Ok(self.inner.client.lock().await.responses(request, listener))
376    }
377
378    pub async fn cancel(&self, request_id: RequestId) -> Result<(), MeshApiError> {
379        self.inner.client.lock().await.cancel(request_id);
380        Ok(())
381    }
382}
383
384#[derive(Clone)]
385pub struct MeshModels {
386    inner: Arc<MeshNodeInner>,
387}
388
389impl MeshModels {
390    pub async fn recommended(&self) -> Result<Vec<ModelSummary>, MeshApiError> {
391        Ok(mesh_llm_node::models::recommended_models()
392            .into_iter()
393            .map(ModelSummary::from)
394            .collect())
395    }
396
397    pub async fn search(&self, query: ModelSearchQuery) -> Result<Vec<ModelSummary>, MeshApiError> {
398        Ok(mesh_llm_node::models::search_models(
399            mesh_llm_node::models::ModelSearchQuery {
400                query: query.query,
401                limit: query.limit.unwrap_or(20),
402            },
403            self.model_cache_dir(),
404        )
405        .into_iter()
406        .map(ModelSummary::from)
407        .collect())
408    }
409
410    pub async fn show(&self, model_ref: impl AsRef<str>) -> Result<ModelDetails, MeshApiError> {
411        let cache_dir = self.model_cache_dir();
412        mesh_llm_node::models::show_model(model_ref, cache_dir)
413            .await
414            .map(ModelDetails::from)
415            .map_err(model_management_error)
416    }
417
418    pub async fn installed(&self) -> Result<Vec<InstalledModel>, MeshApiError> {
419        let cache_dir = self.model_cache_dir();
420        Ok(mesh_llm_node::models::scan_installed_models(cache_dir)
421            .into_iter()
422            .map(InstalledModel::from)
423            .collect())
424    }
425
426    pub async fn cache_status(&self) -> Result<ModelCacheStatus, MeshApiError> {
427        Ok(ModelCacheStatus {
428            cache_dir: self.inner.config.cache_dir.clone(),
429        })
430    }
431
432    pub async fn download(
433        &self,
434        model_ref: impl AsRef<str>,
435        _options: DownloadOptions,
436    ) -> Result<DownloadedModel, MeshApiError> {
437        let cache_dir = self.model_cache_dir();
438        mesh_llm_node::models::download_model(model_ref, cache_dir)
439            .await
440            .map(DownloadedModel::from)
441            .map_err(model_management_error)
442    }
443
444    pub async fn cancel_download(&self, _download_id: DownloadId) -> Result<(), MeshApiError> {
445        Err(MeshApiError::Unsupported {
446            feature: "download cancellation",
447        })
448    }
449
450    pub async fn delete(
451        &self,
452        model_ref: impl AsRef<str>,
453        options: DeleteModelOptions,
454    ) -> Result<DeleteModelResult, MeshApiError> {
455        mesh_llm_node::models::delete_model(
456            model_ref,
457            self.model_cache_dir(),
458            mesh_llm_node::models::DeleteModelOptions {
459                force: options.force,
460            },
461        )
462        .await
463        .map(DeleteModelResult::from)
464        .map_err(model_management_error)
465    }
466
467    pub async fn cleanup(&self, policy: CleanupPolicy) -> Result<CleanupResult, MeshApiError> {
468        mesh_llm_node::models::cleanup_models(
469            self.model_cache_dir(),
470            mesh_llm_node::models::CleanupPolicy {
471                remove_all: policy.remove_all,
472            },
473        )
474        .map(CleanupResult::from)
475        .map_err(model_management_error)
476    }
477
478    pub async fn prune_derived_cache(
479        &self,
480        policy: PrunePolicy,
481    ) -> Result<PruneResult, MeshApiError> {
482        let Some(runtime_dir) = self.inner.config.runtime_dir.clone() else {
483            return Ok(PruneResult::default());
484        };
485        mesh_llm_node::models::prune_derived_cache(
486            runtime_dir,
487            mesh_llm_node::models::PrunePolicy {
488                remove_all: policy.remove_all,
489            },
490        )
491        .map(PruneResult::from)
492        .map_err(model_management_error)
493    }
494}
495
496impl MeshModels {
497    fn model_cache_dir(&self) -> PathBuf {
498        self.inner
499            .config
500            .cache_dir
501            .clone()
502            .unwrap_or_else(mesh_llm_node::models::default_huggingface_cache_dir)
503    }
504}
505
506fn model_management_error(error: anyhow::Error) -> MeshApiError {
507    MeshApiError::ModelManagement {
508        message: error.to_string(),
509    }
510}
511
512impl From<mesh_llm_node::models::ModelSummary> for ModelSummary {
513    fn from(value: mesh_llm_node::models::ModelSummary) -> Self {
514        Self {
515            id: value.id,
516            name: value.name,
517            size_label: value.size_label,
518            description: value.description,
519            capabilities: value.capabilities,
520        }
521    }
522}
523
524impl From<mesh_llm_node::models::ModelDetails> for ModelDetails {
525    fn from(value: mesh_llm_node::models::ModelDetails) -> Self {
526        Self {
527            id: value.id,
528            name: value.name,
529            source: value.source,
530            kind: value.kind,
531            model_ref: value.model_ref,
532            download_ref: value.download_ref,
533            path: value.path,
534            size_bytes: value.size_bytes,
535            size_label: value.size_label,
536            description: value.description,
537            draft: value.draft,
538            installed: value.installed,
539            capabilities: value.capabilities,
540        }
541    }
542}
543
544impl From<mesh_llm_node::models::InstalledModel> for InstalledModel {
545    fn from(value: mesh_llm_node::models::InstalledModel) -> Self {
546        Self {
547            model_ref: value.model_ref,
548            path: value.path,
549            size_bytes: value.size_bytes,
550            capabilities: value.capabilities,
551        }
552    }
553}
554
555impl From<mesh_llm_node::models::DownloadedModel> for DownloadedModel {
556    fn from(value: mesh_llm_node::models::DownloadedModel) -> Self {
557        Self {
558            model_ref: value.model_ref,
559            paths: value.paths,
560            primary_path: value.primary_path,
561            details: value.details.map(ModelDetails::from),
562        }
563    }
564}
565
566impl From<mesh_llm_node::models::DeleteModelResult> for DeleteModelResult {
567    fn from(value: mesh_llm_node::models::DeleteModelResult) -> Self {
568        Self {
569            deleted_paths: value.deleted_paths,
570            reclaimed_bytes: value.reclaimed_bytes,
571        }
572    }
573}
574
575impl From<mesh_llm_node::models::CleanupResult> for CleanupResult {
576    fn from(value: mesh_llm_node::models::CleanupResult) -> Self {
577        Self {
578            deleted_paths: value.deleted_paths,
579            reclaimed_bytes: value.reclaimed_bytes,
580            skipped_paths: value.skipped_paths,
581        }
582    }
583}
584
585impl From<mesh_llm_node::models::PruneResult> for PruneResult {
586    fn from(value: mesh_llm_node::models::PruneResult) -> Self {
587        Self {
588            deleted_paths: value.deleted_paths,
589            reclaimed_bytes: value.reclaimed_bytes,
590        }
591    }
592}
593
594impl From<DevicePolicy> for mesh_llm_node::serving::DevicePolicy {
595    fn from(value: DevicePolicy) -> Self {
596        match value {
597            DevicePolicy::Auto => Self::Auto,
598            DevicePolicy::Cpu => Self::Cpu,
599            DevicePolicy::Gpu { device_ids } => Self::Gpu { device_ids },
600        }
601    }
602}
603
604impl From<UnloadModelOptions> for mesh_llm_node::serving::UnloadOptions {
605    fn from(value: UnloadModelOptions) -> Self {
606        Self {
607            drain_timeout: value.drain_timeout,
608            force: value.force,
609        }
610    }
611}
612
613impl From<UnloadTarget> for mesh_llm_node::serving::UnloadTarget {
614    fn from(value: UnloadTarget) -> Self {
615        match value {
616            UnloadTarget::Model(model_id) => Self::Model(model_id),
617            UnloadTarget::Instance(instance_id) => Self::Instance(instance_id),
618        }
619    }
620}
621
622impl From<mesh_llm_node::serving::ServingModelState> for ServingModelState {
623    fn from(value: mesh_llm_node::serving::ServingModelState) -> Self {
624        match value {
625            mesh_llm_node::serving::ServingModelState::Loading => Self::Loading,
626            mesh_llm_node::serving::ServingModelState::Ready => Self::Ready,
627            mesh_llm_node::serving::ServingModelState::Failed => Self::Failed,
628            mesh_llm_node::serving::ServingModelState::Unloading => Self::Unloading,
629            mesh_llm_node::serving::ServingModelState::Stopped => Self::Stopped,
630            mesh_llm_node::serving::ServingModelState::Unknown(value) => Self::Unknown(value),
631        }
632    }
633}
634
635impl From<mesh_llm_node::serving::ServedModel> for ServedModel {
636    fn from(value: mesh_llm_node::serving::ServedModel) -> Self {
637        Self {
638            model_ref: value.model_ref,
639            profile: value.profile,
640            model_id: value.model_id,
641            instance_id: value.instance_id,
642            state: value.state.into(),
643            backend: value.backend,
644            capabilities: value.capabilities,
645            context_length: value.context_length,
646            error: value.error,
647        }
648    }
649}
650
651impl From<mesh_llm_node::serving::ServingStatus> for ServingStatus {
652    fn from(value: mesh_llm_node::serving::ServingStatus) -> Self {
653        Self {
654            enabled: value.enabled,
655            models: value.models.into_iter().map(ServedModel::from).collect(),
656        }
657    }
658}
659
660fn serving_error(error: anyhow::Error) -> MeshApiError {
661    if let Some(error) = error.downcast_ref::<mesh_llm_node::serving::ServingError>() {
662        return MeshApiError::Serving {
663            message: error.to_string(),
664        };
665    }
666    MeshApiError::Serving {
667        message: error.to_string(),
668    }
669}
670
671#[derive(Clone)]
672pub struct MeshServing {
673    inner: Arc<MeshNodeInner>,
674}
675
676impl MeshServing {
677    pub async fn load(
678        &self,
679        model_ref: impl AsRef<str>,
680        options: LoadModelOptions,
681    ) -> Result<ServedModel, MeshApiError> {
682        let controller = self.serving_controller()?;
683        controller
684            .load(mesh_llm_node::serving::LoadModelRequest {
685                model_ref: model_ref.as_ref().to_string(),
686                device_policy: options.device_policy.into(),
687                profile: options.profile.clone(),
688            })
689            .await
690            .map(ServedModel::from)
691            .map_err(serving_error)
692    }
693
694    pub async fn unload(
695        &self,
696        target: UnloadTarget,
697        options: UnloadModelOptions,
698    ) -> Result<(), MeshApiError> {
699        let controller = self.serving_controller()?;
700        controller
701            .unload(mesh_llm_node::serving::UnloadModelRequest {
702                target: target.into(),
703                options: options.into(),
704            })
705            .await
706            .map_err(serving_error)
707    }
708
709    pub async fn unload_model(
710        &self,
711        model_id: impl AsRef<str>,
712        options: UnloadModelOptions,
713    ) -> Result<(), MeshApiError> {
714        self.unload(UnloadTarget::Model(model_id.as_ref().to_string()), options)
715            .await
716    }
717
718    pub async fn unload_instance(
719        &self,
720        instance_id: impl AsRef<str>,
721        options: UnloadModelOptions,
722    ) -> Result<(), MeshApiError> {
723        self.unload(
724            UnloadTarget::Instance(instance_id.as_ref().to_string()),
725            options,
726        )
727        .await
728    }
729
730    pub async fn served_models(&self) -> Result<Vec<ServedModel>, MeshApiError> {
731        let Some(controller) = self.inner.serving_controller.clone() else {
732            return Ok(Vec::new());
733        };
734        controller
735            .served_models()
736            .await
737            .map(|models| models.into_iter().map(ServedModel::from).collect())
738            .map_err(serving_error)
739    }
740
741    pub async fn status(&self) -> Result<ServingStatus, MeshApiError> {
742        let Some(controller) = self.inner.serving_controller.clone() else {
743            return Ok(ServingStatus {
744                enabled: self.inner.config.serving_enabled,
745                models: Vec::new(),
746            });
747        };
748        controller
749            .status()
750            .await
751            .map(ServingStatus::from)
752            .map_err(serving_error)
753    }
754
755    pub async fn set_device_policy(&self, policy: DevicePolicy) -> Result<(), MeshApiError> {
756        let controller = self.serving_controller()?;
757        controller
758            .set_device_policy(policy.into())
759            .await
760            .map_err(serving_error)
761    }
762
763    fn serving_controller(&self) -> Result<Arc<dyn ServingController>, MeshApiError> {
764        self.inner
765            .serving_controller
766            .clone()
767            .ok_or(MeshApiError::Unsupported {
768                feature: "in-process serving controller",
769            })
770    }
771}
772
773#[derive(Clone)]
774pub struct MeshStatusApi {
775    inner: Arc<MeshNodeInner>,
776}
777
778impl MeshStatusApi {
779    pub async fn node(&self) -> Result<Status, MeshApiError> {
780        Ok(self.inner.client.lock().await.status().await)
781    }
782
783    pub async fn models(&self) -> Result<Vec<Model>, MeshApiError> {
784        self.inner.client.lock().await.list_models().await
785    }
786
787    pub async fn serving(&self) -> Result<ServingStatus, MeshApiError> {
788        let Some(controller) = self.inner.serving_controller.clone() else {
789            return Ok(ServingStatus {
790                enabled: self.inner.config.serving_enabled,
791                models: Vec::new(),
792            });
793        };
794        controller
795            .status()
796            .await
797            .map(ServingStatus::from)
798            .map_err(serving_error)
799    }
800}
801
802#[derive(Clone)]
803pub struct MeshEvents {
804    inner: Arc<MeshNodeInner>,
805}
806
807impl MeshEvents {
808    pub fn is_supported(&self) -> bool {
809        let _ = &self.inner;
810        false
811    }
812}