substrate.c 1.7 KB

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