emacs/types/
vector.rs

1use std::convert::TryInto;
2
3use super::*;
4use crate::{subr, call::IntoLispArgs};
5
6/// A type that represents Lisp vectors. This is a wrapper around [`Value`] that provides
7/// vector-specific methods.
8///
9/// Arguments to #[[`defun`]] having this type will be type-checked. If you want to omit, or delay
10/// this type checking, use [`Value`] instead.
11///
12/// ```
13/// use emacs::{defun, Value, Vector, Result};
14///
15/// #[defun]
16/// fn must_pass_vector(vector: Vector) -> Result<Vector> {
17///     Ok(vector)
18/// }
19///
20/// #[defun]
21/// fn no_type_check(value: Value) -> Result<Vector> {
22///     Ok(Vector::from_value_unchecked(value, 0))
23/// }
24/// ```
25///
26/// [`Value`]: struct.Value.html
27/// [`defun`]: attr.defun.html
28#[derive(Debug, Clone, Copy)]
29pub struct Vector<'e> {
30    value: Value<'e>,
31    len: usize,
32}
33
34impl<'e> Vector<'e> {
35    #[doc(hidden)]
36    #[inline]
37    pub fn from_value_unchecked(value: Value<'e>, len: usize) -> Self {
38        Self { value, len }
39    }
40
41    pub fn get<T: FromLisp<'e>>(&self, i: usize) -> Result<T> {
42        let v = self.value;
43        let env = v.env;
44        // Safety:
45        // - Same lifetime.
46        // - Emacs does bound checking.
47        // - Value doesn't need protection because we are done with it while the vector still lives.
48        unsafe_raw_call_value_unprotected!(env, vec_get, v.raw, i as isize)?.into_rust()
49    }
50
51    pub fn set<T: IntoLisp<'e>>(&self, i: usize, value: T) -> Result<()> {
52        let v = self.value;
53        let env = v.env;
54        let value = value.into_lisp(env)?;
55        // Safety: Same lifetime. Emacs does bound checking.
56        unsafe_raw_call!(env, vec_set, v.raw, i as isize, value.raw)
57    }
58
59    #[deprecated(since = "0.14.0", note = "Use .len() instead")]
60    #[doc(hidden)]
61    pub fn size(&self) -> Result<usize> {
62        Ok(self.len)
63    }
64
65    #[inline]
66    pub fn len(&self) -> usize {
67        self.len
68    }
69
70    #[inline]
71    pub fn value(&self) -> Value<'e> {
72        self.value
73    }
74}
75
76impl<'e> FromLisp<'e> for Vector<'e> {
77    fn from_lisp(value: Value<'e>) -> Result<Vector<'e>> {
78        let env = value.env;
79        let len = unsafe_raw_call!(env, vec_size, value.raw)?.try_into()
80            .expect("Invalid size from Emacs");
81        Ok(Vector { value, len })
82    }
83}
84
85impl<'e> IntoLisp<'e> for Vector<'e> {
86    #[inline(always)]
87    fn into_lisp(self, _: &'e Env) -> Result<Value<'_>> {
88        Ok(self.value)
89    }
90}
91
92/// An iterator over the elements of a [`Vector`], as [`Value`] structs.
93///
94/// [`Vector`]: struct.Vector.html
95/// [`Value`]: struct.Value.html
96pub struct IntoIter<'e> {
97    vector: Vector<'e>,
98    i: usize,
99}
100
101impl<'e> Iterator for IntoIter<'e> {
102    type Item = Value<'e>;
103
104    fn next(&mut self) -> Option<Self::Item> {
105        let i = self.i;
106        if i >= self.vector.len {
107            None
108        } else {
109            self.i += 1;
110            Some(self.vector.get(i).unwrap_or_else(|err| {
111                panic!("Unable to get Emacs vector's element at index {}: {}", i, err)
112            }))
113        }
114    }
115
116    fn size_hint(&self) -> (usize, Option<usize>) {
117        let remaining = self.vector.len - self.i;
118        (remaining, Some(remaining))
119    }
120}
121
122impl<'e> ExactSizeIterator for IntoIter<'e> {}
123
124impl<'e> IntoIterator for Vector<'e> {
125    type Item = Value<'e>;
126
127    type IntoIter = IntoIter<'e>;
128
129    #[inline]
130    fn into_iter(self) -> Self::IntoIter {
131        IntoIter { vector: self, i: 0 }
132    }
133}
134
135impl Env {
136    pub fn make_vector<'e, T: IntoLisp<'e>>(&'e self, length: usize, init: T) -> Result<Vector> {
137        let value = self.call(subr::make_vector, (length, init))?;
138        Ok(Vector::from_value_unchecked(value, length))
139    }
140
141    pub fn vector<'e, A: IntoLispArgs<'e>>(&'e self, args: A) -> Result<Value> {
142        self.call(subr::vector, args)
143    }
144}