cf_rustracing/
carrier.rs

1//! Traits for representing carriers that propagate span contexts across process boundaries.
2use crate::span::SpanContext;
3use crate::Result;
4use std::collections::{BTreeMap, HashMap};
5use std::hash::{BuildHasher, Hash};
6use std::io::{Read, Write};
7
8/// This trait allows to inject `SpanContext` to `TextMap`.
9pub trait InjectToTextMap<T>: Sized
10where
11    T: TextMap,
12{
13    /// Injects `context` to `carrier`.
14    fn inject_to_text_map(context: &SpanContext<Self>, carrier: &mut T) -> Result<()>;
15}
16
17/// This trait allows to extract `SpanContext` from `TextMap`.
18pub trait ExtractFromTextMap<T>: Sized
19where
20    T: TextMap,
21{
22    /// Extracts `SpanContext` from `carrier`.
23    ///
24    /// If `carrier` contains no span context, it will return `Ok(None)`.
25    fn extract_from_text_map(carrier: &T) -> Result<Option<SpanContext<Self>>>;
26}
27
28/// This trait represents carriers which support **Text Map** format.
29///
30/// **Text Map** is an arbitrary string-to-string map with an unrestricted character set
31/// for both keys and values.
32pub trait TextMap {
33    /// Sets the value of `key` in the map to `value`.
34    fn set(&mut self, key: &str, value: &str);
35
36    /// Gets the value of `key'.
37    fn get(&self, key: &str) -> Option<&str>;
38}
39impl<S: BuildHasher> TextMap for HashMap<String, String, S> {
40    fn set(&mut self, key: &str, value: &str) {
41        self.insert(key.to_owned(), value.to_owned());
42    }
43    fn get(&self, key: &str) -> Option<&str> {
44        HashMap::get(self, key).map(|v| v.as_ref())
45    }
46}
47impl TextMap for BTreeMap<String, String> {
48    fn set(&mut self, key: &str, value: &str) {
49        self.insert(key.to_owned(), value.to_owned());
50    }
51    fn get(&self, key: &str) -> Option<&str> {
52        BTreeMap::get(self, key).map(|v| v.as_ref())
53    }
54}
55
56/// This trait allows to inject `SpanContext` to HTTP header.
57pub trait InjectToHttpHeader<T>: Sized
58where
59    T: SetHttpHeaderField,
60{
61    /// Injects `context` to `carrier`.
62    fn inject_to_http_header(context: &SpanContext<Self>, carrier: &mut T) -> Result<()>;
63}
64
65/// This trait allows to extract `SpanContext` from HTTP header.
66pub trait ExtractFromHttpHeader<'a, T>: Sized
67where
68    T: IterHttpHeaderFields<'a>,
69{
70    /// Extracts `SpanContext` from `carrier`.
71    ///
72    /// If `carrier` contains no span context, it will return `Ok(None)`.
73    fn extract_from_http_header(carrier: &'a T) -> Result<Option<SpanContext<Self>>>;
74}
75
76/// This trait allows to insert fields in a HTTP header.
77pub trait SetHttpHeaderField {
78    /// Sets the value of the field named `name` in the HTTP header to `value`.
79    fn set_http_header_field(&mut self, name: &str, value: &str) -> Result<()>;
80}
81impl<S: BuildHasher> SetHttpHeaderField for HashMap<String, String, S> {
82    fn set_http_header_field(&mut self, name: &str, value: &str) -> Result<()> {
83        self.insert(name.to_owned(), value.to_owned());
84        Ok(())
85    }
86}
87
88/// This trait allows to iterate over the fields of a HTTP header.
89pub trait IterHttpHeaderFields<'a> {
90    /// Iterator for traversing HTTP header fields.
91    type Fields: Iterator<Item = (&'a str, &'a [u8])>;
92
93    /// Returns an iterator for traversing the HTTP header fields.
94    fn fields(&'a self) -> Self::Fields;
95}
96impl<'a, K, V, S> IterHttpHeaderFields<'a> for HashMap<K, V, S>
97where
98    K: AsRef<str> + Eq + Hash,
99    V: AsRef<[u8]>,
100    S: BuildHasher,
101{
102    type Fields = Box<dyn Iterator<Item = (&'a str, &'a [u8])> + 'a>;
103
104    fn fields(&'a self) -> Self::Fields {
105        Box::new(self.iter().map(|x| (x.0.as_ref(), x.1.as_ref())))
106    }
107}
108
109/// This trait allows to inject `SpanContext` to binary stream.
110pub trait InjectToBinary<T>: Sized
111where
112    T: Write,
113{
114    /// Injects `context` to `carrier`.
115    fn inject_to_binary(context: &SpanContext<Self>, carrier: &mut T) -> Result<()>;
116}
117
118/// This trait allows to extract `SpanContext` from binary stream.
119pub trait ExtractFromBinary<T>: Sized
120where
121    T: Read,
122{
123    /// Extracts `SpanContext` from `carrier`.
124    ///
125    /// If `carrier` contains no span context, it will return `Ok(None)`.
126    fn extract_from_binary(carrier: &mut T) -> Result<Option<SpanContext<Self>>>;
127}