systemprompt_models/
attribution.rs1use serde::{Deserialize, Serialize};
17use systemprompt_identifiers::{ApiKeyId, ScopeDimension};
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
22#[serde(rename_all = "snake_case")]
23pub enum AttributionSource {
24 Header,
25 ApiKey,
26 Default,
27}
28
29impl AttributionSource {
30 #[must_use]
31 pub const fn as_str(self) -> &'static str {
32 match self {
33 Self::Header => "header",
34 Self::ApiKey => "api_key",
35 Self::Default => "default",
36 }
37 }
38
39 #[must_use]
40 pub fn parse(value: &str) -> Option<Self> {
41 match value {
42 "header" => Some(Self::Header),
43 "api_key" => Some(Self::ApiKey),
44 "default" => Some(Self::Default),
45 _ => None,
46 }
47 }
48}
49
50impl std::fmt::Display for AttributionSource {
51 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52 f.write_str(self.as_str())
53 }
54}
55
56#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
58pub struct AttributionEntry {
59 pub dimension: ScopeDimension,
60 pub value: String,
61 pub source: AttributionSource,
62}
63
64#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
66pub struct RequestAttribution {
67 pub entries: Vec<AttributionEntry>,
68 pub api_key_id: Option<ApiKeyId>,
69}
70
71impl RequestAttribution {
72 #[must_use]
73 pub fn none() -> Self {
74 Self::default()
75 }
76
77 #[must_use]
78 pub fn value_for(&self, dimension: &str) -> Option<&str> {
79 self.entries
80 .iter()
81 .find(|entry| entry.dimension.as_str() == dimension)
82 .map(|entry| entry.value.as_str())
83 }
84}
85
86#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
89pub struct ScopeBinding {
90 pub dimension: ScopeDimension,
91 pub value: String,
92}