nvim_oxi_api/
trait_utils.rs

1use std::error::Error as StdError;
2use std::iter::FusedIterator;
3
4use luajit::{Poppable, Pushable};
5use types::{Array, Function, LuaRef, Object};
6#[cfg(feature = "neovim-0-10")] // On 0.10 and nightly.
7use types::{HlGroupId, Integer};
8
9use crate::IntoResult;
10
11/// A super trait of most common traits implemented on iterators.
12pub trait SuperIterator<I>:
13    Iterator<Item = I> + ExactSizeIterator + DoubleEndedIterator + FusedIterator
14{
15}
16
17impl<I, T> SuperIterator<I> for T where
18    T: Iterator<Item = I>
19        + ExactSizeIterator
20        + DoubleEndedIterator
21        + FusedIterator
22{
23}
24
25macro_rules! impl_into {
26    ($trait:ident, $type:ty) => {
27        impl $trait for $type {
28            fn to_object(self) -> Object {
29                self.into()
30            }
31        }
32    };
33}
34
35/// A trait implemented by strings and integers.
36pub trait StringOrInt {
37    fn to_object(self) -> Object;
38}
39
40impl_into!(StringOrInt, &str);
41impl_into!(StringOrInt, String);
42impl_into!(StringOrInt, i8);
43impl_into!(StringOrInt, u8);
44impl_into!(StringOrInt, i16);
45impl_into!(StringOrInt, u16);
46impl_into!(StringOrInt, i32);
47impl_into!(StringOrInt, u32);
48impl_into!(StringOrInt, i64);
49
50/// A trait implemented by strings and list of strings.
51pub trait StringOrListOfStrings {
52    fn to_object(self) -> Object;
53}
54
55impl_into!(StringOrListOfStrings, &str);
56impl_into!(StringOrListOfStrings, String);
57
58// Here I'd like to use `IntoIterator` instead of `Vec`, but without
59// specilization that'd cause conflicting impls.
60impl<S: Into<String>> StringOrListOfStrings for Vec<S> {
61    #[inline]
62    fn to_object(self) -> Object {
63        Array::from_iter(self.into_iter().map(Into::into)).into()
64    }
65}
66
67/// A trait implemented by closures and [`Function`]s.
68pub trait ToFunction<A, R> {
69    fn into_luaref(self) -> LuaRef;
70}
71
72impl<A, R, F, O> ToFunction<A, R> for F
73where
74    A: Poppable,
75    R: Pushable,
76    F: FnMut(A) -> O + 'static,
77    O: IntoResult<R>,
78    O::Error: StdError + 'static,
79{
80    #[inline]
81    fn into_luaref(self) -> LuaRef {
82        Function::from_fn_mut(self).lua_ref()
83    }
84}
85
86impl<A, R> ToFunction<A, R> for Function<A, R> {
87    #[inline]
88    fn into_luaref(self) -> LuaRef {
89        self.lua_ref()
90    }
91}
92
93/// A trait implemented by closures, [`Function`]s and strings.
94pub trait StringOrFunction<A, R> {
95    fn to_object(self) -> Object;
96}
97
98impl<A, R> StringOrFunction<A, R> for &str {
99    #[inline]
100    fn to_object(self) -> Object {
101        self.into()
102    }
103}
104
105impl<A, R> StringOrFunction<A, R> for String {
106    #[inline]
107    fn to_object(self) -> Object {
108        self.into()
109    }
110}
111
112impl<F, A, R, O> StringOrFunction<A, R> for F
113where
114    F: FnMut(A) -> O + 'static,
115    A: Poppable,
116    R: Pushable,
117    O: IntoResult<R>,
118    O::Error: StdError + 'static,
119{
120    #[inline]
121    fn to_object(self) -> Object {
122        Function::from_fn_mut(self).into()
123    }
124}
125
126impl<A, R> StringOrFunction<A, R> for Function<A, R> {
127    #[inline]
128    fn to_object(self) -> Object {
129        self.into()
130    }
131}
132
133/// A trait implemented by types that can be converted to a highlight group ID.
134#[cfg(feature = "neovim-0-10")] // On 0.10 and nightly.
135#[cfg_attr(
136    docsrs,
137    doc(cfg(any(feature = "neovim-0-10", feature = "neovim-nightly")))
138)]
139pub trait HlGroup: sealed::Sealed {
140    type Error;
141
142    fn to_hl_id(&self) -> Result<HlGroupId, Self::Error>;
143}
144
145#[cfg(feature = "neovim-0-10")] // On 0.10 and nightly.
146impl HlGroup for Integer {
147    type Error = core::convert::Infallible;
148
149    #[inline(always)]
150    fn to_hl_id(&self) -> Result<HlGroupId, Self::Error> {
151        Ok(*self)
152    }
153}
154
155#[cfg(feature = "neovim-0-10")] // On 0.10 and nightly.
156impl HlGroup for &str {
157    type Error = crate::Error;
158
159    #[inline]
160    fn to_hl_id(&self) -> Result<HlGroupId, Self::Error> {
161        let obj = types::String::from(*self).into();
162        let mut err = types::Error::default();
163        let hl_id = unsafe {
164            crate::ffi::helpers::object_to_hl_id(
165                obj,
166                b"hl_group\0".as_ptr() as *const _,
167                &mut err,
168            )
169        };
170        if err.is_err() {
171            Err(err.into())
172        } else {
173            Ok(hl_id)
174        }
175    }
176}
177
178#[cfg(feature = "neovim-0-10")] // On 0.10 and nightly.
179mod sealed {
180    pub trait Sealed {}
181
182    impl Sealed for types::Integer {}
183
184    impl Sealed for &str {}
185}