use std::borrow::Cow;
use std::fmt;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct PluginEventKind(Cow<'static, str>);
impl PluginEventKind {
#[must_use]
pub const fn from_static(value: &'static str) -> Self {
Self(Cow::Borrowed(value))
}
#[must_use]
pub const fn from_owned(value: String) -> Self {
Self(Cow::Owned(value))
}
#[must_use]
pub fn as_str(&self) -> &str {
self.0.as_ref()
}
}
impl fmt::Debug for PluginEventKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("PluginEventKind")
.field(&self.as_str())
.finish()
}
}
impl fmt::Display for PluginEventKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
impl AsRef<str> for PluginEventKind {
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl PartialEq<str> for PluginEventKind {
fn eq(&self, other: &str) -> bool {
self.as_str() == other
}
}
impl PartialEq<&str> for PluginEventKind {
fn eq(&self, other: &&str) -> bool {
self.as_str() == *other
}
}
impl From<&'static str> for PluginEventKind {
fn from(value: &'static str) -> Self {
Self::from_static(value)
}
}
impl From<String> for PluginEventKind {
fn from(value: String) -> Self {
Self::from_owned(value)
}
}
impl From<PluginEventKind> for String {
fn from(value: PluginEventKind) -> Self {
value.0.into_owned()
}
}
impl Serialize for PluginEventKind {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_str(self.as_str())
}
}
impl<'de> Deserialize<'de> for PluginEventKind {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let value = String::deserialize(deserializer)?;
Ok(Self::from_owned(value))
}
}
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct InterfaceId(Cow<'static, str>);
impl InterfaceId {
#[must_use]
pub const fn from_static(value: &'static str) -> Self {
Self(Cow::Borrowed(value))
}
#[must_use]
pub const fn from_owned(value: String) -> Self {
Self(Cow::Owned(value))
}
#[must_use]
pub fn as_str(&self) -> &str {
self.0.as_ref()
}
}
impl fmt::Debug for InterfaceId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("InterfaceId").field(&self.as_str()).finish()
}
}
impl fmt::Display for InterfaceId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
impl AsRef<str> for InterfaceId {
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl PartialEq<str> for InterfaceId {
fn eq(&self, other: &str) -> bool {
self.as_str() == other
}
}
impl PartialEq<&str> for InterfaceId {
fn eq(&self, other: &&str) -> bool {
self.as_str() == *other
}
}
impl From<&'static str> for InterfaceId {
fn from(value: &'static str) -> Self {
Self::from_static(value)
}
}
impl From<String> for InterfaceId {
fn from(value: String) -> Self {
Self::from_owned(value)
}
}
impl From<InterfaceId> for String {
fn from(value: InterfaceId) -> Self {
value.0.into_owned()
}
}
impl Serialize for InterfaceId {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_str(self.as_str())
}
}
impl<'de> Deserialize<'de> for InterfaceId {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let value = String::deserialize(deserializer)?;
Ok(Self::from_owned(value))
}
}
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct OperationId(Cow<'static, str>);
impl OperationId {
#[must_use]
pub const fn from_static(value: &'static str) -> Self {
Self(Cow::Borrowed(value))
}
#[must_use]
pub const fn from_owned(value: String) -> Self {
Self(Cow::Owned(value))
}
#[must_use]
pub fn as_str(&self) -> &str {
self.0.as_ref()
}
}
impl fmt::Debug for OperationId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("OperationId").field(&self.as_str()).finish()
}
}
impl fmt::Display for OperationId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
impl AsRef<str> for OperationId {
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl PartialEq<str> for OperationId {
fn eq(&self, other: &str) -> bool {
self.as_str() == other
}
}
impl PartialEq<&str> for OperationId {
fn eq(&self, other: &&str) -> bool {
self.as_str() == *other
}
}
impl From<&'static str> for OperationId {
fn from(value: &'static str) -> Self {
Self::from_static(value)
}
}
impl From<String> for OperationId {
fn from(value: String) -> Self {
Self::from_owned(value)
}
}
impl From<OperationId> for String {
fn from(value: OperationId) -> Self {
value.0.into_owned()
}
}
impl Serialize for OperationId {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_str(self.as_str())
}
}
impl<'de> Deserialize<'de> for OperationId {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let value = String::deserialize(deserializer)?;
Ok(Self::from_owned(value))
}
}
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct CapabilityId(Cow<'static, str>);
impl CapabilityId {
#[must_use]
pub const fn from_static(value: &'static str) -> Self {
Self(Cow::Borrowed(value))
}
#[must_use]
pub const fn from_owned(value: String) -> Self {
Self(Cow::Owned(value))
}
#[must_use]
pub fn as_str(&self) -> &str {
self.0.as_ref()
}
}
impl fmt::Debug for CapabilityId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("CapabilityId").field(&self.as_str()).finish()
}
}
impl fmt::Display for CapabilityId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
impl AsRef<str> for CapabilityId {
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl PartialEq<str> for CapabilityId {
fn eq(&self, other: &str) -> bool {
self.as_str() == other
}
}
impl PartialEq<&str> for CapabilityId {
fn eq(&self, other: &&str) -> bool {
self.as_str() == *other
}
}
impl From<&'static str> for CapabilityId {
fn from(value: &'static str) -> Self {
Self::from_static(value)
}
}
impl From<String> for CapabilityId {
fn from(value: String) -> Self {
Self::from_owned(value)
}
}
impl From<CapabilityId> for String {
fn from(value: CapabilityId) -> Self {
value.0.into_owned()
}
}
impl Serialize for CapabilityId {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_str(self.as_str())
}
}
impl<'de> Deserialize<'de> for CapabilityId {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let value = String::deserialize(deserializer)?;
Ok(Self::from_owned(value))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn plugin_event_kind_const_is_borrowed() {
const KIND: PluginEventKind = PluginEventKind::from_static("test.fixture/event");
assert_eq!(KIND.as_str(), "test.fixture/event");
assert_eq!(KIND, "test.fixture/event");
}
#[test]
fn interface_id_roundtrips_through_json() {
const ID: InterfaceId = InterfaceId::from_static("windows-events");
let json = serde_json::to_string(&ID).expect("serialize");
assert_eq!(json, "\"windows-events\"");
let decoded: InterfaceId = serde_json::from_str(&json).expect("deserialize");
assert_eq!(decoded, ID);
assert_eq!(decoded.as_str(), "windows-events");
}
#[test]
fn owned_and_static_compare_equal() {
let owned = InterfaceId::from_owned("foo".to_string());
let stat = InterfaceId::from_static("foo");
assert_eq!(owned, stat);
}
#[test]
fn all_newtypes_implement_display() {
let e = PluginEventKind::from_static("ev");
let i = InterfaceId::from_static("if");
let o = OperationId::from_static("op");
let c = CapabilityId::from_static("cap");
assert_eq!(format!("{e}"), "ev");
assert_eq!(format!("{i}"), "if");
assert_eq!(format!("{o}"), "op");
assert_eq!(format!("{c}"), "cap");
}
}