@@ -137,6 +137,8 @@ is equivalent to `buffer[inds...]`. If `check` is `false`, then all indexing arg
137137considered in-bounds. The default value for `check` is `true`, requiring bounds checking for
138138each index.
139139
140+ See also [`SetIndex!`](@ref)
141+
140142!!! Warning
141143 Passing `false` as `check` may result in incorrect results/crashes/corruption for
142144 out-of-bounds indices, similar to inappropriate use of `@inbounds`. The user is
@@ -145,10 +147,10 @@ each index.
145147# Examples
146148
147149```julia
148- julia> ArrayInterfaceCore.GetIndex(1:10)[3]
150+ julia> ArrayInterfaceCore.GetIndex(1:10)(3)
1491513
150152
151- julia> ArrayInterfaceCore.GetIndex{false}(1:10)[11] # shouldn't be in-bounds
153+ julia> ArrayInterfaceCore.GetIndex{false}(1:10)(11) # shouldn't be in-bounds
15215411
153155
154156```
@@ -163,10 +165,52 @@ struct GetIndex{CB,B} <: Function
163165 GetIndex (b) = GetIndex {true} (b)
164166end
165167
166- buffer (g:: GetIndex ) = getfield (g, :buffer )
168+ """
169+ SetIndex!(buffer) = SetIndex!{true}(buffer)
170+ SetIndex!{check}(buffer) -> g
171+
172+ Wraps an indexable buffer in a function type that sets a value at an index when called, so
173+ that `g(val, inds..)` is equivalent to `setindex!(buffer, val, inds...)`. If `check` is
174+ `false`, then all indexing arguments are considered in-bounds. The default value for `check`
175+ is `true`, requiring bounds checking for each index.
176+
177+ See also [`GetIndex`](@ref)
178+
179+ !!! Warning
180+ Passing `false` as `check` may result in incorrect results/crashes/corruption for
181+ out-of-bounds indices, similar to inappropriate use of `@inbounds`. The user is
182+ responsible for ensuring this is correctly used.
183+
184+ # Examples
185+
186+ ```julia
187+
188+ julia> x = [1, 2, 3, 4];
189+
190+ julia> ArrayInterface.SetIndex!(x)(10, 2);
191+
192+ julia> x[2]
193+ 10
194+
195+ ```
196+ """
197+ struct SetIndex!{CB,B} <: Function
198+ buffer:: B
199+
200+ SetIndex! {true,B} (b) where {B} = new {true,B} (b)
201+ SetIndex! {false,B} (b) where {B} = new {false,B} (b)
202+ SetIndex! {check} (b:: B ) where {check,B} = SetIndex! {check,B} (b)
203+ SetIndex! (b) = SetIndex! {true} (b)
204+ end
205+
206+ buffer (x:: Union{SetIndex!,GetIndex} ) = getfield (x, :buffer )
167207
168208Base. @propagate_inbounds @inline (g:: GetIndex{true} )(inds... ) = buffer (g)[inds... ]
169209@inline (g:: GetIndex{false} )(inds... ) = @inbounds (buffer (g)[inds... ])
210+ Base. @propagate_inbounds @inline function (s:: SetIndex!{true} )(v, inds... )
211+ setindex! (buffer (s), v, inds... )
212+ end
213+ @inline (s:: SetIndex!{false} )(v, inds... ) = @inbounds (setindex! (buffer (s), v, inds... ))
170214
171215"""
172216 can_change_size(::Type{T}) -> Bool
@@ -520,6 +564,7 @@ const MatrixIndex = ArrayIndex{2}
520564
521565const VectorIndex = ArrayIndex{1 }
522566
567+ Base. ndims (:: ArrayIndex{N} ) where {N} = N
523568Base. ndims (:: Type{<:ArrayIndex{N}} ) where {N} = N
524569
525570struct BidiagonalIndex <: MatrixIndex
@@ -628,6 +673,7 @@ known_step(@nospecialize T::Type{<:AbstractUnitRange}) = 1
628673
629674"""
630675 is_splat_index(::Type{T}) -> Bool
676+
631677Returns `static(true)` if `T` is a type that splats across multiple dimensions.
632678"""
633679is_splat_index (T:: Type ) = false
@@ -636,9 +682,24 @@ is_splat_index(@nospecialize(x)) = is_splat_index(typeof(x))
636682"""
637683 ndims_index(::Type{I}) -> Int
638684
639- Returns the number of dimension that an instance of `I` maps to when indexing. For example,
640- `CartesianIndex{3}` maps to 3 dimensions. If this method is not explicitly defined, then `1`
641- is returned.
685+ Returns the number of dimensions that an instance of `I` indexes into. If this method is
686+ not explicitly defined, then `1` is returned.
687+
688+ See also [`ndims_shape`](@ref)
689+
690+ # Examples
691+
692+ ```julia
693+ julia> ArrayInterfaceCore.ndims_index(Int)
694+ 1
695+
696+ julia> ArrayInterfaceCore.ndims_index(CartesianIndex(1, 2, 3))
697+ 3
698+
699+ julia> ArrayInterfaceCore.ndims_index([CartesianIndex(1, 2), CartesianIndex(1, 3)])
700+ 2
701+
702+ ```
642703"""
643704ndims_index (:: Type{<:Base.AbstractCartesianIndex{N}} ) where {N} = N
644705# preserve CartesianIndices{0} as they consume a dimension.
@@ -652,8 +713,20 @@ ndims_index(@nospecialize(i)) = ndims_index(typeof(i))
652713"""
653714 ndims_shape(::Type{I}) -> Union{Int,Tuple{Vararg{Int}}}
654715
655- Returns the number of dimension that are represented in shape of the returned array when
716+ Returns the number of dimension that are represented in the shape of the returned array when
656717indexing with an instance of `I`.
718+
719+ See also [`ndims_index`](@ref)
720+
721+ # Examples
722+
723+ ```julia
724+ julia> ArrayInterfaceCore.ndims_shape([CartesianIndex(1, 1), CartesianIndex(1, 2)])
725+ 1
726+
727+ julia> ndims(CartesianIndices((2,2))[[CartesianIndex(1, 1), CartesianIndex(1, 2)]])
728+ 1
729+
657730"""
658731ndims_shape (T:: DataType ) = ndims_index (T)
659732ndims_shape (:: Type{Colon} ) = 1
@@ -671,11 +744,10 @@ ndims_shape(x) = ndims_shape(typeof(x))
671744end
672745
673746"""
674- IndicesInfo{N}(T::Type{<:Tuple}) -> IndicesInfo{N,NI,NS }()
747+ IndicesInfo{N}(T::Type{<:Tuple}) -> IndicesInfo{N,pdims,cdims }()
675748
676- Provides basic trait information for each index type in in the tuple `T`. `NI`, `NS`, and
677- `IS` are tuples of [`ndims_index`](@ref), [`ndims_shape`](@ref), and
678- [`is_splat_index`](@ref) (respectively) for each field of `T`.
749+ Provides basic trait information for each index type in in the tuple `T`. `pdims` and
750+ `cdims` are dimension mappings to the parent and child dimensions respectively.
679751
680752# Examples
681753
0 commit comments