wrapped_mono 0.3.0

`wrapped_mono` is a safe, lightweight wrapper around the mono library. It allows embedding of the mono runtime inside a rust project. Inside this embedded runtime code written in languages supporting the .NET framework, such as C# and F#, can be run. This allows usage of libraries written in those languages, and using them as a scripting language. The mono runtime is used by many game engines, and this wrapper allows using it with projects written in Rust too.
Documentation
use crate::binds::MonoTableInfo;
use crate::Image;
///Representation of a table with metadata.
pub struct MetadataTableInfo {
    pub table: *const MonoTableInfo,
    pub kind: MetadataTableKind,
}
pub type MetadataToken = u32;
///Enum representing all possible kinds of metadata tables.
#[repr(u32)]
#[derive(PartialEq, Eq, Clone, Copy)]
pub enum MetadataTableKind {
    Module = crate::binds::MonoMetaTableEnum_MONO_TABLE_MODULE,
    TypeRef = crate::binds::MonoMetaTableEnum_MONO_TABLE_TYPEREF,
    TypeDef = crate::binds::MonoMetaTableEnum_MONO_TABLE_TYPEDEF,
    FieldPointer = crate::binds::MonoMetaTableEnum_MONO_TABLE_FIELD_POINTER,
    Field = crate::binds::MonoMetaTableEnum_MONO_TABLE_FIELD,
    MethodPointer = crate::binds::MonoMetaTableEnum_MONO_TABLE_METHOD_POINTER,
    Method = crate::binds::MonoMetaTableEnum_MONO_TABLE_METHOD,
    ParamPointer = crate::binds::MonoMetaTableEnum_MONO_TABLE_PARAM_POINTER,
    Param = crate::binds::MonoMetaTableEnum_MONO_TABLE_PARAM,
    InerfaceImpl = crate::binds::MonoMetaTableEnum_MONO_TABLE_INTERFACEIMPL,
    MemberRef = crate::binds::MonoMetaTableEnum_MONO_TABLE_MEMBERREF,
    Constant = crate::binds::MonoMetaTableEnum_MONO_TABLE_CONSTANT,
    CustomAttribute = crate::binds::MonoMetaTableEnum_MONO_TABLE_CUSTOMATTRIBUTE,
    FieldMarshal = crate::binds::MonoMetaTableEnum_MONO_TABLE_FIELDMARSHAL,
    DeclSceurity = crate::binds::MonoMetaTableEnum_MONO_TABLE_DECLSECURITY,
    ClassLayout = crate::binds::MonoMetaTableEnum_MONO_TABLE_CLASSLAYOUT,
    FieldLatout = crate::binds::MonoMetaTableEnum_MONO_TABLE_FIELDLAYOUT,
    StandaloneSig = crate::binds::MonoMetaTableEnum_MONO_TABLE_STANDALONESIG,
    EventMap = crate::binds::MonoMetaTableEnum_MONO_TABLE_EVENTMAP,
    EventPointer = crate::binds::MonoMetaTableEnum_MONO_TABLE_EVENT_POINTER,
    Event = crate::binds::MonoMetaTableEnum_MONO_TABLE_EVENT,
    PropertyMap = crate::binds::MonoMetaTableEnum_MONO_TABLE_PROPERTYMAP,
    PropertyPointer = crate::binds::MonoMetaTableEnum_MONO_TABLE_PROPERTY_POINTER,
    Property = crate::binds::MonoMetaTableEnum_MONO_TABLE_PROPERTY,
    MethodSemantics = crate::binds::MonoMetaTableEnum_MONO_TABLE_METHODSEMANTICS,
    MethodImpl = crate::binds::MonoMetaTableEnum_MONO_TABLE_METHODIMPL,
    ModuleRef = crate::binds::MonoMetaTableEnum_MONO_TABLE_MODULEREF,
    TypeSpec = crate::binds::MonoMetaTableEnum_MONO_TABLE_TYPESPEC,
    ImplMap = crate::binds::MonoMetaTableEnum_MONO_TABLE_IMPLMAP,
    FieldRVA = crate::binds::MonoMetaTableEnum_MONO_TABLE_FIELDRVA,
    Unused6 = crate::binds::MonoMetaTableEnum_MONO_TABLE_UNUSED6,
    Unused7 = crate::binds::MonoMetaTableEnum_MONO_TABLE_UNUSED7,
    Assembly = crate::binds::MonoMetaTableEnum_MONO_TABLE_ASSEMBLY,
    AssemblyProcessor = crate::binds::MonoMetaTableEnum_MONO_TABLE_ASSEMBLYPROCESSOR,
    AssemblyOS = crate::binds::MonoMetaTableEnum_MONO_TABLE_ASSEMBLYOS,
    AssmeblyRef = crate::binds::MonoMetaTableEnum_MONO_TABLE_ASSEMBLYREF,
    AssmeblyRefProcessor = crate::binds::MonoMetaTableEnum_MONO_TABLE_ASSEMBLYREFPROCESSOR,
    AssmeblyRefOS = crate::binds::MonoMetaTableEnum_MONO_TABLE_ASSEMBLYREFOS,
    File = crate::binds::MonoMetaTableEnum_MONO_TABLE_FILE,
    ExportedType = crate::binds::MonoMetaTableEnum_MONO_TABLE_EXPORTEDTYPE,
    ManifestResource = crate::binds::MonoMetaTableEnum_MONO_TABLE_MANIFESTRESOURCE,
    NestedClass = crate::binds::MonoMetaTableEnum_MONO_TABLE_NESTEDCLASS,
    GenericParam = crate::binds::MonoMetaTableEnum_MONO_TABLE_GENERICPARAM,
    MethodSpec = crate::binds::MonoMetaTableEnum_MONO_TABLE_METHODSPEC,
    GenericParamConstraint = crate::binds::MonoMetaTableEnum_MONO_TABLE_GENERICPARAMCONSTRAINT,
    Unused8 = crate::binds::MonoMetaTableEnum_MONO_TABLE_UNUSED8,
    Unused9 = crate::binds::MonoMetaTableEnum_MONO_TABLE_UNUSED9,
    Unused10 = crate::binds::MonoMetaTableEnum_MONO_TABLE_UNUSED10,
    Document = crate::binds::MonoMetaTableEnum_MONO_TABLE_DOCUMENT,
    MethodBody = crate::binds::MonoMetaTableEnum_MONO_TABLE_METHODBODY,
    LocalScope = crate::binds::MonoMetaTableEnum_MONO_TABLE_LOCALSCOPE,
    LocalVariable = crate::binds::MonoMetaTableEnum_MONO_TABLE_LOCALVARIABLE,
    LocalConstant = crate::binds::MonoMetaTableEnum_MONO_TABLE_LOCALCONSTANT,
    ImportScope = crate::binds::MonoMetaTableEnum_MONO_TABLE_IMPORTSCOPE,
    MachineMethod = crate::binds::MonoMetaTableEnum_MONO_TABLE_STATEMACHINEMETHOD,
}
impl MetadataTableInfo {
    /// Creates [`MetadataTableInfo`] from a [`MonoTableInfo`] pointer.
    /// # Safety
    /// *table* must be a valid [`MonoTableInfo`] pointer, and must match kind.
    #[must_use]
    pub unsafe fn from_ptr(table: *const MonoTableInfo, kind: MetadataTableKind) -> Self {
        Self { table, kind }
    }
    ///Get amount of rows in a table.
    #[must_use]
    pub fn get_table_rows(&self) -> i32 {
        unsafe { crate::binds::mono_table_info_get_rows(self.table) }
    }
    ///Gets the token at *`column`* in *`row`*
    #[must_use]
    pub fn decode_row_col(&self, row: i32, column: u32) -> MetadataToken {
        unsafe { crate::binds::mono_metadata_decode_row_col(self.table, row, column) }
    }
}
///Representation of data about assembly.
pub struct AssemblyMetadata {
    pub hash_alg: HashAlgorithm,
    pub major_version: u32,
    pub minor_version: u32,
    pub build_number: u32,
    pub rev_number: u32,
    pub flags: AssemblyFlags,
    pub public_key: u32,
    name: String,
    culture: String,
}
impl AssemblyMetadata {
    #[must_use]
    fn from_meta_table(table: &MetadataTableInfo, img: Image) -> Self {
        assert!(table.kind == MetadataTableKind::Assembly);
        Self {
            hash_alg: HashAlgorithm::from_u32(table.decode_row_col(0, 0)),
            major_version: table.decode_row_col(0, 1),
            minor_version: table.decode_row_col(0, 2),
            build_number: table.decode_row_col(0, 3),
            rev_number: table.decode_row_col(0, 4),
            flags: AssemblyFlags {
                flags: table.decode_row_col(0, 5),
            },
            public_key: table.decode_row_col(0, 6),
            name: img.metadata_string_heap(table.decode_row_col(0, 7)),
            culture: img.metadata_string_heap(table.decode_row_col(0, 8)),
        }
    }
    ///Gets [`AssemblyMetadata`] from an [`Image`]
    #[must_use]
    pub fn from_image(img: Image) -> Self {
        Self::from_meta_table(&img.get_table_info(MetadataTableKind::Assembly), img)
    }
    //Returns name string.
    #[must_use]
    pub fn get_name(&self) -> String {
        self.name.clone()
    }
    ///Returns culture string.
    #[must_use]
    pub fn get_culture(&self) -> String {
        self.culture.clone()
    }
}
///Representation of assembly flags. More info <a href="https://docs.microsoft.com/en-us/dotnet/api/system.reflection.assemblyflags?view=net-6.0"> here </a>
pub struct AssemblyFlags {
    pub flags: u32,
}
#[allow(non_snake_case)]
impl AssemblyFlags {
    ///Checks is `WindowsRuntime` flag is set.
    #[must_use]
    pub fn is_set_WindowsRuntime(&self) -> bool {
        (self.flags & 512) != 0
    }
    ///Checks is `Retargtable` flag is set.
    #[must_use]
    pub fn is_set_Retargtable(&self) -> bool {
        (self.flags & 256) != 0
    }
    ///Checks if `PublicKey` flag is set.
    #[must_use]
    pub fn is_set_PublicKey(&self) -> bool {
        (self.flags & 1) != 0
    }
    ///Checks if `DisableJitCompileOptimizer` flag is set.
    #[must_use]
    pub fn is_set_DisableJitCompileOptimizer(&self) -> bool {
        (self.flags & 16384) != 0
    }
    ///Checks if `EnableJitCompileTracking` flag is set.
    #[must_use]
    pub fn is_set_EnableJitCompileTracking(&self) -> bool {
        (self.flags & 32768) != 0
    }
    ///Returns the `ContentType` mask bits.
    #[must_use]
    pub fn content_type_mask(&self) -> [bool; 2] {
        [(self.flags & 2048) != 0, (self.flags & 1024) != 0]
    }
}
#[warn(non_snake_case)]
impl std::fmt::Display for AssemblyFlags {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "AssemblyFlags{{WindowsRuntime:{}, ",
            self.is_set_WindowsRuntime()
        )?;
        write!(f, "Retargtable:{}, ", self.is_set_Retargtable())?;
        write!(f, "PublicKey:{}, ", self.is_set_PublicKey())?;
        write!(
            f,
            "DisableJitCompileOptimizer:{}, ",
            self.is_set_DisableJitCompileOptimizer()
        )?;
        write!(
            f,
            "EnableJitCompileTracking:{}, ",
            self.is_set_EnableJitCompileTracking()
        )?;
        write!(f, "ContentTypeMask:{:?}}} ", self.content_type_mask())
    }
}
///Assembly hash algorithm type. More info <a href="docs.microsoft.com/en-us/dotnet/api/system.configuration.assemblies.assemblyhashalgorithm?view=net-6.0"> here </a>
#[repr(u32)]
pub enum HashAlgorithm {
    MD5 = 32771,
    None = 0,
    SHA1 = 32772,
    SHA256 = 32780,
    SHA384 = 32781,
    SHA512 = 32782,
}
impl HashAlgorithm {
    fn from_u32(u: u32) -> Self {
        match u {
            32771 => Self::MD5,
            0 => Self::None,
            32772 => Self::SHA1,
            32780 => Self::SHA256,
            32781 => Self::SHA384,
            32782 => Self::SHA512,
            _ => panic!("{u} is not a valid HashAlgorithm"),
        }
    }
}
impl std::fmt::Display for HashAlgorithm {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let s = match self {
            Self::MD5 => "MD5",
            Self::None => "None",
            Self::SHA1 => "SHA1",
            Self::SHA256 => "SHA256",
            Self::SHA384 => "SHA386",
            Self::SHA512 => "SHA512",
        };
        write!(f, "{s}")
    }
}
impl std::fmt::Display for AssemblyMetadata {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "AssemblyMetadata{{")?;
        write!(f, "hash_alg:{}, ", self.hash_alg)?;
        write!(f, "major_version:{}, ", self.major_version)?;
        write!(f, "minor_version:{}, ", self.minor_version)?;
        write!(f, "build_number:{}, ", self.build_number)?;
        write!(f, "rev_number:{}, ", self.rev_number)?;
        write!(f, "flags:{}, ", self.flags)?;
        write!(f, "public_key:{}, ", self.public_key)?;
        write!(f, "Name:{}, ", &self.name)?;
        write!(f, "Culture:{}}}", &self.culture)
    }
}
pub struct AssemblyOSMetadata {
    platform: String,
    major_version: u32,
    minor_version: u32,
}
impl AssemblyOSMetadata {
    #[must_use]
    fn from_meta_table(table: &MetadataTableInfo, img: Image) -> Self {
        assert!(table.kind == MetadataTableKind::AssemblyOS);
        Self {
            platform: img.metadata_string_heap(table.decode_row_col(0, 0)),
            major_version: table.decode_row_col(0, 1),
            minor_version: table.decode_row_col(0, 2),
        }
    }
    ///Gets [`AssemblyMetadata`]
    #[must_use]
    pub fn from_image(img: Image) -> Option<Self> {
        let table = img.get_table_info(MetadataTableKind::AssemblyOS);
        if table.get_table_rows() > 0 {
            Some(Self::from_meta_table(&table, img))
        } else {
            None
        }
    }
    //Returns platform string.
    #[must_use]
    pub fn get_platform(&self) -> String {
        self.platform.clone()
    }
}
impl std::fmt::Display for AssemblyOSMetadata {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "AssemblyOSMetadata{{")?;
        write!(f, "Platform:{}, ", &self.platform)?;
        write!(f, "MajorVersion:{}, ", self.major_version)?;
        write!(f, "MinorVersion:{}}}", self.minor_version)
    }
}