Skip to main content

nv_redfish_core/
lib.rs

1// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2// SPDX-License-Identifier: Apache-2.0
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16//! Core Redfish foundation library used by code generated from the CSDL compiler.
17//!
18//! Purpose
19//! - Serve as a dependency for autogenerated Redfish types produced by the CSDL compiler.
20//! - Provide semantic-unaware primitives that generated code relies on.
21//! - Avoid any knowledge of specific Redfish services, schemas, or OEM semantics.
22//!
23//! Scope (building blocks only)
24//! - Identity and metadata: [`ODataId`], [`ODataETag`]
25//! - EDM value wrappers: [`EdmDateTimeOffset`], [`EdmDuration`]
26//! - Navigation properties: [`NavProperty<T>`]
27//! - Generic operation traits: [`Creatable`], [`Updatable`], [`Deletable`]
28//! - Entity contracts: [`EntityTypeRef`], [`Expandable`]
29//! - Action envelope: [`Action<T, R>`]
30//! - Client abstraction: [`Bmc`] (transport-agnostic interface used by generated code)
31//!
32//! Non-goals
33//! - No service- or schema-specific models are defined here.
34//! - No business logic or policy decisions are embedded here.
35//! - No transport specification
36//!
37//! How generated code uses these primitives
38//! - Each generated entity struct implements [`EntityTypeRef`].
39//! - Navigation properties in generated code are wrapped in [`NavProperty<T>`].
40//! - Generated actions are represented as [`Action<T, R>`].
41//! - If the schema allows it, generated types implement [`Creatable`], [`Updatable`], and/or [`Deletable`]
42//!   and route operations through a user-provided [`Bmc`] implementation.
43//!
44
45#![deny(
46    clippy::all,
47    clippy::pedantic,
48    clippy::nursery,
49    clippy::suspicious,
50    clippy::complexity,
51    clippy::perf
52)]
53#![deny(
54    clippy::absolute_paths,
55    clippy::todo,
56    clippy::unimplemented,
57    clippy::tests_outside_test_module,
58    clippy::panic,
59    clippy::unwrap_used,
60    clippy::unwrap_in_result,
61    clippy::unused_trait_names,
62    clippy::print_stdout,
63    clippy::print_stderr
64)]
65#![deny(missing_docs)]
66
67/// Action-related types.
68pub mod action;
69/// BMC trait and credentials.
70pub mod bmc;
71/// Custom deserialization helpers.
72pub mod deserialize;
73/// Dynamic properties support.
74pub mod dynamic_properties;
75/// `Edm.DateTimeOffset` type.
76pub mod edm_date_time_offset;
77/// `Edm.Duration` type.
78pub mod edm_duration;
79/// `Edm.PrimitiveType` type.
80pub mod edm_primitive_type;
81/// Navigation property wrapper.
82pub mod nav_property;
83/// Type for `@odata.id` identifier.
84pub mod odata;
85/// Support of redfish queries
86pub mod query;
87
88use crate::query::ExpandQuery;
89use serde::{Deserialize, Deserializer, Serialize};
90use std::{future::Future, sync::Arc};
91
92#[doc(inline)]
93pub use action::Action;
94#[doc(inline)]
95pub use action::ActionError;
96#[doc(inline)]
97pub use bmc::Bmc;
98#[doc(inline)]
99pub use deserialize::de_optional_nullable;
100#[doc(inline)]
101pub use deserialize::de_required_nullable;
102#[doc(inline)]
103pub use dynamic_properties::DynamicProperties;
104#[doc(inline)]
105pub use edm_date_time_offset::EdmDateTimeOffset;
106#[doc(inline)]
107pub use edm_duration::EdmDuration;
108#[doc(inline)]
109pub use edm_primitive_type::EdmPrimitiveType;
110#[doc(inline)]
111pub use nav_property::NavProperty;
112#[doc(inline)]
113pub use nav_property::Reference;
114#[doc(inline)]
115pub use nav_property::ReferenceLeaf;
116#[doc(inline)]
117pub use odata::ODataETag;
118#[doc(inline)]
119pub use odata::ODataId;
120#[doc(inline)]
121pub use query::FilterQuery;
122#[doc(inline)]
123pub use query::ToFilterLiteral;
124#[doc(inline)]
125pub use serde_json::Value as AdditionalProperties;
126#[doc(inline)]
127pub use uuid::Uuid as EdmGuid;
128
129/// Entity type reference trait implemented by the CSDL compiler
130/// for all generated entity types and for all `NavProperty<T>` where
131/// `T` is a struct for an entity type.
132pub trait EntityTypeRef {
133    /// Value of `@odata.id` field of the Entity.
134    fn id(&self) -> &ODataId;
135
136    /// Value of `@odata.etag` field of the Entity.
137    fn etag(&self) -> Option<&ODataETag>;
138
139    /// Refresh the entity by fetching it again from the BMC.
140    fn refresh<B: Bmc>(&self, bmc: &B) -> impl Future<Output = Result<Arc<Self>, B::Error>> + Send
141    where
142        Self: Sync + Send + 'static + Sized + for<'de> Deserialize<'de>,
143    {
144        bmc.get::<Self>(self.id())
145    }
146}
147
148/// Defines entity types that support `$expand` via query parameters.
149pub trait Expandable:
150    EntityTypeRef + Send + Sync + Sized + 'static + for<'a> Deserialize<'a>
151{
152    /// Expand the entity according to the provided query.
153    fn expand<B: Bmc>(
154        &self,
155        bmc: &B,
156        query: ExpandQuery,
157    ) -> impl Future<Output = Result<Arc<Self>, B::Error>> + Send {
158        bmc.expand::<Self>(self.id(), query)
159    }
160}
161
162/// Empty struct denoting a unit return type, used for Redfish responses that
163/// do not return any JSON data.
164#[derive(Debug)]
165pub struct Empty {}
166
167impl<'de> Deserialize<'de> for Empty {
168    fn deserialize<D>(_deserializer: D) -> Result<Self, D::Error>
169    where
170        D: Deserializer<'de>,
171    {
172        Ok(Self {})
173    }
174}
175
176/// This trait is assigned to the collections that are marked as
177/// creatable in the CSDL specification.
178pub trait Creatable<V: Sync + Send + Serialize, R: Sync + Send + Sized + for<'de> Deserialize<'de>>:
179    EntityTypeRef + Sized
180{
181    /// Create an entity using `create` as payload.
182    fn create<B: Bmc>(
183        &self,
184        bmc: &B,
185        create: &V,
186    ) -> impl Future<Output = Result<R, B::Error>> + Send {
187        bmc.create::<V, R>(self.id(), create)
188    }
189}
190
191/// This trait is assigned to entity types that are marked as
192/// updatable in the CSDL specification.
193pub trait Updatable<V: Sync + Send + Serialize>: EntityTypeRef + Sized
194where
195    Self: Sync + Send + Sized + for<'de> Deserialize<'de>,
196{
197    /// Update an entity using `update` as payload.
198    fn update<B: Bmc>(
199        &self,
200        bmc: &B,
201        update: &V,
202    ) -> impl Future<Output = Result<Self, B::Error>> + Send {
203        bmc.update::<V, Self>(self.id(), self.etag(), update)
204    }
205}
206
207/// This trait is assigned to entity types that are marked as
208/// deletable in the CSDL specification.
209pub trait Deletable: EntityTypeRef + Sized {
210    /// Delete current entity.
211    fn delete<B: Bmc>(&self, bmc: &B) -> impl Future<Output = Result<Empty, B::Error>> + Send {
212        bmc.delete(self.id())
213    }
214}
215
216/// This trait is assigned to updatable entity types to support
217/// @Redfish.Settings workflow.
218pub trait RedfishSettings<E: EntityTypeRef>: Sized {
219    /// Reference to the enity type object.
220    fn settings_object(&self) -> Option<NavProperty<E>>;
221}
222
223/// Trait for converting enum variants to `snake_case` strings
224pub trait ToSnakeCase {
225    /// Convert this enum variant to a `snake_case` string
226    fn to_snake_case(&self) -> &'static str;
227}
228
229/// Trait for types that can be used as filter properties in `OData` queries
230pub trait FilterProperty {
231    /// Returns the `OData` property path for this property
232    fn property_path(&self) -> &str;
233}