lib/eac_ruby_utils/byte.rb
# frozen_string_literal: true require 'eac_ruby_utils/bit' require 'eac_ruby_utils/bit_array' require 'eac_ruby_utils/patches/module/compare_by' module EacRubyUtils class Byte ASSEMBLY_HEXADECIMAL_PREFIX = '$' BIT_COUNT = 8 BIT_INDEX_RANGE = (0..7).freeze VALUE_RANGE = (0..255).freeze class << self def assert(obj) return obj if obj.is_a?(self) new(obj.to_i) end def from_bit_array(bit_array, big_endian = false) # rubocop:disable Style/OptionalBooleanParameter bit_array = ::EacRubyUtils::BitArray.assert(bit_array) raise ::ArgumentError, "Wrong bit array size: #{bit_array.size}" if bit_array.size != BIT_COUNT bit_array = bit_array.reverse if big_endian bit_array.each_with_index.inject(new(0)) do |a, e| a.bit_set(e[1], e[0]) end end def valid_bit_index?(value) value.is_a?(::Integer) && BIT_INDEX_RANGE.include?(value) end def validate_bit_index(value) return value if valid_bit_index?(value) raise(::ArgumentError, "Invalid bit index: #{value} (Range: #{BIT_INDEX_RANGE})") end def valid_value?(value) value.is_a?(::Integer) && VALUE_RANGE.include?(value) end def validate_value(value) return value if valid_value?(value) raise(::ArgumentError, "Invalid byte value: #{value} (Range: #{VALUE_RANGE})") end end attr_reader :value compare_by :value def initialize(value) self.value = value end # @param bit_index [Integer] # @return [EacRubyUtils::Bit] def [](bit_index) bit_get(bit_index) end # @param bit_index [Integer] # @return [EacRubyUtils::Bit] def bit_get(bit_index) self.class.validate_bit_index(bit_index) ::EacRubyUtils::Bit.new((value & (1 << bit_index)) >> bit_index) end def bit_set(bit_index, bit_value) self.class.validate_bit_index(bit_index) bit = ::EacRubyUtils::Bit.assert(bit_value) mask = (1 << bit_index) self.class.new(bit.zero? ? value & ~mask : value | mask) end # @return [EacRubyUtils::BitArray] def to_bit_array(range = BIT_INDEX_RANGE) ::EacRubyUtils::BitArray.new(range.map { |bit_index| self[bit_index] }) end # @return [Integer] def to_i value end # @return [String] def to_asm_hex ASSEMBLY_HEXADECIMAL_PREFIX + to_hex end # @return [String] def to_hex value.to_s(16).upcase.rjust(2, '0') end private attr_writer :value end end