com.scalacraft.domain.v2.binary

unconstrained

package unconstrained

Visibility
  1. Public
  2. All

Type Members

  1. case class Octet(octet: Option[Int]) extends Product with Serializable

    An Octet represents an integer in the range [0, 255].

    An Octet represents an integer in the range [0, 255].

    This class does not constrain the value of the octet beyond requiring a non-null constructor argument.

    The value maybe outside the given range or undefined.

    Pattern Matching

    Pattern matching is supported as the following examples demonstrate,

    5 match {
      case Octet(n) => n // Some(5)
      case _ => None
    }

    The match target can be a string,

    val s: String = "ff"
    s match {
      case Octet(n) => n // Some(255)
      case _ => None
    }

    A null or whitespace string will match to Octet(None) while a non-hex value will not match.

    val s: String = " " * 4
    s match {
      case Octet(n) => n  // None
      case _ => None
    }
    val s = "foobarbaz"
    s match {
      case Octet(n) => n
      case _ => None  // None
    }
    Implicit Conversions

    Implicit conversions exists which allow an instance of Octet to be used when an Option[Int] or Option[String] is required.

    val octet = Octet(1022)  // The value is not constrained
    val i: Option[Int] = octet  // Some(1022)

    A conversion to an option of the constrained version of this class is also available.

    octet

    An optional octet value

  2. case class OctetPair(hi: Option[Octet], lo: Option[Octet]) extends Product with Serializable

    An unconstrained OctetPair represents two Octets which are themselves unconstrained.

    An unconstrained OctetPair represents two Octets which are themselves unconstrained.

    In addition to using unconstrained octets each octet is optional. This allows an invalid pair to be created when we have only valid octets to select from.

    When interpreted as recording a single integer value using this expression 256 * hi + lo the allowable range has a minimum of -0x8080000000 and maximum equalling 0x807ffffeff.

    In decimal the representable range is [-551903297536, 551903297279].

    Pattern Matching

    Pattern matching is supported as the following examples demonstrate,

    0x3490 match {
      case OctetPair(hi, lo) => (hi, lo) // (Some(Octet(Some(0x34))), Some(Octet(Some(0x90)))
      case _ => None
    }

    Matching will succeed against integer values larger than the range of two constrained octets,

    0x4251d match {
      case OctetPair(hi, lo) => (hi, lo) // (Some(Octet(Some(0x425))), Some(Octet(Some(0x1d)))
      case _ => None
    }

    Negative values are matched,

    -257 match {
      case OctetPair(hi, lo) => (hi, lo) // (Some(Octet(Some(-1))), Some(Octet(Some(-1)))
      case _ => None
    }

    The match target can be a string,

    val s: String = "4020"
    
    s match {
      case OctetPair(hi, lo) => (hi, lo) // (Some(Octet(Some(0x40))), Some(Octet(Some(0x20)))
      case _ => None
    }
    Implicit Conversions

    An implicit conversion is supplied which allows an instance of OctetPair to be used where Option[String] is required.

    val octetPair = OctetPair(Some(Octet(0xab)), Some(Octet(0x17)))
    val s: Option[String] = octetPair
    s foreach(println) // ab17

    A conversion to an option of the constrained version of this class is also available.

    Value distribution between hi and lo octets

    With a hi and lo octet the range of representable values is bounded below by

    256 * min-int-value + min-int-value

    and above by

    256 * max-int-value + max-int-value

    When matching against values included in this sub-range,

    [256 * min-int-value - 255, 256 * max-int-value + 255]

    the value of the lo octet will always be in this inclusive range,

    [0, 255]

    For values that lie outside of this range the lo octet will take on values from one of these two inclusive ranges,

    [min-int-value, -256]
    [256, max-int-value]

    while the hi octet will be one of these two values,

    min-int-value
    max-int-value

    Notionally the hi octet overflows or underflows before the lo octet.

    Value Distribution Examples

    When OctetPair is called on to match a value outside of the normal range for two octets it will use the full range of the hi and lo octets. This involves a design choice around which octet exceeds 0xff first. The choice here is to fill the hi octet first and move onto the lo octet only when the hi octct can no longer be incremented.

    "0" matches to (0x0, 0x0). The table below shows how other value are distributed across the hi and lo octets.

    Target        Match                    Notes
    ------        -----                    -----
    "10000"       (0x100, 0x0)             The equal valued alternative (0xff, 0x100) is not used because the hi octet should be incremented out of range first.
    "100ff"       (0x100, 0xff)
    "10100"       (0x101, 0x0)
    "7fffffff"    (0x7fffff, 0xff)
    "7fffffffff"  (0x7fffffff, 0xff)
    "8000000000"  (0x7fffffff, 0x100)      This shows the lo octet being incremented out of range when the hi octet has arrived at the integer maximum.
    "8000000201"  (0x7fffffff, 0x301)      This shows the lo octet continuing to increase while the hi octet remains fixed.
    "807ffffeff"  (0x7fffffff, 0x7fffffff) At this point we cannot increase the match target any further and still match.
    "807fffff00"                           This is not matched because both the hi and lo octet were maxed out representing "807ffffeff".

    Equivalent choices are made as the match target decrements towards the minimum value representable by two integers.

    hi

    non-null octet option representing the high order octet in this pair

    lo

    non-null octet option representing the low order octet in this pair

Value Members

  1. object Octet extends Serializable

  2. object OctetPair extends Serializable

Ungrouped