1use crate::{
3 bindings::{
4 g_log, g_object_get_property, g_object_ref, g_object_set_property, g_object_unref,
5 g_type_check_instance_is_a, g_value_dup_boxed, g_value_get_boolean, g_value_get_double,
6 g_value_get_int, g_value_get_object, g_value_get_string, g_value_init, g_value_set_boolean,
7 g_value_set_boxed, g_value_set_double, g_value_set_enum, g_value_set_int,
8 g_value_set_object, g_value_set_string, g_value_set_uint64, g_value_unset,
9 vips_array_double_get_type, vips_array_image_get_type, vips_array_int_get_type,
10 vips_blob_get_type, vips_cache_operation_buildp, vips_enum_from_nick, vips_error_buffer,
11 vips_error_clear, vips_image_get_type, vips_interpolate_get_type, vips_object_get_argument,
12 vips_object_set_from_string, vips_object_unref_outputs, vips_operation_new,
13 vips_source_get_type, vips_target_get_type, vips_value_get_array_double,
14 vips_value_get_array_image, vips_value_set_array_double, vips_value_set_array_image,
15 vips_value_set_array_int, GLogLevelFlags_G_LOG_LEVEL_WARNING, GParamSpec, GTypeInstance,
16 GValue, VipsArgumentClass, VipsArgumentInstance, VipsBlob, VipsImage, VipsObject,
17 VipsOperation,
18 },
19 utils::{
20 get_g_type, new_c_string, G_TYPE_BOOLEAN, G_TYPE_DOUBLE, G_TYPE_INT, G_TYPE_STRING,
21 G_TYPE_UINT64,
22 },
23 Result,
24};
25use std::{
26 ffi::{c_char, c_int, c_void},
27 mem::MaybeUninit,
28};
29
30pub fn call(operation: &str, option: VOption) -> Result<c_int> {
32 call_option_string(
33 operation,
34 "",
35 option,
36 )
37}
38
39pub fn call_option_string(operation: &str, option_string: &str, option: VOption) -> Result<c_int> {
41 let operation = new_c_string(operation)?;
42 let option_string = new_c_string(option_string)?;
43 call_option_string_(
44 operation.as_ptr(),
45 option_string.as_ptr(),
46 option,
47 )
48}
49
50pub(crate) fn call_option_string_(
51 operation: *const c_char,
52 option_string: *const c_char,
53 option: VOption,
54) -> Result<c_int> {
55 unsafe {
56 let mut vips_operation = vips_operation_new(operation);
57
58 if !option_string.is_null()
59 && vips_object_set_from_string(
60 vips_operation as *mut VipsObject,
61 option_string,
62 ) < 0
63 {
64 vips_object_unref_outputs(vips_operation as *mut VipsObject);
65 g_object_unref(vips_operation as *mut c_void);
66 return Ok(1);
67 }
68
69 set_opreration(
70 vips_operation,
71 &option,
72 )?;
73
74 let result = vips_cache_operation_buildp(&mut vips_operation);
75
76 if result < 0 {
77 vips_object_unref_outputs(vips_operation as *mut VipsObject);
78 g_object_unref(vips_operation as *mut c_void);
79 return Ok(1);
80 }
81
82 get_operation(
83 vips_operation,
84 option,
85 )?;
86
87 g_object_unref(vips_operation as *mut c_void);
88
89 Ok(result)
90 }
91}
92
93enum VipsValue<'a> {
94 Bool(bool),
95 MutBool(&'a mut bool),
96 Int(i32),
97 MutInt(&'a mut i32),
98 Uint(u64),
99 Double(f64),
100 MutDouble(&'a mut f64),
101 Str(&'a str),
102 CStr(*mut c_char),
103 Image(&'a crate::VipsImage),
104 MutImage(&'a mut crate::VipsImage),
105 IntArray(&'a [i32]),
106 DoubleArray(&'a [f64]),
107 DoubleVec(Vec<f64>),
108 MutDoubleArray(&'a mut Vec<f64>),
109 ImageArray(&'a [crate::VipsImage]),
110 Blob(&'a crate::region::VipsBlob),
111 MutBlob(&'a mut crate::region::VipsBlob),
112 Target(&'a crate::connection::VipsTarget),
113 Source(&'a crate::connection::VipsSource),
114 Interpolate(&'a crate::interpolate::VipsInterpolate),
115}
116
117struct Pair<'a> {
118 input: bool,
119 name: String,
120 value: VipsValue<'a>,
121}
122
123impl<'a> Pair<'a> {
124 fn input(name: &str, value: VipsValue<'a>) -> Self {
125 Self {
126 input: true,
127 name: name.to_string(),
128 value,
129 }
130 }
131
132 fn output(name: &str, value: VipsValue<'a>) -> Self {
133 Self {
134 input: false,
135 name: name.to_string(),
136 value,
137 }
138 }
139}
140
141#[derive(Default)]
143pub struct VOption<'a> {
144 options: Vec<Pair<'a>>,
145}
146
147impl<'a> VOption<'a> {
148 pub fn new() -> Self {
149 Self {
150 options: Vec::new(),
151 }
152 }
153}
154
155fn get_operation(vips_operation: *mut VipsOperation, option: VOption) -> Result<()> {
156 unsafe {
157 for pair in option.options {
158 if pair.input {
159 continue;
160 }
161
162 let mut gvalue = MaybeUninit::<GValue>::zeroed();
163 let gvalue_ptr = gvalue.as_mut_ptr();
164 let name = new_c_string(pair.name)?;
165
166 match pair.value {
167 VipsValue::MutBool(out) => {
168 g_value_init(
169 gvalue_ptr,
170 get_g_type(G_TYPE_BOOLEAN)?,
171 );
172 g_object_get_property(
173 vips_operation.cast(),
174 name.as_ptr(),
175 gvalue_ptr,
176 );
177 *out = g_value_get_boolean(gvalue_ptr) != 0;
178 }
179 VipsValue::MutInt(out) => {
180 g_value_init(
181 gvalue_ptr,
182 get_g_type(G_TYPE_INT)?,
183 );
184 g_object_get_property(
185 vips_operation.cast(),
186 name.as_ptr(),
187 gvalue_ptr,
188 );
189 *out = g_value_get_int(gvalue_ptr);
190 }
191 VipsValue::MutDouble(out) => {
192 g_value_init(
193 gvalue_ptr,
194 get_g_type(G_TYPE_DOUBLE)?,
195 );
196 g_object_get_property(
197 vips_operation.cast(),
198 name.as_ptr(),
199 gvalue_ptr,
200 );
201 *out = g_value_get_double(gvalue_ptr);
202 }
203 VipsValue::MutDoubleArray(out) => {
204 g_value_init(
205 gvalue_ptr,
206 vips_array_double_get_type(),
207 );
208 g_object_get_property(
209 vips_operation.cast(),
210 name.as_ptr(),
211 gvalue_ptr,
212 );
213 let mut len = 0;
214 let array = vips_value_get_array_double(
215 gvalue_ptr,
216 &mut len,
217 );
218 let result = std::slice::from_raw_parts(
219 array,
220 len as usize,
221 );
222 out.extend(result);
223 }
224 VipsValue::MutBlob(out) => {
225 g_value_init(
226 gvalue_ptr,
227 vips_blob_get_type(),
228 );
229 g_object_get_property(
230 vips_operation.cast(),
231 name.as_ptr(),
232 gvalue_ptr,
233 );
234 let out_blob: *mut VipsBlob = g_value_dup_boxed(gvalue_ptr).cast();
235 out.ctx = out_blob;
236 }
237 VipsValue::MutImage(out) => {
238 g_value_init(
239 gvalue_ptr,
240 vips_image_get_type(),
241 );
242 g_object_get_property(
243 vips_operation.cast(),
244 name.as_ptr(),
245 gvalue_ptr,
246 );
247 let out_image: *mut VipsImage = g_value_get_object(gvalue_ptr).cast();
248 out.ctx = out_image;
249 }
250 _ => {}
251 }
252 g_value_unset(gvalue_ptr);
253 }
254 }
255
256 Ok(())
257}
258
259fn set_opreration(operation: *mut VipsOperation, option: &VOption) -> Result<()> {
260 unsafe {
261 for pair in &option.options {
262 if !pair.input {
263 continue;
264 }
265
266 let mut gvalue = MaybeUninit::<GValue>::zeroed();
267 let gvalue_ptr = gvalue.as_mut_ptr();
268
269 match pair.value {
270 VipsValue::Bool(value) => {
271 g_value_init(
272 gvalue_ptr,
273 get_g_type(G_TYPE_BOOLEAN)?,
274 );
275 g_value_set_boolean(
276 gvalue_ptr,
277 value.into(),
278 );
279 }
280 VipsValue::Int(value) => {
281 g_value_init(
282 gvalue_ptr,
283 get_g_type(G_TYPE_INT)?,
284 );
285 g_value_set_int(
286 gvalue_ptr,
287 value,
288 );
289 }
290 VipsValue::Uint(value) => {
291 g_value_init(
292 gvalue_ptr,
293 get_g_type(G_TYPE_UINT64)?,
294 );
295 g_value_set_uint64(
296 gvalue_ptr,
297 value,
298 );
299 }
300 VipsValue::Double(value) => {
301 g_value_init(
302 gvalue_ptr,
303 get_g_type(G_TYPE_DOUBLE)?,
304 );
305 g_value_set_double(
306 gvalue_ptr,
307 value,
308 );
309 }
310 VipsValue::Str(value) => {
311 let str = new_c_string(value)?;
312 g_value_init(
313 gvalue_ptr,
314 get_g_type(G_TYPE_STRING)?,
315 );
316 g_value_set_string(
317 gvalue_ptr,
318 str.as_ptr(),
319 );
320 }
321 VipsValue::CStr(value) => {
322 g_value_init(
323 gvalue_ptr,
324 get_g_type(G_TYPE_STRING)?,
325 );
326 g_value_set_string(
327 gvalue_ptr,
328 value,
329 );
330 }
331 VipsValue::IntArray(value) => {
332 g_value_init(
333 gvalue_ptr,
334 vips_array_int_get_type(),
335 );
336 vips_value_set_array_int(
337 gvalue_ptr,
338 value.as_ptr(),
339 value.len() as c_int,
340 );
341 }
342 VipsValue::DoubleArray(value) => {
343 g_value_init(
344 gvalue_ptr,
345 vips_array_double_get_type(),
346 );
347 vips_value_set_array_double(
348 gvalue_ptr,
349 value.as_ptr(),
350 value.len() as c_int,
351 );
352 }
353 VipsValue::Image(value) => {
354 g_value_init(
355 gvalue_ptr,
356 vips_image_get_type(),
357 );
358 g_value_set_object(
359 gvalue_ptr,
360 value.ctx as *mut c_void,
361 );
362 }
363 VipsValue::ImageArray(value) => {
364 g_value_init(
365 gvalue_ptr,
366 vips_array_image_get_type(),
367 );
368 vips_value_set_array_image(
369 gvalue_ptr,
370 value.len() as c_int,
371 );
372 let array = vips_value_get_array_image(
373 gvalue_ptr,
374 &mut 0,
375 );
376 let array = std::slice::from_raw_parts_mut(
377 array,
378 value.len(),
379 );
380 for i in 0..value.len() {
381 g_object_ref(value[i].ctx as *mut c_void);
382 array[i] = value[i].ctx;
383 }
384 }
385 VipsValue::Blob(value) => {
386 g_value_init(
387 gvalue_ptr,
388 vips_blob_get_type(),
389 );
390 g_value_set_boxed(
391 gvalue_ptr,
392 value.ctx as *const c_void,
393 );
394 }
395 VipsValue::Source(value) => {
396 g_value_init(
397 gvalue_ptr,
398 vips_source_get_type(),
399 );
400 g_value_set_object(
401 gvalue_ptr,
402 value.ctx as *mut c_void,
403 );
404 }
405 VipsValue::Target(value) => {
406 g_value_init(
407 gvalue_ptr,
408 vips_target_get_type(),
409 );
410 g_value_set_object(
411 gvalue_ptr,
412 value.ctx as *mut c_void,
413 );
414 }
415 VipsValue::Interpolate(value) => {
416 g_value_init(
417 gvalue_ptr,
418 vips_interpolate_get_type(),
419 );
420 g_value_set_object(
421 gvalue_ptr,
422 value.ctx as *mut c_void,
423 );
424 }
425 _ => {}
426 }
427
428 set_property(
429 operation,
430 &pair.name,
431 gvalue_ptr,
432 )?;
433 g_value_unset(gvalue_ptr);
434 }
435 }
436
437 Ok(())
438}
439
440fn set_property(operation: *mut VipsOperation, name: &str, value: *mut GValue) -> Result<()> {
441 unsafe {
442 let object: *mut VipsObject = operation.cast();
443 let name = new_c_string(name)?;
444
445 let mut pspec: *mut GParamSpec = std::ptr::null_mut();
446 let mut argument_class: *mut VipsArgumentClass = std::ptr::null_mut();
447 let mut argument_instance: *mut VipsArgumentInstance = std::ptr::null_mut();
448 if vips_object_get_argument(
449 object,
450 name.as_ptr(),
451 &mut pspec,
452 &mut argument_class,
453 &mut argument_instance,
454 ) < 0
455 {
456 g_warning()?;
457 vips_error_clear();
458 return Ok(());
459 }
460
461 let is_param_spec_enum = g_type_check_instance_is_a(
462 pspec as *mut GTypeInstance,
463 get_g_type("GParamEnum")?,
464 ) != 0;
465
466 if is_param_spec_enum && (*value).g_type == get_g_type(G_TYPE_STRING)? {
467 let pspec_type = (*pspec).value_type;
468 let enum_value = vips_enum_from_nick(
469 (*object).nickname,
470 pspec_type,
471 g_value_get_string(value),
472 );
473 if enum_value < 0 {
474 g_warning()?;
475 vips_error_clear();
476 return Ok(());
477 }
478
479 let mut gvalue = MaybeUninit::<GValue>::zeroed();
480 let value2 = gvalue.as_mut_ptr();
481 g_value_init(
482 value2,
483 pspec_type,
484 );
485 g_value_set_enum(
486 value2,
487 enum_value,
488 );
489 g_object_set_property(
490 object.cast(),
491 name.as_ptr(),
492 value2,
493 );
494 g_value_unset(value2);
495 } else {
496 g_object_set_property(
497 object.cast(),
498 name.as_ptr(),
499 value,
500 );
501 }
502 }
503
504 Ok(())
505}
506
507fn g_warning() -> Result<()> {
508 let domain = new_c_string("GLib-GObject")?;
509 let format = new_c_string("%s")?;
510 unsafe {
511 g_log(
512 domain.as_ptr(),
513 GLogLevelFlags_G_LOG_LEVEL_WARNING,
514 format.as_ptr(),
515 vips_error_buffer(),
516 )
517 };
518 Ok(())
519}
520
521pub trait Setter<'a, T> {
523 fn set(self, name: &str, value: T) -> VOption<'a>;
524 fn add(&mut self, name: &str, value: T);
525}
526
527impl<'a> Setter<'a, bool> for VOption<'a> {
529 fn set(mut self, name: &str, value: bool) -> VOption<'a> {
530 self.options
531 .push(
532 Pair::input(
533 name,
534 VipsValue::Bool(value),
535 ),
536 );
537 self
538 }
539 fn add(&mut self, name: &str, value: bool) {
540 self.options
541 .push(
542 Pair::input(
543 name,
544 VipsValue::Bool(value),
545 ),
546 );
547 }
548}
549
550impl<'a> Setter<'a, i32> for VOption<'a> {
552 fn set(mut self, name: &str, value: i32) -> VOption<'a> {
553 self.options
554 .push(
555 Pair::input(
556 name,
557 VipsValue::Int(value),
558 ),
559 );
560 self
561 }
562 fn add(&mut self, name: &str, value: i32) {
563 self.options
564 .push(
565 Pair::input(
566 name,
567 VipsValue::Int(value),
568 ),
569 );
570 }
571}
572
573impl<'a> Setter<'a, u64> for VOption<'a> {
575 fn set(mut self, name: &str, value: u64) -> VOption<'a> {
576 self.options
577 .push(
578 Pair::input(
579 name,
580 VipsValue::Uint(value),
581 ),
582 );
583 self
584 }
585 fn add(&mut self, name: &str, value: u64) {
586 self.options
587 .push(
588 Pair::input(
589 name,
590 VipsValue::Uint(value),
591 ),
592 );
593 }
594}
595
596impl<'a> Setter<'a, f64> for VOption<'a> {
598 fn set(mut self, name: &str, value: f64) -> VOption<'a> {
599 self.options
600 .push(
601 Pair::input(
602 name,
603 VipsValue::Double(value),
604 ),
605 );
606 self
607 }
608 fn add(&mut self, name: &str, value: f64) {
609 self.options
610 .push(
611 Pair::input(
612 name,
613 VipsValue::Double(value),
614 ),
615 );
616 }
617}
618
619impl<'a> Setter<'a, &'a str> for VOption<'a> {
621 fn set(mut self, name: &str, value: &'a str) -> VOption<'a> {
622 self.options
623 .push(
624 Pair::input(
625 name,
626 VipsValue::Str(value),
627 ),
628 );
629 self
630 }
631 fn add(&mut self, name: &str, value: &'a str) {
632 self.options
633 .push(
634 Pair::input(
635 name,
636 VipsValue::Str(value),
637 ),
638 );
639 }
640}
641
642impl<'a> Setter<'a, &'a String> for VOption<'a> {
643 fn set(mut self, name: &str, value: &'a String) -> VOption<'a> {
644 self.options
645 .push(
646 Pair::input(
647 name,
648 VipsValue::Str(value),
649 ),
650 );
651 self
652 }
653 fn add(&mut self, name: &str, value: &'a String) {
654 self.options
655 .push(
656 Pair::input(
657 name,
658 VipsValue::Str(value),
659 ),
660 );
661 }
662}
663
664impl<'a> Setter<'a, *mut c_char> for VOption<'a> {
666 fn set(mut self, name: &str, value: *mut c_char) -> VOption<'a> {
667 self.options
668 .push(
669 Pair::input(
670 name,
671 VipsValue::CStr(value),
672 ),
673 );
674 self
675 }
676 fn add(&mut self, name: &str, value: *mut c_char) {
677 self.options
678 .push(
679 Pair::input(
680 name,
681 VipsValue::CStr(value),
682 ),
683 );
684 }
685}
686
687impl<'a> Setter<'a, &'a crate::VipsImage> for VOption<'a> {
689 fn set(mut self, name: &str, value: &'a crate::VipsImage) -> VOption<'a> {
690 self.options
691 .push(
692 Pair::input(
693 name,
694 VipsValue::Image(value),
695 ),
696 );
697 self
698 }
699 fn add(&mut self, name: &str, value: &'a crate::VipsImage) {
700 self.options
701 .push(
702 Pair::input(
703 name,
704 VipsValue::Image(value),
705 ),
706 );
707 }
708}
709
710impl<'a> Setter<'a, &'a [i32]> for VOption<'a> {
712 fn set(mut self, name: &str, value: &'a [i32]) -> VOption<'a> {
713 self.options
714 .push(
715 Pair::input(
716 name,
717 VipsValue::IntArray(value),
718 ),
719 );
720 self
721 }
722 fn add(&mut self, name: &str, value: &'a [i32]) {
723 self.options
724 .push(
725 Pair::input(
726 name,
727 VipsValue::IntArray(value),
728 ),
729 );
730 }
731}
732
733impl<'a, const N: usize> Setter<'a, &'a [i32; N]> for VOption<'a> {
734 fn set(mut self, name: &str, value: &'a [i32; N]) -> VOption<'a> {
735 self.options
736 .push(
737 Pair::input(
738 name,
739 VipsValue::IntArray(value),
740 ),
741 );
742 self
743 }
744 fn add(&mut self, name: &str, value: &'a [i32; N]) {
745 self.options
746 .push(
747 Pair::input(
748 name,
749 VipsValue::IntArray(value),
750 ),
751 );
752 }
753}
754
755impl<'a> Setter<'a, &'a [f64]> for VOption<'a> {
757 fn set(mut self, name: &str, value: &'a [f64]) -> VOption<'a> {
758 self.options
759 .push(
760 Pair::input(
761 name,
762 VipsValue::DoubleArray(value),
763 ),
764 );
765 self
766 }
767 fn add(&mut self, name: &str, value: &'a [f64]) {
768 self.options
769 .push(
770 Pair::input(
771 name,
772 VipsValue::DoubleArray(value),
773 ),
774 );
775 }
776}
777
778impl<'a, const N: usize> Setter<'a, &'a [f64; N]> for VOption<'a> {
779 fn set(mut self, name: &str, value: &'a [f64; N]) -> VOption<'a> {
780 self.options
781 .push(
782 Pair::input(
783 name,
784 VipsValue::DoubleArray(value),
785 ),
786 );
787 self
788 }
789 fn add(&mut self, name: &str, value: &'a [f64; N]) {
790 self.options
791 .push(
792 Pair::input(
793 name,
794 VipsValue::DoubleArray(value),
795 ),
796 );
797 }
798}
799
800impl<'a> Setter<'a, &'a [crate::VipsImage]> for VOption<'a> {
802 fn set(mut self, name: &str, value: &'a [crate::VipsImage]) -> VOption<'a> {
803 self.options
804 .push(
805 Pair::input(
806 name,
807 VipsValue::ImageArray(value),
808 ),
809 );
810 self
811 }
812 fn add(&mut self, name: &str, value: &'a [crate::VipsImage]) {
813 self.options
814 .push(
815 Pair::input(
816 name,
817 VipsValue::ImageArray(value),
818 ),
819 );
820 }
821}
822
823impl<'a, const N: usize> Setter<'a, &'a [crate::VipsImage; N]> for VOption<'a> {
824 fn set(mut self, name: &str, value: &'a [crate::VipsImage; N]) -> VOption<'a> {
825 self.options
826 .push(
827 Pair::input(
828 name,
829 VipsValue::ImageArray(value),
830 ),
831 );
832 self
833 }
834 fn add(&mut self, name: &str, value: &'a [crate::VipsImage; N]) {
835 self.options
836 .push(
837 Pair::input(
838 name,
839 VipsValue::ImageArray(value),
840 ),
841 );
842 }
843}
844
845impl<'a> Setter<'a, &'a crate::region::VipsBlob> for VOption<'a> {
847 fn set(mut self, name: &str, value: &'a crate::region::VipsBlob) -> VOption<'a> {
848 self.options
849 .push(
850 Pair::input(
851 name,
852 VipsValue::Blob(value),
853 ),
854 );
855 self
856 }
857 fn add(&mut self, name: &str, value: &'a crate::region::VipsBlob) {
858 self.options
859 .push(
860 Pair::input(
861 name,
862 VipsValue::Blob(value),
863 ),
864 );
865 }
866}
867
868impl<'a> Setter<'a, &'a crate::connection::VipsTarget> for VOption<'a> {
870 fn set(mut self, name: &str, value: &'a crate::connection::VipsTarget) -> VOption<'a> {
871 self.options
872 .push(
873 Pair::input(
874 name,
875 VipsValue::Target(value),
876 ),
877 );
878 self
879 }
880 fn add(&mut self, name: &str, value: &'a crate::connection::VipsTarget) {
881 self.options
882 .push(
883 Pair::input(
884 name,
885 VipsValue::Target(value),
886 ),
887 );
888 }
889}
890
891impl<'a> Setter<'a, &'a crate::connection::VipsSource> for VOption<'a> {
893 fn set(mut self, name: &str, value: &'a crate::connection::VipsSource) -> VOption<'a> {
894 self.options
895 .push(
896 Pair::input(
897 name,
898 VipsValue::Source(value),
899 ),
900 );
901 self
902 }
903 fn add(&mut self, name: &str, value: &'a crate::connection::VipsSource) {
904 self.options
905 .push(
906 Pair::input(
907 name,
908 VipsValue::Source(value),
909 ),
910 );
911 }
912}
913
914impl<'a> Setter<'a, &'a crate::interpolate::VipsInterpolate> for VOption<'a> {
916 fn set(mut self, name: &str, value: &'a crate::interpolate::VipsInterpolate) -> VOption<'a> {
917 self.options
918 .push(
919 Pair::input(
920 name,
921 VipsValue::Interpolate(value),
922 ),
923 );
924 self
925 }
926 fn add(&mut self, name: &str, value: &'a crate::interpolate::VipsInterpolate) {
927 self.options
928 .push(
929 Pair::input(
930 name,
931 VipsValue::Interpolate(value),
932 ),
933 );
934 }
935}
936
937impl<'a> Setter<'a, &'a mut bool> for VOption<'a> {
939 fn set(mut self, name: &str, value: &'a mut bool) -> VOption<'a> {
940 self.options
941 .push(
942 Pair::output(
943 name,
944 VipsValue::MutBool(value),
945 ),
946 );
947 self
948 }
949 fn add(&mut self, name: &str, value: &'a mut bool) {
950 self.options
951 .push(
952 Pair::output(
953 name,
954 VipsValue::MutBool(value),
955 ),
956 );
957 }
958}
959
960impl<'a> Setter<'a, &'a mut i32> for VOption<'a> {
962 fn set(mut self, name: &str, value: &'a mut i32) -> VOption<'a> {
963 self.options
964 .push(
965 Pair::output(
966 name,
967 VipsValue::MutInt(value),
968 ),
969 );
970 self
971 }
972 fn add(&mut self, name: &str, value: &'a mut i32) {
973 self.options
974 .push(
975 Pair::output(
976 name,
977 VipsValue::MutInt(value),
978 ),
979 );
980 }
981}
982
983impl<'a> Setter<'a, &'a mut f64> for VOption<'a> {
985 fn set(mut self, name: &str, value: &'a mut f64) -> VOption<'a> {
986 self.options
987 .push(
988 Pair::output(
989 name,
990 VipsValue::MutDouble(value),
991 ),
992 );
993 self
994 }
995 fn add(&mut self, name: &str, value: &'a mut f64) {
996 self.options
997 .push(
998 Pair::output(
999 name,
1000 VipsValue::MutDouble(value),
1001 ),
1002 );
1003 }
1004}
1005
1006impl<'a> Setter<'a, &'a mut crate::VipsImage> for VOption<'a> {
1008 fn set(mut self, name: &str, value: &'a mut crate::VipsImage) -> VOption<'a> {
1009 self.options
1010 .push(
1011 Pair::output(
1012 name,
1013 VipsValue::MutImage(value),
1014 ),
1015 );
1016 self
1017 }
1018 fn add(&mut self, name: &str, value: &'a mut crate::VipsImage) {
1019 self.options
1020 .push(
1021 Pair::output(
1022 name,
1023 VipsValue::MutImage(value),
1024 ),
1025 );
1026 }
1027}
1028
1029impl<'a> Setter<'a, &'a mut Vec<f64>> for VOption<'a> {
1031 fn set(mut self, name: &str, value: &'a mut Vec<f64>) -> VOption<'a> {
1032 self.options
1033 .push(
1034 Pair::output(
1035 name,
1036 VipsValue::MutDoubleArray(value),
1037 ),
1038 );
1039 self
1040 }
1041 fn add(&mut self, name: &str, value: &'a mut Vec<f64>) {
1042 self.options
1043 .push(
1044 Pair::output(
1045 name,
1046 VipsValue::MutDoubleArray(value),
1047 ),
1048 );
1049 }
1050}
1051
1052impl<'a> Setter<'a, &'a mut crate::region::VipsBlob> for VOption<'a> {
1054 fn set(mut self, name: &str, value: &'a mut crate::region::VipsBlob) -> VOption<'a> {
1055 self.options
1056 .push(
1057 Pair::output(
1058 name,
1059 VipsValue::MutBlob(value),
1060 ),
1061 );
1062 self
1063 }
1064 fn add(&mut self, name: &str, value: &'a mut crate::region::VipsBlob) {
1065 self.options
1066 .push(
1067 Pair::output(
1068 name,
1069 VipsValue::MutBlob(value),
1070 ),
1071 );
1072 }
1073}