@@ -489,6 +489,7 @@ fn module_name(camel_case: &str) -> String {
489
489
// Annotation IDs, as defined in rust.capnp.
490
490
const NAME_ANNOTATION_ID : u64 = 0xc2fe4c6d100166d0 ;
491
491
const PARENT_MODULE_ANNOTATION_ID : u64 = 0xabee386cd1450364 ;
492
+ const OPTION_ANNOTATION_ID : u64 = 0xabfef22c4ee1964e ;
492
493
493
494
fn name_annotation_value ( annotation : schema_capnp:: annotation:: Reader ) -> capnp:: Result < & str > {
494
495
if let schema_capnp:: value:: Text ( t) = annotation. get_value ( ) ?. which ( ) ? {
@@ -553,6 +554,32 @@ fn capnp_name_to_rust_name(capnp_name: &str, name_kind: NameKind) -> String {
553
554
}
554
555
}
555
556
557
+ fn is_option_field ( field : schema_capnp:: field:: Reader ) -> capnp:: Result < bool > {
558
+ use capnp:: schema_capnp:: * ;
559
+
560
+ let enabled = field
561
+ . get_annotations ( ) ?
562
+ . iter ( )
563
+ . any ( |a| a. get_id ( ) == OPTION_ANNOTATION_ID ) ;
564
+
565
+ if enabled {
566
+ let supported = match field. which ( ) ? {
567
+ field:: Which :: Group ( _) => false ,
568
+ field:: Which :: Slot ( field) => {
569
+ let ty = field. get_type ( ) ?;
570
+ ty. is_pointer ( ) ? && !matches ! ( ty. which( ) ?, type_:: Interface ( _) )
571
+ }
572
+ } ;
573
+ if !supported {
574
+ return Err ( capnp:: Error :: failed (
575
+ "$Rust.option annotation only supported on pointer fields (support for optional interfaces isn't implemented yet)" . to_string ( ) ,
576
+ ) ) ;
577
+ }
578
+ }
579
+
580
+ Ok ( enabled)
581
+ }
582
+
556
583
fn prim_default ( value : & schema_capnp:: value:: Reader ) -> :: capnp:: Result < Option < String > > {
557
584
use capnp:: schema_capnp:: value;
558
585
match value. which ( ) ? {
@@ -665,37 +692,46 @@ pub fn getter_text(
665
692
offset : usize ,
666
693
default : T ,
667
694
zero : T ,
668
- ) -> FormattedText {
695
+ ) -> String {
669
696
if default == zero {
670
- Line ( format ! ( "self.{member}.get_data_field::<{typ}>({offset})" ) )
697
+ format ! ( "self.{member}.get_data_field::<{typ}>({offset})" )
671
698
} else {
672
- Line ( format ! (
673
- "self.{member}.get_data_field_mask::<{typ}>({offset}, {default})"
674
- ) )
699
+ format ! ( "self.{member}.get_data_field_mask::<{typ}>({offset}, {default})" )
675
700
}
676
701
}
677
702
678
703
let raw_type = reg_field. get_type ( ) ?;
679
- let typ = raw_type. type_string ( ctx, module) ?;
704
+ let inner_type = raw_type. type_string ( ctx, module) ?;
680
705
let default_value = reg_field. get_default_value ( ) ?;
681
706
let default = default_value. which ( ) ?;
682
707
let default_name = format ! (
683
708
"DEFAULT_{}" ,
684
709
snake_to_upper_case( & camel_to_snake_case( get_field_name( * field) ?) )
685
710
) ;
711
+ let should_get_option = is_option_field ( * field) ?;
686
712
687
- let mut result_type = match raw_type. which ( ) ? {
688
- type_:: Enum ( _) => fmt ! ( ctx, "::core::result::Result<{typ},{capnp}::NotInSchema>" ) ,
689
- type_:: AnyPointer ( _) if !raw_type. is_parameter ( ) ? => typ. clone ( ) ,
690
- type_:: Interface ( _) => {
713
+ let typ = if should_get_option {
714
+ format ! ( "Option<{}>" , inner_type)
715
+ } else {
716
+ inner_type
717
+ } ;
718
+
719
+ let ( is_fallible, mut result_type) = match raw_type. which ( ) ? {
720
+ type_:: Enum ( _) => (
721
+ true ,
722
+ fmt ! ( ctx, "::core::result::Result<{typ},{capnp}::NotInSchema>" ) ,
723
+ ) ,
724
+ type_:: AnyPointer ( _) if !raw_type. is_parameter ( ) ? => ( false , typ. clone ( ) ) ,
725
+ type_:: Interface ( _) => (
726
+ true ,
691
727
fmt ! (
692
728
ctx,
693
729
"{capnp}::Result<{}>" ,
694
730
raw_type. type_string( ctx, Leaf :: Client ) ?
695
- )
696
- }
697
- _ if raw_type. is_prim ( ) ? => typ. clone ( ) ,
698
- _ => fmt ! ( ctx, "{capnp}::Result<{typ}>" ) ,
731
+ ) ,
732
+ ) ,
733
+ _ if raw_type. is_prim ( ) ? => ( false , typ. clone ( ) ) ,
734
+ _ => ( true , fmt ! ( ctx, "{capnp}::Result<{typ}>" ) ) ,
699
735
} ;
700
736
701
737
if is_fn {
@@ -706,80 +742,114 @@ pub fn getter_text(
706
742
}
707
743
}
708
744
709
- let getter_code = match ( raw_type. which ( ) ?, default) {
745
+ let getter_fragment = match ( raw_type. which ( ) ?, default) {
710
746
( type_:: Void ( ( ) ) , value:: Void ( ( ) ) ) => {
711
747
if is_fn {
712
- Line ( "" . to_string ( ) )
748
+ "" . to_string ( )
713
749
} else {
714
- Line ( "()" . to_string ( ) )
750
+ "()" . to_string ( )
715
751
}
716
- } ,
752
+ }
717
753
( type_:: Bool ( ( ) ) , value:: Bool ( b) ) => {
718
754
if b {
719
- Line ( format ! ( "self.{member}.get_bool_field_mask({offset}, true)" ) )
755
+ format ! ( "self.{member}.get_bool_field_mask({offset}, true)" )
720
756
} else {
721
- Line ( format ! ( "self.{member}.get_bool_field({offset})" ) )
757
+ format ! ( "self.{member}.get_bool_field({offset})" )
722
758
}
723
759
}
724
760
( type_:: Int8 ( ( ) ) , value:: Int8 ( i) ) => primitive_case ( & typ, & member, offset, i, 0 ) ,
725
761
( type_:: Int16 ( ( ) ) , value:: Int16 ( i) ) => primitive_case ( & typ, & member, offset, i, 0 ) ,
726
762
( type_:: Int32 ( ( ) ) , value:: Int32 ( i) ) => primitive_case ( & typ, & member, offset, i, 0 ) ,
727
763
( type_:: Int64 ( ( ) ) , value:: Int64 ( i) ) => primitive_case ( & typ, & member, offset, i, 0 ) ,
728
764
( type_:: Uint8 ( ( ) ) , value:: Uint8 ( i) ) => primitive_case ( & typ, & member, offset, i, 0 ) ,
729
- ( type_:: Uint16 ( ( ) ) , value:: Uint16 ( i) ) => primitive_case ( & typ, & member, offset, i, 0 ) ,
730
- ( type_:: Uint32 ( ( ) ) , value:: Uint32 ( i) ) => primitive_case ( & typ, & member, offset, i, 0 ) ,
731
- ( type_:: Uint64 ( ( ) ) , value:: Uint64 ( i) ) => primitive_case ( & typ, & member, offset, i, 0 ) ,
732
- ( type_:: Float32 ( ( ) ) , value:: Float32 ( f) ) =>
733
- primitive_case ( & typ, & member, offset, f. to_bits ( ) , 0 ) ,
734
- ( type_:: Float64 ( ( ) ) , value:: Float64 ( f) ) =>
735
- primitive_case ( & typ, & member, offset, f. to_bits ( ) , 0 ) ,
765
+ ( type_:: Uint16 ( ( ) ) , value:: Uint16 ( i) ) => {
766
+ primitive_case ( & typ, & member, offset, i, 0 )
767
+ }
768
+ ( type_:: Uint32 ( ( ) ) , value:: Uint32 ( i) ) => {
769
+ primitive_case ( & typ, & member, offset, i, 0 )
770
+ }
771
+ ( type_:: Uint64 ( ( ) ) , value:: Uint64 ( i) ) => {
772
+ primitive_case ( & typ, & member, offset, i, 0 )
773
+ }
774
+ ( type_:: Float32 ( ( ) ) , value:: Float32 ( f) ) => {
775
+ primitive_case ( & typ, & member, offset, f. to_bits ( ) , 0 )
776
+ }
777
+ ( type_:: Float64 ( ( ) ) , value:: Float64 ( f) ) => {
778
+ primitive_case ( & typ, & member, offset, f. to_bits ( ) , 0 )
779
+ }
736
780
( type_:: Enum ( _) , value:: Enum ( d) ) => {
737
781
if d == 0 {
738
- Line ( format ! ( "::core::convert::TryInto::try_into(self.{member}.get_data_field::<u16>({offset}))" ) )
782
+ format ! ( "::core::convert::TryInto::try_into(self.{member}.get_data_field::<u16>({offset}))" )
739
783
} else {
740
- Line (
741
- format ! (
742
- "::core::convert::TryInto::try_into(self.{member}.get_data_field_mask::<u16>({offset}, {d}))" ) )
784
+ format ! (
785
+ "::core::convert::TryInto::try_into(self.{member}.get_data_field_mask::<u16>({offset}, {d}))" )
743
786
}
744
787
}
745
788
746
- ( type_:: Text ( ( ) ) , value:: Text ( _) ) |
747
- ( type_:: Data ( ( ) ) , value:: Data ( _) ) |
748
- ( type_:: List ( _) , value:: List ( _) ) |
749
- ( type_:: Struct ( _) , value:: Struct ( _) ) => {
789
+ ( type_:: Text ( ( ) ) , value:: Text ( _) )
790
+ | ( type_:: Data ( ( ) ) , value:: Data ( _) )
791
+ | ( type_:: List ( _) , value:: List ( _) )
792
+ | ( type_:: Struct ( _) , value:: Struct ( _) ) => {
750
793
let default = if reg_field. get_had_explicit_default ( ) {
751
794
default_decl = Some ( crate :: pointer_constants:: word_array_declaration (
752
795
ctx,
753
796
& default_name,
754
797
:: capnp:: raw:: get_struct_pointer_section ( default_value) . get ( 0 ) ,
755
- crate :: pointer_constants:: WordArrayDeclarationOptions { public : true } ) ?) ;
756
- format ! ( "Some(&_private::{default_name}[..])" )
798
+ crate :: pointer_constants:: WordArrayDeclarationOptions { public : true } ,
799
+ ) ?) ;
800
+ format ! ( "::core::option::Option::Some(&_private::{default_name}[..])" )
757
801
} else {
758
802
"::core::option::Option::None" . to_string ( )
759
803
} ;
760
804
761
805
if is_reader {
762
- Line ( fmt ! ( ctx,
763
- "{capnp}::traits::FromPointerReader::get_from_pointer(&self.{member}.get_pointer_field({offset}), {default})" ) )
806
+ fmt ! ( ctx,
807
+ "{capnp}::traits::FromPointerReader::get_from_pointer(&self.{member}.get_pointer_field({offset}), {default})" )
764
808
} else {
765
- Line ( fmt ! ( ctx, "{capnp}::traits::FromPointerBuilder::get_from_pointer(self.{member}.get_pointer_field({offset}), {default})" ) )
809
+ fmt ! ( ctx, "{capnp}::traits::FromPointerBuilder::get_from_pointer(self.{member}.get_pointer_field({offset}), {default})" )
766
810
}
767
811
}
768
812
769
813
( type_:: Interface ( _) , value:: Interface ( _) ) => {
770
- Line ( fmt ! ( ctx, "match self.{member}.get_pointer_field({offset}).get_capability() {{ ::core::result::Result::Ok(c) => ::core::result::Result::Ok({capnp}::capability::FromClientHook::new(c)), ::core::result::Result::Err(e) => ::core::result::Result::Err(e)}}" ) )
814
+ fmt ! ( ctx, "match self.{member}.get_pointer_field({offset}).get_capability() {{ ::core::result::Result::Ok(c) => ::core::result::Result::Ok({capnp}::capability::FromClientHook::new(c)), ::core::result::Result::Err(e) => ::core::result::Result::Err(e)}}" )
771
815
}
772
816
( type_:: AnyPointer ( _) , value:: AnyPointer ( _) ) => {
773
817
if !raw_type. is_parameter ( ) ? {
774
- Line ( fmt ! ( ctx, "{capnp}::any_pointer::{module_string}::new(self.{member}.get_pointer_field({offset}))" ) )
818
+ fmt ! ( ctx, "{capnp}::any_pointer::{module_string}::new(self.{member}.get_pointer_field({offset}))" )
775
819
} else if is_reader {
776
- Line ( fmt ! ( ctx, "{capnp}::traits::FromPointerReader::get_from_pointer(&self.{member}.get_pointer_field({offset}), ::core::option::Option::None)" ) )
820
+ fmt ! ( ctx, "{capnp}::traits::FromPointerReader::get_from_pointer(&self.{member}.get_pointer_field({offset}), ::core::option::Option::None)" )
777
821
} else {
778
- Line ( fmt ! ( ctx, "{capnp}::traits::FromPointerBuilder::get_from_pointer(self.{member}.get_pointer_field({offset}), ::core::option::Option::None)" ) )
822
+ fmt ! ( ctx, "{capnp}::traits::FromPointerBuilder::get_from_pointer(self.{member}.get_pointer_field({offset}), ::core::option::Option::None)" )
779
823
}
780
824
}
781
825
_ => return Err ( Error :: failed ( "default value was of wrong type" . to_string ( ) ) ) ,
782
826
} ;
827
+
828
+ let getter_code = if should_get_option {
829
+ Branch ( vec ! [
830
+ Line ( format!(
831
+ "if self.{member}.is_pointer_field_null({offset}) {{"
832
+ ) ) ,
833
+ Indent ( Box :: new( Line (
834
+ if is_fallible {
835
+ "core::result::Result::Ok(core::option::Option::None)"
836
+ } else {
837
+ "::core::option::Option::None"
838
+ }
839
+ . to_string( ) ,
840
+ ) ) ) ,
841
+ Line ( "} else {" . to_string( ) ) ,
842
+ Indent ( Box :: new( Line ( if is_fallible {
843
+ format!( "{getter_fragment}.map(::core::option::Option::Some)" )
844
+ } else {
845
+ format!( "::core::option::Option::Some({getter_fragment})" )
846
+ } ) ) ) ,
847
+ Line ( "}" . to_string( ) ) ,
848
+ ] )
849
+ } else {
850
+ Line ( getter_fragment)
851
+ } ;
852
+
783
853
Ok ( ( result_type, getter_code, default_decl) )
784
854
}
785
855
}
@@ -2454,7 +2524,7 @@ fn generate_node(
2454
2524
) ) ) ;
2455
2525
2456
2526
client_impl_interior. push ( Indent ( Box :: new ( Line ( format ! (
2457
- "self.client.new_call(_private::TYPE_ID, {ordinal}, None)"
2527
+ "self.client.new_call(_private::TYPE_ID, {ordinal}, ::core::option::Option:: None)"
2458
2528
) ) ) ) ) ;
2459
2529
client_impl_interior. push ( Line ( "}" . to_string ( ) ) ) ;
2460
2530
0 commit comments