Skip to main content

datafusion_ffi/
ffi_option.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! FFI-safe Option and Result types that do not require `IStable` bounds.
19//!
20//! stabby's `Option<T>` and `Result<T, E>` require `T: IStable` for niche
21//! optimization. Many of our FFI structs contain self-referential function
22//! pointers and cannot implement `IStable`. These simple `#[repr(C)]` types
23//! provide the same FFI-safe semantics without that constraint.
24
25use stabby::string::String as SString;
26
27/// An FFI-safe option type.
28#[repr(C, u8)]
29#[derive(Debug, Clone)]
30pub enum FFI_Option<T> {
31    Some(T),
32    None,
33}
34
35impl<T> From<Option<T>> for FFI_Option<T> {
36    fn from(opt: Option<T>) -> Self {
37        match opt {
38            Some(v) => FFI_Option::Some(v),
39            None => FFI_Option::None,
40        }
41    }
42}
43
44impl<T> From<FFI_Option<T>> for Option<T> {
45    fn from(opt: FFI_Option<T>) -> Self {
46        match opt {
47            FFI_Option::Some(v) => Some(v),
48            FFI_Option::None => None,
49        }
50    }
51}
52
53impl<T> FFI_Option<T> {
54    pub fn as_ref(&self) -> Option<&T> {
55        match self {
56            FFI_Option::Some(v) => Some(v),
57            FFI_Option::None => None,
58        }
59    }
60
61    pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> FFI_Option<U> {
62        match self {
63            FFI_Option::Some(v) => FFI_Option::Some(f(v)),
64            FFI_Option::None => FFI_Option::None,
65        }
66    }
67
68    pub fn into_option(self) -> Option<T> {
69        self.into()
70    }
71}
72
73/// An FFI-safe result type with SString as the error type.
74#[repr(C, u8)]
75#[derive(Debug, Clone)]
76pub enum FFI_Result<T> {
77    Ok(T),
78    Err(SString),
79}
80
81impl<T> FFI_Result<T> {
82    pub fn is_ok(&self) -> bool {
83        matches!(self, FFI_Result::Ok(_))
84    }
85
86    pub fn is_err(&self) -> bool {
87        matches!(self, FFI_Result::Err(_))
88    }
89
90    pub fn unwrap_err(self) -> SString {
91        match self {
92            FFI_Result::Err(e) => e,
93            FFI_Result::Ok(_) => panic!("called unwrap_err on Ok"),
94        }
95    }
96
97    pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> FFI_Result<U> {
98        match self {
99            FFI_Result::Ok(v) => FFI_Result::Ok(f(v)),
100            FFI_Result::Err(e) => FFI_Result::Err(e),
101        }
102    }
103
104    pub fn into_result(self) -> Result<T, SString> {
105        self.into()
106    }
107}
108
109impl<T> From<FFI_Result<T>> for Result<T, SString> {
110    fn from(res: FFI_Result<T>) -> Self {
111        match res {
112            FFI_Result::Ok(v) => Ok(v),
113            FFI_Result::Err(e) => Err(e),
114        }
115    }
116}
117
118impl<T, E: ToString> From<Result<T, E>> for FFI_Result<T> {
119    fn from(res: Result<T, E>) -> Self {
120        match res {
121            Ok(v) => FFI_Result::Ok(v),
122            Err(e) => FFI_Result::Err(SString::from(e.to_string().as_str())),
123        }
124    }
125}
126
127impl<T: PartialEq> PartialEq for FFI_Result<T> {
128    fn eq(&self, other: &Self) -> bool {
129        match (self, other) {
130            (FFI_Result::Ok(a), FFI_Result::Ok(b)) => a == b,
131            (FFI_Result::Err(a), FFI_Result::Err(b)) => a == b,
132            _ => false,
133        }
134    }
135}