Class: RubyTorrent::TypedStruct
- Inherits:
-
Object
- Object
- RubyTorrent::TypedStruct
- Defined in:
- lib/rubytorrent/typedstruct.rb
Overview
type-checking struct meant for easy translation from and to bencoded dicts.
Instance Attribute Summary collapse
-
#dirty ⇒ Object
Returns the value of attribute dirty.
-
#fields ⇒ Object
readonly
writer below.
Instance Method Summary collapse
-
#initialize {|_self| ... } ⇒ TypedStruct
constructor
A new instance of TypedStruct.
- #method_missing(meth, *args) ⇒ Object
-
#parse(dict) ⇒ Object
given a Hash from a bencoded dict, parses it according to the rules you’ve set up with field, required, label, etc.
- #to_bencoding ⇒ Object
Constructor Details
#initialize {|_self| ... } ⇒ TypedStruct
Returns a new instance of TypedStruct.
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/rubytorrent/typedstruct.rb', line 38 def initialize @required = {} @label = {} @coerce = {} @field = {} @array = {} @dirty = false @values = {} yield self if block_given? @field.each do |f, type| @required[f] ||= false @label[f] ||= f.to_s @array[f] ||= false end end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(meth, *args) ⇒ Object
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/rubytorrent/typedstruct.rb', line 56 def method_missing(meth, *args) if meth.to_s =~ /^(.*?)=$/ # p [meth, args] f = $1.intern raise ArgumentError, "no such value #{f}" unless @field.has_key? f type = @field[f] o = args[0] if @array[f] raise TypeError, "for #{f}, expecting Array, got #{o.class}" unless o.kind_of? ::Array o.each { |e| raise TypeError, "for elements of #{f}, expecting #{type}, got #{e.class}" unless e.kind_of? type } @values[f] = o @dirty = true else raise TypeError, "for #{f}, expecting #{type}, got #{o.class}" unless o.kind_of? type @values[f] = o @dirty = true end else raise ArgumentError, "no such value #{meth}" unless @field.has_key? meth # p [meth, @values[meth]] @values[meth] end end |
Instance Attribute Details
#dirty ⇒ Object
Returns the value of attribute dirty.
35 36 37 |
# File 'lib/rubytorrent/typedstruct.rb', line 35 def dirty @dirty end |
#fields ⇒ Object (readonly)
writer below
36 37 38 |
# File 'lib/rubytorrent/typedstruct.rb', line 36 def fields @fields end |
Instance Method Details
#parse(dict) ⇒ Object
given a Hash from a bencoded dict, parses it according to the rules you’ve set up with field, required, label, etc.
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/rubytorrent/typedstruct.rb', line 104 def parse(dict) @required.each do |f, reqd| flabel = @label[f] raise TypedStructError, "missing required parameter #{flabel} (dict has #{dict.keys.join(', ')})" if reqd && !(dict.member? flabel) if dict.member? flabel v = dict[flabel] if @coerce.member? f v = @coerce[f][v] end if @array[f] raise TypeError, "for #{flabel}, expecting Array, got #{v.class} instead" unless v.kind_of? ::Array end self.send("#{f}=", v) end end ## disabled the following line as applications seem to put tons of ## weird fields in their .torrent files. # dict.each { |k, v| raise TypedStructError, %{unknown field "#{k}"} unless @field.member?(k.to_sym) || @label.values.member?(k) } end |
#to_bencoding ⇒ Object
126 127 128 129 |
# File 'lib/rubytorrent/typedstruct.rb', line 126 def to_bencoding @required.each { |f, reqd| raise ArgumentError, "missing required parameter #{f}" if reqd && self.send(f).nil? } @field.extend(HashMapHash).map_hash { |f, type| [@label[f], self.send(f)] }.to_bencoding end |