#[cfg(feature = "serde")]
use alloc::string::String;
use alloc::{boxed::Box, string::ToString};
use core::fmt;
#[cfg(feature = "serde")]
use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error as DeError};
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "arbitrary", derive(proptest_derive::Arbitrary))]
#[cfg_attr(all(feature = "arbitrary", test), miden_test_serde_macros::serde_test)]
#[non_exhaustive]
#[repr(u8)]
pub enum TargetType {
#[default]
Library = 0,
Executable = 1,
Kernel = 2,
AccountComponent = 3,
Note = 4,
TransactionScript = 5,
}
impl TargetType {
pub const fn is_executable(&self) -> bool {
matches!(self, Self::Executable)
}
pub const fn is_library(&self) -> bool {
!self.is_executable()
}
pub const fn as_str(&self) -> &'static str {
match self {
Self::Library => "library",
Self::Executable => "executable",
Self::Kernel => "kernel",
Self::AccountComponent => "account-component",
Self::Note => "note",
Self::TransactionScript => "transaction-script",
}
}
}
impl TryFrom<u8> for TargetType {
type Error = InvalidTargetTypeError;
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0 => Ok(Self::Library),
1 => Ok(Self::Executable),
2 => Ok(Self::Kernel),
3 => Ok(Self::AccountComponent),
4 => Ok(Self::Note),
5 => Ok(Self::TransactionScript),
_ => Err(InvalidTargetTypeError::Tag(value)),
}
}
}
impl From<TargetType> for u8 {
#[inline(always)]
fn from(kind: TargetType) -> Self {
kind as u8
}
}
impl fmt::Display for TargetType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
impl core::str::FromStr for TargetType {
type Err = InvalidTargetTypeError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"lib" | "library" => Ok(Self::Library),
"bin" | "program" | "executable" => Ok(Self::Executable),
"kernel" => Ok(Self::Kernel),
"account" | "account-component" => Ok(Self::AccountComponent),
"note" => Ok(Self::Note),
"tx-script" | "transaction-script" => Ok(Self::TransactionScript),
s => Err(InvalidTargetTypeError::Name(s.to_string().into_boxed_str())),
}
}
}
#[cfg(feature = "serde")]
impl Serialize for TargetType {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
if serializer.is_human_readable() {
serializer.serialize_str(self.as_str())
} else {
serializer.serialize_u8(*self as u8)
}
}
}
#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for TargetType {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
if deserializer.is_human_readable() {
let s = String::deserialize(deserializer)?;
s.parse::<TargetType>().map_err(|err| DeError::custom(err.to_string()))
} else {
let tag = u8::deserialize(deserializer)?;
Self::try_from(tag).map_err(|err| DeError::custom(err.to_string()))
}
}
}
mod serialization {
use alloc::string::ToString;
use miden_core::serde::*;
use super::TargetType;
impl Serializable for TargetType {
fn write_into<W: ByteWriter>(&self, target: &mut W) {
target.write_u8(*self as u8);
}
}
impl Deserializable for TargetType {
fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
TargetType::try_from(source.read_u8()?)
.map_err(|err| DeserializationError::InvalidValue(err.to_string()))
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum InvalidTargetTypeError {
Tag(u8),
Name(Box<str>),
}
impl fmt::Display for InvalidTargetTypeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Tag(tag) => write!(f, "invalid target type tag: {tag}"),
Self::Name(name) => write!(f, "invalid target type: '{name}'"),
}
}
}