ruby-amt 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/AUTHORS +1 -0
- data/COPYING +15 -0
- data/ChangeLog +392 -0
- data/GPL +674 -0
- data/Rakefile +292 -0
- data/VERSION +1 -0
- data/doc/default.css +211 -0
- data/doc/default.template +78 -0
- data/doc/documentation.page +40 -0
- data/doc/img/bg.jpg +0 -0
- data/doc/img/image.jpg +0 -0
- data/doc/img/line.jpg +0 -0
- data/doc/img/shadow.jpg +0 -0
- data/doc/index.page +61 -0
- data/doc/installation.page +115 -0
- data/doc/news.page +25 -0
- data/doc/news/release_0_1_0.page +16 -0
- data/doc/virtual +2 -0
- data/lib/amt/pt_status.rb +59 -0
- data/lib/amt/service.rb +16 -0
- data/lib/amt/service/basic.rb +159 -0
- data/lib/amt/service/hardware_asset.rb +83 -0
- data/lib/amt/service/hardware_asset/amt_information_table.rb +49 -0
- data/lib/amt/service/hardware_asset/asset.rb +118 -0
- data/lib/amt/service/hardware_asset/baseboard.rb +31 -0
- data/lib/amt/service/hardware_asset/bios.rb +65 -0
- data/lib/amt/service/hardware_asset/computer_system.rb +30 -0
- data/lib/amt/service/hardware_asset/fru.rb +37 -0
- data/lib/amt/service/hardware_asset/media_device.rb +63 -0
- data/lib/amt/service/hardware_asset/memory_module.rb +91 -0
- data/lib/amt/service/hardware_asset/portable_battery.rb +80 -0
- data/lib/amt/service/hardware_asset/processor.rb +123 -0
- data/lib/amt/service/hardware_asset/vpro_verification_table.rb +120 -0
- data/lib/amt/service/network_administration.rb +181 -0
- data/lib/amt/service/network_administration/structures.rb +29 -0
- data/lib/amt/service/remote_control.rb +73 -0
- data/lib/amt/service/remote_control/structures.rb +120 -0
- data/lib/amt/service/security_administration.rb +430 -0
- data/lib/amt/service/security_administration/structures.rb +117 -0
- data/lib/amt/system.rb +134 -0
- data/lib/amt/utility.rb +33 -0
- data/lib/amt/utility/bit_struct.rb +164 -0
- data/lib/amt/utility/enum.rb +119 -0
- data/lib/amt/version.rb +8 -0
- data/setup.rb +1585 -0
- metadata +125 -0
@@ -0,0 +1,117 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'amt/service/security_administration'
|
4
|
+
require 'amt/utility'
|
5
|
+
|
6
|
+
module AMT
|
7
|
+
module Service
|
8
|
+
class SecurityAdministration
|
9
|
+
|
10
|
+
# Enumeration containing names of AMT interfaces that can be enabled/disabled. Used for
|
11
|
+
# SecurityAdministration#set_enabled_interfaces and
|
12
|
+
# SecurityAdministration#get_enabled_interfaces.
|
13
|
+
class EnabledInterface < AMT::Utility::Enum
|
14
|
+
multi_add %w[WebUI SerialOverLAN IdeRedirection]
|
15
|
+
end
|
16
|
+
|
17
|
+
# The AMT SOAP interface enumeration. Used for SecurityAdministration#set_tls_options
|
18
|
+
# and SecurityAdministration#get_tls_options.
|
19
|
+
class Interface < AMT::Utility::Enum
|
20
|
+
multi_add %w[NetworkInterface LocalHostInterface]
|
21
|
+
end
|
22
|
+
|
23
|
+
# The TLS Authentication method enumeration. Used for SecurityAdministration#set_tls_options
|
24
|
+
# and SecurityAdministration#get_tls_options.
|
25
|
+
class TlsAuthentication < AMT::Utility::Enum
|
26
|
+
multi_add %w[NoAuth ServerAuth MutualAuth]
|
27
|
+
end
|
28
|
+
|
29
|
+
# Struct class containing version information as returned by
|
30
|
+
# SecurityAdministration#get_core_version.
|
31
|
+
CoreVersion = Struct.new(:major, :minor, :micro)
|
32
|
+
|
33
|
+
# Mapping of provisioning mode name to value. Used for SecurityAdministration#unprovision and
|
34
|
+
# SecurityAdministration#get_provisioning_mode.
|
35
|
+
class ProvisioningMode < AMT::Utility::Enum
|
36
|
+
multi_add(0 => :current, 1 => :enterprise, 2 => :small_business, 3 => :remote_connectivity)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Struct class containing information about an user ACL. The +user+ field may either contain a
|
40
|
+
# binary String identifying a Kerberos SID or a User class instance, the +access_permission+
|
41
|
+
# field contains an instance of AccessPermission and +realms+ contains a list of UserAclRealm
|
42
|
+
# instances. Used for SecurityAdministration#add_user_acl_entry_ex and
|
43
|
+
# SecurityAdministration#update_user_acl_entry_ex.
|
44
|
+
UserAclEntryEx = Struct.new(:user, :access_permission, :realms)
|
45
|
+
|
46
|
+
# Class containing information about a user. Either a plain text password or an already hashed
|
47
|
+
# password must be provided. If a plain text password is provided, the hashed password is
|
48
|
+
# automatically calculated.
|
49
|
+
class User
|
50
|
+
|
51
|
+
# The username to be used. May only contain 7-bit ASCII characters, in the range of 33- 126,
|
52
|
+
# excluding ‘:’, ‘,’, ‘<’, ‘>’, ‘&’, and ‘”’ characters. Length is limited to 16 characters.
|
53
|
+
attr_reader :username
|
54
|
+
|
55
|
+
# The password for the user. This or #hashed_password must be set.
|
56
|
+
attr_reader :password
|
57
|
+
|
58
|
+
# The hashed password for the user. This or #password must be set.
|
59
|
+
attr_reader :hashed_password
|
60
|
+
|
61
|
+
|
62
|
+
# Create a new User object with the given +username+ and, optionally, +password+.
|
63
|
+
def initialize(username, password = nil)
|
64
|
+
self.username = username
|
65
|
+
self.password = password
|
66
|
+
end
|
67
|
+
|
68
|
+
# Contains the characters that are allowed in the username.
|
69
|
+
ALLOWED_USERNAME_CHARS = (33..126).to_a - ":,<>&\"".unpack('c*')
|
70
|
+
|
71
|
+
# Set the username to +value+. If the username is not valid, an ArgumentError is raised.
|
72
|
+
def username=(value)
|
73
|
+
value.each_byte do |b|
|
74
|
+
ALLOWED_USERNAME_CHARS.include?(b) || raise(ArgumentError, "invalid character in username")
|
75
|
+
end
|
76
|
+
raise(ArgumentError, 'username length is limited to 16 characters') if value.length > 16
|
77
|
+
raise(ArgumentError, 'username must not be empty') if value.length == 0
|
78
|
+
@username = value
|
79
|
+
end
|
80
|
+
|
81
|
+
# Set the #password to +value+ and clear the #hashed_password.
|
82
|
+
def password=(value)
|
83
|
+
@hashed_password, @password = nil, value
|
84
|
+
end
|
85
|
+
|
86
|
+
# Set the #hashed_password to +value+ and clear the #password.
|
87
|
+
def hashed_password=(value)
|
88
|
+
@password, @hashed_password = nil, value
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
# Access permissions enumeration. Used in the UserAclEntryEx structure.
|
94
|
+
class AccessPermission < AMT::Utility::Enum
|
95
|
+
multi_add %w[LocalAccessPermission NetworkAccessPermission AnyAccessPermission]
|
96
|
+
end
|
97
|
+
|
98
|
+
# The user ACL realms enumeration. Used in the UserAclEntryEx structure.
|
99
|
+
class UserAclRealm < AMT::Utility::Enum
|
100
|
+
multi_add(0 => :invalid, 1 => :rcs, 2 => :redirection, 3 => :pt_administration,
|
101
|
+
4 => :hardware_asset, 5 => :remote_control, 6 => :storage,
|
102
|
+
7 => :event_manager, 8 => :storage_admin, 9 => :agent_presence_local,
|
103
|
+
10 => :agent_presence_remote, 11 => :circuit_breaker, 12 => :network_time,
|
104
|
+
13 => :general_info, 14 => :firmware_update, 15 => :eit, 16 => :local_un,
|
105
|
+
17 => :endpoint_access_control, 18 => :endpoint_access_control_admin,
|
106
|
+
19 => :event_log_reader, 20 => :security_audit_log, 21 => :user_access_control,
|
107
|
+
22 => :reserved, 23 => :anti_theft)
|
108
|
+
end
|
109
|
+
|
110
|
+
# Struct class containing the fields for a global power policy (used by
|
111
|
+
# SecurityAdministration#set_global_power_policy and
|
112
|
+
# SecurityAdministration#get_global_power_policy).
|
113
|
+
GlobalPowerPolicy = Struct.new(:idle_wake_timeout)
|
114
|
+
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
data/lib/amt/system.rb
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
##
|
4
|
+
# This is the API documentation for ruby-amt!
|
5
|
+
#
|
6
|
+
# Have a look at the \AMT module which provides a good starting point!
|
7
|
+
|
8
|
+
|
9
|
+
#
|
10
|
+
# The ruby-amt library provides access to the SOAP services provided by Intel AMT devices. Before
|
11
|
+
# you decide whether to use the library or not, you should know the following:
|
12
|
+
#
|
13
|
+
# * The library has been designed to be used with Intel AMT 5.0 devices. This is the reason why no
|
14
|
+
# deprecated methods have been implemented.
|
15
|
+
#
|
16
|
+
# * Furthermore, the library has been designed to be used with Intel AMT devices in SMB mode. So
|
17
|
+
# SOAP methods which are only useful for devices in Enterprise Mode have not been implemented. One
|
18
|
+
# reason is that I don't have access to devices in Enterprise Mode and therefore cannot test these
|
19
|
+
# methods.
|
20
|
+
#
|
21
|
+
# = Short Overview
|
22
|
+
#
|
23
|
+
# The library provides a "low-level" implementation of the client side of the SOAP services (as
|
24
|
+
# classes in AMT::Service) as well as a class (AMT::System) for high-level access. The adjective
|
25
|
+
# "low-level" is not really correct since the implementation of the client side of the SOAP services
|
26
|
+
# is not done by generating code from WSDL files (which normally results in a direct mapping of the
|
27
|
+
# SOAP methods and data structures) but by hand-crafting the code and providing simple but adequate
|
28
|
+
# data structures.
|
29
|
+
#
|
30
|
+
# So, although the SOAP service classes directly represent SOAP services and their methods, their
|
31
|
+
# usage in an application is actually quite simple. However, there are some AMT work flows which
|
32
|
+
# require calling more than one method or getting available states before actually setting
|
33
|
+
# something. This can easily be overlooked by people not acquainted with Intel AMT. Therefore there
|
34
|
+
# exists a class for high-level access to the AMT functionality of a system which takes this burden
|
35
|
+
# of you.
|
36
|
+
#
|
37
|
+
# = Library Organization
|
38
|
+
#
|
39
|
+
# This module houses all modules/classes that are in the ruby-amt library. There are three main
|
40
|
+
# modules/classes:
|
41
|
+
#
|
42
|
+
# [AMT::Service]
|
43
|
+
# This module contains all SOAP service classes. There is a one-to-one mapping from
|
44
|
+
# the Intel AMT SOAP services to classes in this module. Note that not all SOAP services are
|
45
|
+
# implemented because some are not really useful for a management application.
|
46
|
+
#
|
47
|
+
# [AMT::Utility]
|
48
|
+
# This module houses utility classes that are used by other classes (mostly the service classes).
|
49
|
+
#
|
50
|
+
# [AMT::System]
|
51
|
+
# This is the class that can be used for high-level access to the functionality of an AMT system.
|
52
|
+
#
|
53
|
+
# = Library Usage
|
54
|
+
#
|
55
|
+
# == Direct use of SOAP Service Classes
|
56
|
+
#
|
57
|
+
# All service classes are derived from AMT::Service::Basic and have the same initialization
|
58
|
+
# parameters. You need to provide at least the hostname of the AMT device, a username and a
|
59
|
+
# password.
|
60
|
+
#
|
61
|
+
# You don't need to load an individual service class, just use
|
62
|
+
#
|
63
|
+
# require 'amt/service'
|
64
|
+
#
|
65
|
+
# since this will automatically load any service class and any data structures that are needed on
|
66
|
+
# demand.
|
67
|
+
#
|
68
|
+
# For example, the AMT::Service::RemoteControl service can be created like this:
|
69
|
+
#
|
70
|
+
# rcs = AMT::Service::RemoteControl.new('amt.example.com', 'admin', 'P@ssw0rD')
|
71
|
+
#
|
72
|
+
# After that you can just call the method you would like to invoke on the AMT system. But before
|
73
|
+
# that you should read the method description sothat you know what parameters to pass. Since the
|
74
|
+
# SOAP service classes are not created from WSDL files, they provide a nicer, more Ruby like
|
75
|
+
# interface to the SOAP methods. However, this also means that the method signature sometimes
|
76
|
+
# differs a little bit from the method signature as defined in the "Network Interface Guide" (which
|
77
|
+
# can be found in the Intel AMT SDK).
|
78
|
+
#
|
79
|
+
# Take the AMT::Service::RemoteControl#get_system_power_state as example:
|
80
|
+
#
|
81
|
+
# sps = rcs.get_system_power_state
|
82
|
+
#
|
83
|
+
# Since this method takes no parameters, there is no difference in this respect. The method would
|
84
|
+
# nominally return a bit structure as an unsigned 32 bit integer. However, this has been changed
|
85
|
+
# sothat it returns an instance of AMT::Service::RemoteControl::SystemPowerState which provides easy
|
86
|
+
# access to the fields of the bit structure. For example:
|
87
|
+
#
|
88
|
+
# sps.power_state # => :s0
|
89
|
+
# sps.watchdog_expired? # => false
|
90
|
+
# sps.power_source # => :ac
|
91
|
+
#
|
92
|
+
# Such a conversion of input or output arguments is true for all implemented methods. The special
|
93
|
+
# data structures needed by a service are defined in the namespace of the service. For example, all
|
94
|
+
# data structures needed as input or returned as output for the RemoteControl service are defined
|
95
|
+
# unter AMT::Service::RemoteControl.
|
96
|
+
#
|
97
|
+
# So how does one provide input parameters? We take the AMT::Service::RemoteControl#remote_control
|
98
|
+
# method as example. You can learn from the method description that it has one mandatory and several
|
99
|
+
# optional arguments. Additionally, it is stated which type the arguments have. In its simplest
|
100
|
+
# form, one needs to provide just a value for the +command+ parameter which should be an instance of
|
101
|
+
# AMT::Service::RemoteControl::RemoteControlCommand. Checking out the class we see that it is a
|
102
|
+
# subclass of AMT::Utility::Enum. This allows us to use any of the following ways to power up an AMT
|
103
|
+
# system which is currently powered down:
|
104
|
+
#
|
105
|
+
# rcs.remote_control(AMT::Service::RemoteControl::RemoteControlCommand.for(:0x11))
|
106
|
+
# rcs.remote_control(AMT::Service::RemoteControl::RemoteControlCommand.for(:power_up))
|
107
|
+
# rcs.remote_control(0x11)
|
108
|
+
# rcs.remote_control(:power_up)
|
109
|
+
#
|
110
|
+
# As you can see, one doesn't actually need to create an instance of the RemoteControlCommand class,
|
111
|
+
# one just needs to provide either a valid enumeration value or enumeration name! <b>This is true
|
112
|
+
# everywhere a subclass of AMT::Utility::Enum is expected.</b>
|
113
|
+
#
|
114
|
+
# A simliar short-cut is available when an instance of a subclass of AMT::Utility::BitStruct is
|
115
|
+
# expected - see AMT::Utility::BitStruct.new !
|
116
|
+
#
|
117
|
+
# Here is a final example with some optional parameters:
|
118
|
+
#
|
119
|
+
# rcs.remote_control(:power_up, 343, :boot_options => [:lock_keyboard], :special_command => :pxe_boot)
|
120
|
+
#
|
121
|
+
#
|
122
|
+
# == High-level Interface
|
123
|
+
#
|
124
|
+
# The high-level interface is not implemented currently.
|
125
|
+
#
|
126
|
+
module AMT
|
127
|
+
|
128
|
+
# High-level access to AMT functionality.
|
129
|
+
#
|
130
|
+
# NOT IMPLEMENTED
|
131
|
+
class System
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
data/lib/amt/utility.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module AMT
|
4
|
+
|
5
|
+
# This module houses utility classes that are used by the other AMT classes.
|
6
|
+
module Utility
|
7
|
+
|
8
|
+
autoload :BitStruct, 'amt/utility/bit_struct'
|
9
|
+
autoload :Enum, 'amt/utility/enum'
|
10
|
+
|
11
|
+
|
12
|
+
# Create a UUID string from binary data which can either have a length of 16 characters (then it
|
13
|
+
# is considered to be a binary UUID) or a length of 32 characters (an already unpacked binary
|
14
|
+
# UUID).
|
15
|
+
def self.binary_to_uuid(data)
|
16
|
+
data = data.unpack('H32').first if data.length == 16
|
17
|
+
a = data.scan(/../)
|
18
|
+
a[0,4].reverse.join('') + "-" + a[4,2].reverse.join('') + "-" + a[6,2].reverse.join('') +
|
19
|
+
"-" + a[8,2].join('') + "-" + a[10,6].join('')
|
20
|
+
end
|
21
|
+
|
22
|
+
# Convert a UUID string to binary data.
|
23
|
+
def self.uuid_to_binary(uuid)
|
24
|
+
[uuid[0,8].scan(/../).reverse.join('') +
|
25
|
+
uuid[9,4].scan(/../).reverse.join('') +
|
26
|
+
uuid[14,4].scan(/../).reverse.join('') +
|
27
|
+
uuid[19,4].scan(/../).join('') +
|
28
|
+
uuid[24,12].scan(/../).join('')].pack('H32')
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module AMT
|
4
|
+
|
5
|
+
module Utility
|
6
|
+
|
7
|
+
# A very simple base class which can be used to extract information from a number based on its
|
8
|
+
# bits, or to set it.
|
9
|
+
#
|
10
|
+
# It isn't useful to create objects directly from this class but one should create a subclass
|
11
|
+
# and use the provided class methods to define how to interpret the bits of a number.
|
12
|
+
class BitStruct
|
13
|
+
|
14
|
+
# Interpret the bit with the +index+ (starting from zero) as boolean flag named +name+ (should
|
15
|
+
# be a Symbol). If the bit at the index is +1+, the flag is interpreted as +true+. The
|
16
|
+
# optional parameter +desc+ can be used to provide a textual representation of the +true+
|
17
|
+
# state.
|
18
|
+
#
|
19
|
+
# This method also adds accessor methods for the property. For example, if the property is
|
20
|
+
# called +amt_enabled+, the created getter method is called <tt>#amt_enabled?</tt> and the
|
21
|
+
# setter method is called <tt>#amt_enabled!</tt>. Note the trailing question/exclamation
|
22
|
+
# marks.
|
23
|
+
#
|
24
|
+
# Example usage:
|
25
|
+
#
|
26
|
+
# boolean 5, :amt_enabled, 'AMT is enabled'
|
27
|
+
def self.boolean(index, name, desc = name.to_s)
|
28
|
+
index = (0x1 << index)
|
29
|
+
(@boolean ||= []) << [name, desc]
|
30
|
+
define_method("#{name}?") do
|
31
|
+
@value & index == index
|
32
|
+
end
|
33
|
+
define_method("#{name}!") do
|
34
|
+
@value |= index
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
# Same as BitStruct.boolean but +mask+ defines a bit mask and the value is only +true+ if all
|
40
|
+
# bits specified by the bit mask (ie. all bits that are +1+ in the bit mask) are set.
|
41
|
+
#
|
42
|
+
# Example usage:
|
43
|
+
#
|
44
|
+
# mboolean 0b101, :amt_enabled, 'AMT is enabled'
|
45
|
+
def self.mboolean(mask, name, desc = name.to_s)
|
46
|
+
(@boolean ||= []) << [name, desc]
|
47
|
+
define_method("#{name}?") do
|
48
|
+
@value & mask == mask
|
49
|
+
end
|
50
|
+
define_method("#{name}!") do
|
51
|
+
@value |= mask
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
# Interpret the bits in the +bit_range+ (starting from zero) as unsigned integer named +name+
|
57
|
+
# (should be a Symbol). The optional parameter +desc+ can be used to provide a textual
|
58
|
+
# representation of the meaning of the value.
|
59
|
+
#
|
60
|
+
# This method also adds accessor methods for the property. For example, if the property is
|
61
|
+
# called +version+, the created getter method is called <tt>#version</tt> and the setter
|
62
|
+
# method is called <tt>#version=</tt>.
|
63
|
+
#
|
64
|
+
# Example usage:
|
65
|
+
#
|
66
|
+
# unsigned 2..5, :version, 'The integer version of the AMT device'
|
67
|
+
def self.unsigned(bit_range, name, desc = name.to_s)
|
68
|
+
mask = (2**(bit_range.end - bit_range.begin + 1) - 1) << bit_range.begin
|
69
|
+
(@unsigned ||= []) << [name, desc]
|
70
|
+
define_method(name) do
|
71
|
+
(@value & mask) >> bit_range.begin
|
72
|
+
end
|
73
|
+
define_method("#{name}=") do |number|
|
74
|
+
@value |= (number << bit_range.begin) & mask
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Interpret the bits in the +bit_range+ (starting from zero) as unsigned integer value of an
|
79
|
+
# enumeration called +name+ (should be a Symbol).
|
80
|
+
#
|
81
|
+
# The parameter +values+ specifies the mapping from number to meaning (normally a String). The
|
82
|
+
# optional parameter +desc+ can be used to provide a textual representation of the meaning of
|
83
|
+
# the enumeration.
|
84
|
+
#
|
85
|
+
# This method also adds accessor methods for the property. For example, if the property is
|
86
|
+
# called +version+, the created getter method is called <tt>#version</tt> and the setter
|
87
|
+
# method is called <tt>#version=</tt>.
|
88
|
+
#
|
89
|
+
# Example usage:
|
90
|
+
#
|
91
|
+
# enum 0..1, :device_type, {0 => 'Foo', 1 => 'Bar', 2 => 'Baz', 3 => Quux'}
|
92
|
+
def self.enum(bit_range, name, values, desc = name.to_s)
|
93
|
+
mask = (2**(bit_range.end - bit_range.begin + 1) - 1) << bit_range.begin
|
94
|
+
(@enum ||= []) << [name, values, desc]
|
95
|
+
define_method(name) do
|
96
|
+
values[(@value & mask) >> bit_range.begin]
|
97
|
+
end
|
98
|
+
define_method("#{name}=") do |number|
|
99
|
+
@value |= (number << bit_range.begin) & mask
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# Return a hash of all defined fields for this class. The hash keys are <tt>:boolean</tt> for
|
104
|
+
# the boolean properties, <tt>:unsigned</tt> for the unsigned integer properties and
|
105
|
+
# <tt>:enum</tt> for the enumeration properties. The hash values are arrays with information
|
106
|
+
# (depending on the type of the field) about the fields.
|
107
|
+
def self.fields
|
108
|
+
{:boolean => @boolean || [], :unsigned => @unsigned || [], :enum => @enum || []}
|
109
|
+
end
|
110
|
+
|
111
|
+
# The integer value which should be interpreted bit-wise.
|
112
|
+
attr_reader :value
|
113
|
+
|
114
|
+
# Create a new object. If +value+ is an integer, it is used directly and interpreted bit-wise.
|
115
|
+
# If +value+ is an array, it is processed in the following way:
|
116
|
+
#
|
117
|
+
# * symbols are interpreted as boolean fields
|
118
|
+
# * two-item arrays where the first item is a symbol and the second an integer are interpreted
|
119
|
+
# as unsigned or enum fields (depending in which category the symbol falls).
|
120
|
+
def initialize(value = 0)
|
121
|
+
if value.kind_of?(Integer)
|
122
|
+
@value = value
|
123
|
+
elsif value.kind_of?(Array)
|
124
|
+
@value = 0
|
125
|
+
value.each do |sym, val|
|
126
|
+
if val.nil?
|
127
|
+
send("#{sym}!")
|
128
|
+
else
|
129
|
+
send("#{sym}=", val)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
else
|
133
|
+
raise ArgumentError, 'invalid argument type specified'
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def inspect #:nodoc:
|
138
|
+
bools = self.class.fields[:boolean].select {|n,d| send("#{n}?")}.collect {|n, d| n.to_s}
|
139
|
+
unsigns = self.class.fields[:unsigned].collect {|n, d| "#{n}=#{send(n)}"}
|
140
|
+
enum = self.class.fields[:enum].collect {|n, d| "#{n}=#{send(n)}"}
|
141
|
+
"#<#{self.class.name} #{(bools + unsigns + enum).join(', ')}>"
|
142
|
+
end
|
143
|
+
|
144
|
+
# Return an array with textual representations for output purposes of the the fields specified
|
145
|
+
# by +used_fields+.
|
146
|
+
def list(used_fields = [:boolean, :unsigned, :enum])
|
147
|
+
result = []
|
148
|
+
if used_fields.include?(:boolean)
|
149
|
+
result += self.class.fields[:boolean].select {|n,d| send("#{n}?")}.collect {|n,d| d}
|
150
|
+
end
|
151
|
+
if used_fields.include?(:unsigned)
|
152
|
+
result += self.class.fields[:unsigned].collect {|n, d| "#{d}=#{send(n)}"}
|
153
|
+
end
|
154
|
+
if used_fields.include?(:enum)
|
155
|
+
result += self.class.fields[:enum].collect {|n, d| "#{d}=#{send(n)}"}
|
156
|
+
end
|
157
|
+
result
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
161
|
+
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|