substrate.c 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. #include <stdint.h>
  2. #include <stddef.h>
  3. #include "stdlib.h"
  4. // 32 bit integer as as scale compact integer
  5. // https://docs.substrate.io/reference/scale-codec/#fn-1
  6. uint8_t *compact_encode_u32(uint8_t *dest, uint32_t val)
  7. {
  8. if (val < 64)
  9. {
  10. *dest++ = val << 2;
  11. }
  12. else if (val < 0x4000)
  13. {
  14. *((uint16_t *)dest) = (val << 2) | 1;
  15. dest += 2;
  16. }
  17. else if (val < 0x40000000)
  18. {
  19. *((uint32_t *)dest) = (val << 2) | 2;
  20. dest += 4;
  21. }
  22. else
  23. {
  24. *dest++ = 3;
  25. *((uint32_t *)dest) = val;
  26. dest += 4;
  27. }
  28. return dest;
  29. }
  30. uint8_t *compact_decode_u32(uint8_t *dest, uint32_t *val)
  31. {
  32. switch (*dest & 3)
  33. {
  34. case 0:
  35. *val = *dest >> 2;
  36. dest += 1;
  37. break;
  38. case 1:
  39. *val = *((uint16_t *)dest) >> 2;
  40. dest += 2;
  41. break;
  42. case 2:
  43. *val = *((uint32_t *)dest) >> 2;
  44. dest += 4;
  45. break;
  46. default:
  47. // sizes of 2**30 (1GB) or larger are not allowed
  48. __builtin_unreachable();
  49. }
  50. return dest;
  51. }
  52. uint8_t *scale_encode_string(uint8_t *dest, uint8_t *data, uint32_t len)
  53. {
  54. uint8_t *data_dst = compact_encode_u32(dest, len);
  55. while (len--)
  56. {
  57. *data_dst++ = *data++;
  58. }
  59. return data_dst;
  60. }
  61. struct vector *scale_decode_string(uint8_t **from)
  62. {
  63. uint8_t *src = *from;
  64. uint32_t size_array;
  65. src = compact_decode_u32(src, &size_array);
  66. struct vector *v = __malloc(sizeof(*v) + size_array);
  67. v->len = size_array;
  68. v->size = size_array;
  69. uint8_t *data = v->data;
  70. while (size_array--)
  71. {
  72. *data++ = *src++;
  73. }
  74. *from = src;
  75. return v;
  76. }