relay_profiling/
profile_chunk.rs1use serde::Deserialize;
2
3use crate::{
4 AndroidProfileChunk, PerfettoProfileChunk, ProfileError, ProfileType, V2ProfileChunk, sample,
5};
6
7pub trait ProfileChunk {
9 fn platform(&self) -> &str;
11
12 fn profile_type(&self) -> ProfileType {
16 ProfileType::from_platform(self.platform())
17 }
18
19 fn normalize(&mut self) -> Result<(), ProfileError>;
21}
22
23#[derive(Debug)]
25pub enum AnyProfileChunk {
26 Android(Box<AndroidProfileChunk>),
27 Perfetto(Box<PerfettoProfileChunk>),
28 V2(Box<V2ProfileChunk>),
29}
30
31impl From<Box<V2ProfileChunk>> for AnyProfileChunk {
32 fn from(chunk: Box<V2ProfileChunk>) -> Self {
33 Self::V2(chunk)
34 }
35}
36
37impl From<Box<AndroidProfileChunk>> for AnyProfileChunk {
38 fn from(chunk: Box<AndroidProfileChunk>) -> Self {
39 Self::Android(chunk)
40 }
41}
42
43impl From<Box<PerfettoProfileChunk>> for AnyProfileChunk {
44 fn from(chunk: Box<PerfettoProfileChunk>) -> Self {
45 Self::Perfetto(chunk)
46 }
47}
48
49impl From<AndroidOrV2ProfileChunk> for AnyProfileChunk {
50 fn from(chunk: AndroidOrV2ProfileChunk) -> Self {
51 match chunk {
52 AndroidOrV2ProfileChunk::Android(c) => Self::Android(c),
53 AndroidOrV2ProfileChunk::V2(c) => Self::V2(c),
54 }
55 }
56}
57
58impl ProfileChunk for AnyProfileChunk {
59 fn platform(&self) -> &str {
60 match self {
61 AnyProfileChunk::Android(chunk) => chunk.platform(),
62 AnyProfileChunk::Perfetto(chunk) => chunk.platform(),
63 AnyProfileChunk::V2(chunk) => chunk.platform(),
64 }
65 }
66
67 fn normalize(&mut self) -> Result<(), ProfileError> {
68 match self {
69 AnyProfileChunk::Android(chunk) => chunk.normalize(),
70 AnyProfileChunk::Perfetto(chunk) => chunk.normalize(),
71 AnyProfileChunk::V2(chunk) => chunk.normalize(),
72 }
73 }
74}
75
76impl relay_protocol::Getter for AnyProfileChunk {
77 fn get_value(&self, path: &str) -> Option<relay_protocol::Val<'_>> {
78 match self {
79 AnyProfileChunk::Android(chunk) => chunk.get_value(path),
80 AnyProfileChunk::Perfetto(chunk) => chunk.get_value(path),
81 AnyProfileChunk::V2(chunk) => chunk.get_value(path),
82 }
83 }
84}
85
86impl relay_filter::Filterable for AnyProfileChunk {
87 fn release(&self) -> Option<&str> {
88 match self {
89 AnyProfileChunk::Android(chunk) => chunk.release(),
90 AnyProfileChunk::Perfetto(chunk) => chunk.release(),
91 AnyProfileChunk::V2(chunk) => chunk.release(),
92 }
93 }
94}
95
96pub enum AndroidOrV2ProfileChunk {
98 Android(Box<AndroidProfileChunk>),
99 V2(Box<V2ProfileChunk>),
100}
101
102impl ProfileChunk for AndroidOrV2ProfileChunk {
103 fn platform(&self) -> &str {
104 match self {
105 AndroidOrV2ProfileChunk::Android(chunk) => chunk.platform(),
106 AndroidOrV2ProfileChunk::V2(chunk) => chunk.platform(),
107 }
108 }
109
110 fn normalize(&mut self) -> Result<(), ProfileError> {
111 match self {
112 AndroidOrV2ProfileChunk::Android(chunk) => chunk.normalize(),
113 AndroidOrV2ProfileChunk::V2(chunk) => chunk.normalize(),
114 }
115 }
116}
117
118impl AndroidOrV2ProfileChunk {
119 pub fn parse(data: &[u8]) -> Result<Self, ProfileError> {
121 #[derive(Debug, Deserialize)]
122 struct MinimalProfile {
123 platform: String,
124 #[serde(default)]
125 version: sample::Version,
126 }
127
128 let minimal: MinimalProfile = {
129 let d = &mut serde_json::Deserializer::from_slice(data);
130 serde_path_to_error::deserialize(d)
131 }?;
132
133 match (minimal.platform.as_str(), minimal.version) {
134 ("android", _) => AndroidProfileChunk::parse(data)
138 .map(Box::new)
139 .map(Self::Android),
140 (_, sample::Version::V2) => V2ProfileChunk::parse(data).map(Box::new).map(Self::V2),
141 (_, sample::Version::V1) => Err(ProfileError::PlatformNotSupported),
142 (_, sample::Version::Unknown) => Err(ProfileError::PlatformNotSupported),
143 }
144 }
145}