blob: 7aabe85afa1ff05eb602a25a4b43ce603f9e5069 [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
use crate::{
archive::ToolResultAddress, attachment::ATTACHMENT_RESOURCE_PREFIX, interaction::entity_id,
shell_result::RESOURCE_REF_PREFIX,
};
/// A Session resource locator; resolving it never grants access to its content.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ResourceAddress {
Attachment(String),
Task(String),
ToolResult(String),
}
impl ResourceAddress {
/// Ordinary filesystem paths have no resource address.
pub fn parse(path: &str) -> Result<Option<Self>, &'static str> {
if path.starts_with("archive:") || path.starts_with("maka://runtime/tool-results/") {
return ToolResultAddress::parse(path)
.map(|address| Some(Self::ToolResult(address.event_id().to_owned())));
}
for (short, full, attachment) in [
("attachment:", ATTACHMENT_RESOURCE_PREFIX, true),
("task:", RESOURCE_REF_PREFIX, false),
] {
if let Some(id) = path.strip_prefix(short).or_else(|| path.strip_prefix(full)) {
entity_id(id)?;
return Ok(Some(if attachment {
Self::Attachment(id.into())
} else {
Self::Task(id.into())
}));
}
}
if path.contains("://") {
return Err("Unsupported Maka address; use a path returned by a tool");
}
Ok(None)
}
pub fn id(&self) -> &str {
match self {
Self::Attachment(id) | Self::Task(id) | Self::ToolResult(id) => id,
}
}
pub fn with_id(mut self, resolved: String) -> Self {
match &mut self {
Self::Attachment(id) | Self::Task(id) | Self::ToolResult(id) => *id = resolved,
}
self
}
pub fn canonical_path(&self) -> Result<String, &'static str> {
match self {
Self::Attachment(id) => {
entity_id(id)?;
Ok(format!("{ATTACHMENT_RESOURCE_PREFIX}{id}"))
}
Self::Task(id) => {
entity_id(id)?;
Ok(format!("{RESOURCE_REF_PREFIX}{id}"))
}
Self::ToolResult(id) => ToolResultAddress::event_path(id),
}
}
/// A compact, still valid locator. No ID truncation or uniqueness assumption.
pub fn compact_path(&self) -> Result<String, &'static str> {
let path = self.canonical_path()?;
let (prefix, id) = match self {
Self::Attachment(_) => ("attachment:", &path[ATTACHMENT_RESOURCE_PREFIX.len()..]),
Self::Task(_) => ("task:", &path[RESOURCE_REF_PREFIX.len()..]),
Self::ToolResult(_) => ("archive:", &path["maka://runtime/tool-results/".len()..]),
};
Ok(format!("{prefix}{id}"))
}
}