Skip to main content

libdd_profiling_protobuf/
string.rs

1// Copyright 2025-Present Datadog, Inc. https://www.datadoghq.com/
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::{varint, Value, WireType};
5use std::fmt;
6use std::io::{self, Write};
7
8unsafe impl Value for &str {
9    const WIRE_TYPE: WireType = WireType::LengthDelimited;
10
11    fn proto_len(&self) -> u64 {
12        self.len() as u64
13    }
14
15    fn encode<W: Write>(&self, writer: &mut W) -> io::Result<()> {
16        writer.write_all(self.as_bytes())
17    }
18}
19
20// todo: for OTEL, needs to be i32::MAX rather than u32::MAX.
21/// Represents an offset into the Profile's string table. Note that it cannot
22/// exceed u32 because an entire protobuf message must not be larger than or
23/// equal to 2 GiB. By the time you encode the tag and length prefix for each
24/// string, there's no way to get this many unique-ish strings without first
25/// exceeding the protobuf 2 GiB limit.
26///
27/// A value of 0 means "no string" or "empty string" (they are synonymous).
28/// cbindgen:field-names=[offset]
29#[repr(C)]
30#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
31#[cfg_attr(feature = "bolero", derive(bolero::generator::TypeGenerator))]
32pub struct StringOffset(u32);
33
34impl fmt::Display for StringOffset {
35    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
36        self.0.fmt(f)
37    }
38}
39
40/// # Safety
41/// The Default implementation will return all zero-representations.
42unsafe impl Value for StringOffset {
43    const WIRE_TYPE: WireType = WireType::Varint;
44
45    fn proto_len(&self) -> u64 {
46        varint::proto_len(u64::from(self))
47    }
48
49    fn encode<W: Write>(&self, writer: &mut W) -> io::Result<()> {
50        varint::encode(u64::from(self), writer)
51    }
52}
53
54impl TryFrom<usize> for StringOffset {
55    type Error = <u32 as TryFrom<usize>>::Error;
56
57    fn try_from(value: usize) -> Result<Self, Self::Error> {
58        Ok(StringOffset(u32::try_from(value)?))
59    }
60}
61
62impl TryFrom<&usize> for StringOffset {
63    type Error = <u32 as TryFrom<usize>>::Error;
64
65    fn try_from(value: &usize) -> Result<Self, Self::Error> {
66        StringOffset::try_from(*value)
67    }
68}
69
70impl From<StringOffset> for usize {
71    fn from(s: StringOffset) -> Self {
72        s.0 as usize
73    }
74}
75
76impl From<&StringOffset> for usize {
77    fn from(s: &StringOffset) -> Self {
78        s.0 as usize
79    }
80}
81
82impl From<u8> for StringOffset {
83    fn from(value: u8) -> Self {
84        StringOffset(value as u32)
85    }
86}
87
88impl From<u16> for StringOffset {
89    fn from(value: u16) -> Self {
90        StringOffset(value as u32)
91    }
92}
93
94impl From<u32> for StringOffset {
95    fn from(value: u32) -> Self {
96        StringOffset(value)
97    }
98}
99
100impl From<&u32> for StringOffset {
101    fn from(value: &u32) -> Self {
102        StringOffset(*value)
103    }
104}
105
106impl From<StringOffset> for u32 {
107    fn from(s: StringOffset) -> Self {
108        s.0
109    }
110}
111
112impl From<&StringOffset> for u32 {
113    fn from(s: &StringOffset) -> Self {
114        s.0
115    }
116}
117
118impl From<StringOffset> for u64 {
119    fn from(s: StringOffset) -> Self {
120        s.0 as u64
121    }
122}
123
124impl From<&StringOffset> for u64 {
125    fn from(s: &StringOffset) -> Self {
126        s.0 as u64
127    }
128}
129
130impl TryFrom<u64> for StringOffset {
131    type Error = <u32 as TryFrom<u64>>::Error;
132
133    fn try_from(value: u64) -> Result<Self, Self::Error> {
134        Ok(StringOffset(u32::try_from(value)?))
135    }
136}
137
138impl TryFrom<&u64> for StringOffset {
139    type Error = <u32 as TryFrom<u64>>::Error;
140
141    fn try_from(value: &u64) -> Result<Self, Self::Error> {
142        StringOffset::try_from(*value)
143    }
144}
145
146impl From<StringOffset> for i64 {
147    fn from(s: StringOffset) -> Self {
148        s.0 as i64
149    }
150}
151
152impl From<&StringOffset> for i64 {
153    fn from(s: &StringOffset) -> Self {
154        s.0 as i64
155    }
156}
157
158impl TryFrom<i64> for StringOffset {
159    type Error = <u32 as TryFrom<i64>>::Error;
160
161    fn try_from(value: i64) -> Result<Self, Self::Error> {
162        Ok(StringOffset(u32::try_from(value)?))
163    }
164}
165
166impl TryFrom<&i64> for StringOffset {
167    type Error = <u32 as TryFrom<i64>>::Error;
168
169    fn try_from(value: &i64) -> Result<Self, Self::Error> {
170        StringOffset::try_from(*value)
171    }
172}
173
174impl StringOffset {
175    pub const ZERO: Self = Self(0);
176
177    #[inline]
178    pub const fn new(offset: u32) -> Self {
179        Self(offset)
180    }
181
182    #[inline]
183    pub const fn is_zero(&self) -> bool {
184        self.0 == 0
185    }
186}