@@ -202,36 +202,59 @@ defmodule RockSolid.Traversal do
202202 end
203203 end
204204
205+ @ doc """
206+ Same as `fetch_in_schema/2` but raises on error
207+ """
208+ @ spec fetch_in_schema! ( any ( ) , list ( String . t ( ) ) ) :: any ( )
209+ def fetch_in_schema! ( schema , path ) do
210+ case fetch_in_schema ( schema , path ) do
211+ { :ok , value } -> value
212+ { :error , exc } when is_exception ( exc ) -> raise exc
213+ end
214+ end
215+
205216 @ doc """
206217 Returns the value at the given location in the schema.
207218
208219 The path argument may contain a leading "#". You can convert a JSON Pointer string
209220 to a valid path by calling `to_path/1`
210221
211222 ## Examples
212- iex> RockSolid.Traversal.get_in_schema(%{"foo" => %{"bar" => "baz"}}, ["#", "foo", "bar"])
213- "baz"
214223
215- iex> RockSolid.Traversal.get_in_schema(%{"foo" => ["a", "b"]}, ["#", "foo", "1"])
216- "b"
224+ iex> RockSolid.Traversal.fetch_in_schema(%{"foo" => %{"bar" => "baz"}}, ["#", "foo", "bar"])
225+ {:ok, "baz"}
226+
227+ iex> RockSolid.Traversal.fetch_in_schema(%{"foo" => ["a", "b"]}, ["#", "foo", "1"])
228+ {:ok, "b"}
229+
230+ iex> RockSolid.Traversal.fetch_in_schema(%{"foo" => ["a", "b"]}, ["#", "foo", "3"])
231+ {:error, %RockSolid.Traversal.InvalidPath{key: "3", schema: ["a", "b"]}}
232+
233+ iex> RockSolid.Traversal.fetch_in_schema(%{"foo" => 2}, ["#","bar"])
234+ {:error, %RockSolid.Traversal.InvalidPath{key: "bar", schema: %{"foo" => 2}}}
217235 """
218- @ spec get_in_schema ( any ( ) , list ( String . t ( ) ) ) :: any ( )
219- def get_in_schema ( schema , [ ] ) , do: schema
220- def get_in_schema ( schema , [ "#" | rest ] ) , do: get_in_schema ( schema , rest )
236+ @ spec fetch_in_schema ( any ( ) , list ( String . t ( ) ) ) :: { :ok , any ( ) } | { :error , Exception . t ( ) }
237+ def fetch_in_schema ( schema , [ ] ) , do: { :ok , schema }
238+ def fetch_in_schema ( schema , [ "#" | rest ] ) , do: fetch_in_schema ( schema , rest )
221239
222- def get_in_schema ( schema , [ k | rest ] ) when is_map ( schema ) do
240+ def fetch_in_schema ( schema , [ k | rest ] ) when is_map ( schema ) do
223241 key = if Map . has_key? ( schema , k ) , do: k , else: URI . decode ( k )
224242
225243 if Map . has_key? ( schema , key ) do
226- get_in_schema ( schema [ key ] , rest )
244+ fetch_in_schema ( schema [ key ] , rest )
227245 else
228- # This one should never happen anyway
229- raise InvalidPath , key: key , schema: schema
246+ { :error , % InvalidPath { key: key , schema: schema } }
230247 end
231248 end
232249
233- def get_in_schema ( schema , [ k | rest ] ) when is_list ( schema ) ,
234- do: get_in_schema ( Enum . at ( schema , String . to_integer ( k ) ) , rest )
250+ def fetch_in_schema ( schema , [ k | rest ] ) when is_list ( schema ) do
251+ with { index , "" } <- Integer . parse ( k ) ,
252+ { :ok , element } <- Enum . fetch ( schema , index ) do
253+ fetch_in_schema ( element , rest )
254+ else
255+ _ -> { :error , % InvalidPath { key: k , schema: schema } }
256+ end
257+ end
235258
236259 @ doc """
237260 Sets a value in the given (existing) path and returns the updated schema
0 commit comments