1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
use super::*;
use std::marker::*;
use std::ops::*;
pub trait PrimitiveArray<T> where Self : Sized, T : Clone + Default {
fn new(env: &Env, size: usize) -> Self;
fn from(env: &Env, elements: &[T]) -> Self;
fn len(&self) -> usize;
fn get_region(&self, start: usize, elements: &mut [T]);
fn set_region(&self, start: usize, elements: &[T]);
fn get_region_as_vec(&self, range: impl RangeBounds<usize>) -> Vec<T> {
let len = self.len();
let start = match range.start_bound() {
Bound::Unbounded => 0,
Bound::Included(n) => *n,
Bound::Excluded(n) => *n+1,
};
let end = match range.end_bound() {
Bound::Unbounded => len,
Bound::Included(n) => *n+1,
Bound::Excluded(n) => *n,
};
assert!(start <= end);
assert!(end <= len);
let vec_len = end - start;
let mut vec = Vec::new();
vec.resize(vec_len, Default::default());
self.get_region(start, &mut vec[..]);
vec
}
fn as_vec(&self) -> Vec<T> {
self.get_region_as_vec(0..self.len())
}
}
#[test] fn bool_ffi_assumptions_test() {
use std::mem::*;
assert_eq!(size_of::<jboolean>(), 1);
assert_eq!(size_of::<bool>(), 1);
assert_eq!(unsafe { std::mem::transmute::<bool, u8>(true ) }, JNI_TRUE );
assert_eq!(unsafe { std::mem::transmute::<bool, u8>(false) }, JNI_FALSE);
}
macro_rules! primitive_array {
(#[repr(transparent)] pub struct $name:ident = $type:ident { $new_array:ident $set_region:ident $get_region:ident } ) => {
#[repr(transparent)] pub struct $name(ObjectAndEnv);
unsafe impl AsValidJObjectAndEnv for $name {}
unsafe impl AsJValue for $name { fn as_jvalue(&self) -> jni_sys::jvalue { jni_sys::jvalue { l: self.0.object } } }
impl PrimitiveArray<$type> for $name {
fn new(env: &Env, size: usize) -> Self {
assert!(size <= std::i32::MAX as usize);
let size = size as jsize;
let env = env.as_jni_env();
unsafe {
let object = (**env).$new_array.unwrap()(env, size);
let exception = (**env).ExceptionOccurred.unwrap()(env);
assert!(exception.is_null());
Self(ObjectAndEnv { object, env })
}
}
fn from(env: &Env, elements: &[$type]) -> Self {
let array = Self::new(env, elements.len());
let size = elements.len() as jsize;
let env = array.0.env as *mut JNIEnv;
let object = array.0.object;
unsafe {
(**env).$set_region.unwrap()(env, object, 0, size, elements.as_ptr() as *const _);
}
array
}
fn len(&self) -> usize {
unsafe { (**self.0.env).GetArrayLength.unwrap()(self.0.env as *mut _, self.0.object) as usize }
}
fn get_region(&self, start: usize, elements: &mut [$type]) {
assert!(start <= std::i32::MAX as usize);
assert!(elements.len() <= std::i32::MAX as usize);
let self_len = self.len() as jsize;
let elements_len = elements.len() as jsize;
let start = start as jsize;
let end = start + elements_len;
assert!(start <= end);
assert!(end <= self_len);
unsafe { (**self.0.env).$get_region.unwrap()(self.0.env as *mut _, self.0.object, start, elements_len, elements.as_mut_ptr() as *mut _) };
}
fn set_region(&self, start: usize, elements: &[$type]) {
assert!(start <= std::i32::MAX as usize);
assert!(elements.len() <= std::i32::MAX as usize);
let self_len = self.len() as jsize;
let elements_len = elements.len() as jsize;
let start = start as jsize;
let end = start + elements_len;
assert!(start <= end);
assert!(end <= self_len);
unsafe { (**self.0.env).$set_region.unwrap()(self.0.env as *mut _, self.0.object, start, elements_len, elements.as_ptr() as *const _) };
}
}
};
}
primitive_array! { #[repr(transparent)] pub struct BooleanArray = bool { NewBooleanArray SetBooleanArrayRegion GetBooleanArrayRegion } }
primitive_array! { #[repr(transparent)] pub struct ByteArray = jbyte { NewByteArray SetByteArrayRegion GetByteArrayRegion } }
primitive_array! { #[repr(transparent)] pub struct CharArray = jchar { NewCharArray SetCharArrayRegion GetCharArrayRegion } }
primitive_array! { #[repr(transparent)] pub struct ShortArray = jshort { NewShortArray SetShortArrayRegion GetShortArrayRegion } }
primitive_array! { #[repr(transparent)] pub struct IntArray = jint { NewIntArray SetIntArrayRegion GetIntArrayRegion } }
primitive_array! { #[repr(transparent)] pub struct LongArray = jlong { NewLongArray SetLongArrayRegion GetLongArrayRegion } }
primitive_array! { #[repr(transparent)] pub struct FloatArray = jfloat { NewFloatArray SetFloatArrayRegion GetFloatArrayRegion } }
primitive_array! { #[repr(transparent)] pub struct DoubleArray = jdouble { NewDoubleArray SetDoubleArrayRegion GetDoubleArrayRegion } }