common.ts 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. import { Idl, IdlField, IdlTypeDef, IdlEnumVariant, IdlType } from "../idl.js";
  2. import { IdlError } from "../error.js";
  3. export function accountSize(idl: Idl, idlAccount: IdlTypeDef): number {
  4. if (idlAccount.type.kind === "enum") {
  5. let variantSizes = idlAccount.type.variants.map(
  6. (variant: IdlEnumVariant) => {
  7. if (variant.fields === undefined) {
  8. return 0;
  9. }
  10. return variant.fields
  11. .map((f: IdlField | IdlType) => {
  12. if (!(typeof f === "object" && "name" in f)) {
  13. throw new Error("Tuple enum variants not yet implemented.");
  14. }
  15. return typeSize(idl, f.type);
  16. })
  17. .reduce((a: number, b: number) => a + b);
  18. }
  19. );
  20. return Math.max(...variantSizes) + 1;
  21. }
  22. if (idlAccount.type.fields === undefined) {
  23. return 0;
  24. }
  25. return idlAccount.type.fields
  26. .map((f) => typeSize(idl, f.type))
  27. .reduce((a, b) => a + b, 0);
  28. }
  29. // Returns the size of the type in bytes. For variable length types, just return
  30. // 1. Users should override this value in such cases.
  31. function typeSize(idl: Idl, ty: IdlType): number {
  32. switch (ty) {
  33. case "bool":
  34. return 1;
  35. case "u8":
  36. return 1;
  37. case "i8":
  38. return 1;
  39. case "i16":
  40. return 2;
  41. case "u16":
  42. return 2;
  43. case "u32":
  44. return 4;
  45. case "i32":
  46. return 4;
  47. case "u64":
  48. return 8;
  49. case "i64":
  50. return 8;
  51. case "u128":
  52. return 16;
  53. case "i128":
  54. return 16;
  55. case "bytes":
  56. return 1;
  57. case "string":
  58. return 1;
  59. case "publicKey":
  60. return 32;
  61. default:
  62. if ("vec" in ty) {
  63. return 1;
  64. }
  65. if ("option" in ty) {
  66. return 1 + typeSize(idl, ty.option);
  67. }
  68. if ("coption" in ty) {
  69. return 4 + typeSize(idl, ty.coption);
  70. }
  71. if ("defined" in ty) {
  72. const filtered = idl.types?.filter((t) => t.name === ty.defined) ?? [];
  73. if (filtered.length !== 1) {
  74. throw new IdlError(`Type not found: ${JSON.stringify(ty)}`);
  75. }
  76. let typeDef = filtered[0];
  77. return accountSize(idl, typeDef);
  78. }
  79. if ("array" in ty) {
  80. let arrayTy = ty.array[0];
  81. let arraySize = ty.array[1];
  82. return typeSize(idl, arrayTy) * arraySize;
  83. }
  84. throw new Error(`Invalid type ${JSON.stringify(ty)}`);
  85. }
  86. }