Skip to content

Instantly share code, notes, and snippets.

@mraleph
Last active May 5, 2025 14:00
Show Gist options
  • Select an option

  • Save mraleph/4eb5ccbb38904075141e to your computer and use it in GitHub Desktop.

Select an option

Save mraleph/4eb5ccbb38904075141e to your computer and use it in GitHub Desktop.
manual big endian conversion in Dart
library writer;
import 'dart:typed_data';
/// Writer wraps a fixed size Uint8List and writes values into it using
/// big-endian byte order.
class Writer {
/// Output buffer.
final Uint8List out;
/// Current position within [out].
var position = 0;
Writer._create(this.out);
factory Writer(size) {
final out = new Uint8List(size);
if (Endianness.HOST_ENDIAN == Endianness.LITTLE_ENDIAN) {
return new _WriterForLEHost._create(out);
} else {
return new _WriterForBEHost._create(out);
}
}
writeFloat64(double v);
writeFloat32(double v);
writeInt32(int v) {
out[position + 3] = v;
out[position + 2] = (v >> 8);
out[position + 1] = (v >> 16);
out[position + 0] = (v >> 24);
position += 4;
}
writeInt16(int v) {
out[position + 1] = v;
out[position + 0] = (v >> 8);
position += 2;
}
writeInt8(int v) {
out[position] = v;
position++;
}
writeString(String str) {
out.setAll(position, str.codeUnits);
position += str.codeUnits.length;
}
}
/// Lists used for data convertion (alias each other).
final Uint8List _convU8 = new Uint8List(8);
final Float32List _convF32 = new Float32List.view(_convU8.buffer);
final Float64List _convF64 = new Float64List.view(_convU8.buffer);
/// Writer used on little-endian host.
class _WriterForLEHost extends Writer {
_WriterForLEHost._create(out) : super._create(out);
writeFloat64(double v) {
_convF64[0] = v;
out[position + 7] = _convU8[0];
out[position + 6] = _convU8[1];
out[position + 5] = _convU8[2];
out[position + 4] = _convU8[3];
out[position + 3] = _convU8[4];
out[position + 2] = _convU8[5];
out[position + 1] = _convU8[6];
out[position + 0] = _convU8[7];
position += 8;
}
writeFloat32(double v) {
_convF32[0] = v;
out[position + 3] = _convU8[0];
out[position + 2] = _convU8[1];
out[position + 1] = _convU8[2];
out[position + 0] = _convU8[3];
position += 4;
}
}
/// Writer used on the big-endian host.
class _WriterForBEHost extends Writer {
_WriterForBEHost._create(out) : super._create(out);
writeFloat64(double v) {
_convF64[0] = v;
out[position + 0] = _convU8[0];
out[position + 1] = _convU8[1];
out[position + 2] = _convU8[2];
out[position + 3] = _convU8[3];
out[position + 4] = _convU8[4];
out[position + 5] = _convU8[5];
out[position + 6] = _convU8[6];
out[position + 7] = _convU8[7];
position += 8;
}
writeFloat32(double v) {
_convF32[0] = v;
out[position + 0] = _convU8[0];
out[position + 1] = _convU8[1];
out[position + 2] = _convU8[2];
out[position + 3] = _convU8[3];
position += 4;
}
}
@devfelipereis

devfelipereis commented Mar 8, 2021

Copy link
Copy Markdown

I'm trying to convert this hex "F8424660" to timestamp but without success. Can you give me some advice?
The expected value is: 1615217400

In fact I need to convert some hex values to int, float and so on. Using little endian.
I'm a beginner in dart and I'm little confused on how to do this.

@mraleph

mraleph commented Mar 8, 2021

Copy link
Copy Markdown
Author

@devfelipereis Well, good answer to your question depends on where and how you get this hex from. Are you getting hex value or are you getting a sequence of bytes from somewhere?

Well, 1615217400 is 604642f8 in hex, so F8424660 is a big endian version of this. You can reverse byte order manually, e.g.

  final value = int.parse('F8424660', radix: 16);
  final timestamp = (value & 0xFF) << 24 | (value & 0xFF00) << 8 | (value & 0xFF0000) >> 8 | (value & 0xFF000000) >> 24;
  print(timestamp); // => 1615217400

There is nothing too Dart specific here.

@devfelipereis

Copy link
Copy Markdown

@mraleph I'm getting something like this:

534D627480650300A201F84246600000F0420000F2420000F4420000803F000000400000404000007A4400002041005043470050C3466666663FCDCC4C3F3333333F00007042333333333333E33F9A9999999999D93F40016001200100E700E700E700E700E700E7B803BD03B30332

this data comes from a bluetooth device. Then I need to break this in parts and extract some informations.

Timestamp is in the position 20-28. Some values are float, some are int. What I need to do is get this values and parse to the correct type.

What should I study do understand how this conversions work? Thank you!

@mraleph

mraleph commented Mar 9, 2021

Copy link
Copy Markdown
Author

If you want to understand fundamentals then you should study how different types are represented in memory and have a grasp of things like big/little endian byte orders.

For parsing you can use ByteData class, it allows you to extract specific types from a sequence of bytes.

If data arrives to you as hex string you can convert it into a List<int> using hex codec from package:convert, after that you can create ByteData from it, e.g.

import 'dart:typed_data';
import 'package:convert/convert.dart';

void parse(String s) {
  // Convert hex from the given string to a sequence of bytes (first two characters become first byte and so on). 
  final bd = ByteData.sublistView(Uint8List.fromList(hex.decode(s)));
  print(bd.getInt32(10, Endian.little)); // print timestamp (should print  1615217400)
}

void main() {
  
 parse('534D627480650300A201F84246600000F0420000F2420000F4420000803F000000400000404000007A4400002041005043470050C3466666663FCDCC4C3F3333333F00007042333333333333E33F9A9999999999D93F40016001200100E700E700E700E700E700E7B803BD03B30332');
}

@devfelipereis

Copy link
Copy Markdown

@mraleph thank you so much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment