Skip to main content

mun_abi/
lib.rs

1//! The Mun ABI
2//!
3//! The Mun ABI defines the binary format used to communicate between the Mun Compiler and Mun
4//! Runtime.
5#![warn(missing_docs)]
6
7use std::ffi::CStr;
8use std::fmt;
9
10pub use assembly_info::AssemblyInfo;
11pub use dispatch_table::DispatchTable;
12pub use function_info::{FunctionDefinition, FunctionPrototype, FunctionSignature};
13pub use module_info::ModuleInfo;
14pub use primitive::PrimitiveType;
15pub use struct_info::{StructDefinition, StructMemoryKind};
16pub use type_id::HasStaticTypeId;
17pub use type_id::{ArrayTypeId, PointerTypeId, TypeId};
18pub use type_info::{HasStaticTypeName, TypeDefinition, TypeDefinitionData};
19pub use type_lut::TypeLut;
20
21// C bindings can be manually generated by running `cargo gen-abi`.
22mod assembly_info;
23mod dispatch_table;
24mod function_info;
25mod module_info;
26mod primitive;
27pub mod static_type_map;
28mod struct_info;
29mod type_id;
30mod type_info;
31mod type_lut;
32
33#[cfg(test)]
34mod test_utils;
35
36/// Defines the current ABI version
37#[allow(clippy::zero_prefixed_literal)]
38pub const ABI_VERSION: u32 = 00_03_00;
39/// Defines the name for the `get_info` function
40pub const GET_INFO_FN_NAME: &str = "get_info";
41/// Defines the name for the `get_version` function
42pub const GET_VERSION_FN_NAME: &str = "get_version";
43/// Defines the name for the `set_allocator_handle` function
44pub const SET_ALLOCATOR_HANDLE_FN_NAME: &str = "set_allocator_handle";
45
46/// Represents a globally unique identifier (GUID).
47#[repr(C)]
48#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
49pub struct Guid(pub [u8; 16]);
50
51impl Guid {
52    /// Create a GUID from a string by computing its hash.
53    pub const fn from_str(str: &str) -> Guid {
54        Guid(extendhash::md5::compute_hash(str.as_bytes()))
55    }
56
57    /// Create a GUID from a string by computing its hash.
58    pub fn from_cstr(str: &CStr) -> Guid {
59        Guid(extendhash::md5::compute_hash(str.to_bytes()))
60    }
61}
62
63impl fmt::Display for Guid {
64    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65        let hyphenated = format_hyphenated(&self.0);
66
67        // SAFETY: The encoded buffer is ASCII encoded
68        let hyphenated = unsafe { std::str::from_utf8_unchecked(&hyphenated) };
69
70        return f.write_str(hyphenated);
71
72        #[inline]
73        const fn format_hyphenated(src: &[u8; 16]) -> [u8; 36] {
74            const LUT: [u8; 16] = [
75                b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'a', b'b', b'c', b'd',
76                b'e', b'f',
77            ];
78
79            let groups = [(0, 8), (9, 13), (14, 18), (19, 23), (24, 36)];
80            let mut dst = [0; 36];
81
82            let mut group_idx = 0;
83            let mut i = 0;
84            while group_idx < 5 {
85                let (start, end) = groups[group_idx];
86                let mut j = start;
87                while j < end {
88                    let x = src[i];
89                    i += 1;
90
91                    dst[j] = LUT[(x >> 4) as usize];
92                    dst[j + 1] = LUT[(x & 0x0f) as usize];
93                    j += 2;
94                }
95                if group_idx < 4 {
96                    dst[end] = b'-';
97                }
98                group_idx += 1;
99            }
100            dst
101        }
102    }
103}
104
105#[cfg(feature = "serde")]
106impl serde::Serialize for Guid {
107    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
108    where
109        S: serde::Serializer,
110    {
111        serializer.serialize_str(&format!("{}", self))
112    }
113}
114
115/// Represents the privacy level of modules, functions, or variables.
116#[repr(u8)]
117#[derive(Clone, Copy, Debug, Eq, PartialEq)]
118#[cfg_attr(feature = "serde", derive(serde::Serialize))]
119pub enum Privacy {
120    /// Publicly (and privately) accessible
121    Public = 0,
122    /// Privately accessible
123    Private = 1,
124}
125
126// TODO: Fix leakage of pointer types in struct fields due to integration tests and test utils