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