Class: RubyTorrent::TypedStruct

Inherits:
Object
  • Object
show all
Defined in:
lib/rubytorrent/typedstruct.rb

Overview

type-checking struct meant for easy translation from and to bencoded dicts.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize {|_self| ... } ⇒ TypedStruct

Returns a new instance of TypedStruct.

Yields:

  • (_self)

Yield Parameters:



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

#dirtyObject

Returns the value of attribute dirty.



35
36
37
# File 'lib/rubytorrent/typedstruct.rb', line 35

def dirty
  @dirty
end

#fieldsObject (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_bencodingObject



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