Skip to main content

apple_vision/
sdk.rs

1//! Vision SDK-wide enums, string constants, and version helpers.
2
3use core::fmt;
4
5macro_rules! vision_string_enum {
6    (
7        $(#[$meta:meta])*
8        pub enum $name:ident {
9            $( $variant:ident => $value:literal ),+ $(,)?
10        }
11    ) => {
12        $(#[$meta])*
13        #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
14        pub enum $name {
15            $( $variant ),+
16        }
17
18        impl $name {
19            /// Every currently-known SDK value for the enum family.
20            pub const ALL: &'static [Self] = &[
21                $( Self::$variant ),+
22            ];
23
24            /// Return the raw string value used by Vision.
25            #[must_use]
26            pub const fn as_str(self) -> &'static str {
27                match self {
28                    $( Self::$variant => $value ),+
29                }
30            }
31
32            /// Parse a raw Vision string value.
33            #[allow(clippy::should_implement_trait)]
34            #[must_use]
35            pub fn from_str(value: &str) -> Option<Self> {
36                match value {
37                    $( $value => Some(Self::$variant), )+
38                    _ => None,
39                }
40            }
41        }
42
43        impl AsRef<str> for $name {
44            fn as_ref(&self) -> &str {
45                self.as_str()
46            }
47        }
48
49        impl fmt::Display for $name {
50            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51                f.write_str(self.as_str())
52            }
53        }
54    };
55}
56
57vision_string_enum! {
58    /// Mirrors `VNAnimalIdentifier`.
59    pub enum AnimalIdentifier {
60        Dog => "Dog",
61        Cat => "Cat",
62    }
63}
64
65vision_string_enum! {
66    /// Mirrors `VNBarcodeSymbology`.
67    pub enum BarcodeSymbology {
68        Aztec => "VNBarcodeSymbologyAztec",
69        Codabar => "VNBarcodeSymbologyCodabar",
70        Code128 => "VNBarcodeSymbologyCode128",
71        Code39 => "VNBarcodeSymbologyCode39",
72        Code39Checksum => "VNBarcodeSymbologyCode39Checksum",
73        Code39FullAscii => "VNBarcodeSymbologyCode39FullASCII",
74        Code39FullAsciiChecksum => "VNBarcodeSymbologyCode39FullASCIIChecksum",
75        Code93 => "VNBarcodeSymbologyCode93",
76        Code93i => "VNBarcodeSymbologyCode93i",
77        DataMatrix => "VNBarcodeSymbologyDataMatrix",
78        Ean13 => "VNBarcodeSymbologyEAN13",
79        Ean8 => "VNBarcodeSymbologyEAN8",
80        Gs1DataBar => "VNBarcodeSymbologyGS1DataBar",
81        Gs1DataBarExpanded => "VNBarcodeSymbologyGS1DataBarExpanded",
82        Gs1DataBarLimited => "VNBarcodeSymbologyGS1DataBarLimited",
83        I2of5 => "VNBarcodeSymbologyI2of5",
84        I2of5Checksum => "VNBarcodeSymbologyI2of5Checksum",
85        Itf14 => "VNBarcodeSymbologyITF14",
86        MsiPlessey => "VNBarcodeSymbologyMSIPlessey",
87        MicroPdf417 => "VNBarcodeSymbologyMicroPDF417",
88        MicroQr => "VNBarcodeSymbologyMicroQR",
89        Pdf417 => "VNBarcodeSymbologyPDF417",
90        Qr => "VNBarcodeSymbologyQR",
91        Upce => "VNBarcodeSymbologyUPCE",
92    }
93}
94
95vision_string_enum! {
96    /// Mirrors `VNComputeStage` and its exported string constants.
97    pub enum ComputeStage {
98        Main => "VNComputeStageMain",
99        PostProcessing => "VNComputeStagePostProcessing",
100    }
101}
102
103vision_string_enum! {
104    /// Mirrors `VNImageOption`.
105    pub enum ImageOption {
106        Properties => "VNImageOptionProperties",
107        CameraIntrinsics => "VNImageOptionCameraIntrinsics",
108        CiContext => "VNImageOptionCIContext",
109    }
110}
111
112vision_string_enum! {
113    /// Mirrors `VNRecognizedPointGroupKeyAll`.
114    pub enum RecognizedPointGroupKey {
115        All => "VNIPOAll",
116    }
117}
118
119vision_string_enum! {
120    /// Mirrors `VNRecognizedPoint3DGroupKeyAll`.
121    pub enum RecognizedPoint3DGroupKey {
122        All => "VNIPOAll",
123    }
124}
125
126/// Mirrors `VNImageCropAndScaleOption`.
127#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
128#[repr(usize)]
129pub enum ImageCropAndScaleOption {
130    CenterCrop = 0,
131    ScaleFit = 1,
132    ScaleFill = 2,
133    ScaleFitRotate90Ccw = 0x101,
134    ScaleFillRotate90Ccw = 0x102,
135}
136
137impl ImageCropAndScaleOption {
138    /// Every currently-known SDK value.
139    pub const ALL: &'static [Self] = &[
140        Self::CenterCrop,
141        Self::ScaleFit,
142        Self::ScaleFill,
143        Self::ScaleFitRotate90Ccw,
144        Self::ScaleFillRotate90Ccw,
145    ];
146
147    #[must_use]
148    pub const fn as_raw(self) -> usize {
149        self as usize
150    }
151
152    #[must_use]
153    pub const fn from_raw(raw: usize) -> Option<Self> {
154        match raw {
155            0 => Some(Self::CenterCrop),
156            1 => Some(Self::ScaleFit),
157            2 => Some(Self::ScaleFill),
158            0x101 => Some(Self::ScaleFitRotate90Ccw),
159            0x102 => Some(Self::ScaleFillRotate90Ccw),
160            _ => None,
161        }
162    }
163}
164
165#[cfg(feature = "coreml")]
166impl From<ImageCropAndScaleOption> for crate::coreml::CoreMLImageCropAndScaleOption {
167    fn from(value: ImageCropAndScaleOption) -> Self {
168        match value {
169            ImageCropAndScaleOption::CenterCrop => Self::CenterCrop,
170            ImageCropAndScaleOption::ScaleFit => Self::ScaleFit,
171            ImageCropAndScaleOption::ScaleFill => Self::ScaleFill,
172            ImageCropAndScaleOption::ScaleFitRotate90Ccw => Self::ScaleFitRotate90CCW,
173            ImageCropAndScaleOption::ScaleFillRotate90Ccw => Self::ScaleFillRotate90CCW,
174        }
175    }
176}
177
178#[cfg(feature = "coreml")]
179impl From<crate::coreml::CoreMLImageCropAndScaleOption> for ImageCropAndScaleOption {
180    fn from(value: crate::coreml::CoreMLImageCropAndScaleOption) -> Self {
181        match value {
182            crate::coreml::CoreMLImageCropAndScaleOption::CenterCrop => Self::CenterCrop,
183            crate::coreml::CoreMLImageCropAndScaleOption::ScaleFit => Self::ScaleFit,
184            crate::coreml::CoreMLImageCropAndScaleOption::ScaleFill => Self::ScaleFill,
185            crate::coreml::CoreMLImageCropAndScaleOption::ScaleFitRotate90CCW => {
186                Self::ScaleFitRotate90Ccw
187            }
188            crate::coreml::CoreMLImageCropAndScaleOption::ScaleFillRotate90CCW => {
189                Self::ScaleFillRotate90Ccw
190            }
191        }
192    }
193}
194
195/// Mirrors `VNElementType`.
196#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
197#[repr(usize)]
198pub enum ElementType {
199    Unknown = 0,
200    Float32 = 1,
201    Float64 = 2,
202}
203
204impl ElementType {
205    pub const ALL: &'static [Self] = &[Self::Unknown, Self::Float32, Self::Float64];
206
207    #[must_use]
208    pub const fn as_raw(self) -> usize {
209        self as usize
210    }
211
212    #[must_use]
213    pub const fn from_raw(raw: usize) -> Option<Self> {
214        match raw {
215            0 => Some(Self::Unknown),
216            1 => Some(Self::Float32),
217            2 => Some(Self::Float64),
218            _ => None,
219        }
220    }
221
222    #[must_use]
223    pub const fn size_in_bytes(self) -> usize {
224        match self {
225            Self::Unknown => 0,
226            Self::Float32 => 4,
227            Self::Float64 => 8,
228        }
229    }
230}
231
232/// Mirrors `VNPointsClassification`.
233#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
234#[repr(i32)]
235pub enum PointsClassification {
236    Disconnected = 0,
237    OpenPath = 1,
238    ClosedPath = 2,
239}
240
241impl PointsClassification {
242    pub const ALL: &'static [Self] = &[Self::Disconnected, Self::OpenPath, Self::ClosedPath];
243
244    #[must_use]
245    pub const fn as_raw(self) -> i32 {
246        self as i32
247    }
248
249    #[must_use]
250    pub const fn from_raw(raw: i32) -> Option<Self> {
251        match raw {
252            0 => Some(Self::Disconnected),
253            1 => Some(Self::OpenPath),
254            2 => Some(Self::ClosedPath),
255            _ => None,
256        }
257    }
258}
259
260/// Mirrors `VNBarcodeCompositeType`.
261#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
262#[repr(i32)]
263pub enum BarcodeCompositeType {
264    None = 0,
265    Linked = 1,
266    Gs1TypeA = 2,
267    Gs1TypeB = 3,
268    Gs1TypeC = 4,
269}
270
271impl BarcodeCompositeType {
272    pub const ALL: &'static [Self] = &[
273        Self::None,
274        Self::Linked,
275        Self::Gs1TypeA,
276        Self::Gs1TypeB,
277        Self::Gs1TypeC,
278    ];
279
280    #[must_use]
281    pub const fn as_raw(self) -> i32 {
282        self as i32
283    }
284
285    #[must_use]
286    pub const fn from_raw(raw: i32) -> Option<Self> {
287        match raw {
288            0 => Some(Self::None),
289            1 => Some(Self::Linked),
290            2 => Some(Self::Gs1TypeA),
291            3 => Some(Self::Gs1TypeB),
292            4 => Some(Self::Gs1TypeC),
293            _ => None,
294        }
295    }
296}
297
298/// Mirrors `VNErrorCode`.
299#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
300#[repr(i32)]
301pub enum VisionErrorCode {
302    TuriCore = -1,
303    Success = 0,
304    RequestCancelled = 1,
305    InvalidFormat = 2,
306    OperationFailed = 3,
307    OutOfBounds = 4,
308    InvalidOption = 5,
309    Io = 6,
310    MissingOption = 7,
311    NotImplemented = 8,
312    Internal = 9,
313    OutOfMemory = 10,
314    Unknown = 11,
315    InvalidOperation = 12,
316    InvalidImage = 13,
317    InvalidArgument = 14,
318    InvalidModel = 15,
319    UnsupportedRevision = 16,
320    DataUnavailable = 17,
321    TimeStampNotFound = 18,
322    UnsupportedRequest = 19,
323    Timeout = 20,
324    UnsupportedComputeStage = 21,
325    UnsupportedComputeDevice = 22,
326}
327
328impl VisionErrorCode {
329    pub const ALL: &'static [Self] = &[
330        Self::TuriCore,
331        Self::Success,
332        Self::RequestCancelled,
333        Self::InvalidFormat,
334        Self::OperationFailed,
335        Self::OutOfBounds,
336        Self::InvalidOption,
337        Self::Io,
338        Self::MissingOption,
339        Self::NotImplemented,
340        Self::Internal,
341        Self::OutOfMemory,
342        Self::Unknown,
343        Self::InvalidOperation,
344        Self::InvalidImage,
345        Self::InvalidArgument,
346        Self::InvalidModel,
347        Self::UnsupportedRevision,
348        Self::DataUnavailable,
349        Self::TimeStampNotFound,
350        Self::UnsupportedRequest,
351        Self::Timeout,
352        Self::UnsupportedComputeStage,
353        Self::UnsupportedComputeDevice,
354    ];
355
356    #[must_use]
357    pub const fn as_raw(self) -> i32 {
358        self as i32
359    }
360
361    #[must_use]
362    pub const fn from_raw(raw: i32) -> Option<Self> {
363        match raw {
364            -1 => Some(Self::TuriCore),
365            0 => Some(Self::Success),
366            1 => Some(Self::RequestCancelled),
367            2 => Some(Self::InvalidFormat),
368            3 => Some(Self::OperationFailed),
369            4 => Some(Self::OutOfBounds),
370            5 => Some(Self::InvalidOption),
371            6 => Some(Self::Io),
372            7 => Some(Self::MissingOption),
373            8 => Some(Self::NotImplemented),
374            9 => Some(Self::Internal),
375            10 => Some(Self::OutOfMemory),
376            11 => Some(Self::Unknown),
377            12 => Some(Self::InvalidOperation),
378            13 => Some(Self::InvalidImage),
379            14 => Some(Self::InvalidArgument),
380            15 => Some(Self::InvalidModel),
381            16 => Some(Self::UnsupportedRevision),
382            17 => Some(Self::DataUnavailable),
383            18 => Some(Self::TimeStampNotFound),
384            19 => Some(Self::UnsupportedRequest),
385            20 => Some(Self::Timeout),
386            21 => Some(Self::UnsupportedComputeStage),
387            22 => Some(Self::UnsupportedComputeDevice),
388            _ => None,
389        }
390    }
391}
392
393/// Mirrors `VNErrorDomain`.
394pub const VISION_ERROR_DOMAIN: &str = "com.apple.Vision";
395
396extern "C" {
397    static VNVisionVersionNumber: f64;
398}
399
400/// Return the linked Vision framework version number.
401#[must_use]
402pub fn vision_version_number() -> f64 {
403    // SAFETY: `VNVisionVersionNumber` is a valid extern static provided by the Vision framework.
404    unsafe { VNVisionVersionNumber }
405}