@@ -269,39 +269,61 @@ defmodule Keyword do
269269 @ doc since: "1.13.0"
270270 @ spec validate ( keyword ( ) , values :: [ atom ( ) | { atom ( ) , term ( ) } ] ) ::
271271 { :ok , keyword ( ) } | { :error , [ atom ] }
272+ def validate ( [ ] , values ) when is_list ( values ) , do: { :ok , move_pairs! ( values , [ ] ) }
273+
272274 def validate ( keyword , values ) when is_list ( keyword ) and is_list ( values ) do
273- validate ( keyword , values , [ ] , keyword , [ ] )
275+ validate_merge ( keyword , values , [ ] , keyword )
274276 end
275277
276- defp validate ( [ { key , _ } | keyword ] , values1 , values2 , original , bad_keys ) when is_atom ( key ) do
277- case find_key! ( key , values1 , values2 ) do
278- { values1 , values2 } ->
279- validate ( keyword , values1 , values2 , original , bad_keys )
280-
281- :error ->
282- case find_key! ( key , values2 , values1 ) do
283- { values1 , values2 } ->
284- validate ( keyword , values1 , values2 , original , bad_keys )
278+ defp validate_merge ( [ ] , values , values_pre , original ) ,
279+ do: { :ok , move_pairs! ( values , move_pairs! ( values_pre , original ) ) }
285280
286- :error ->
287- validate ( keyword , values1 , values2 , original , [ key | bad_keys ] )
288- end
281+ defp validate_merge ( [ { key , _ } = pair | keyword ] , [ head | tail ] , values_pre , original )
282+ when is_atom ( key ) do
283+ case head do
284+ ^ key -> validate_merge ( keyword , tail , values_pre , original )
285+ { ^ key , _ } -> validate_merge ( keyword , tail , values_pre , original )
286+ _ -> validate_merge ( [ pair | keyword ] , tail , [ head | values_pre ] , original )
289287 end
290288 end
291289
292- defp validate ( [ ] , values1 , values2 , original , [ ] ) do
293- { :ok , move_pairs! ( values1 , move_pairs! ( values2 , original ) ) }
294- end
290+ defp validate_merge ( [ { key , _ } | keyword ] , [ ] , values_pre , original ) when is_atom ( key ) do
291+ case find_key! ( key , values_pre , [ ] ) do
292+ { new_values , new_values_pre } ->
293+ validate_merge ( keyword , new_values , new_values_pre , original )
295294
296- defp validate ( [ ] , _values1 , _values2 , _original , bad_keys ) do
297- { :error , bad_keys }
295+ :error ->
296+ validate_fallback ( keyword , values_pre , [ key ] )
297+ end
298298 end
299299
300- defp validate ( [ pair | _ ] , _values1 , _values2 , _original , [ ] ) do
301- raise ArgumentError ,
302- "expected a keyword list as first argument, got invalid entry: #{ inspect ( pair ) } "
300+ defp validate_merge ( [ pair | _ ] , _ , _ , _ ) ,
301+ do:
302+ raise (
303+ ArgumentError ,
304+ "expected a keyword list as first argument, got invalid entry: #{ inspect ( pair ) } "
305+ )
306+
307+ defp validate_fallback ( [ { key , _ } | keyword ] , values , bad_keys )
308+ when is_atom ( key ) do
309+ case find_key! ( key , values , [ ] ) do
310+ { rest , acc } ->
311+ validate_fallback ( keyword , rest ++ acc , bad_keys )
312+
313+ :error ->
314+ validate_fallback ( keyword , values , [ key | bad_keys ] )
315+ end
303316 end
304317
318+ defp validate_fallback ( [ ] , _ , bad ) , do: { :error , bad }
319+
320+ defp validate_fallback ( [ p | _ ] , _ , _ ) ,
321+ do:
322+ raise (
323+ ArgumentError ,
324+ "expected a keyword list as first argument, got invalid entry: #{ inspect ( p ) } "
325+ )
326+
305327 defp find_key! ( key , [ key | rest ] , acc ) , do: { rest , acc }
306328 defp find_key! ( key , [ { key , _ } | rest ] , acc ) , do: { rest , acc }
307329 defp find_key! ( key , [ head | tail ] , acc ) , do: find_key! ( key , tail , [ head | acc ] )
0 commit comments