get_helpers/
lib.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Helpers to build GET (Guest Emulation Transport) protocol payloads.
5
6#![forbid(unsafe_code)]
7
8use get_protocol::LogFlags;
9use get_protocol::LogLevel;
10use get_protocol::LogType;
11use get_protocol::TRACE_LOGGING_FIELDS_MAX_SIZE;
12use get_protocol::TRACE_LOGGING_MESSAGE_MAX_SIZE;
13use get_protocol::TRACE_LOGGING_NAME_MAX_SIZE;
14use get_protocol::TRACE_LOGGING_TARGET_MAX_SIZE;
15use get_protocol::TraceLoggingBufferOffset;
16use get_protocol::TraceLoggingNotificationHeader;
17use guid::Guid;
18use zerocopy::IntoBytes;
19
20/// Truncates the specified slice by the specified length.
21fn truncate_slice(input: &[u8], len: usize) -> &[u8] {
22    if input.len() <= len {
23        input
24    } else {
25        &input[..len]
26    }
27}
28
29/// Helper function to build the tracelogging buffer with the specified fields
30pub fn build_tracelogging_notification_buffer(
31    log_type: LogType,
32    level: LogLevel,
33    flags: LogFlags,
34    activity_id: Option<Guid>,
35    related_activity_id: Option<Guid>,
36    correlation_id: Option<Guid>,
37    name: Option<&[u8]>,
38    target: Option<&[u8]>,
39    fields: Option<&[u8]>,
40    message: &[u8],
41    timestamp: u64,
42) -> Vec<u8> {
43    let name = name.map_or(&[] as &[u8], |slice| {
44        truncate_slice(slice, TRACE_LOGGING_NAME_MAX_SIZE)
45    });
46    let name_size = name.len();
47    let name_offset = 0;
48
49    let target = target.map_or(&[] as &[u8], |slice| {
50        truncate_slice(slice, TRACE_LOGGING_TARGET_MAX_SIZE)
51    });
52    let target_size = target.len();
53    let target_offset = name_offset + name_size;
54
55    let fields = fields.map_or(&[] as &[u8], |slice| {
56        truncate_slice(slice, TRACE_LOGGING_FIELDS_MAX_SIZE)
57    });
58    let fields_size = fields.len();
59    let fields_offset = target_offset + target_size;
60
61    let message = truncate_slice(message, TRACE_LOGGING_MESSAGE_MAX_SIZE);
62    let message_size = message.len();
63    let message_offset = fields_offset + fields_size;
64
65    let mut buffer = vec![];
66
67    let header = TraceLoggingNotificationHeader {
68        log_type,
69        level: level.into(),
70        flags,
71        name: TraceLoggingBufferOffset {
72            size: name_size as u16,
73            offset: name_offset as u16,
74        },
75        target: TraceLoggingBufferOffset {
76            size: target_size as u16,
77            offset: target_offset as u16,
78        },
79        fields: TraceLoggingBufferOffset {
80            size: fields_size as u16,
81            offset: fields_offset as u16,
82        },
83        message: TraceLoggingBufferOffset {
84            size: message_size as u16,
85            offset: message_offset as u16,
86        },
87        mbz0: 0,
88        activity_id: activity_id.unwrap_or(Guid::ZERO),
89        related_activity_id: related_activity_id.unwrap_or(Guid::ZERO),
90        correlation_id: correlation_id.unwrap_or(Guid::ZERO),
91        timestamp,
92    };
93
94    buffer.extend_from_slice(header.as_bytes());
95    buffer.extend_from_slice(name);
96    buffer.extend_from_slice(target);
97    buffer.extend_from_slice(fields);
98    buffer.extend_from_slice(message);
99
100    buffer
101}