rs_vips/
voption.rs

1#![allow(unused_imports)]
2use 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, vips_area_unref,
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    unref_area,
20    utils::{
21        get_g_type, new_c_string, G_TYPE_BOOLEAN, G_TYPE_DOUBLE, G_TYPE_INT, G_TYPE_STRING,
22        G_TYPE_UINT64,
23    },
24};
25use std::{mem::MaybeUninit, os::raw::c_void};
26
27/// Runs the vips operation with options
28pub fn call(operation: &str, option: VOption) -> std::os::raw::c_int {
29    call_option_string(
30        operation,
31        "",
32        option,
33    )
34}
35
36/// Runs the vips operation with options
37pub fn call_option_string(
38    operation: &str,
39    option_string: &str,
40    option: VOption,
41) -> std::os::raw::c_int {
42    let operation = new_c_string(operation).unwrap();
43    let option_string = new_c_string(option_string).unwrap();
44    call_option_string_(
45        operation.as_ptr(),
46        option_string.as_ptr() as _,
47        option,
48    )
49}
50
51pub(crate) fn call_option_string_(
52    operation: *const i8,
53    option_string: *mut i8,
54    option: VOption,
55) -> std::os::raw::c_int {
56    unsafe {
57        let mut vips_operation = vips_operation_new(operation);
58
59        if !option_string.is_null()
60            && vips_object_set_from_string(
61                vips_operation as _,
62                option_string,
63            ) < 0
64        {
65            vips_object_unref_outputs(vips_operation as _);
66            g_object_unref(vips_operation as _);
67            return 1;
68        }
69
70        set_opreration(
71            vips_operation,
72            &option,
73        );
74
75        let result = vips_cache_operation_buildp(&mut vips_operation);
76
77        if result < 0 {
78            vips_object_unref_outputs(vips_operation as _);
79            g_object_unref(vips_operation as _);
80            return 1;
81        }
82
83        get_operation(
84            vips_operation,
85            option,
86        );
87
88        g_object_unref(vips_operation as _);
89
90        result
91    }
92}
93
94enum VipsValue<'a> {
95    Bool(bool),
96    MutBool(&'a mut bool),
97    Int(i32),
98    MutInt(&'a mut i32),
99    Uint(u64),
100    Double(f64),
101    MutDouble(&'a mut f64),
102    Str(&'a str),
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/// VOption, a list of name-value pairs
142#[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) {
156    unsafe {
157        for opt in option.options {
158            if opt.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(opt.name).unwrap();
165
166            match opt.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: i32 = 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
257fn set_opreration(operation: *mut VipsOperation, option: &VOption) {
258    unsafe {
259        for pair in &option.options {
260            if !pair.input {
261                continue;
262            }
263
264            let mut gvalue = MaybeUninit::<GValue>::zeroed();
265            let gvalue_ptr = gvalue.as_mut_ptr();
266
267            match pair.value {
268                VipsValue::Bool(value) => {
269                    g_value_init(
270                        gvalue_ptr,
271                        get_g_type(G_TYPE_BOOLEAN),
272                    );
273                    g_value_set_boolean(
274                        gvalue_ptr,
275                        value.into(),
276                    );
277                }
278                VipsValue::Int(value) => {
279                    g_value_init(
280                        gvalue_ptr,
281                        get_g_type(G_TYPE_INT),
282                    );
283                    g_value_set_int(
284                        gvalue_ptr,
285                        value,
286                    );
287                }
288                VipsValue::Uint(value) => {
289                    g_value_init(
290                        gvalue_ptr,
291                        get_g_type(G_TYPE_UINT64),
292                    );
293                    g_value_set_uint64(
294                        gvalue_ptr,
295                        value,
296                    );
297                }
298                VipsValue::Double(value) => {
299                    g_value_init(
300                        gvalue_ptr,
301                        get_g_type(G_TYPE_DOUBLE),
302                    );
303                    g_value_set_double(
304                        gvalue_ptr,
305                        value,
306                    );
307                }
308                VipsValue::Str(value) => {
309                    let str = new_c_string(value).unwrap();
310                    g_value_init(
311                        gvalue_ptr,
312                        get_g_type(G_TYPE_STRING),
313                    );
314                    g_value_set_string(
315                        gvalue_ptr,
316                        str.as_ptr(),
317                    );
318                }
319                VipsValue::IntArray(value) => {
320                    g_value_init(
321                        gvalue_ptr,
322                        vips_array_int_get_type(),
323                    );
324                    vips_value_set_array_int(
325                        gvalue_ptr,
326                        value.as_ptr(),
327                        value.len() as _,
328                    );
329                }
330                VipsValue::DoubleArray(value) => {
331                    g_value_init(
332                        gvalue_ptr,
333                        vips_array_double_get_type(),
334                    );
335                    vips_value_set_array_double(
336                        gvalue_ptr,
337                        value.as_ptr(),
338                        value.len() as _,
339                    );
340                }
341                VipsValue::Image(value) => {
342                    g_value_init(
343                        gvalue_ptr,
344                        vips_image_get_type(),
345                    );
346                    g_value_set_object(
347                        gvalue_ptr,
348                        value.ctx as *mut c_void,
349                    );
350                }
351                VipsValue::ImageArray(value) => {
352                    g_value_init(
353                        gvalue_ptr,
354                        vips_array_image_get_type(),
355                    );
356                    vips_value_set_array_image(
357                        gvalue_ptr,
358                        value.len() as _,
359                    );
360                    let array = vips_value_get_array_image(
361                        gvalue_ptr,
362                        &mut 0,
363                    );
364                    let array = std::slice::from_raw_parts_mut(
365                        array,
366                        value.len() as _,
367                    );
368                    for i in 0..value.len() {
369                        g_object_ref(value[i].ctx as _);
370                        array[i] = value[i].ctx;
371                    }
372                }
373                VipsValue::Blob(value) => {
374                    g_value_init(
375                        gvalue_ptr,
376                        vips_blob_get_type(),
377                    );
378                    g_value_set_boxed(
379                        gvalue_ptr,
380                        value.ctx as *const c_void,
381                    );
382                }
383                VipsValue::Source(value) => {
384                    g_value_init(
385                        gvalue_ptr,
386                        vips_source_get_type(),
387                    );
388                    g_value_set_object(
389                        gvalue_ptr,
390                        value.ctx as *mut c_void,
391                    );
392                }
393                VipsValue::Target(value) => {
394                    g_value_init(
395                        gvalue_ptr,
396                        vips_target_get_type(),
397                    );
398                    g_value_set_object(
399                        gvalue_ptr,
400                        value.ctx as *mut c_void,
401                    );
402                }
403                VipsValue::Interpolate(value) => {
404                    g_value_init(
405                        gvalue_ptr,
406                        vips_interpolate_get_type(),
407                    );
408                    g_value_set_object(
409                        gvalue_ptr,
410                        value.ctx as *mut c_void,
411                    );
412                }
413                _ => {}
414            }
415
416            set_property(
417                operation,
418                &pair.name,
419                gvalue_ptr,
420            );
421            g_value_unset(gvalue_ptr);
422        }
423    }
424}
425
426fn set_property(operation: *mut VipsOperation, name: &str, value: *mut GValue) {
427    unsafe {
428        let object: *mut VipsObject = operation.cast();
429        let name = new_c_string(name).unwrap();
430
431        let mut pspec: *mut GParamSpec = std::ptr::null_mut();
432        let mut argument_class: *mut VipsArgumentClass = std::ptr::null_mut();
433        let mut argument_instance: *mut VipsArgumentInstance = std::ptr::null_mut();
434        if vips_object_get_argument(
435            object,
436            name.as_ptr(),
437            &mut pspec,
438            &mut argument_class,
439            &mut argument_instance,
440        ) < 0
441        {
442            g_warning();
443            vips_error_clear();
444            return;
445        }
446
447        let is_param_spec_enum = g_type_check_instance_is_a(
448            pspec as *mut GTypeInstance,
449            get_g_type("GParamEnum"),
450        ) != 0;
451
452        if is_param_spec_enum && (*value).g_type == get_g_type(G_TYPE_STRING) {
453            let pspec_type = (*pspec).value_type;
454            let enum_value = vips_enum_from_nick(
455                (*object).nickname,
456                pspec_type,
457                g_value_get_string(value),
458            );
459            if enum_value < 0 {
460                g_warning();
461                vips_error_clear();
462                return;
463            }
464
465            let mut gvalue = MaybeUninit::<GValue>::zeroed();
466            let value2 = gvalue.as_mut_ptr();
467            g_value_init(
468                value2,
469                pspec_type,
470            );
471            g_value_set_enum(
472                value2,
473                enum_value,
474            );
475            g_object_set_property(
476                object.cast(),
477                name.as_ptr(),
478                value2,
479            );
480            g_value_unset(value2);
481        } else {
482            g_object_set_property(
483                object.cast(),
484                name.as_ptr(),
485                value,
486            );
487        }
488    }
489}
490
491fn g_warning() {
492    let domain = new_c_string("GLib-GObject").unwrap();
493    let format = new_c_string("%s").unwrap();
494    unsafe {
495        g_log(
496            domain.as_ptr(),
497            GLogLevelFlags_G_LOG_LEVEL_WARNING,
498            format.as_ptr(),
499            vips_error_buffer(),
500        )
501    };
502}
503
504/// Set the value of a name-value pair of VOption
505pub trait Setter<'a, T> {
506    fn set(self, name: &str, value: T) -> VOption<'a>;
507    fn add(&mut self, name: &str, value: T);
508}
509
510// input bool
511impl<'a> Setter<'a, bool> for VOption<'a> {
512    fn set(mut self, name: &str, value: bool) -> VOption<'a> {
513        self.options
514            .push(
515                Pair::input(
516                    name,
517                    VipsValue::Bool(value),
518                ),
519            );
520        self
521    }
522    fn add(&mut self, name: &str, value: bool) {
523        self.options
524            .push(
525                Pair::input(
526                    name,
527                    VipsValue::Bool(value),
528                ),
529            );
530    }
531}
532
533// input i32
534impl<'a> Setter<'a, i32> for VOption<'a> {
535    fn set(mut self, name: &str, value: i32) -> VOption<'a> {
536        self.options
537            .push(
538                Pair::input(
539                    name,
540                    VipsValue::Int(value),
541                ),
542            );
543        self
544    }
545    fn add(&mut self, name: &str, value: i32) {
546        self.options
547            .push(
548                Pair::input(
549                    name,
550                    VipsValue::Int(value),
551                ),
552            );
553    }
554}
555
556// input u64
557impl<'a> Setter<'a, u64> for VOption<'a> {
558    fn set(mut self, name: &str, value: u64) -> VOption<'a> {
559        self.options
560            .push(
561                Pair::input(
562                    name,
563                    VipsValue::Uint(value),
564                ),
565            );
566        self
567    }
568    fn add(&mut self, name: &str, value: u64) {
569        self.options
570            .push(
571                Pair::input(
572                    name,
573                    VipsValue::Uint(value),
574                ),
575            );
576    }
577}
578
579// input f64
580impl<'a> Setter<'a, f64> for VOption<'a> {
581    fn set(mut self, name: &str, value: f64) -> VOption<'a> {
582        self.options
583            .push(
584                Pair::input(
585                    name,
586                    VipsValue::Double(value),
587                ),
588            );
589        self
590    }
591    fn add(&mut self, name: &str, value: f64) {
592        self.options
593            .push(
594                Pair::input(
595                    name,
596                    VipsValue::Double(value),
597                ),
598            );
599    }
600}
601
602// input &str
603impl<'a> Setter<'a, &'a str> for VOption<'a> {
604    fn set(mut self, name: &str, value: &'a str) -> VOption<'a> {
605        self.options
606            .push(
607                Pair::input(
608                    name,
609                    VipsValue::Str(value),
610                ),
611            );
612        self
613    }
614    fn add(&mut self, name: &str, value: &'a str) {
615        self.options
616            .push(
617                Pair::input(
618                    name,
619                    VipsValue::Str(value),
620                ),
621            );
622    }
623}
624
625impl<'a> Setter<'a, &'a String> for VOption<'a> {
626    fn set(mut self, name: &str, value: &'a String) -> VOption<'a> {
627        self.options
628            .push(
629                Pair::input(
630                    name,
631                    VipsValue::Str(value),
632                ),
633            );
634        self
635    }
636    fn add(&mut self, name: &str, value: &'a String) {
637        self.options
638            .push(
639                Pair::input(
640                    name,
641                    VipsValue::Str(value),
642                ),
643            );
644    }
645}
646
647// input VipsImage
648impl<'a> Setter<'a, &'a crate::VipsImage> for VOption<'a> {
649    fn set(mut self, name: &str, value: &'a crate::VipsImage) -> VOption<'a> {
650        self.options
651            .push(
652                Pair::input(
653                    name,
654                    VipsValue::Image(value),
655                ),
656            );
657        self
658    }
659    fn add(&mut self, name: &str, value: &'a crate::VipsImage) {
660        self.options
661            .push(
662                Pair::input(
663                    name,
664                    VipsValue::Image(value),
665                ),
666            );
667    }
668}
669
670// input &[i32]
671impl<'a> Setter<'a, &'a [i32]> for VOption<'a> {
672    fn set(mut self, name: &str, value: &'a [i32]) -> VOption<'a> {
673        self.options
674            .push(
675                Pair::input(
676                    name,
677                    VipsValue::IntArray(value),
678                ),
679            );
680        self
681    }
682    fn add(&mut self, name: &str, value: &'a [i32]) {
683        self.options
684            .push(
685                Pair::input(
686                    name,
687                    VipsValue::IntArray(value),
688                ),
689            );
690    }
691}
692
693impl<'a, const N: usize> Setter<'a, &'a [i32; N]> for VOption<'a> {
694    fn set(mut self, name: &str, value: &'a [i32; N]) -> VOption<'a> {
695        self.options
696            .push(
697                Pair::input(
698                    name,
699                    VipsValue::IntArray(value),
700                ),
701            );
702        self
703    }
704    fn add(&mut self, name: &str, value: &'a [i32; N]) {
705        self.options
706            .push(
707                Pair::input(
708                    name,
709                    VipsValue::IntArray(value),
710                ),
711            );
712    }
713}
714
715// input &[f64]
716impl<'a> Setter<'a, &'a [f64]> for VOption<'a> {
717    fn set(mut self, name: &str, value: &'a [f64]) -> VOption<'a> {
718        self.options
719            .push(
720                Pair::input(
721                    name,
722                    VipsValue::DoubleArray(value),
723                ),
724            );
725        self
726    }
727    fn add(&mut self, name: &str, value: &'a [f64]) {
728        self.options
729            .push(
730                Pair::input(
731                    name,
732                    VipsValue::DoubleArray(value),
733                ),
734            );
735    }
736}
737
738impl<'a, const N: usize> Setter<'a, &'a [f64; N]> for VOption<'a> {
739    fn set(mut self, name: &str, value: &'a [f64; N]) -> VOption<'a> {
740        self.options
741            .push(
742                Pair::input(
743                    name,
744                    VipsValue::DoubleArray(value),
745                ),
746            );
747        self
748    }
749    fn add(&mut self, name: &str, value: &'a [f64; N]) {
750        self.options
751            .push(
752                Pair::input(
753                    name,
754                    VipsValue::DoubleArray(value),
755                ),
756            );
757    }
758}
759
760// input &[VipsImage]
761impl<'a> Setter<'a, &'a [crate::VipsImage]> for VOption<'a> {
762    fn set(mut self, name: &str, value: &'a [crate::VipsImage]) -> VOption<'a> {
763        self.options
764            .push(
765                Pair::input(
766                    name,
767                    VipsValue::ImageArray(value),
768                ),
769            );
770        self
771    }
772    fn add(&mut self, name: &str, value: &'a [crate::VipsImage]) {
773        self.options
774            .push(
775                Pair::input(
776                    name,
777                    VipsValue::ImageArray(value),
778                ),
779            );
780    }
781}
782
783impl<'a, const N: usize> Setter<'a, &'a [crate::VipsImage; N]> for VOption<'a> {
784    fn set(mut self, name: &str, value: &'a [crate::VipsImage; N]) -> VOption<'a> {
785        self.options
786            .push(
787                Pair::input(
788                    name,
789                    VipsValue::ImageArray(value),
790                ),
791            );
792        self
793    }
794    fn add(&mut self, name: &str, value: &'a [crate::VipsImage; N]) {
795        self.options
796            .push(
797                Pair::input(
798                    name,
799                    VipsValue::ImageArray(value),
800                ),
801            );
802    }
803}
804
805// input VipsBlob
806impl<'a> Setter<'a, &'a crate::region::VipsBlob> for VOption<'a> {
807    fn set(mut self, name: &str, value: &'a crate::region::VipsBlob) -> VOption<'a> {
808        self.options
809            .push(
810                Pair::input(
811                    name,
812                    VipsValue::Blob(value),
813                ),
814            );
815        self
816    }
817    fn add(&mut self, name: &str, value: &'a crate::region::VipsBlob) {
818        self.options
819            .push(
820                Pair::input(
821                    name,
822                    VipsValue::Blob(value),
823                ),
824            );
825    }
826}
827
828// input VipsTarget
829impl<'a> Setter<'a, &'a crate::connection::VipsTarget> for VOption<'a> {
830    fn set(mut self, name: &str, value: &'a crate::connection::VipsTarget) -> VOption<'a> {
831        self.options
832            .push(
833                Pair::input(
834                    name,
835                    VipsValue::Target(value),
836                ),
837            );
838        self
839    }
840    fn add(&mut self, name: &str, value: &'a crate::connection::VipsTarget) {
841        self.options
842            .push(
843                Pair::input(
844                    name,
845                    VipsValue::Target(value),
846                ),
847            );
848    }
849}
850
851// input VipsSource
852impl<'a> Setter<'a, &'a crate::connection::VipsSource> for VOption<'a> {
853    fn set(mut self, name: &str, value: &'a crate::connection::VipsSource) -> VOption<'a> {
854        self.options
855            .push(
856                Pair::input(
857                    name,
858                    VipsValue::Source(value),
859                ),
860            );
861        self
862    }
863    fn add(&mut self, name: &str, value: &'a crate::connection::VipsSource) {
864        self.options
865            .push(
866                Pair::input(
867                    name,
868                    VipsValue::Source(value),
869                ),
870            );
871    }
872}
873
874// input VipsInterpolate
875impl<'a> Setter<'a, &'a crate::interpolate::VipsInterpolate> for VOption<'a> {
876    fn set(mut self, name: &str, value: &'a crate::interpolate::VipsInterpolate) -> VOption<'a> {
877        self.options
878            .push(
879                Pair::input(
880                    name,
881                    VipsValue::Interpolate(value),
882                ),
883            );
884        self
885    }
886    fn add(&mut self, name: &str, value: &'a crate::interpolate::VipsInterpolate) {
887        self.options
888            .push(
889                Pair::input(
890                    name,
891                    VipsValue::Interpolate(value),
892                ),
893            );
894    }
895}
896
897// output bool
898impl<'a> Setter<'a, &'a mut bool> for VOption<'a> {
899    fn set(mut self, name: &str, value: &'a mut bool) -> VOption<'a> {
900        self.options
901            .push(
902                Pair::output(
903                    name,
904                    VipsValue::MutBool(value),
905                ),
906            );
907        self
908    }
909    fn add(&mut self, name: &str, value: &'a mut bool) {
910        self.options
911            .push(
912                Pair::output(
913                    name,
914                    VipsValue::MutBool(value),
915                ),
916            );
917    }
918}
919
920// output i32
921impl<'a> Setter<'a, &'a mut i32> for VOption<'a> {
922    fn set(mut self, name: &str, value: &'a mut i32) -> VOption<'a> {
923        self.options
924            .push(
925                Pair::output(
926                    name,
927                    VipsValue::MutInt(value),
928                ),
929            );
930        self
931    }
932    fn add(&mut self, name: &str, value: &'a mut i32) {
933        self.options
934            .push(
935                Pair::output(
936                    name,
937                    VipsValue::MutInt(value),
938                ),
939            );
940    }
941}
942
943// output f64
944impl<'a> Setter<'a, &'a mut f64> for VOption<'a> {
945    fn set(mut self, name: &str, value: &'a mut f64) -> VOption<'a> {
946        self.options
947            .push(
948                Pair::output(
949                    name,
950                    VipsValue::MutDouble(value),
951                ),
952            );
953        self
954    }
955    fn add(&mut self, name: &str, value: &'a mut f64) {
956        self.options
957            .push(
958                Pair::output(
959                    name,
960                    VipsValue::MutDouble(value),
961                ),
962            );
963    }
964}
965
966// output VipsImage
967impl<'a> Setter<'a, &'a mut crate::VipsImage> for VOption<'a> {
968    fn set(mut self, name: &str, value: &'a mut crate::VipsImage) -> VOption<'a> {
969        self.options
970            .push(
971                Pair::output(
972                    name,
973                    VipsValue::MutImage(value),
974                ),
975            );
976        self
977    }
978    fn add(&mut self, name: &str, value: &'a mut crate::VipsImage) {
979        self.options
980            .push(
981                Pair::output(
982                    name,
983                    VipsValue::MutImage(value),
984                ),
985            );
986    }
987}
988
989// output Vec<f64>
990impl<'a> Setter<'a, &'a mut Vec<f64>> for VOption<'a> {
991    fn set(mut self, name: &str, value: &'a mut Vec<f64>) -> VOption<'a> {
992        self.options
993            .push(
994                Pair::output(
995                    name,
996                    VipsValue::MutDoubleArray(value),
997                ),
998            );
999        self
1000    }
1001    fn add(&mut self, name: &str, value: &'a mut Vec<f64>) {
1002        self.options
1003            .push(
1004                Pair::output(
1005                    name,
1006                    VipsValue::MutDoubleArray(value),
1007                ),
1008            );
1009    }
1010}
1011
1012// output VipsBlob
1013impl<'a> Setter<'a, &'a mut crate::region::VipsBlob> for VOption<'a> {
1014    fn set(mut self, name: &str, value: &'a mut crate::region::VipsBlob) -> VOption<'a> {
1015        self.options
1016            .push(
1017                Pair::output(
1018                    name,
1019                    VipsValue::MutBlob(value),
1020                ),
1021            );
1022        self
1023    }
1024    fn add(&mut self, name: &str, value: &'a mut crate::region::VipsBlob) {
1025        self.options
1026            .push(
1027                Pair::output(
1028                    name,
1029                    VipsValue::MutBlob(value),
1030                ),
1031            );
1032    }
1033}