Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Potential improvements to TypedData #55671

Open
FireSourcery opened this issue May 8, 2024 · 0 comments
Open

Potential improvements to TypedData #55671

FireSourcery opened this issue May 8, 2024 · 0 comments
Labels
area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. library-typed-data type-enhancement A request for a change that isn't a bug

Comments

@FireSourcery
Copy link

  1. Unified "view as" interface on ByteData or ByteBuffer

At this time, as[Typed]List view functions are associated to ByteBuffer, and get[Typed]Int values functions are associated to ByteData. (Some optimization requirement is behind this?)

To implement the most general interface, accept any sequence of bytes, one would do either:

  onBytes(TypedData bytes, ...) {...}  
  onByteBuffer(ByteBuffer bytes, int offset, ...) {..} // or ByteBuffer with an offset

 // further conversion prompts 2 inputs for offset, as well as this intermediate step. Not so fluid...
  int toInt() => buffer.asByteData([offset]).getInt64([offset], endian);

Perhaps the most fitting would be to include the ByteData interface as a default interface in ByteBuffer. It seems more intuitive ByteBuffer holds a default get/set interface for accessing its contents, as well as contain the entirety of conversions. Homogenous list views can be views.

A work around for now

extension ByteBufferData on ByteBuffer {
  int wordAt<R extends NativeType>(int byteOffset, [Endian endian = Endian.little]) => asByteData().wordAt<R>(byteOffset, endian);
  int? wordAtOrNull<R extends NativeType>(int byteOffset, [Endian endian = Endian.little]) => asByteData().wordAtOrNull<R>(byteOffset, endian);
  void setWordAt<R extends NativeType>(int byteOffset, int value, [Endian endian = Endian.little]) => asByteData().setWordAt<R>(byteOffset, value, endian);
}

extension GenericWord on ByteData {

  int wordAt<R extends NativeType>(int byteOffset, [Endian endian = Endian.little]) {
    return switch (R) {
      const (Int8) => getInt8(byteOffset),
      const (Int16) => getInt16(byteOffset, endian),
      const (Int32) => getInt32(byteOffset, endian),
      const (Uint8) => getUint8(byteOffset),
      const (Uint16) => getUint16(byteOffset, endian),
      const (Uint32) => getUint32(byteOffset, endian),
      _ => throw UnimplementedError(),
    };
  }

  int? wordAtOrNull<R extends NativeType>(int byteOffset, [Endian endian = Endian.little]) {
    return (byteOffset + sizeOf<R>() <= lengthInBytes) ? wordAt<R>(byteOffset, endian) : null;
  }

  void setWordAt<R extends NativeType>(int byteOffset, int value, [Endian endian = Endian.little]) {
    return switch (R) {
      const (Int8) => setInt8(byteOffset, value),
      const (Int16) => setInt16(byteOffset, value, endian),
      const (Int32) => setInt32(byteOffset, value, endian),
      const (Uint8) => setUint8(byteOffset, value),
      const (Uint16) => setUint16(byteOffset, value, endian),
      const (Uint32) => setUint32(byteOffset, value, endian),
      _ => throw UnimplementedError(),
    };
  } 
}
  1. _TypedIntList endian conversion support.

While lists constructed on the host platform and then read on the host platform is of no consequence to endianess. Handing network data would find a library implementation to be an asset.

something of the following nature, maybe not efficient, but correctness takes precedence.

  List<int> _sublistView<R extends TypedData>([int typedOffset = 0]) {
    return switch (R) {
      const (Uint8List) => Uint8List.sublistView(this, typedOffset),
      const (Uint16List) => Uint16List.sublistView(this, typedOffset),
      const (Uint32List) => Uint32List.sublistView(this, typedOffset),
      const (Int8List) => Int8List.sublistView(this, typedOffset),
      const (Int16List) => Int16List.sublistView(this, typedOffset),
      const (Int32List) => Int32List.sublistView(this, typedOffset), 
      _ => throw UnimplementedError(),
    };
  }
 
  List<int> _castList<R extends TypedData>(Endian endian, [int typedOffset = 0]) {
    return EndianCastList<R>(this, endian);
  }

  static Endian hostEndian = Endian.host; // resolve once storing results

  List<int> sublistView<R extends TypedData>([int typedOffset = 0, Endian endian = Endian.little]) {
    return ((hostEndian != endian) && (R != Uint8List) && (R != Int8List)) ? _castList<R>(endian, typedOffset) : _sublistView<R>(typedOffset);
  }

class EndianCastList<R extends TypedData> extends ListBase<int> {
  EndianCastList(this._source, this._endian);

  TypedData _source;
  Endian _endian;

  @override
  int get length => _source.lengthInBytes ~/ _source.elementSizeInBytes; 

  @override
  int operator [](int index) {
    final byteData = ByteData.sublistView(_source);
    return switch (R) {
      const (Uint16List) => byteData.getUint16(index * _source.elementSizeInBytes, _endian), 
      ... 
    };
  }
 
}
  1. Generic interface
    Something as exemplified above using existing type markers, streamline dependencies which use multiple types.

  2. Documentation duplication.
    This does seem quite trivial, and I considered omitting the thought. But I suppose food for thought. While we pay regards to code duplication, for the human side of maintenance, interpretation.. mass amounts of repeated documentation text (perhaps can be condense to a centralized description), by the same principle, could be obfuscating key takeaways.

@lrhn lrhn added area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. library-typed-data type-enhancement A request for a change that isn't a bug labels May 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. library-typed-data type-enhancement A request for a change that isn't a bug
Projects
None yet
Development

No branches or pull requests

2 participants