use std::collections::BTreeMap;
use crate::cap::CapId;
use crate::promise::PromiseId;
#[derive(Debug, Clone, PartialEq)]
pub enum Value {
Null,
Bool(bool),
Int(i64),
Float(f64),
Text(String),
List(Vec<Value>),
Map(BTreeMap<String, Value>),
Secret,
Module(Vec<u8>),
Path(String),
}
impl Value {
pub fn text(value: impl Into<String>) -> Value {
Value::Text(value.into())
}
pub fn path(value: impl Into<String>) -> Value {
Value::Path(value.into())
}
pub fn list(items: impl IntoIterator<Item = Value>) -> Value {
Value::List(items.into_iter().collect())
}
pub fn map<K: Into<String>, I: IntoIterator<Item = (K, Value)>>(entries: I) -> Value {
Value::Map(
entries
.into_iter()
.map(|(key, value)| (key.into(), value))
.collect(),
)
}
pub fn as_text(&self) -> Option<&str> {
match self {
Value::Text(text) => Some(text),
_ => None,
}
}
pub fn as_path(&self) -> Option<&str> {
match self {
Value::Path(path) => Some(path),
_ => None,
}
}
pub fn wire_size(&self) -> u64 {
match self {
Value::Null => 1,
Value::Bool(_) => 2,
Value::Int(_) | Value::Float(_) => 9,
Value::Text(text) | Value::Path(text) => 5 + text.len() as u64,
Value::Secret => 1,
Value::Module(bytes) => 5 + bytes.len() as u64,
Value::List(items) => 5 + items.iter().map(Value::wire_size).sum::<u64>(),
Value::Map(entries) => {
5 + entries
.iter()
.map(|(key, value)| 5 + key.len() as u64 + value.wire_size())
.sum::<u64>()
}
}
}
pub fn is_tainted(&self) -> bool {
match self {
Value::Secret => true,
Value::List(items) => items.iter().any(Value::is_tainted),
Value::Map(entries) => entries.values().any(Value::is_tainted),
_ => false,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum Arg {
Value(Value),
Promise(PromiseId),
Cap(CapId),
}
impl Arg {
pub fn value(value: Value) -> Arg {
Arg::Value(value)
}
pub fn text(value: impl Into<String>) -> Arg {
Arg::Value(Value::Text(value.into()))
}
pub fn promise(&self) -> Option<PromiseId> {
match self {
Arg::Promise(id) => Some(*id),
_ => None,
}
}
pub fn wire_size(&self) -> u64 {
match self {
Arg::Value(value) => value.wire_size(),
Arg::Promise(_) => 8,
Arg::Cap(_) => 16,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Call {
pub method: String,
pub args: Vec<Arg>,
pub path_scope: Option<String>,
pub redact: bool,
pub read_only: bool,
pub tool_allows_process: bool,
pub budget: crate::budget::Budget,
}
impl Call {
pub fn new(method: impl Into<String>, args: Vec<Arg>) -> Call {
Call {
method: method.into(),
args,
path_scope: None,
redact: false,
read_only: false,
tool_allows_process: false,
budget: crate::budget::Budget::default(),
}
}
pub fn first(&self) -> Option<&Arg> {
self.args.first()
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum Response {
Value(Value),
Module(Vec<u8>),
Labels(Vec<String>),
}
impl Response {
pub fn into_value(self) -> Value {
match self {
Response::Value(value) => value,
Response::Module(bytes) => Value::Module(bytes),
Response::Labels(labels) => Value::List(labels.into_iter().map(Value::Text).collect()),
}
}
}