@@ -9,6 +9,47 @@ use crate::types::traits::AsTypeRef;
9
9
use crate :: types:: { Type , ArrayType , BasicTypeEnum , VectorType , PointerType , FunctionType } ;
10
10
use crate :: values:: { AsValueRef , ArrayValue , GenericValue , IntValue } ;
11
11
12
+ use regex:: Regex ;
13
+
14
+ /// How to interpret a string or digits used to construct an integer constant.
15
+ #[ derive( Clone , Copy , Debug , EnumAsGetters , EnumIntoGetters , EnumToGetters , Eq , Hash , PartialEq ) ]
16
+ pub enum StringRadix {
17
+ /// Binary 0 or 1
18
+ Binary = 2 ,
19
+ /// Octal 0-7
20
+ Octal = 8 ,
21
+ /// Decimal 0-9
22
+ Decimal = 10 ,
23
+ /// Hexadecimal with upper or lowercase letters up to F.
24
+ Hexadecimal = 16 ,
25
+ /// Alphanumeric, 0-9 and all 26 letters in upper or lowercase.
26
+ Alphanumeric = 36 ,
27
+ }
28
+ impl StringRadix {
29
+ /// Create a radix from a base.
30
+ pub fn from_u8 ( value : u8 ) -> Option < StringRadix > {
31
+ match value {
32
+ 2 => Some ( StringRadix :: Binary ) ,
33
+ 8 => Some ( StringRadix :: Octal ) ,
34
+ 10 => Some ( StringRadix :: Decimal ) ,
35
+ 16 => Some ( StringRadix :: Hexadecimal ) ,
36
+ 36 => Some ( StringRadix :: Alphanumeric ) ,
37
+ _ => None
38
+ }
39
+ }
40
+
41
+ /// Create a Regex that matches valid strings for the given radix.
42
+ pub fn to_regex ( & self ) -> Regex {
43
+ match self {
44
+ StringRadix :: Binary => Regex :: new ( r"^[-+]?[01]+$" ) . unwrap ( ) ,
45
+ StringRadix :: Octal => Regex :: new ( r"^[-+]?[0-7]+$" ) . unwrap ( ) ,
46
+ StringRadix :: Decimal => Regex :: new ( r"^[-+]?[0-9]+$" ) . unwrap ( ) ,
47
+ StringRadix :: Hexadecimal => Regex :: new ( r"^[-+]?[0-9abcdefABCDEF]+$" ) . unwrap ( ) ,
48
+ StringRadix :: Alphanumeric => Regex :: new ( r"^[-+]?[0-9[:alpha:]]+$" ) . unwrap ( ) ,
49
+ }
50
+ }
51
+ }
52
+
12
53
/// An `IntType` is the type of an integer constant or variable.
13
54
#[ derive( Debug , PartialEq , Eq , Clone , Copy ) ]
14
55
pub struct IntType {
@@ -209,32 +250,32 @@ impl IntType {
209
250
///
210
251
/// ```no_run
211
252
/// use inkwell::context::Context;
253
+ /// use inkwell::types::StringRadix;
212
254
///
213
255
/// let context = Context::create();
214
256
/// let i8_type = context.i8_type();
215
- /// let i8_val = i8_type.const_int_from_string("0121", 10 );
257
+ /// let i8_val = i8_type.const_int_from_string("0121", StringRadix::Decimal).unwrap( );
216
258
///
217
259
/// assert_eq!(i8_val.print_to_string().to_string(), "i8 121");
218
260
///
219
- /// let i8_val = i8_type.const_int_from_string("0121", 3 );
261
+ /// let i8_val = i8_type.const_int_from_string("0121", StringRadix::from_u8(10).unwrap()).unwrap( );
220
262
///
221
263
/// assert_eq!(i8_val.print_to_string().to_string(), "i8 16");
222
264
///
223
- /// // Unexpected outputs:
224
- /// let i8_val = i8_type.const_int_from_string("0121", 2);
225
- ///
226
- /// assert_eq!(i8_val.print_to_string().to_string(), "i8 3");
227
- ///
228
- /// let i8_val = i8_type.const_int_from_string("ABCD", 2);
265
+ /// let i8_val = i8_type.const_int_from_string("0121", StringRadix::Binary);
266
+ /// assert!(i8_val.is_none());
229
267
///
230
- /// assert_eq!(i8_val.print_to_string().to_string(), "i8 -15");
268
+ /// let i8_val = i8_type.const_int_from_string("ABCD", StringRadix::Binary);
269
+ /// assert!(i8_val.is_none());
231
270
/// ```
232
- pub fn const_int_from_string ( & self , slice : & str , radix : u8 ) -> IntValue {
271
+ pub fn const_int_from_string ( & self , slice : & str , radix : StringRadix ) -> Option < IntValue > {
272
+ if !radix. to_regex ( ) . is_match ( slice) {
273
+ return None
274
+ }
233
275
let value = unsafe {
234
- LLVMConstIntOfStringAndSize ( self . as_type_ref ( ) , slice. as_ptr ( ) as * const i8 , slice. len ( ) as u32 , radix)
276
+ LLVMConstIntOfStringAndSize ( self . as_type_ref ( ) , slice. as_ptr ( ) as * const i8 , slice. len ( ) as u32 , radix as u8 )
235
277
} ;
236
-
237
- IntValue :: new ( value)
278
+ Some ( IntValue :: new ( value) )
238
279
}
239
280
240
281
/// Create a constant `IntValue` of arbitrary precision.
0 commit comments