donet_core/
dctype.rs

1/*
2    This file is part of Donet.
3
4    Copyright © 2024 Max Rodriguez <[email protected]>
5
6    Donet is free software; you can redistribute it and/or modify
7    it under the terms of the GNU Affero General Public License,
8    as published by the Free Software Foundation, either version 3
9    of the License, or (at your option) any later version.
10
11    Donet is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14    GNU Affero General Public License for more details.
15
16    You should have received a copy of the GNU Affero General Public
17    License along with Donet. If not, see <https://www.gnu.org/licenses/>.
18*/
19
20//! Represents all data types supported by the DC language
21//! and developer-defined type alias definitions.
22
23use crate::globals::DgSizeTag;
24use crate::hashgen::*;
25
26/// The DCTypeEnum variants have assigned u8 values
27/// to keep compatibility with Astron's DC hash inputs.
28#[repr(u8)] // 8-bit alignment, unsigned
29#[derive(Debug, Clone, PartialEq, Eq)]
30#[rustfmt::skip]
31pub enum DCTypeEnum {
32    // Numeric Types
33    TInt8 = 0, TInt16 = 1, TInt32 = 2, TInt64 = 3,
34    TUInt8 = 4, TChar = 8, TUInt16 = 5, TUInt32 = 6, TUInt64 = 7,
35    TFloat32 = 9, TFloat64 = 10,
36
37    // Sized Data Types (Array Types)
38    TString = 11, // a string with a fixed byte length
39    TVarString = 12, // a string with a variable byte length
40    TBlob = 13, TVarBlob = 14,
41    TBlob32 = 19, TVarBlob32 = 20,
42    TArray = 15, TVarArray = 16,
43
44    // Complex DC Types
45    TStruct = 17, TMethod = 18,
46}
47
48impl std::fmt::Display for DCTypeEnum {
49    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50        match self {
51            Self::TInt8 => write!(f, "int8"),
52            Self::TInt16 => write!(f, "int16"),
53            Self::TInt32 => write!(f, "int32"),
54            Self::TInt64 => write!(f, "int64"),
55            Self::TUInt8 => write!(f, "uint8"),
56            Self::TChar => write!(f, "char"),
57            Self::TUInt16 => write!(f, "uint16"),
58            Self::TUInt32 => write!(f, "uint32"),
59            Self::TUInt64 => write!(f, "uint64"),
60            Self::TFloat32 => write!(f, "float32"),
61            Self::TFloat64 => write!(f, "float64"),
62            Self::TString => write!(f, "string"),
63            Self::TVarString => write!(f, "var string"),
64            Self::TBlob => write!(f, "blob"),
65            Self::TVarBlob => write!(f, "var blob"),
66            Self::TBlob32 => write!(f, "blob32"),
67            Self::TVarBlob32 => write!(f, "var blob32"),
68            Self::TArray => write!(f, "array"),
69            Self::TVarArray => write!(f, "var array"),
70            Self::TStruct => write!(f, "struct"),
71            Self::TMethod => write!(f, "method"),
72        }
73    }
74}
75
76#[derive(Debug, Clone, PartialEq, Eq)]
77pub struct DCTypeDefinition {
78    alias: Option<String>,
79    pub data_type: DCTypeEnum,
80    pub size: DgSizeTag,
81}
82
83/// Creates a new DCTypeDefinition struct with a DC type set.
84impl From<DCTypeEnum> for DCTypeDefinition {
85    fn from(value: DCTypeEnum) -> Self {
86        Self {
87            alias: None,
88            data_type: value,
89            size: 0_u16,
90        }
91    }
92}
93
94impl std::fmt::Display for DCTypeDefinition {
95    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
96        write!(f, "typedef ")?;
97        self.data_type.fmt(f)?;
98        if self.has_alias() {
99            write!(f, " ")?;
100            self.alias.clone().unwrap().fmt(f)?;
101        }
102        write!(f, ";")?;
103        writeln!(f)
104    }
105}
106
107impl LegacyDCHash for DCTypeDefinition {
108    fn generate_hash(&self, hashgen: &mut DCHashGenerator) {
109        hashgen.add_int(i32::from(self.data_type.clone() as u8));
110
111        if self.alias.is_some() {
112            hashgen.add_string(self.alias.clone().unwrap())
113        }
114    }
115}
116
117impl DCTypeDefinition {
118    pub fn get_dc_type(&self) -> DCTypeEnum {
119        self.data_type.clone()
120    }
121
122    #[inline(always)]
123    pub fn is_variable_length(&self) -> bool {
124        self.size == 0_u16
125    }
126
127    #[inline(always)]
128    pub fn get_size(&self) -> DgSizeTag {
129        self.size
130    }
131
132    #[inline(always)]
133    pub fn has_alias(&self) -> bool {
134        self.alias.is_some()
135    }
136
137    pub fn get_alias(&self) -> Result<String, ()> {
138        if self.alias.is_some() {
139            Ok(self.alias.clone().unwrap())
140        } else {
141            Err(())
142        }
143    }
144
145    pub fn set_alias(&mut self, alias: String) {
146        self.alias = Some(alias);
147    }
148}
149
150#[derive(Copy, Clone, PartialEq)] // required for unwrapping when in an option type
151pub enum DCNumber {
152    Integer(i64),
153    UnsignedInteger(u64),
154    FloatingPoint(f64),
155}
156
157impl From<DCNumber> for i32 {
158    fn from(value: DCNumber) -> i32 {
159        match value {
160            DCNumber::Integer(x) => x as i32,
161            DCNumber::UnsignedInteger(x) => x as i32,
162            DCNumber::FloatingPoint(x) => x as i32,
163        }
164    }
165}
166
167/// Converts a `DCNumber` to an `i64` primitive type.
168///
169/// Panics if `DCNumber` is not of variant `Integer`.
170impl From<DCNumber> for i64 {
171    fn from(value: DCNumber) -> Self {
172        match value {
173            DCNumber::Integer(x) => x,
174            _ => panic!("DCNumber is not of variant `Integer`."),
175        }
176    }
177}
178
179/// Converts a `DCNumber` to an `u64` primitive type.
180///
181/// Panics if `DCNumber` is not of variant `UnsignedInteger`.
182impl From<DCNumber> for u64 {
183    fn from(value: DCNumber) -> Self {
184        match value {
185            DCNumber::UnsignedInteger(x) => x,
186            _ => panic!("DCNumber is not of variant `UnsignedInteger`."),
187        }
188    }
189}
190
191/// Converts a `DCNumber` to an `f64` primitive type.
192///
193/// Panics if `DCNumber` is not of variant `FloatingPoint`.
194impl From<DCNumber> for f64 {
195    fn from(value: DCNumber) -> Self {
196        match value {
197            DCNumber::FloatingPoint(x) => x,
198            _ => panic!("DCNumber is not of variant `FloatingPoint`."),
199        }
200    }
201}