@@ -3,12 +3,11 @@ use std::convert::TryInto;
33use super :: * ;
44use crate :: { subr, call:: IntoLispArgs } ;
55
6- /// A type that represents Lisp vectors. This is a newtype wrapper around [`Value`] that provides
6+ /// A type that represents Lisp vectors. This is a wrapper around [`Value`] that provides
77/// vector-specific methods.
88///
9- /// Arguments to #[[`defun`]] having this type will be type-checked. This type checking can be
10- /// omitted by manually wrapping a [`Value`]. Note that Emacs still does type checking when calling
11- /// methods on the vector.
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.
1211///
1312/// ```
1413/// use emacs::{defun, Value, Vector, Result};
@@ -20,62 +19,121 @@ use crate::{subr, call::IntoLispArgs};
2019///
2120/// #[defun]
2221/// fn no_type_check(value: Value) -> Result<Vector> {
23- /// Ok(Vector(value))
22+ /// Ok(Vector::from_value_unchecked (value, 0 ))
2423/// }
2524/// ```
2625///
2726/// [`Value`]: struct.Value.html
2827/// [`defun`]: attr.defun.html
2928#[ derive( Debug , Clone , Copy ) ]
30- pub struct Vector < ' e > ( pub Value < ' e > ) ;
29+ pub struct Vector < ' e > {
30+ value : Value < ' e > ,
31+ len : usize ,
32+ }
3133
3234impl < ' 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+
3341 pub fn get < T : FromLisp < ' e > > ( & self , i : usize ) -> Result < T > {
34- let v = self . 0 ;
42+ let v = self . value ;
3543 let env = v. env ;
3644 // Safety: Same lifetime. Emacs does bound checking.
3745 unsafe_raw_call_value ! ( env, vec_get, v. raw, i as isize ) ?. into_rust ( )
3846 }
3947
4048 pub fn set < T : IntoLisp < ' e > > ( & self , i : usize , value : T ) -> Result < ( ) > {
41- let v = self . 0 ;
49+ let v = self . value ;
4250 let env = v. env ;
4351 let value = value. into_lisp ( env) ?;
4452 // Safety: Same lifetime. Emacs does bound checking.
4553 unsafe_raw_call ! ( env, vec_set, v. raw, i as isize , value. raw)
4654 }
4755
56+ #[ deprecated( since = "0.14.0" , note = "Use .len() instead" ) ]
57+ #[ doc( hidden) ]
4858 pub fn size ( & self ) -> Result < usize > {
49- let v = self . 0 ;
50- let env = v. env ;
51- let result =
52- unsafe_raw_call_no_exit ! ( env, vec_size, v. raw) . try_into ( ) . expect ( "invalid size from Emacs" ) ;
53- env. handle_exit ( result)
59+ Ok ( self . len )
60+ }
61+
62+ #[ inline]
63+ pub fn len ( & self ) -> usize {
64+ self . len
65+ }
66+
67+ #[ inline]
68+ pub fn value ( & self ) -> Value < ' e > {
69+ self . value
5470 }
5571}
5672
5773impl < ' e > FromLisp < ' e > for Vector < ' e > {
5874 fn from_lisp ( value : Value < ' e > ) -> Result < Vector < ' e > > {
59- let vector = Vector ( value) ;
60- // TODO: Confirm that this is indeed cheaper than calling vectorp and signaling error.
61- vector . size ( ) ? ;
62- Ok ( vector )
75+ let env = value. env ;
76+ let len = unsafe_raw_call ! ( env , vec_size , value . raw ) ? . try_into ( )
77+ . expect ( "Invalid size from Emacs" ) ;
78+ Ok ( Vector { value , len } )
6379 }
6480}
6581
6682impl < ' e > IntoLisp < ' e > for Vector < ' e > {
6783 #[ inline( always) ]
6884 fn into_lisp ( self , _: & ' e Env ) -> Result < Value < ' _ > > {
69- Ok ( self . 0 )
85+ Ok ( self . value )
86+ }
87+ }
88+
89+ /// An iterator over the elements of a [`Vector`], as [`Value`] structs.
90+ ///
91+ /// [`Vector`]: struct.Vector.html
92+ /// [`Value`]: struct.Value.html
93+ pub struct IntoIter < ' e > {
94+ vector : Vector < ' e > ,
95+ i : usize ,
96+ }
97+
98+ impl < ' e > Iterator for IntoIter < ' e > {
99+ type Item = Value < ' e > ;
100+
101+ fn next ( & mut self ) -> Option < Self :: Item > {
102+ let i = self . i ;
103+ if i >= self . vector . len {
104+ None
105+ } else {
106+ self . i += 1 ;
107+ Some ( self . vector . get ( i) . unwrap_or_else ( |err| panic ! ( err) ) )
108+ }
109+ }
110+
111+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
112+ let remaining = self . vector . len - self . i ;
113+ ( remaining, Some ( remaining) )
114+ }
115+ }
116+
117+ impl < ' e > ExactSizeIterator for IntoIter < ' e > { }
118+
119+ impl < ' e > IntoIterator for Vector < ' e > {
120+ type Item = Value < ' e > ;
121+
122+ type IntoIter = IntoIter < ' e > ;
123+
124+ #[ inline]
125+ fn into_iter ( self ) -> Self :: IntoIter {
126+ IntoIter { vector : self , i : 0 }
70127 }
71128}
72129
73130impl Env {
74131 pub fn make_vector < ' e , T : IntoLisp < ' e > > ( & ' e self , length : usize , init : T ) -> Result < Vector > {
75- self . call ( subr:: make_vector, ( length, init) ) . map ( Vector )
132+ let value = self . call ( subr:: make_vector, ( length, init) ) ?;
133+ Ok ( Vector :: from_value_unchecked ( value, length) )
76134 }
77135
78- pub fn vector < ' e , A : IntoLispArgs < ' e > > ( & ' e self , args : A ) -> Result < Vector > {
79- self . call ( subr:: vector, args) . map ( Vector )
136+ pub fn vector < ' e , A : IntoLispArgs < ' e > > ( & ' e self , args : A ) -> Result < Value > {
137+ self . call ( subr:: vector, args)
80138 }
81139}
0 commit comments