1
+ use std;
1
2
use std:: cell:: RefCell ;
2
3
use std:: vec:: Vec ;
3
4
use std:: rc:: Rc ;
@@ -213,7 +214,7 @@ pub fn gen_mod(links: &[(String, LinkType)], globs: Vec<Global>, span: Span) ->
213
214
e. name = unnamed_name ( & mut ctx, e. name . clone ( ) ) ;
214
215
}
215
216
let e = ei. borrow ( ) ;
216
- defs. extend ( cenum_to_rs ( & mut ctx, enum_name ( & e. name ) , e. kind , & e. items ) . into_iter ( ) )
217
+ defs. extend ( cenum_to_rs ( & mut ctx, enum_name ( & e. name ) , e. kind , e . layout , & e. items ) . into_iter ( ) )
217
218
} ,
218
219
GVar ( vi) => {
219
220
let v = vi. borrow ( ) ;
@@ -477,7 +478,7 @@ fn ctypedef_to_rs(ctx: &mut GenCtx, name: String, ty: &Type) -> Vec<P<ast::Item>
477
478
if is_empty {
478
479
ei. borrow_mut ( ) . name = name. clone ( ) ;
479
480
let e = ei. borrow ( ) ;
480
- cenum_to_rs ( ctx, name, e. kind , & e. items )
481
+ cenum_to_rs ( ctx, name, e. kind , e . layout , & e. items )
481
482
} else {
482
483
vec ! ( mk_item( ctx, name, ty) )
483
484
}
@@ -699,24 +700,81 @@ fn const_to_rs(ctx: &mut GenCtx, name: String, val: i64, val_ty: ast::Ty) -> P<a
699
700
} )
700
701
}
701
702
702
- fn enum_kind_to_rust_type_name ( kind : IKind ) -> & ' static str {
703
+ fn enum_kind_is_signed ( kind : IKind ) -> bool {
703
704
match kind {
704
- ISChar => "i8" ,
705
- IUChar => "u8" ,
706
- IShort => "i16" ,
707
- IUShort => "u16" ,
708
- IInt => "i32" ,
709
- IUInt => "u32" ,
710
- ILong => "i64" ,
711
- IULong => "u64" ,
712
- _ => unreachable ! ( ) ,
705
+ IBool => false ,
706
+ ISChar => true ,
707
+ IUChar => false ,
708
+ IShort => true ,
709
+ IUShort => false ,
710
+ IInt => true ,
711
+ IUInt => false ,
712
+ ILong => true ,
713
+ IULong => false ,
714
+ ILongLong => true ,
715
+ IULongLong => false ,
713
716
}
714
717
}
715
718
716
- fn cenum_to_rs ( ctx : & mut GenCtx , name : String , kind : IKind , enum_items : & [ EnumItem ] )
719
+ fn enum_size_to_rust_type_name ( signed : bool , size : usize ) -> & ' static str {
720
+ match ( signed, size) {
721
+ ( true , 1 ) => "i8" ,
722
+ ( false , 1 ) => "u8" ,
723
+ ( true , 2 ) => "i16" ,
724
+ ( false , 2 ) => "u16" ,
725
+ ( true , 4 ) => "i32" ,
726
+ ( false , 4 ) => "u32" ,
727
+ ( true , 8 ) => "i64" ,
728
+ ( false , 8 ) => "u64" ,
729
+ _ => unreachable ! ( "invalid enum decl: signed: {}, size: {}" , signed, size) ,
730
+ }
731
+ }
732
+
733
+ fn enum_size_to_unsigned_max_value ( size : usize ) -> u64 {
734
+ match size {
735
+ 1 => std:: u8:: MAX as u64 ,
736
+ 2 => std:: u16:: MAX as u64 ,
737
+ 4 => std:: u32:: MAX as u64 ,
738
+ 8 => std:: u64:: MAX ,
739
+ _ => unreachable ! ( "invalid enum size: {}" , size)
740
+ }
741
+ }
742
+
743
+ fn cenum_value_to_int_lit (
744
+ ctx : & mut GenCtx ,
745
+ enum_is_signed : bool ,
746
+ size : usize ,
747
+ value : i64 )
748
+ -> P < ast:: Expr > {
749
+ if enum_is_signed {
750
+ let int_lit =
751
+ ast:: LitKind :: Int ( value. abs ( ) as u64 , ast:: LitIntType :: Unsuffixed ) ;
752
+ let expr = ctx. ext_cx . expr_lit ( ctx. span , int_lit) ;
753
+ if value < 0 {
754
+ ctx. ext_cx . expr (
755
+ ctx. span , ast:: ExprKind :: Unary ( ast:: UnOp :: Neg , expr) )
756
+ } else {
757
+ expr
758
+ }
759
+ } else {
760
+ let u64_value =
761
+ value as u64 & enum_size_to_unsigned_max_value ( size) ;
762
+ let int_lit =
763
+ ast:: LitKind :: Int ( u64_value, ast:: LitIntType :: Unsuffixed ) ;
764
+ ctx. ext_cx . expr_lit ( ctx. span , int_lit)
765
+ }
766
+ }
767
+
768
+
769
+ fn cenum_to_rs ( ctx : & mut GenCtx ,
770
+ name : String ,
771
+ kind : IKind ,
772
+ layout : Layout ,
773
+ enum_items : & [ EnumItem ] )
717
774
-> Vec < P < ast:: Item > > {
718
775
let enum_name = ctx. ext_cx . ident_of ( & name) ;
719
776
let enum_ty = ctx. ext_cx . ty_ident ( ctx. span , enum_name) ;
777
+ let enum_is_signed = enum_kind_is_signed ( kind) ;
720
778
721
779
let mut variants = vec ! [ ] ;
722
780
let mut found_values = HashMap :: new ( ) ;
@@ -741,12 +799,8 @@ fn cenum_to_rs(ctx: &mut GenCtx, name: String, kind: IKind, enum_items: &[EnumIt
741
799
742
800
found_values. insert ( item. val , name) ;
743
801
744
- let int_lit = ast:: LitKind :: Int ( item. val . abs ( ) as u64 , ast:: LitIntType :: Unsuffixed ) ;
745
- let mut value = ctx. ext_cx . expr_lit ( ctx. span , int_lit) ;
746
- if item. val < 0 {
747
- let negated = ast:: ExprKind :: Unary ( ast:: UnOp :: Neg , value) ;
748
- value = ctx. ext_cx . expr ( ctx. span , negated) ;
749
- }
802
+ let value = cenum_value_to_int_lit (
803
+ ctx, enum_is_signed, layout. size , item. val ) ;
750
804
751
805
variants. push ( respan ( ctx. span , ast:: Variant_ {
752
806
name : name,
@@ -756,7 +810,7 @@ fn cenum_to_rs(ctx: &mut GenCtx, name: String, kind: IKind, enum_items: &[EnumIt
756
810
} ) ) ;
757
811
}
758
812
759
- let enum_repr = InternedString :: new ( enum_kind_to_rust_type_name ( kind ) ) ;
813
+ let enum_repr = InternedString :: new ( enum_size_to_rust_type_name ( enum_is_signed , layout . size ) ) ;
760
814
761
815
let repr_arg = ctx. ext_cx . meta_word ( ctx. span , enum_repr) ;
762
816
let repr_list = ctx. ext_cx . meta_list ( ctx. span , InternedString :: new ( "repr" ) , vec ! [ repr_arg] ) ;
0 commit comments