ruby/lib/yaml/types.rb

197 строки
4.4 KiB
Ruby

#
# Classes required by the full core typeset
#
module YAML
#
# Default private type
#
class PrivateType
attr_accessor :type_id, :value
def initialize( type, val )
@type_id = type; @value = val
end
def to_yaml( opts = {} )
YAML::quick_emit( self.object_id, opts ) { |out|
out << " !!#{@type_id}"
value.to_yaml( :Emitter => out )
}
end
end
#
# Default domain type
#
class DomainType
attr_accessor :domain, :type_id, :value
def initialize( domain, type, val )
@domain = domain; @type_id = type; @value = val
end
def to_yaml_type
dom = @domain.dup
if dom =~ /\.yaml\.org,2002$/
dom = $`
end
"#{dom}/#{@type_id}"
end
def to_yaml( opts = {} )
YAML::quick_emit( self.object_id, opts ) { |out|
out << " !#{to_yaml_type} "
value.to_yaml( :Emitter => out )
}
end
end
#
# YAML Hash class to support comments and defaults
#
class SpecialHash < Object::Hash
attr_accessor :default
def inspect
self.default.to_s
end
def to_s
self.default.to_s
end
def update( h )
if YAML::SpecialHash === h
@default = h.default if h.default
end
super( h )
end
def to_yaml( opts = {} )
opts[:DefaultKey] = self.default
super( opts )
end
end
#
# Builtin collection: !omap
#
class Omap < Array
def self.[]( *vals )
o = Omap.new
0.step( vals.length - 1, 2 ) { |i|
o[vals[i]] = vals[i+1]
}
o
end
def []( k )
self.assoc( k ).to_a[1]
end
def []=( k, *rest )
val, set = rest.reverse
if ( tmp = self.assoc( k ) ) and not set
tmp[1] = val
else
self << [ k, val ]
end
val
end
def has_key?( k )
self.assoc( k ) ? true : false
end
def is_complex_yaml?
true
end
def to_yaml( opts = {} )
YAML::quick_emit( self.object_id, opts ) { |out|
out.seq( "!omap" ) { |seq|
self.each { |v|
seq.add( Hash[ *v ] )
}
}
}
end
end
YAML.add_builtin_type( "omap" ) { |type, val|
if Array === val
p = Omap.new
val.each { |v|
if Hash === v
p.concat( v.to_a ) # Convert the map to a sequence
else
raise YAML::Error, "Invalid !omap entry: " + val.inspect
end
}
else
raise YAML::Error, "Invalid !omap: " + val.inspect
end
p
}
#
# Builtin collection: !pairs
#
class Pairs < Array
def self.[]( *vals )
p = Pairs.new
0.step( vals.length - 1, 2 ) { |i|
p[vals[i]] = vals[i+1]
}
p
end
def []( k )
self.assoc( k ).to_a
end
def []=( k, val )
self << [ k, val ]
val
end
def has_key?( k )
self.assoc( k ) ? true : false
end
def is_complex_yaml?
true
end
def to_yaml( opts = {} )
YAML::quick_emit( self.object_id, opts ) { |out|
out.seq( "!pairs" ) { |seq|
self.each { |v|
seq.add( Hash[ *v ] )
}
}
}
end
end
YAML.add_builtin_type( "pairs" ) { |type, val|
if Array === val
p = Pairs.new
val.each { |v|
if Hash === v
p.concat( v.to_a ) # Convert the map to a sequence
else
raise YAML::Error, "Invalid !pairs entry: " + val.inspect
end
}
else
raise YAML::Error, "Invalid !pairs: " + val.inspect
end
p
}
#
# Builtin collection: !set
#
class Set < Hash
def to_yaml_type
"!set"
end
end
YAML.add_builtin_type( 'set' ) { |type, val|
if Array === val
val = Set[ *val ]
elsif Hash === val
Set[ val ]
else
raise YAML::Error, "Invalid map explicitly tagged !map: " + val.inspect
end
val
}
end