lib/dense/path.rb in dense-1.1.1 vs lib/dense/path.rb in dense-1.1.2
- old
+ new
@@ -21,19 +21,74 @@
fail ArgumentError.new(
"couldn't determine path from #{s.inspect}"
) unless @path
end
- def self.make(path_array)
+ class << self
- return nil if path_array.nil?
- return path_array if path_array.is_a?(Dense::Path)
+ def make(path_or_array_or_string)
- path = Dense::Path.allocate
- path.instance_eval { @path = path_array }
- path.instance_eval { @original = path.to_s }
+ case (pas = path_or_array_or_string)
+ when nil then nil
+ when Dense::Path then pas
+ when Array then make_from_array(pas)
+ when String then Dense::Path.new(pas)
+ else
+ fail ArgumentError.new(
+ "cannot make Dense::Path instance out of #{pas.inspect}")
+ end
+ end
- path
+ protected
+
+ def symbolize!(o)
+
+ if o.is_a?(Array)
+ o
+ .each { |e| symbolize!(e) }
+ elsif o.is_a?(Hash)
+ o.keys
+ .select { |k| k.is_a?(String) }
+ .each { |k| o[k.to_sym] = o.delete(k) }
+ end
+ end
+
+ def make_from_array(path_array)
+
+ symbolize!(path_array)
+ validate(path_array)
+
+ path = Dense::Path.allocate
+ path.instance_eval { @path = path_array }
+ path.instance_eval { @original = path.to_s }
+
+ path
+ end
+
+ def validate(path_array)
+
+ path_array
+ .each_with_index { |elt, i|
+ (elt.is_a?(Array) ? elt : [ elt ])
+ .each { |e| validate_path_elt(e, i) } }
+
+ true
+ end
+
+ def validate_path_elt(elt, i)
+
+ return if elt.is_a?(Integer)
+ return if elt.is_a?(String)
+ return if [ :dot, :dotstar, :star ].include?(elt)
+
+ if elt.is_a?(Hash)
+ ks = elt.keys.sort
+ return if ks == [ :end, :start, :step ]
+ return if ks == [ :count, :start ]
+ end
+
+ fail TypeError.new("not a path element (@#{i}): #{elt.inspect}")
+ end
end
def single?
! @path.find { |e| e.is_a?(Symbol) || e.is_a?(Hash) || e.is_a?(Array) }