1#[macro_export]
43macro_rules! split_by_comma {
44 (
47 {$($input:tt)*},
48 $macro:path $(,$args:tt)*
49 ) => {
50 $crate::split_by_comma! {
51 {$($input)*},
52 {}, {}, $macro $(,$args)*
55 }
56 };
57 (
61 {
62 ,
63 $($rest:tt)*
64 },
65 {
66 $(
67 {$($prev_split:tt)*}
68 )*
69 },
70 {
71 $($current_split:tt)*
72 },
73 $macro:path $(,$args:tt)*
74 ) => {
75 $crate::split_by_comma! {
76 {
77 $($rest)*
78 },
79 {
80 $(
81 {$($prev_split)*}
82 )*
83 {
84 $($current_split)*
85 }
86 },
87 {},
88 $macro $(,$args)*
89 }
90 };
91 (
94 {},
95 {
96 $(
97 {$($prev_split:tt)*}
98 )*
99 },
100 {
101 $($current_split:tt)+
102 },
103 $macro:path $(,$args:tt)*
104 ) => {
105 $crate::split_by_comma! {
106 {},
107 {
108 $(
109 {$($prev_split)*}
110 )*
111 {
112 $($current_split)+
113 }
114 },
115 {},
116 $macro $(,$args)*
117 }
118 };
119 (
121 {
122 $first:tt
123 $($rest:tt)*
124 },
125 {
126 $(
127 {$($prev_split:tt)*}
128 )*
129 },
130 {
131 $($current_split:tt)*
132 },
133 $macro:path $(,$args:tt)*
134 ) => {
135 $crate::split_by_comma! {
136 {
137 $($rest)*
138 },
139 {
140 $(
141 {$($prev_split)*}
142 )*
143 },
144 {
145 $($current_split)* $first
146 },
147 $macro $(,$args)*
148 }
149 };
150 (
152 {},
153 {
154 $(
155 {$($prev_split:tt)*}
156 )*
157 },
158 {},
159 $macro:path $(,$args:tt)*
160 ) => {
161 $macro! {
162 {
163 $(
164 {$($prev_split)*}
165 )*
166 }
167 $(,$args)*
168 }
169 };
170}
171#[macro_export]
186macro_rules! gen_class_name {
187 ($single_part_class:ident $($param_name:ident)?) => {
189 $crate::gen_class_name! { @inner java.lang.$single_part_class }
190 };
191 ($($class:ident).+ $($param_name:ident)?) => {
192 $crate::gen_class_name! { @inner $($class).+ }
193 };
194 (@inner $last:ident) => {
195 stringify! {$last}
196 };
197 (@inner $first:ident . $($rest:ident).+) => {
198 concat! {stringify! {$first}, "/", $crate::gen_class_name! {@inner $($rest).+} }
199 }
200}
201
202#[macro_export]
219macro_rules! gen_jni_type_sig {
220 (boolean $($param_name:ident)?) => {
221 "Z"
222 };
223 (byte $($param_name:ident)?) => {
224 "B"
225 };
226 (char $($param_name:ident)?) => {
227 "C"
228 };
229 (short $($param_name:ident)?) => {
230 "S"
231 };
232 (int $($param_name:ident)?) => {
233 "I"
234 };
235 (long $($param_name:ident)?) => {
236 "J"
237 };
238 (float $($param_name:ident)?) => {
239 "F"
240 };
241 (double $($param_name:ident)?) => {
242 "D"
243 };
244 (void) => {
245 "V"
246 };
247 (Class $(< ? >)? $($param_name:ident)?) => {
248 $crate::gen_jni_type_sig! { java.lang.Class }
249 };
250 ($($class_part:ident).+ $($param_name:ident)?) => {
251 concat! {"L", $crate::gen_class_name! {$($class_part).+}, ";"}
252 };
253 ($($class_part:ident).+ [] $($param_name:ident)?) => {
254 concat! { "[", $crate::gen_jni_type_sig! {$($class_part).+}}
255 };
256 ($($invalid:tt)*) => {
257 compile_error!(concat!("unsupported type `", stringify!($($invalid)*), "`"))
258 };
259}
260
261#[macro_export]
281macro_rules! cast_jvalue {
282 ({ boolean }, $value:expr) => {{ $value.z().expect("should be bool") }};
283 ({ byte }, $value:expr) => {{ $value.b().expect("should be byte") }};
284 ({ char }, $value:expr) => {{ $value.c().expect("should be char") }};
285 ({ double }, $value:expr) => {{ $value.d().expect("should be double") }};
286 ({ float }, $value:expr) => {{ $value.f().expect("should be float") }};
287 ({ int }, $value:expr) => {{ $value.i().expect("should be int") }};
288 ({ long }, $value:expr) => {{ $value.j().expect("should be long") }};
289 ({ short }, $value:expr) => {{ $value.s().expect("should be short") }};
290 ({ void }, $value:expr) => {{ $value.v().expect("should be void") }};
291 ({ byte[] }, $value:expr) => {{
292 let obj = $value.l().expect("should be object");
293 unsafe { jni::objects::JByteArray::from_raw(obj.into_raw()) }
294 }};
295 ({ $($class:tt)+ }, $value:expr) => {{ $value.l().expect("should be object") }};
296}
297
298#[macro_export]
321macro_rules! to_jvalue {
322 ({ boolean $($param_name:ident)? }, $value:expr) => {{ jni::objects::JValue::Bool($value as _) }};
323 ({ byte $($param_name:ident)? }, $value:expr) => {{ jni::objects::JValue::Byte($value as _) }};
324 ({ char $($param_name:ident)? }, $value:expr) => {{ jni::objects::JValue::Char($value as _) }};
325 ({ double $($param_name:ident)? }, $value:expr) => {{ jni::objects::JValue::Double($value as _) }};
326 ({ float $($param_name:ident)? }, $value:expr) => {{ jni::objects::JValue::Float($value as _) }};
327 ({ int $($param_name:ident)? }, $value:expr) => {{ jni::objects::JValue::Int($value as _) }};
328 ({ long $($param_name:ident)? }, $value:expr) => {{ jni::objects::JValue::Long($value as _) }};
329 ({ short $($param_name:ident)? }, $value:expr) => {{ jni::objects::JValue::Short($value as _) }};
330 ({ void }, $value:expr) => {{
331 compile_error! {concat! {"unlike to pass void value: ", stringify! {$value} }}
332 }};
333 ({ $($class:ident)+ $([])? $($param_name:ident)? }, $value:expr) => {{ jni::objects::JValue::Object($value as _) }};
334}
335
336#[macro_export]
373macro_rules! gen_jni_sig {
374 ({$({$($args:tt)+})*}, {return {$($ret:tt)*}}) => {{
376 concat! {
377 "(", $($crate::gen_jni_type_sig!{ $($args)+ },)* ")",
378 $crate::gen_jni_type_sig! {$($ret)+}
379 }
380 }};
381 ({$($ret:tt)*}, {$($args:tt)*}) => {{
382 $crate::split_by_comma! {
383 {$($args)*},
384 $crate::gen_jni_sig,
385 {return {$($ret)*}}
386 }
387 }};
388 ({{$func_name:ident, {$($ret:tt)*}, {$($args:tt)*}}}) => {{
390 $crate::gen_jni_sig! {
391 {$($ret)*}, {$($args)*}
392 }
393 }};
394 ($($input:tt)*) => {{
395 $crate::split_extract_plain_native_methods! {{$($input)*;}, $crate::gen_jni_sig}
396 }}
397}
398
399#[macro_export]
400macro_rules! for_all_plain_native_methods {
401 ($macro:path $(,$args:tt)*) => {
402 $macro! {
403 {
404 public static native void tracingSlf4jEvent(String threadName, String name, int level, String message, String stackTrace);
405
406 public static native boolean tracingSlf4jEventEnabled(int level);
407
408 public static native int defaultVnodeCount();
409
410 public static native boolean validateCdcSourceColumnType(
411 int cdcTableType,
412 String upstreamTypeName,
413 int rwTypeName,
414 long charMaxLength,
415 boolean isUnsigned,
416 String postgresUdtName);
417
418 static native long iteratorNewStreamChunk(long pointer);
419
420 static native boolean iteratorNext(long pointer);
421
422 public static native void initObjectStoreForTest(String stateStoreUrl, String dataDirectory);
423
424 public static native void putObject(String objectName, byte[] data);
425
426 public static native String getObjectStoreType();
427
428 public static native void deleteObjects(String dir);
429
430 public static native byte[] getObject(String objectName);
431
432 public static native String[] listObject(String dir);
433
434 static native void iteratorClose(long pointer);
435
436 static native long newStreamChunkFromPayload(byte[] streamChunkPayload);
437
438 static native long newStreamChunkFromPretty(String str);
439
440 static native void streamChunkClose(long pointer);
441
442 static native byte[] iteratorGetKey(long pointer);
443
444 static native int iteratorGetOp(long pointer);
445
446 static native boolean iteratorIsNull(long pointer, int index);
447
448 static native short iteratorGetInt16Value(long pointer, int index);
449
450 static native int iteratorGetInt32Value(long pointer, int index);
451
452 static native long iteratorGetInt64Value(long pointer, int index);
453
454 static native float iteratorGetFloatValue(long pointer, int index);
455
456 static native double iteratorGetDoubleValue(long pointer, int index);
457
458 static native boolean iteratorGetBooleanValue(long pointer, int index);
459
460 static native String iteratorGetStringValue(long pointer, int index);
461
462 static native java.time.LocalDateTime iteratorGetTimestampValue(long pointer, int index);
463
464 static native java.time.OffsetDateTime iteratorGetTimestamptzValue(long pointer, int index);
465
466 static native java.math.BigDecimal iteratorGetDecimalValue(long pointer, int index);
467
468 static native java.time.LocalTime iteratorGetTimeValue(long pointer, int index);
469
470 static native java.time.LocalDate iteratorGetDateValue(long pointer, int index);
471
472 static native String iteratorGetIntervalValue(long pointer, int index);
473
474 static native String iteratorGetJsonbValue(long pointer, int index);
475
476 static native byte[] iteratorGetByteaValue(long pointer, int index);
477
478 static native Object iteratorGetArrayValue(long pointer, int index, Class<?> clazz);
480
481 public static native boolean sendCdcSourceMsgToChannel(long channelPtr, byte[] msg);
482
483 public static native boolean sendCdcSourceErrorToChannel(long channelPtr, String errorMsg);
484
485 public static native void cdcSourceSenderClose(long channelPtr);
486
487 public static native com.risingwave.java.binding.JniSinkWriterStreamRequest
488 recvSinkWriterRequestFromChannel(long channelPtr);
489
490 public static native boolean sendSinkWriterResponseToChannel(long channelPtr, byte[] msg);
491
492 public static native boolean sendSinkWriterErrorToChannel(long channelPtr, String msg);
493
494 public static native byte[] recvSinkCoordinatorRequestFromChannel(long channelPtr);
495
496 public static native boolean sendSinkCoordinatorResponseToChannel(long channelPtr, byte[] msg);
497 }
498 $(,$args)*
499 }
500 };
501}
502
503#[macro_export]
533macro_rules! split_extract_plain_native_methods {
534 (
535 {$($input:tt)*},
536 $macro:path
537 $(,$extra_args:tt)*
538 ) => {{
539 $crate::split_extract_plain_native_methods! {
540 {$($input)*},
541 {},
542 $macro
543 $(,$extra_args)*
544 }
545 }};
546 (
547 {
548 $(public)? static native $($first:tt)*
549 },
550 {
551 $($second:tt)*
552 },
553 $macro:path
554 $(,$extra_args:tt)*
555 ) => {
556 $crate::split_extract_plain_native_methods! {
557 {
558 $($first)*
559 },
560 {
561 $($second)*
562 },
563 $macro
564 $(,$extra_args)*
565 }
566 };
567 (
568 {
569 $($ret:tt).+ $func_name:ident($($args:tt)*); $($rest:tt)*
570 },
571 {
572 $({$prev_func_name:ident, {$($prev_ret:tt)*}, {$($prev_args:tt)*}})*
573 },
574 $macro:path
575 $(,$extra_args:tt)*
576 ) => {
577 $crate::split_extract_plain_native_methods! {
578 {$($rest)*},
579 {
580 $({$prev_func_name, {$($prev_ret)*}, {$($prev_args)*}})*
581 {$func_name, {$($ret).+}, {$($args)*}}
582 },
583 $macro
584 $(,$extra_args)*
585 }
586 };
587 (
588 {
589 $($ret:tt).+ [] $func_name:ident($($args:tt)*); $($rest:tt)*
590 },
591 {
592 $({$prev_func_name:ident, {$($prev_ret:tt)*}, {$($prev_args:tt)*}})*
593 },
594 $macro:path
595 $(,$extra_args:tt)*
596 ) => {
597 $crate::split_extract_plain_native_methods! {
598 {$($rest)*},
599 {
600 $({$prev_func_name, {$($prev_ret)*}, {$($prev_args)*}})*
601 {$func_name, {$($ret).+ []}, {$($args)*}}
602 },
603 $macro
604 $(,$extra_args)*
605 }
606 };
607 (
608 {},
609 {
610 $({$func_name:ident, {$($ret:tt)*}, {$($args:tt)*}})*
611 },
612 $macro:path
613 $(,$extra_args:tt)*
614 ) => {
615 $macro! {
616 {
617 $({$func_name, {$($ret)*}, {$($args)*}})*
618 }
619 $(,$extra_args)*
620 }
621 };
622 ($($invalid:tt)*) => {
623 compile_error!(concat!("unable to split extract `", stringify!($($invalid)*), "`"))
624 };
625}
626
627#[macro_export]
630macro_rules! for_all_native_methods {
631 ($macro:path $(,$args:tt)*) => {{
632 $crate::for_all_plain_native_methods! {
633 $crate::for_all_native_methods,
634 $macro
635 $(,$args)*
636 }
637 }};
638 (
639 {
640 $({$func_name:ident, {$($ret:tt)*}, {$($args:tt)*}})*
641 },
642 $macro:path
643 $(,$extra_args:tt)*
644 ) => {{
645 $macro! {
646 {$({$func_name, {$($ret)*}, {$($args)*}})*}
647 $(,$extra_args)*
648 }
649 }};
650 (
651 {$($input:tt)*},
652 $macro:path
653 $(,$extra_args:tt)*
654 ) => {{
655 $crate::split_extract_plain_native_methods! {
656 {$($input)*},
657 $crate::for_all_native_methods,
658 $macro
659 $(,$extra_args)*
660 }
661 }};
662}
663
664#[macro_export]
687macro_rules! convert_args_list {
688 (
689 {
690 {$($first_args:tt)+}
691 $({$($args:tt)+})*
692 },
693 {
694 {$first_value:expr}
695 $({$value:expr})*
696 },
697 {
698 $({$converted:expr})*
699 }) => {
700 $crate::convert_args_list! {
701 {$({$($args)+})*},
702 {$({$value})*},
703 {
704 $({$converted})*
705 {
706 $crate::to_jvalue! {
707 {$($first_args)+},
708 {$first_value}
709 }
710 }
711 }
712 }
713 };
714 ({$($args:tt)+}, {}, {$({$converted:expr})*}) => {
715 compile_error! {concat!{"trailing argument not passed: ", stringify!{$($args)+}}}
716 };
717 ({}, {$($value:tt)+}, {$({$converted:expr})*}) => {
718 compile_error! {concat!{"trailing extra value passed: ", stringify!{$($value)+}}}
719 };
720 ({}, {}, {$({$converted:expr})*}) => {
721 [$(
722 $converted
723 ),*]
724 };
725 ({$($args:tt)*}, {$($value:expr),*}) => {{
726 $crate::split_by_comma! {
727 {$($args)*},
728 $crate::convert_args_list,
729 {$({$value})*},
730 {}
731 }
732 }};
733 ($($invalid:tt)*) => {
734 compile_error!(concat!("failed to convert `", stringify!($($invalid)*), "`"))
735 };
736}
737
738#[macro_export]
739macro_rules! call_static_method {
740 (
741 {{$func_name:ident, {$($ret:tt)*}, {$($args:tt)*}}},
742 {$($class:ident).+},
743 {$env:expr} $(, $method_args:expr)*
744 ) => {{
745 $crate::call_static_method! {
746 $env,
747 $crate::gen_class_name!($($class).+),
748 stringify! {$func_name},
749 {{$($ret)*}, {$($args)*}}
750 $(, $method_args)*
751 }
752 }};
753 ($env:expr, {$($class:ident).+}, {$($method:tt)*} $(, $args:expr)*) => {{
754 $crate::split_extract_plain_native_methods! {
755 {$($method)*;},
756 $crate::call_static_method,
757 {$($class).+},
758 {$env} $(, $args)*
759 }
760 }};
761 (
762 $env:expr,
763 $class_name:expr,
764 $func_name:expr,
765 {{$($ret:tt)*}, {$($args:tt)*}}
766 $(, $method_args:expr)*
767 ) => {{
768 $env.call_static_method(
769 $class_name,
770 $func_name,
771 $crate::gen_jni_sig! { {$($ret)+}, {$($args)*}},
772 &{
773 $crate::convert_args_list! {
774 {$($args)*},
775 {$($method_args),*}
776 }
777 },
778 ).map(|jvalue| {
779 $crate::cast_jvalue! {
780 {$($ret)*},
781 jvalue
782 }
783 })
784 }};
785}
786
787#[macro_export]
788macro_rules! call_method {
789 (
790 {{$func_name:ident, {$($ret:tt)*}, {$($args:tt)*}}},
791 $env:expr, $obj:expr $(, $method_args:expr)*
792 ) => {{
793 $env.call_method(
794 $obj,
795 stringify!{$func_name},
796 $crate::gen_jni_sig! { {$($ret)+}, {$($args)*}},
797 &{
798 $crate::convert_args_list! {
799 {$($args)*},
800 {$($method_args),*}
801 }
802 },
803 ).map(|jvalue| {
804 $crate::cast_jvalue! {
805 {$($ret)*},
806 jvalue
807 }
808 })
809 }};
810 ($env:expr, $obj:expr, {$($method:tt)*} $(, $args:expr)*) => {{
811 $crate::split_extract_plain_native_methods! {
812 {$($method)*;},
813 $crate::call_method,
814 $env, $obj $(, $args)*
815 }
816 }};
817}
818
819#[macro_export]
820macro_rules! gen_native_method_entry {
821 (
822 $class_prefix:ident, $func_name:ident, {$($ret:tt)+}, {$($args:tt)*}
823 ) => {{
824 {
825 let fn_ptr = $crate::paste! {[<$class_prefix $func_name> ]} as *mut c_void;
826 let sig = $crate::gen_jni_sig! { {$($ret)+}, {$($args)*}};
827 jni::NativeMethod {
828 name: jni::strings::JNIString::from(stringify! {$func_name}),
829 sig: jni::strings::JNIString::from(sig),
830 fn_ptr,
831 }
832 }
833 }};
834}
835
836#[cfg(test)]
837mod tests {
838 use std::fmt::Formatter;
839
840 #[test]
841 fn test_for_all_gen() {
842 macro_rules! gen_array {
843 (test) => {{
844 for_all_native_methods! {
845 {
846 public static native int defaultVnodeCount();
847 static native long hummockIteratorNew(byte[] readPlan);
848 public static native byte[] rowGetKey(long pointer);
849 },
850 gen_array
851 }
852 }};
853 (all) => {{
854 for_all_native_methods! {
855 gen_array
856 }
857 }};
858 ({$({ $func_name:ident, {$($ret:tt)+}, {$($args:tt)*} })*}) => {{
859 [
860 $(
861 (stringify! {$func_name}, gen_jni_sig! { {$($ret)+}, {$($args)*}}),
862 )*
863 ]
864 }};
865 }
866 let sig: [(_, _); 3] = gen_array!(test);
867 assert_eq!(
868 sig,
869 [
870 ("defaultVnodeCount", "()I"),
871 ("hummockIteratorNew", "([B)J"),
872 ("rowGetKey", "(J)[B")
873 ]
874 );
875
876 let sig = gen_array!(all);
877 assert!(!sig.is_empty());
878 }
879
880 #[test]
881 fn test_all_native_methods() {
882 let expected = expect_test::expect![[r#"
884 [
885 tracingSlf4jEvent (Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V,
886 tracingSlf4jEventEnabled (I)Z,
887 defaultVnodeCount ()I,
888 validateCdcSourceColumnType (ILjava/lang/String;IJZLjava/lang/String;)Z,
889 iteratorNewStreamChunk (J)J,
890 iteratorNext (J)Z,
891 initObjectStoreForTest (Ljava/lang/String;Ljava/lang/String;)V,
892 putObject (Ljava/lang/String;[B)V,
893 getObjectStoreType ()Ljava/lang/String;,
894 deleteObjects (Ljava/lang/String;)V,
895 getObject (Ljava/lang/String;)[B,
896 listObject (Ljava/lang/String;)[Ljava/lang/String;,
897 iteratorClose (J)V,
898 newStreamChunkFromPayload ([B)J,
899 newStreamChunkFromPretty (Ljava/lang/String;)J,
900 streamChunkClose (J)V,
901 iteratorGetKey (J)[B,
902 iteratorGetOp (J)I,
903 iteratorIsNull (JI)Z,
904 iteratorGetInt16Value (JI)S,
905 iteratorGetInt32Value (JI)I,
906 iteratorGetInt64Value (JI)J,
907 iteratorGetFloatValue (JI)F,
908 iteratorGetDoubleValue (JI)D,
909 iteratorGetBooleanValue (JI)Z,
910 iteratorGetStringValue (JI)Ljava/lang/String;,
911 iteratorGetTimestampValue (JI)Ljava/time/LocalDateTime;,
912 iteratorGetTimestamptzValue (JI)Ljava/time/OffsetDateTime;,
913 iteratorGetDecimalValue (JI)Ljava/math/BigDecimal;,
914 iteratorGetTimeValue (JI)Ljava/time/LocalTime;,
915 iteratorGetDateValue (JI)Ljava/time/LocalDate;,
916 iteratorGetIntervalValue (JI)Ljava/lang/String;,
917 iteratorGetJsonbValue (JI)Ljava/lang/String;,
918 iteratorGetByteaValue (JI)[B,
919 iteratorGetArrayValue (JILjava/lang/Class;)Ljava/lang/Object;,
920 sendCdcSourceMsgToChannel (J[B)Z,
921 sendCdcSourceErrorToChannel (JLjava/lang/String;)Z,
922 cdcSourceSenderClose (J)V,
923 recvSinkWriterRequestFromChannel (J)Lcom/risingwave/java/binding/JniSinkWriterStreamRequest;,
924 sendSinkWriterResponseToChannel (J[B)Z,
925 sendSinkWriterErrorToChannel (JLjava/lang/String;)Z,
926 recvSinkCoordinatorRequestFromChannel (J)[B,
927 sendSinkCoordinatorResponseToChannel (J[B)Z,
928 ]
929 "#]];
930
931 struct MethodInfo {
932 name: &'static str,
933 sig: &'static str,
934 }
935
936 impl std::fmt::Debug for MethodInfo {
937 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
938 write!(f, "{:40} {}", self.name, self.sig)
939 }
940 }
941
942 macro_rules! gen_all_native_method_info {
943 () => {{
944 $crate::for_all_native_methods! {
945 gen_all_native_method_info
946 }
947 }};
948 ({$({$func_name:ident, {$($ret:tt)*}, {$($args:tt)*}})*}) => {
949 [$(
950 (
951 MethodInfo {
952 name: stringify! {$func_name},
953 sig: $crate::gen_jni_sig! {
954 {$($ret)*}, {$($args)*}
955 },
956 }
957 )
958 ),*]
959 }
960 }
961 let info = gen_all_native_method_info!();
962 expected.assert_debug_eq(&info);
963 }
964}