Skip to main content

nv_redfish_csdl_compiler/
one_or_collection.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
16use std::fmt::Debug;
17use std::fmt::Formatter;
18use std::fmt::Result as FmtResult;
19
20/// One item or collection of items for types.
21///
22/// This is common construction in compiler when we need to describe
23/// singleton or collection of items of specific type.
24pub enum OneOrCollection<T> {
25    One(T),
26    Collection(T),
27}
28
29impl<T> OneOrCollection<T> {
30    /// Inner type.
31    #[must_use]
32    pub const fn inner(&self) -> &T {
33        match self {
34            Self::One(v) | Self::Collection(v) => v,
35        }
36    }
37}
38
39impl<T> OneOrCollection<T> {
40    /// Maps inner value with funciton `f`.
41    pub fn map<F, R>(self, f: F) -> OneOrCollection<R>
42    where
43        F: FnOnce(T) -> R,
44    {
45        match self {
46            Self::One(v) => OneOrCollection::<R>::One(f(v)),
47            Self::Collection(v) => OneOrCollection::<R>::Collection(f(v)),
48        }
49    }
50
51    /// Convert from `OneOrCollection<T>` to `OneOrCollection<&T>`.
52    #[inline]
53    pub const fn as_ref(&self) -> OneOrCollection<&T> {
54        match self {
55            Self::One(v) => OneOrCollection::<&T>::One(v),
56            Self::Collection(v) => OneOrCollection::<&T>::Collection(v),
57        }
58    }
59}
60
61impl<T: Debug> Debug for OneOrCollection<T> {
62    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
63        match self {
64            Self::One(v) => write!(f, "One({v:?})"),
65            Self::Collection(v) => write!(f, "Collection({v:?})"),
66        }
67    }
68}
69
70// This is generic implementation based on what T is implementing.  We
71// are fine with exact copy on clone but if T implements Clone without
72// Copy we still want to have clone.
73#[allow(clippy::expl_impl_clone_on_copy)]
74impl<T: Clone> Clone for OneOrCollection<T> {
75    fn clone(&self) -> Self {
76        match self {
77            Self::One(v) => Self::One(v.clone()),
78            Self::Collection(v) => Self::Collection(v.clone()),
79        }
80    }
81}
82
83impl<T: Copy> Copy for OneOrCollection<T> {}
84
85impl<T: PartialEq> PartialEq for OneOrCollection<T> {
86    #[inline]
87    fn eq(&self, other: &Self) -> bool {
88        match (self, other) {
89            (Self::One(v1), Self::One(v2)) | (Self::Collection(v1), Self::Collection(v2)) => {
90                v1.eq(v2)
91            }
92            _ => false,
93        }
94    }
95}
96
97impl<T: Eq> Eq for OneOrCollection<T> {}