relay_event_schema/protocol/
attributes.rs1use relay_protocol::{Annotated, Empty, FromValue, IntoValue, Object, SkipSerialization, Value};
2use std::fmt;
3
4use crate::processor::ProcessValue;
5
6#[derive(Clone, PartialEq, Empty, FromValue, IntoValue, ProcessValue)]
7pub struct Attribute {
8 #[metastructure(flatten)]
9 pub value: AttributeValue,
10
11 #[metastructure(additional_properties)]
13 pub other: Object<Value>,
14}
15
16impl Attribute {
17 pub fn new(attribute_type: AttributeType, value: Value) -> Self {
18 Self {
19 value: AttributeValue {
20 ty: Annotated::new(attribute_type),
21 value: Annotated::new(value),
22 },
23 other: Object::new(),
24 }
25 }
26}
27
28impl fmt::Debug for Attribute {
29 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30 f.debug_struct("Attribute")
31 .field("value", &self.value.value)
32 .field("type", &self.value.ty)
33 .field("other", &self.other)
34 .finish()
35 }
36}
37
38#[derive(Debug, Clone, PartialEq, Empty, FromValue, IntoValue, ProcessValue)]
39pub struct AttributeValue {
40 #[metastructure(field = "type", required = true, trim = false)]
41 pub ty: Annotated<AttributeType>,
42 #[metastructure(required = true, pii = "true")]
43 pub value: Annotated<Value>,
44}
45
46#[derive(Debug, Clone, PartialEq, Eq)]
47pub enum AttributeType {
48 Boolean,
49 Integer,
50 Double,
51 String,
52 Unknown(String),
53}
54
55impl ProcessValue for AttributeType {}
56
57impl AttributeType {
58 pub fn as_str(&self) -> &str {
59 match self {
60 Self::Boolean => "boolean",
61 Self::Integer => "integer",
62 Self::Double => "double",
63 Self::String => "string",
64 Self::Unknown(value) => value,
65 }
66 }
67
68 pub fn unknown_string() -> String {
69 "unknown".to_string()
70 }
71}
72
73impl fmt::Display for AttributeType {
74 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75 write!(f, "{}", self.as_str())
76 }
77}
78
79impl From<String> for AttributeType {
80 fn from(value: String) -> Self {
81 match value.as_str() {
82 "boolean" => Self::Boolean,
83 "integer" => Self::Integer,
84 "double" => Self::Double,
85 "string" => Self::String,
86 _ => Self::Unknown(value),
87 }
88 }
89}
90
91impl Empty for AttributeType {
92 #[inline]
93 fn is_empty(&self) -> bool {
94 false
95 }
96}
97
98impl FromValue for AttributeType {
99 fn from_value(value: Annotated<Value>) -> Annotated<Self> {
100 match String::from_value(value) {
101 Annotated(Some(value), meta) => Annotated(Some(value.into()), meta),
102 Annotated(None, meta) => Annotated(None, meta),
103 }
104 }
105}
106
107impl IntoValue for AttributeType {
108 fn into_value(self) -> Value
109 where
110 Self: Sized,
111 {
112 Value::String(match self {
113 Self::Unknown(s) => s,
114 s => s.to_string(),
115 })
116 }
117
118 fn serialize_payload<S>(&self, s: S, _behavior: SkipSerialization) -> Result<S::Ok, S::Error>
119 where
120 Self: Sized,
121 S: serde::Serializer,
122 {
123 serde::ser::Serialize::serialize(self.as_str(), s)
124 }
125}