use anyhow::Context;
use base64::prelude::*;
use mcvm_shared::output::{Message, MessageLevel};
use serde::{Deserialize, Serialize};
pub static STARTING_DELIMITER: &str = "%_";
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum OutputAction {
Text(String, MessageLevel),
Message(Message),
StartProcess,
EndProcess,
StartSection,
EndSection,
SetResult(String),
SetState(serde_json::Value),
}
impl OutputAction {
pub fn serialize(&self, use_base64: bool, protocol_version: u16) -> anyhow::Result<String> {
let json = serde_json::to_string(&self).context("Failed to serialize output action")?;
let out = if use_base64 {
let base64 = BASE64_STANDARD.encode(json);
base64
} else {
json
};
if protocol_version >= 2 {
Ok(format!("{STARTING_DELIMITER}{out}"))
} else {
Ok(out)
}
}
pub fn deserialize(
action: &str,
use_base64: bool,
protocol_version: u16,
) -> anyhow::Result<Option<Self>> {
let action = if protocol_version >= 2 {
if action.starts_with(STARTING_DELIMITER) {
&action[STARTING_DELIMITER.len()..]
} else {
return Ok(None);
}
} else {
action
};
let json = if use_base64 {
BASE64_STANDARD
.decode(action)
.context("Failed to decode action base64")?
} else {
action.bytes().collect()
};
let action =
serde_json::from_slice(&json).context("Failed to deserialize output action")?;
Ok(Some(action))
}
}