@@ -16,8 +16,7 @@ use std::str;
1616use std:: time:: SystemTime ;
1717
1818use self :: debugid:: { CodeId , DebugId } ;
19- use serde:: Serializer ;
20- use serde:: { Deserialize , Serialize } ;
19+ use serde:: { de, Deserialize , Deserializer , Serialize , Serializer } ;
2120use thiserror:: Error ;
2221use url:: Url ;
2322use uuid:: Uuid ;
@@ -1121,6 +1120,23 @@ impl Context {
11211120 Context :: Other ( ..) => "unknown" ,
11221121 }
11231122 }
1123+
1124+ /// Returns the `Context` based on the type key and provided json payload.
1125+ pub fn from_type (
1126+ r#type : & str ,
1127+ payload : serde_json:: Value ,
1128+ ) -> Result < Context , serde_json:: Error > {
1129+ Ok ( match r#type {
1130+ "device" => Self :: from ( DeviceContext :: deserialize ( payload) ?) ,
1131+ "os" => Self :: from ( OsContext :: deserialize ( payload) ?) ,
1132+ "runtime" => Self :: from ( RuntimeContext :: deserialize ( payload) ?) ,
1133+ "app" => Self :: from ( AppContext :: deserialize ( payload) ?) ,
1134+ "browser" => Self :: from ( BrowserContext :: deserialize ( payload) ?) ,
1135+ "trace" => Self :: from ( TraceContext :: deserialize ( payload) ?) ,
1136+ "gpu" => Self :: from ( GpuContext :: deserialize ( payload) ?) ,
1137+ _ => Context :: Other ( Map :: deserialize ( payload) ?) ,
1138+ } )
1139+ }
11241140}
11251141
11261142/// Optional device screen orientation
@@ -1477,6 +1493,41 @@ into_context!(Trace, TraceContext);
14771493into_context ! ( Gpu , GpuContext ) ;
14781494into_context ! ( Profile , ProfileContext ) ;
14791495
1496+ struct ContextsVisitor ;
1497+
1498+ impl < ' de > de:: Visitor < ' de > for ContextsVisitor {
1499+ type Value = Map < String , Context > ;
1500+
1501+ fn expecting ( & self , formatter : & mut fmt:: Formatter ) -> fmt:: Result {
1502+ formatter. write_str ( "invalid `contexts` object provided" )
1503+ }
1504+
1505+ fn visit_map < A > ( self , mut access : A ) -> Result < Self :: Value , A :: Error >
1506+ where
1507+ A : de:: MapAccess < ' de > ,
1508+ {
1509+ let mut map: Map < String , Context > = Map :: new ( ) ;
1510+
1511+ while let Some ( ( key, value) ) = access. next_entry :: < String , Value > ( ) ? {
1512+ match Context :: from_type ( & key, value) {
1513+ Ok ( context) => {
1514+ map. insert ( key, context) ;
1515+ }
1516+ Err ( e) => return Err ( de:: Error :: custom ( e. to_string ( ) ) ) ,
1517+ }
1518+ }
1519+
1520+ Ok ( map)
1521+ }
1522+ }
1523+
1524+ fn deserialize_contexts < ' de , D > ( deserializer : D ) -> Result < Map < String , Context > , D :: Error >
1525+ where
1526+ D : Deserializer < ' de > ,
1527+ {
1528+ deserializer. deserialize_map ( ContextsVisitor { } )
1529+ }
1530+
14801531mod event {
14811532 use super :: * ;
14821533
@@ -1578,7 +1629,11 @@ pub struct Event<'a> {
15781629 #[ serde( default , skip_serializing_if = "Option::is_none" ) ]
15791630 pub request : Option < Request > ,
15801631 /// Optional contexts.
1581- #[ serde( default , skip_serializing_if = "Map::is_empty" ) ]
1632+ #[ serde(
1633+ default ,
1634+ skip_serializing_if = "Map::is_empty" ,
1635+ deserialize_with = "deserialize_contexts"
1636+ ) ]
15821637 pub contexts : Map < String , Context > ,
15831638 /// List of breadcrumbs to send along.
15841639 #[ serde( default , skip_serializing_if = "Values::is_empty" ) ]
@@ -1943,7 +1998,11 @@ pub struct Transaction<'a> {
19431998 /// The collection of finished spans part of this transaction.
19441999 pub spans : Vec < Span > ,
19452000 /// Optional contexts.
1946- #[ serde( default , skip_serializing_if = "Map::is_empty" ) ]
2001+ #[ serde(
2002+ default ,
2003+ skip_serializing_if = "Map::is_empty" ,
2004+ deserialize_with = "deserialize_contexts"
2005+ ) ]
19472006 pub contexts : Map < String , Context > ,
19482007 /// Optionally HTTP request data to be sent along.
19492008 #[ serde( default , skip_serializing_if = "Option::is_none" ) ]
0 commit comments