zlink_core/varlink_service/
info.rs1#[cfg(feature = "introspection")]
2use crate::introspect::Type;
3use alloc::{borrow::Cow, vec::Vec};
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
10#[cfg_attr(feature = "introspection", derive(Type))]
11#[cfg_attr(feature = "introspection", zlink(crate = "crate"))]
12pub struct Info<'a> {
13 #[serde(borrow)]
15 pub vendor: Cow<'a, str>,
16 #[serde(borrow)]
18 pub product: Cow<'a, str>,
19 #[serde(borrow)]
21 pub version: Cow<'a, str>,
22 #[serde(borrow)]
24 pub url: Cow<'a, str>,
25 #[serde(borrow)]
27 pub interfaces: Vec<Cow<'a, str>>,
28}
29
30impl<'a> Info<'a> {
31 pub fn new(
33 vendor: impl Into<Cow<'a, str>>,
34 product: impl Into<Cow<'a, str>>,
35 version: impl Into<Cow<'a, str>>,
36 url: impl Into<Cow<'a, str>>,
37 interfaces: impl IntoIterator<Item = impl Into<Cow<'a, str>>>,
38 ) -> Self {
39 Self {
40 vendor: vendor.into(),
41 product: product.into(),
42 version: version.into(),
43 url: url.into(),
44 interfaces: interfaces.into_iter().map(Into::into).collect(),
45 }
46 }
47
48 pub fn into_owned(self) -> Info<'static> {
50 Info {
51 vendor: Cow::Owned(self.vendor.into_owned()),
52 product: Cow::Owned(self.product.into_owned()),
53 version: Cow::Owned(self.version.into_owned()),
54 url: Cow::Owned(self.url.into_owned()),
55 interfaces: self
56 .interfaces
57 .into_iter()
58 .map(|s| Cow::Owned(s.into_owned()))
59 .collect(),
60 }
61 }
62}
63
64#[derive(Debug, Clone, PartialEq, Serialize)]
80pub struct OwnedInfo(Info<'static>);
81
82impl OwnedInfo {
83 pub fn new(
85 vendor: impl Into<Cow<'static, str>>,
86 product: impl Into<Cow<'static, str>>,
87 version: impl Into<Cow<'static, str>>,
88 url: impl Into<Cow<'static, str>>,
89 interfaces: impl IntoIterator<Item = impl Into<Cow<'static, str>>>,
90 ) -> Self {
91 Self(Info::new(vendor, product, version, url, interfaces))
92 }
93
94 pub fn inner(&self) -> &Info<'static> {
96 &self.0
97 }
98
99 pub fn into_inner(self) -> Info<'static> {
101 self.0
102 }
103}
104
105impl core::ops::Deref for OwnedInfo {
106 type Target = Info<'static>;
107
108 fn deref(&self) -> &Self::Target {
109 &self.0
110 }
111}
112
113impl core::ops::DerefMut for OwnedInfo {
114 fn deref_mut(&mut self) -> &mut Self::Target {
115 &mut self.0
116 }
117}
118
119impl<'a> From<Info<'a>> for OwnedInfo {
120 fn from(info: Info<'a>) -> Self {
121 Self(info.into_owned())
122 }
123}
124
125impl<'de> Deserialize<'de> for OwnedInfo {
126 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
127 where
128 D: serde::Deserializer<'de>,
129 {
130 use alloc::string::String;
131
132 #[derive(Deserialize)]
134 struct InfoOwned {
135 vendor: String,
136 product: String,
137 version: String,
138 url: String,
139 interfaces: Vec<String>,
140 }
141
142 let info = InfoOwned::deserialize(deserializer)?;
143 Ok(Self(Info {
144 vendor: Cow::Owned(info.vendor),
145 product: Cow::Owned(info.product),
146 version: Cow::Owned(info.version),
147 url: Cow::Owned(info.url),
148 interfaces: info.interfaces.into_iter().map(Cow::Owned).collect(),
149 }))
150 }
151}
152
153#[cfg(test)]
154mod tests {
155 use super::*;
156
157 #[test]
158 fn serialization() {
159 let mut interfaces = Vec::new();
160 interfaces.push("com.example.test");
161
162 let info = Info::new(
163 "Test Vendor",
164 "Test Product",
165 "1.0.0",
166 "https://example.com",
167 interfaces,
168 );
169
170 let json = serde_json::to_string(&info).unwrap();
171
172 assert!(json.contains("Test Vendor"));
173 assert!(json.contains("com.example.test"));
174 }
175
176 #[test]
177 fn deserialization() {
178 let json = r#"{
179 "vendor": "Test Vendor",
180 "product": "Test Product",
181 "version": "1.0.0",
182 "url": "https://example.com",
183 "interfaces": ["com.example.test", "com.example.other"]
184 }"#;
185
186 let info: Info<'_> = serde_json::from_str(json).unwrap();
187
188 assert_eq!(info.vendor, "Test Vendor");
189 assert_eq!(info.product, "Test Product");
190 assert_eq!(info.version, "1.0.0");
191 assert_eq!(info.url, "https://example.com");
192 assert_eq!(info.interfaces.len(), 2);
193 assert_eq!(info.interfaces[0], "com.example.test");
194 assert_eq!(info.interfaces[1], "com.example.other");
195 }
196
197 #[test]
198 fn round_trip_serialization() {
199 let mut interfaces = Vec::new();
200 interfaces.push("com.example.test");
201 interfaces.push("com.example.other");
202
203 let original = Info::new(
204 "Test Vendor",
205 "Test Product",
206 "1.0.0",
207 "https://example.com",
208 interfaces,
209 );
210
211 let json = serde_json::to_string(&original).unwrap();
213
214 let deserialized: Info<'_> = serde_json::from_str(&json).unwrap();
216
217 assert_eq!(original, deserialized);
219 }
220}