zlink_core/varlink_service/
interface_description.rs1use core::fmt::Debug;
2
3use crate::idl::Interface;
4#[cfg(feature = "introspection")]
5use crate::introspect::Type;
6#[cfg(feature = "idl-parse")]
7use alloc::string::String;
8#[cfg(feature = "idl-parse")]
9use serde::Deserialize;
10use serde::Serialize;
11
12#[derive(Debug, Serialize, Clone)]
18#[cfg_attr(feature = "introspection", derive(Type))]
19#[cfg_attr(feature = "introspection", zlink(crate = "crate"))]
20pub struct InterfaceDescription<'a> {
21 description: Description<'a>,
22}
23
24impl<'a> InterfaceDescription<'a> {
25 pub fn parse(&self) -> crate::Result<Interface<'_>> {
30 match &self.description {
31 Description::Parsed(interface) => Ok(interface.clone()),
32 #[cfg(feature = "idl-parse")]
33 Description::Raw(description) => description.as_str().try_into(),
34 }
35 }
36
37 pub fn as_raw(&self) -> Option<&str> {
39 match &self.description {
40 Description::Parsed(_) => None,
41 #[cfg(feature = "idl-parse")]
42 Description::Raw(description) => Some(description.as_str()),
43 }
44 }
45}
46
47impl<'a> From<&Interface<'a>> for InterfaceDescription<'a> {
48 fn from(interface: &Interface<'a>) -> Self {
49 Self {
50 description: Description::Parsed(interface.clone()),
51 }
52 }
53}
54
55#[cfg(feature = "idl-parse")]
56impl<'de> Deserialize<'de> for InterfaceDescription<'static> {
57 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
58 where
59 D: serde::Deserializer<'de>,
60 {
61 use core::fmt;
62
63 use serde::de::{Error, MapAccess, Visitor};
64
65 struct IDVisitor;
66
67 impl<'de> Visitor<'de> for IDVisitor {
68 type Value = InterfaceDescription<'static>;
69
70 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
71 formatter.write_str("a valid interface description")
72 }
73
74 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
75 where
76 A: MapAccess<'de>,
77 {
78 let (field_name, description): (&str, String) = map
79 .next_entry()?
80 .ok_or_else(|| A::Error::invalid_length(0, &self))?;
81 if field_name != "description" {
82 return Err(A::Error::unknown_field(field_name, &["description"]));
83 }
84
85 Ok(InterfaceDescription {
86 description: Description::Raw(description),
87 })
88 }
89 }
90
91 deserializer.deserialize_map(IDVisitor)
92 }
93}
94
95#[derive(Debug, Clone)]
96enum Description<'a> {
97 Parsed(Interface<'a>),
98 #[cfg(feature = "idl-parse")]
99 Raw(String),
100}
101
102#[cfg(feature = "introspection")]
103impl Type for Description<'_> {
104 const TYPE: &'static crate::idl::Type<'static> = &crate::idl::Type::String;
105}
106
107impl Serialize for Description<'_> {
108 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
109 where
110 S: serde::Serializer,
111 {
112 match self {
113 Description::Parsed(interface) => serializer.collect_str(interface),
114 #[cfg(feature = "idl-parse")]
115 Description::Raw(description) => serializer.serialize_str(description),
116 }
117 }
118}
119
120#[cfg(feature = "idl-parse")]
121impl<'de> Deserialize<'de> for Description<'static> {
122 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
123 where
124 D: serde::Deserializer<'de>,
125 {
126 let description = String::deserialize(deserializer)?;
127 Ok(Description::Raw(description))
128 }
129}