Allocating bits from stored byte32 to different byte variables

Hello all, I’m a bit new to allocating data to its correct bytes and was hoping someone could explain this process here.

  struct SubwayArrivalDetail {
    bytes5 lat;
    bytes6 lon;
    bytes8 arrival;
  }

  function getSubwayArrivalDetailStruct(bytes32 _data)
    private
    pure
    returns (SubwayArrivalDetail memory)
  {
    SubwayArrivalDetail memory subwayArrivalDetail = SubwayArrivalDetail(
      bytes5(_data << 8), // 40 bites
      bytes6(_data << 32), // 48 bits
      bytes8(_data << 56) // 64 bits = 152 bits
      // bytes8(bytes5(_data << 56))[],
    );
    return subwayArrivalDetail;
  }

its still incorrect but, the idea is to allocate a byte32 string that contains bits of data for specific byte variables (defined by struct)

In sense, this is a way to read that specific data that is stored onchain within this contract (data collected via offchain)

Here is a working example I am using as reference:

  function getFlightDetailStruct(bytes32 _data)
    private
    pure
    returns (FlightDetail memory)
  {
    FlightDetail memory flightDetail = FlightDetail(
      uint8(bytes1(_data)),
      bytes3(_data << 8),
      bytes3(_data << 32),
      uint40(bytes5(_data << 56)),
      uint40(bytes5(_data << 96)),
      uint40(bytes5(_data << 136)),
      uint40(bytes5(_data << 176)),
      uint40(bytes5(_data << 216))
    );
    return flightDetail;
  }

You just need some masking in addition to byte shifts. E.g. to get the 0x2233 part out of bytes4 x = 0x11223344 you’d do: (x && 0x00ffff00) >> 8. Or you can get a similar effect by shifting left and then right: (x << 8) >> 16.

In the example you pasted the type conversion does the job of that second shift. That’s because fixed bytes are left-aligned and uints are right-aligned. Switching from one to the other shifts the content. To ilustrate:

x                                      | 0x11223344
x << 8                                 | 0x22334400
bytes2(x << 8)                         | 0x2233
uint16(bytes2(x << 8))                 |     0x2233
uint32(uint16(bytes2(x << 8)))         | 0x00002233
bytes4(uint32(uint16(bytes2(x << 8)))) | 0x00002233
1 Like