blob: 104060c87d227ed519e0fbe86a776d82d9eb78d3 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::ID;
pub struct SegmentRef {
trace_id: ID,
segment_id: ID,
span_id: i32,
parent_service_instance_id: i32,
entry_service_instance_id: i32,
network_address: Option<String>,
network_address_id: i32,
entry_endpoint: Option<String>,
entry_endpoint_id: i32,
parent_endpoint: Option<String>,
parent_endpoint_id: i32,
}
impl SegmentRef {
pub fn from_text(value: &str) -> Option<Self> {
let strings: Vec<&str> = value.split("-").collect();
if strings.len() == 9 {
// Ignore string[0].
let trace_id = match SegmentRef::string_to_id(strings[1]) {
Some(id) => { id }
_ => { return None; }
};
let segment_id = match SegmentRef::string_to_id(strings[2]) {
Some(id) => { id }
_ => { return None; }
};
let span_id = match strings[3].parse::<i32>() {
Ok(id) => { id }
_ => { return None; }
};
let parent_service_instance_id = match strings[4].parse::<i32>() {
Ok(id) => { id }
_ => { return None; }
};
let entry_service_instance_id = match strings[5].parse::<i32>() {
Ok(id) => { id }
_ => { return None; }
};
let (network_address, network_address_id) = match SegmentRef::decode_base64_to_string_or_id(strings[6]) {
Some(decoded) => { decoded }
_ => { return None; }
};
let (entry_endpoint, entry_endpoint_id) = match SegmentRef::decode_base64_to_string_or_id(strings[7]) {
Some(decoded) => { decoded }
_ => { return None; }
};
let (parent_endpoint, parent_endpoint_id) = match SegmentRef::decode_base64_to_string_or_id(strings[8]) {
Some(decoded) => { decoded }
_ => { return None; }
};
Some(SegmentRef {
trace_id,
segment_id,
span_id,
parent_service_instance_id,
entry_service_instance_id,
network_address,
network_address_id,
entry_endpoint,
entry_endpoint_id,
parent_endpoint,
parent_endpoint_id,
})
} else {
None
}
}
pub fn get_trace_id(&self) -> ID {
self.trace_id.clone()
}
fn string_to_id(text: &str) -> Option<ID> {
match base64::decode(text) {
Ok(value) => {
match String::from_utf8(value) {
Ok(str) => {
match ID::from(str) {
Ok(id) => { Some(id) }
_ => None
}
}
_ => { None }
}
}
_ => { None }
}
}
fn decode_base64_to_string_or_id(text: &str) -> Option<(Option<String>, i32)> {
match base64::decode(text) {
Ok(value) => {
match String::from_utf8(value) {
Ok(str) => {
if str.starts_with("#") {
let network: Vec<&str> = str.split("#").collect();
(Some((Some(network[1].to_string()), 0)))
} else {
match str.parse::<i32>() {
Ok(id) => { Some((None, id)) }
_ => { None }
}
}
}
_ => { None }
}
}
_ => { None }
}
}
}
#[cfg(test)]
mod segment_ref_tests {
use crate::ID;
use crate::segment_ref::SegmentRef;
#[test]
fn test_deserialize_context_carrier() {
let carrier = SegmentRef::from_text("1-My40LjU=-MS4yLjM=-4-1-1-IzEyNy4wLjAuMTo4MDgw-Iy9wb3J0YWw=-MTIz").unwrap();
assert_eq!(carrier.trace_id == ID::new(3, 4, 5), true);
assert_eq!(carrier.segment_id == ID::new(1, 2, 3), true);
assert_eq!(carrier.span_id, 4);
assert_eq!(carrier.entry_service_instance_id, 1);
assert_eq!(carrier.parent_service_instance_id, 1);
assert_eq!(carrier.network_address, Some("127.0.0.1:8080".to_string()));
assert_eq!(carrier.entry_endpoint, Some("/portal".to_string()));
assert_eq!(carrier.parent_endpoint_id, 123);
}
}