use super::{PluginWorkspaceReadError, PluginWorkspaceWriteError, WorkspaceAccessKind};
use crate::{
fs_utils::EscapedDisplayText,
plugin::{PluginIdentity, WorkspacePath, WorkspacePathRef},
};
use std::fmt::{Debug, Display, Formatter};
#[derive(Debug)]
pub struct PluginWorkspaceIoReport {
identity: PluginIdentity,
completions: Vec<PluginWorkspaceIoCompletion>,
}
impl PluginWorkspaceIoReport {
pub(super) const fn new(
identity: PluginIdentity,
completions: Vec<PluginWorkspaceIoCompletion>,
) -> Self {
Self {
identity,
completions,
}
}
#[must_use]
pub fn identity(&self) -> &str {
self.identity_proof().as_str()
}
#[must_use]
pub const fn identity_proof(&self) -> &PluginIdentity {
&self.identity
}
#[must_use]
pub fn completions(&self) -> &[PluginWorkspaceIoCompletion] {
&self.completions
}
}
pub enum PluginWorkspaceIoCompletion {
Read(PluginWorkspaceReadCompletion),
Write(PluginWorkspaceWriteCompletion),
}
impl PluginWorkspaceIoCompletion {
#[must_use]
pub const fn kind(&self) -> WorkspaceAccessKind {
match self {
Self::Read(_) => WorkspaceAccessKind::Read,
Self::Write(_) => WorkspaceAccessKind::Write,
}
}
#[must_use]
pub const fn workspace_path(&self) -> WorkspacePathRef<'_> {
match self {
Self::Read(completion) => completion.workspace_path(),
Self::Write(completion) => completion.workspace_path(),
}
}
#[must_use]
pub fn workspace_relative_path(&self) -> &str {
match self {
Self::Read(completion) => completion.workspace_relative_path(),
Self::Write(completion) => completion.workspace_relative_path(),
}
}
#[must_use]
pub const fn is_ok(&self) -> bool {
match self {
Self::Read(completion) => completion.outcome().is_ok(),
Self::Write(completion) => completion.outcome().is_ok(),
}
}
#[must_use]
pub const fn as_read(&self) -> Option<&PluginWorkspaceReadCompletion> {
match self {
Self::Read(completion) => Some(completion),
Self::Write(_) => None,
}
}
#[must_use]
pub const fn as_write(&self) -> Option<&PluginWorkspaceWriteCompletion> {
match self {
Self::Read(_) => None,
Self::Write(completion) => Some(completion),
}
}
}
impl Debug for PluginWorkspaceIoCompletion {
fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::Read(completion) => completion.fmt(formatter),
Self::Write(completion) => completion.fmt(formatter),
}
}
}
pub struct PluginWorkspaceReadCompletion {
workspace_path: WorkspacePath,
outcome: Result<PluginWorkspaceReadSuccess, PluginWorkspaceReadError>,
}
impl PluginWorkspaceReadCompletion {
pub(super) const fn new(
workspace_path: WorkspacePath,
outcome: Result<PluginWorkspaceReadSuccess, PluginWorkspaceReadError>,
) -> Self {
Self {
workspace_path,
outcome,
}
}
#[must_use]
pub const fn workspace_path(&self) -> WorkspacePathRef<'_> {
self.workspace_path.as_ref()
}
#[must_use]
pub fn workspace_relative_path(&self) -> &str {
self.workspace_path.as_str()
}
pub const fn outcome(&self) -> &Result<PluginWorkspaceReadSuccess, PluginWorkspaceReadError> {
&self.outcome
}
}
impl Debug for PluginWorkspaceReadCompletion {
fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
formatter
.debug_struct("PluginWorkspaceReadCompletion")
.field("kind", &WorkspaceAccessKind::Read)
.field("path_byte_len", &self.workspace_path.as_str().len())
.field("outcome", &self.outcome)
.finish()
}
}
pub struct PluginWorkspaceWriteCompletion {
workspace_path: WorkspacePath,
outcome: Result<PluginWorkspaceWriteSuccess, PluginWorkspaceWriteError>,
}
impl PluginWorkspaceWriteCompletion {
pub(super) const fn new(
workspace_path: WorkspacePath,
outcome: Result<PluginWorkspaceWriteSuccess, PluginWorkspaceWriteError>,
) -> Self {
Self {
workspace_path,
outcome,
}
}
#[must_use]
pub const fn workspace_path(&self) -> WorkspacePathRef<'_> {
self.workspace_path.as_ref()
}
#[must_use]
pub fn workspace_relative_path(&self) -> &str {
self.workspace_path.as_str()
}
pub const fn outcome(&self) -> &Result<PluginWorkspaceWriteSuccess, PluginWorkspaceWriteError> {
&self.outcome
}
}
impl Debug for PluginWorkspaceWriteCompletion {
fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
formatter
.debug_struct("PluginWorkspaceWriteCompletion")
.field("kind", &WorkspaceAccessKind::Write)
.field("path_byte_len", &self.workspace_path.as_str().len())
.field("outcome", &self.outcome)
.finish()
}
}
#[derive(Eq, PartialEq)]
pub struct PluginWorkspaceReadSuccess {
display_path: EscapedDisplayText,
bytes: Vec<u8>,
}
impl PluginWorkspaceReadSuccess {
pub(super) const fn new(display_path: EscapedDisplayText, bytes: Vec<u8>) -> Self {
Self {
display_path,
bytes,
}
}
#[must_use]
pub const fn display_path(&self) -> &EscapedDisplayText {
&self.display_path
}
#[must_use]
pub fn bytes(&self) -> &[u8] {
&self.bytes
}
}
impl Debug for PluginWorkspaceReadSuccess {
fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
formatter
.debug_struct("PluginWorkspaceReadSuccess")
.field("display_path_byte_len", &self.display_path.as_str().len())
.field("byte_len", &self.bytes.len())
.finish()
}
}
#[derive(Clone, Eq, PartialEq)]
pub enum PluginWorkspaceObserveOutcome {
Bytes(PluginWorkspaceObserveBytes),
Rejected,
}
impl PluginWorkspaceObserveOutcome {
#[must_use]
pub fn from_read_outcome(
outcome: &Result<PluginWorkspaceReadSuccess, PluginWorkspaceReadError>,
) -> Self {
match outcome {
Ok(success) => Self::Bytes(PluginWorkspaceObserveBytes {
bytes: success.bytes.clone(),
}),
Err(_source) => Self::Rejected,
}
}
#[must_use]
pub(super) fn from_read_result(
outcome: Result<PluginWorkspaceReadSuccess, PluginWorkspaceReadError>,
) -> Self {
match outcome {
Ok(success) => Self::Bytes(PluginWorkspaceObserveBytes {
bytes: success.bytes,
}),
Err(_source) => Self::Rejected,
}
}
#[must_use]
pub const fn is_ok(&self) -> bool {
matches!(self, Self::Bytes(_))
}
#[must_use]
pub const fn shape(&self) -> PluginWorkspaceObserveOutcomeShape {
match self {
Self::Bytes(bytes) => PluginWorkspaceObserveOutcomeShape::Bytes {
byte_len: bytes.len(),
},
Self::Rejected => PluginWorkspaceObserveOutcomeShape::Rejected,
}
}
#[must_use]
pub fn bytes(&self) -> Option<&[u8]> {
match self {
Self::Bytes(bytes) => Some(bytes.as_slice()),
Self::Rejected => None,
}
}
#[must_use]
pub fn into_bytes(self) -> Option<Vec<u8>> {
match self {
Self::Bytes(bytes) => Some(bytes.into_vec()),
Self::Rejected => None,
}
}
}
impl Debug for PluginWorkspaceObserveOutcome {
fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
formatter
.debug_struct("PluginWorkspaceObserveOutcome")
.field("shape", &self.shape())
.finish()
}
}
impl From<&PluginWorkspaceReadCompletion> for PluginWorkspaceObserveOutcome {
fn from(completion: &PluginWorkspaceReadCompletion) -> Self {
Self::from_read_outcome(completion.outcome())
}
}
impl TryFrom<&PluginWorkspaceIoCompletion> for PluginWorkspaceObserveOutcome {
type Error = PluginWorkspaceObserveProjectionError;
fn try_from(completion: &PluginWorkspaceIoCompletion) -> Result<Self, Self::Error> {
match completion {
PluginWorkspaceIoCompletion::Read(completion) => Ok(Self::from(completion)),
PluginWorkspaceIoCompletion::Write(_completion) => {
Err(PluginWorkspaceObserveProjectionError::WrongOperation {
kind: WorkspaceAccessKind::Write,
})
}
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum PluginWorkspaceObserveOutcomeShape {
Bytes {
byte_len: usize,
},
Rejected,
}
impl PluginWorkspaceObserveOutcomeShape {
#[must_use]
pub const fn is_ok(self) -> bool {
matches!(self, Self::Bytes { .. })
}
}
impl Display for PluginWorkspaceObserveOutcomeShape {
fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::Bytes { byte_len } => write!(formatter, "bytes byte_len={byte_len}"),
Self::Rejected => formatter.write_str("rejected"),
}
}
}
#[derive(Clone, Eq, PartialEq)]
pub struct PluginWorkspaceObserveBytes {
bytes: Vec<u8>,
}
impl PluginWorkspaceObserveBytes {
#[must_use]
pub fn as_slice(&self) -> &[u8] {
&self.bytes
}
#[must_use]
pub const fn len(&self) -> usize {
self.bytes.len()
}
#[must_use]
pub const fn is_empty(&self) -> bool {
self.bytes.is_empty()
}
#[must_use]
pub fn into_vec(self) -> Vec<u8> {
self.bytes
}
}
impl Debug for PluginWorkspaceObserveBytes {
fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
formatter
.debug_struct("PluginWorkspaceObserveBytes")
.field("byte_len", &self.bytes.len())
.finish()
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, thiserror::Error)]
#[non_exhaustive]
pub enum PluginWorkspaceObserveProjectionError {
#[error("workspace observe projection requires read completion, got {kind}")]
WrongOperation {
kind: WorkspaceAccessKind,
},
}
impl PluginWorkspaceObserveProjectionError {
#[must_use]
pub const fn kind(self) -> WorkspaceAccessKind {
match self {
Self::WrongOperation { kind } => kind,
}
}
}
#[derive(Eq, PartialEq)]
pub struct PluginWorkspaceWriteSuccess {
display_path: EscapedDisplayText,
}
impl PluginWorkspaceWriteSuccess {
pub(super) const fn new(display_path: EscapedDisplayText) -> Self {
Self { display_path }
}
#[must_use]
pub const fn display_path(&self) -> &EscapedDisplayText {
&self.display_path
}
}
impl Debug for PluginWorkspaceWriteSuccess {
fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
formatter
.debug_struct("PluginWorkspaceWriteSuccess")
.field("display_path_byte_len", &self.display_path.as_str().len())
.finish()
}
}