Skip to content

Commit fa5b5e0

Browse files
committed
correct mistake when casting, pointer to pointer was unnecessary
1 parent c06acf9 commit fa5b5e0

File tree

4 files changed

+72
-201
lines changed

4 files changed

+72
-201
lines changed

examples/sum_int.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
44
use libsqlite3_sys::sqlite3_int64;
55
use sqlite_loadable::prelude::*;
6-
use sqlite_loadable::window::{WindowFunctionCallbacks, define_window_function};
6+
use sqlite_loadable::window::define_window_function;
77
use sqlite_loadable::{api, Result};
88

99
/// Example inspired by sqlite3's sumint
@@ -41,8 +41,10 @@ pub fn x_inverse(context: *mut sqlite3_context, values: &[*mut sqlite3_value]) -
4141
#[sqlite_entrypoint]
4242
pub fn sqlite3_sumint_init(db: *mut sqlite3) -> Result<()> {
4343
let flags = FunctionFlags::UTF8 | FunctionFlags::DETERMINISTIC;
44-
define_window_function(db, "sumint", -1, flags,
45-
WindowFunctionCallbacks::new(x_step, x_final, x_value, x_inverse))?;
44+
define_window_function(
45+
db, "sumint", -1, flags,
46+
x_step, x_final, Some(x_value), Some(x_inverse),
47+
)?;
4648
Ok(())
4749
}
4850

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ pub use bit_flags::FunctionFlags;
2727
pub use scalar::{define_scalar_function, define_scalar_function_with_aux};
2828

2929
#[doc(inline)]
30-
pub use window::{WindowFunctionCallbacksWithAux, define_window_function_with_aux};
30+
pub use window::{WindowFunctionCallbacks, define_window_function};
3131

3232
#[doc(inline)]
3333
pub use collation::define_collation;

src/window.rs

Lines changed: 61 additions & 192 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,17 @@ use crate::{
1515
};
1616
use sqlite3ext_sys::{sqlite3, sqlite3_context, sqlite3_user_data, sqlite3_value};
1717

18-
// TODO typedef repeating parameter types, across multiple files
19-
2018
fn create_window_function(
2119
db: *mut sqlite3,
2220
name: &str,
2321
num_args: c_int,
2422
func_flags: FunctionFlags,
2523
p_app: *mut c_void,
26-
x_step: Option<unsafe extern "C" fn(*mut sqlite3_context, i32, *mut *mut sqlite3_value)>,
27-
x_final: Option<unsafe extern "C" fn(*mut sqlite3_context)>,
24+
x_step: unsafe extern "C" fn(*mut sqlite3_context, i32, *mut *mut sqlite3_value),
25+
x_final: unsafe extern "C" fn(*mut sqlite3_context),
2826
x_value: Option<unsafe extern "C" fn(*mut sqlite3_context)>,
2927
x_inverse: Option<unsafe extern "C" fn(*mut sqlite3_context, i32, *mut *mut sqlite3_value)>,
30-
destroy: Option<unsafe extern "C" fn(*mut c_void)>,
28+
destroy: unsafe extern "C" fn(*mut c_void),
3129
) -> Result<()> {
3230

3331
let cname = CString::new(name)?;
@@ -38,11 +36,11 @@ fn create_window_function(
3836
num_args,
3937
func_flags.bits(),
4038
p_app,
41-
x_step,
42-
x_final,
39+
Some(x_step),
40+
Some(x_final),
4341
x_value,
4442
x_inverse,
45-
destroy,
43+
Some(destroy),
4644
)
4745
};
4846

@@ -53,46 +51,25 @@ fn create_window_function(
5351
}
5452
}
5553

54+
type ValueCallback = fn(context: *mut sqlite3_context, values: &[*mut sqlite3_value]) -> Result<()>;
55+
type ContextCallback = fn(context: *mut sqlite3_context) -> Result<()>;
56+
5657
pub struct WindowFunctionCallbacks
5758
{
58-
x_step: fn(context: *mut sqlite3_context, values: &[*mut sqlite3_value]) -> Result<()>,
59-
x_final: fn(context: *mut sqlite3_context) -> Result<()>,
60-
x_value: fn(context: *mut sqlite3_context) -> Result<()>,
61-
x_inverse: fn(context: *mut sqlite3_context, values: &[*mut sqlite3_value]) -> Result<()>,
59+
x_step: ValueCallback,
60+
x_final: ContextCallback,
61+
x_value: Option<ContextCallback>,
62+
x_inverse: Option<ValueCallback>,
6263
}
6364

6465
impl WindowFunctionCallbacks {
6566
pub fn new(
66-
x_step: fn(context: *mut sqlite3_context, values: &[*mut sqlite3_value]) -> Result<()>,
67-
x_final: fn(context: *mut sqlite3_context) -> Result<()>,
68-
x_value: fn(context: *mut sqlite3_context) -> Result<()>,
69-
x_inverse: fn(context: *mut sqlite3_context, values: &[*mut sqlite3_value]) -> Result<()>
67+
x_step: ValueCallback,
68+
x_final: ContextCallback,
69+
x_value: Option<ContextCallback>,
70+
x_inverse: Option<ValueCallback>
7071
) -> Self {
71-
WindowFunctionCallbacks {
72-
x_step,
73-
x_final,
74-
x_value,
75-
x_inverse,
76-
}
77-
}
78-
}
79-
80-
pub struct WindowFunctionCallbacksWithAux<T>
81-
{
82-
x_step: fn(context: *mut sqlite3_context, values: &[*mut sqlite3_value], aux: &T) -> Result<()>,
83-
x_final: fn(context: *mut sqlite3_context, aux: &T) -> Result<()>,
84-
x_value: fn(context: *mut sqlite3_context, aux: &T) -> Result<()>,
85-
x_inverse: fn(context: *mut sqlite3_context, values: &[*mut sqlite3_value], aux: &T) -> Result<()>,
86-
}
87-
88-
impl<T> WindowFunctionCallbacksWithAux<T> {
89-
pub fn new(
90-
x_step: fn(context: *mut sqlite3_context, values: &[*mut sqlite3_value], aux: &T) -> Result<()>,
91-
x_final: fn(context: *mut sqlite3_context, aux: &T) -> Result<()>,
92-
x_value: fn(context: *mut sqlite3_context, aux: &T) -> Result<()>,
93-
x_inverse: fn(context: *mut sqlite3_context, values: &[*mut sqlite3_value], aux: &T) -> Result<()>
94-
) -> Self {
95-
WindowFunctionCallbacksWithAux {
72+
Self {
9673
x_step,
9774
x_final,
9875
x_value,
@@ -102,148 +79,33 @@ impl<T> WindowFunctionCallbacksWithAux<T> {
10279
}
10380

10481
// TODO add documentation
105-
// TODO add new test with aux object
106-
// TODO parentheses matching
107-
/// The aux parameter can be used to pass another context object altogether
108-
pub fn define_window_function_with_aux<T>(
109-
db: *mut sqlite3,
110-
name: &str,
111-
num_args: c_int,
112-
func_flags: FunctionFlags,
113-
callbacks: WindowFunctionCallbacksWithAux<T>,
114-
aux: T,
115-
) -> Result<()>
116-
{
117-
let callbacks_pointer = Box::into_raw(Box::new(callbacks));
118-
let aux_pointer: *mut T = Box::into_raw(Box::new(aux));
119-
let app_pointer = Box::into_raw(Box::new((callbacks_pointer, aux_pointer)));
120-
121-
unsafe extern "C" fn x_step_wrapper<T>(
122-
context: *mut sqlite3_context,
123-
argc: c_int,
124-
argv: *mut *mut sqlite3_value,
125-
)
126-
{
127-
let x = sqlite3_user_data(context).cast::<(*mut WindowFunctionCallbacksWithAux<T>, *mut T)>();
128-
let boxed_function = Box::from_raw((*x).0).as_ref().x_step;
129-
let aux = (*x).1;
130-
// .collect slows things waaaay down, so stick with slice for now
131-
let args = slice::from_raw_parts(argv, argc as usize);
132-
let b: Box<T> = Box::from_raw(aux);
133-
match boxed_function(context, args, &*b) {
134-
Ok(()) => (),
135-
Err(e) => {
136-
if api::result_error(context, &e.result_error_message()).is_err() {
137-
api::result_error_code(context, SQLITE_INTERNAL);
138-
}
139-
}
140-
}
141-
Box::into_raw(b);
142-
}
143-
144-
unsafe extern "C" fn x_inverse_wrapper<T>(
145-
context: *mut sqlite3_context,
146-
argc: c_int,
147-
argv: *mut *mut sqlite3_value,
148-
)
149-
{
150-
let x = sqlite3_user_data(context).cast::<(*mut WindowFunctionCallbacksWithAux<T>, *mut T)>();
151-
let boxed_function = Box::from_raw((*x).0).as_ref().x_inverse;
152-
let aux = (*x).1;
153-
// .collect slows things waaaay down, so stick with slice for now
154-
let args = slice::from_raw_parts(argv, argc as usize);
155-
let b = Box::from_raw(aux);
156-
match boxed_function(context, args, &*b) {
157-
Ok(()) => (),
158-
Err(e) => {
159-
if api::result_error(context, &e.result_error_message()).is_err() {
160-
api::result_error_code(context, SQLITE_INTERNAL);
161-
}
162-
}
163-
}
164-
Box::into_raw(b);
165-
}
166-
167-
unsafe extern "C" fn x_final_wrapper<T>(
168-
context: *mut sqlite3_context,
169-
)
170-
{
171-
let x = sqlite3_user_data(context).cast::<(*mut WindowFunctionCallbacksWithAux<T>, *mut T)>();
172-
let boxed_function = Box::from_raw((*x).0).as_ref().x_final;
173-
let aux = (*x).1;
174-
let b = Box::from_raw(aux);
175-
match boxed_function(context, &*b) {
176-
Ok(()) => (),
177-
Err(e) => {
178-
if api::result_error(context, &e.result_error_message()).is_err() {
179-
api::result_error_code(context, SQLITE_INTERNAL);
180-
}
181-
}
182-
}
183-
Box::into_raw(b);
184-
}
185-
186-
unsafe extern "C" fn x_value_wrapper<T>(
187-
context: *mut sqlite3_context,
188-
)
189-
{
190-
let x = sqlite3_user_data(context).cast::<(*mut WindowFunctionCallbacksWithAux<T>, *mut T)>();
191-
let boxed_function = Box::from_raw((*x).0).as_ref().x_value;
192-
let aux = (*x).1;
193-
let b = Box::from_raw(aux);
194-
match boxed_function(context, &*b) {
195-
Ok(()) => (),
196-
Err(e) => {
197-
if api::result_error(context, &e.result_error_message()).is_err() {
198-
api::result_error_code(context, SQLITE_INTERNAL);
199-
}
200-
}
201-
}
202-
Box::into_raw(b);
203-
}
204-
205-
create_window_function(
206-
db,
207-
name,
208-
num_args,
209-
func_flags,
210-
// app_pointer,
211-
app_pointer.cast::<c_void>(),
212-
Some(x_step_wrapper::<T>),
213-
Some(x_final_wrapper::<T>),
214-
Some(x_value_wrapper::<T>),
215-
Some(x_inverse_wrapper::<T>),
216-
None, // Note: release resources in x_final if necessary
217-
)
218-
219-
220-
}
221-
222-
// TODO add documentation
223-
// TODO parentheses matching
22482
/// The aux parameter can be used to pass another context object altogether
22583
pub fn define_window_function(
22684
db: *mut sqlite3,
22785
name: &str,
22886
num_args: c_int,
22987
func_flags: FunctionFlags,
230-
callbacks: WindowFunctionCallbacks,
88+
x_step: ValueCallback,
89+
x_final: ContextCallback,
90+
x_value: Option<ContextCallback>,
91+
x_inverse: Option<ValueCallback>
23192
) -> Result<()>
23293
{
233-
let callbacks_pointer = Box::into_raw(Box::new(callbacks));
234-
let app_pointer = Box::into_raw(Box::new(callbacks_pointer));
94+
let app_pointer = Box::into_raw(
95+
Box::new(
96+
WindowFunctionCallbacks::new(x_step, x_final, x_value, x_inverse)
97+
)
98+
);
23599

236100
unsafe extern "C" fn x_step_wrapper(
237101
context: *mut sqlite3_context,
238102
argc: c_int,
239103
argv: *mut *mut sqlite3_value,
240104
)
241105
{
242-
let x = sqlite3_user_data(context).cast::<*mut WindowFunctionCallbacks>();
243-
let boxed_function = Box::from_raw(*x).as_ref().x_step;
244-
// .collect slows things waaaay down, so stick with slice for now
106+
let x = sqlite3_user_data(context).cast::<WindowFunctionCallbacks>();
245107
let args = slice::from_raw_parts(argv, argc as usize);
246-
match boxed_function(context, args) {
108+
match ((*x).x_step)(context, args) {
247109
Ok(()) => (),
248110
Err(e) => {
249111
if api::result_error(context, &e.result_error_message()).is_err() {
@@ -259,27 +121,26 @@ pub fn define_window_function(
259121
argv: *mut *mut sqlite3_value,
260122
)
261123
{
262-
let x = sqlite3_user_data(context).cast::<*mut WindowFunctionCallbacks>();
263-
let boxed_function = Box::from_raw(*x).as_ref().x_inverse;
264-
// .collect slows things waaaay down, so stick with slice for now
265-
let args = slice::from_raw_parts(argv, argc as usize);
266-
match boxed_function(context, args) {
267-
Ok(()) => (),
268-
Err(e) => {
269-
if api::result_error(context, &e.result_error_message()).is_err() {
270-
api::result_error_code(context, SQLITE_INTERNAL);
124+
let x = sqlite3_user_data(context).cast::<WindowFunctionCallbacks>();
125+
if let Some(x_inverse) = (*x).x_inverse {
126+
let args = slice::from_raw_parts(argv, argc as usize);
127+
match x_inverse(context, args) {
128+
Ok(()) => (),
129+
Err(e) => {
130+
if api::result_error(context, &e.result_error_message()).is_err() {
131+
api::result_error_code(context, SQLITE_INTERNAL);
132+
}
271133
}
272-
}
134+
}
273135
}
274136
}
275137

276138
unsafe extern "C" fn x_final_wrapper(
277139
context: *mut sqlite3_context,
278140
)
279141
{
280-
let x = sqlite3_user_data(context).cast::<*mut WindowFunctionCallbacks>();
281-
let boxed_function = Box::from_raw(*x).as_ref().x_final;
282-
match boxed_function(context) {
142+
let x = sqlite3_user_data(context).cast::<WindowFunctionCallbacks>();
143+
match ((*x).x_final)(context) {
283144
Ok(()) => (),
284145
Err(e) => {
285146
if api::result_error(context, &e.result_error_message()).is_err() {
@@ -293,30 +154,38 @@ pub fn define_window_function(
293154
context: *mut sqlite3_context,
294155
)
295156
{
296-
let x = sqlite3_user_data(context).cast::<*mut WindowFunctionCallbacks>();
297-
let boxed_function = Box::from_raw(*x).as_ref().x_value;
298-
match boxed_function(context) {
299-
Ok(()) => (),
300-
Err(e) => {
301-
if api::result_error(context, &e.result_error_message()).is_err() {
302-
api::result_error_code(context, SQLITE_INTERNAL);
157+
let x = sqlite3_user_data(context).cast::<WindowFunctionCallbacks>();
158+
if let Some(x_value) = (*x).x_value {
159+
match x_value(context) {
160+
Ok(()) => (),
161+
Err(e) => {
162+
if api::result_error(context, &e.result_error_message()).is_err() {
163+
api::result_error_code(context, SQLITE_INTERNAL);
164+
}
303165
}
304-
}
166+
}
305167
}
306168
}
307169

170+
unsafe extern "C" fn destroy(
171+
p_app: *mut c_void,
172+
)
173+
{
174+
let callbacks = p_app.cast::<WindowFunctionCallbacks>();
175+
let _ = Box::from(callbacks); // drop
176+
}
177+
308178
create_window_function(
309179
db,
310180
name,
311181
num_args,
312182
func_flags,
313-
// app_pointer,
314183
app_pointer.cast::<c_void>(),
315-
Some(x_step_wrapper),
316-
Some(x_final_wrapper),
184+
x_step_wrapper,
185+
x_final_wrapper,
317186
Some(x_value_wrapper),
318187
Some(x_inverse_wrapper),
319-
None, // Note: release resources in x_final if necessary
188+
destroy,
320189
)
321190

322191

0 commit comments

Comments
 (0)