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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
use super::*;
use std::marker::*;
use std::ops::*;
pub trait PrimitiveArray<T> where Self : Sized + AsValidJObjectAndEnv, T : Clone + Default {
fn new<'env>(env: &'env Env, size: usize) -> Local<'env, Self>;
fn len(&self) -> usize;
fn get_region(&self, start: usize, elements: &mut [T]);
fn set_region(&self, start: usize, elements: &[T]);
fn from<'env>(env: &'env Env, elements: &[T]) -> Local<'env, Self> {
let array = Self::new(env, elements.len());
array.set_region(0, elements);
array
}
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: &'env Env, size: usize) -> Local<'env, 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());
Local::from_env_object(env, object)
}
}
fn from<'env>(env: &'env Env, elements: &[$type]) -> Local<'env, 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 } }