1use std::collections::BTreeMap;
9
10use crate::cap::CapId;
11use crate::promise::PromiseId;
12
13#[derive(Debug, Clone, PartialEq)]
15pub enum Value {
16 Null,
18 Bool(bool),
20 Int(i64),
22 Float(f64),
24 Text(String),
26 List(Vec<Value>),
28 Map(BTreeMap<String, Value>),
30 Secret,
32 Module(Vec<u8>),
34 Path(String),
36}
37
38impl Value {
39 pub fn text(value: impl Into<String>) -> Value {
41 Value::Text(value.into())
42 }
43
44 pub fn path(value: impl Into<String>) -> Value {
46 Value::Path(value.into())
47 }
48
49 pub fn list(items: impl IntoIterator<Item = Value>) -> Value {
51 Value::List(items.into_iter().collect())
52 }
53
54 pub fn map<K: Into<String>, I: IntoIterator<Item = (K, Value)>>(entries: I) -> Value {
56 Value::Map(
57 entries
58 .into_iter()
59 .map(|(key, value)| (key.into(), value))
60 .collect(),
61 )
62 }
63
64 pub fn as_text(&self) -> Option<&str> {
66 match self {
67 Value::Text(text) => Some(text),
68 _ => None,
69 }
70 }
71
72 pub fn as_path(&self) -> Option<&str> {
74 match self {
75 Value::Path(path) => Some(path),
76 _ => None,
77 }
78 }
79
80 pub fn wire_size(&self) -> u64 {
82 match self {
83 Value::Null => 1,
84 Value::Bool(_) => 2,
85 Value::Int(_) | Value::Float(_) => 9,
86 Value::Text(text) | Value::Path(text) => 5 + text.len() as u64,
87 Value::Secret => 1,
88 Value::Module(bytes) => 5 + bytes.len() as u64,
89 Value::List(items) => 5 + items.iter().map(Value::wire_size).sum::<u64>(),
90 Value::Map(entries) => {
91 5 + entries
92 .iter()
93 .map(|(key, value)| 5 + key.len() as u64 + value.wire_size())
94 .sum::<u64>()
95 }
96 }
97 }
98
99 pub fn is_tainted(&self) -> bool {
101 match self {
102 Value::Secret => true,
103 Value::List(items) => items.iter().any(Value::is_tainted),
104 Value::Map(entries) => entries.values().any(Value::is_tainted),
105 _ => false,
106 }
107 }
108}
109
110#[derive(Debug, Clone, PartialEq)]
112pub enum Arg {
113 Value(Value),
115 Promise(PromiseId),
117 Cap(CapId),
119}
120
121impl Arg {
122 pub fn value(value: Value) -> Arg {
124 Arg::Value(value)
125 }
126
127 pub fn text(value: impl Into<String>) -> Arg {
129 Arg::Value(Value::Text(value.into()))
130 }
131
132 pub fn promise(&self) -> Option<PromiseId> {
134 match self {
135 Arg::Promise(id) => Some(*id),
136 _ => None,
137 }
138 }
139
140 pub fn wire_size(&self) -> u64 {
142 match self {
143 Arg::Value(value) => value.wire_size(),
144 Arg::Promise(_) => 8,
145 Arg::Cap(_) => 16,
146 }
147 }
148}
149
150#[derive(Debug, Clone, PartialEq)]
152pub struct Call {
153 pub method: String,
155 pub args: Vec<Arg>,
157 pub path_scope: Option<String>,
159 pub redact: bool,
161 pub read_only: bool,
163 pub tool_allows_process: bool,
165 pub budget: crate::budget::Budget,
167}
168
169impl Call {
170 pub fn new(method: impl Into<String>, args: Vec<Arg>) -> Call {
172 Call {
173 method: method.into(),
174 args,
175 path_scope: None,
176 redact: false,
177 read_only: false,
178 tool_allows_process: false,
179 budget: crate::budget::Budget::default(),
180 }
181 }
182
183 pub fn first(&self) -> Option<&Arg> {
185 self.args.first()
186 }
187}
188
189#[derive(Debug, Clone, PartialEq)]
191pub enum Response {
192 Value(Value),
194 Module(Vec<u8>),
196 Labels(Vec<String>),
198}
199
200impl Response {
201 pub fn into_value(self) -> Value {
203 match self {
204 Response::Value(value) => value,
205 Response::Module(bytes) => Value::Module(bytes),
206 Response::Labels(labels) => Value::List(labels.into_iter().map(Value::Text).collect()),
207 }
208 }
209}