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

Improve JSDocs by adding examples of usages #1210

Merged
merged 4 commits into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 42 additions & 4 deletions src/utils/calldata/formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@ import { isBigInt } from '../num';
import { decodeShortString } from '../shortString';

const guard = {
/**
* Checks if the data is a BigInt (BN) and throws an error if not.
*
* @param {Record<string, any>} data - The data object containing the key to check.
* @param {Record<string, any>} type - The type definition object.
* @param {string} key - The key in the data object to check.
* @throws {Error} If the data type does not match the expected BigInt (BN) type.
*/
isBN: (data: Record<string, any>, type: Record<string, any>, key: string) => {
if (!isBigInt(data[key]))
throw new Error(
Expand All @@ -10,6 +18,15 @@ const guard = {
} to be BN instead it is ${typeof data[key]}`
);
},

/**
* Throws an error for unhandled formatter types.
*
* @param {Record<string, any>} data - The data object containing the key.
* @param {Record<string, any>} type - The type definition object.
* @param {string} key - The key in the data object to check.
* @throws {Error} If the formatter encounters an unknown type.
*/
unknown: (data: Record<string, any>, type: Record<string, any>, key: string) => {
throw new Error(`Unhandled formatter type on ${key}:${type[key]} for data ${key}:${data[key]}`);
},
Expand All @@ -18,16 +35,37 @@ const guard = {
/**
* Formats the given data based on the provided type definition.
*
* @param {any} data - The data to be formatted.
* @param {any} type - The type definition for the data.
* @param {Record<string, any>} data - The data to be formatted.
* @param {Record<string, any>} type - The type definition for the data.
* @param {any} [sameType] - The same type definition to be used (optional).
* @returns - The formatted data.
* @returns {Record<string, any>} The formatted data.
*
* @example
* // Example 1: Formatting a simple object
* const data = { value: '123', name: 'test' };
* const type = { value: 'number', name: 'string' };
* const formatted = formatter(data, type);
* // formatted: { value: 123, name: 'test' }
*
* @example
* // Example 2: Formatting an object with nested structures
* const data = { user: { id: '123', age: '30' }, active: '1' };
* const type = { user: { id: 'number', age: 'number' }, active: 'number' };
* const formatted = formatter(data, type);
* // formatted: { user: { id: 123, age: 30 }, active: 1 }
*
* @example
* // Example 3: Handling arrays in the data object
* const data = { items: ['1', '2', '3'], name: 'test' };
* const type = { items: ['number'], name: 'string' };
* const formatted = formatter(data, type);
* // formatted: { items: [1, 2, 3], name: 'test' }
*/
export default function formatter(
data: Record<string, any>,
type: Record<string, any>,
sameType?: any
) {
): Record<string, any> {
// match data element with type element
return Object.entries(data).reduce(
(acc, [key, value]: [any, any]) => {
Expand Down
53 changes: 50 additions & 3 deletions src/utils/calldata/tuple.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
/* eslint-disable no-plusplus */
import { isCairo1Type, isTypeNamedTuple } from './cairo';

/**
* Parse a named tuple string into an object containing its name and type.
* @param namedTuple - The named tuple string in the format "name:type".
* @returns An object with `name` and `type` properties.
*/
function parseNamedTuple(namedTuple: string): any {
const name = namedTuple.substring(0, namedTuple.indexOf(':'));
const type = namedTuple.substring(name.length + ':'.length);
return { name, type };
}

/**
* Parse a sub-tuple within a tuple string.
* @param s - The tuple string.
* @returns An object containing the sub-tuple array and the remaining string.
*/
function parseSubTuple(s: string) {
if (!s.includes('(')) return { subTuple: [], result: s };
const subTuple: string[] = [];
Expand Down Expand Up @@ -37,6 +47,11 @@ function parseSubTuple(s: string) {
};
}

/**
* Extract and parse a Cairo 0 tuple into its components.
* @param type - The Cairo 0 tuple string.
* @returns An array of tuple components or named tuple objects.
*/
function extractCairo0Tuple(type: string) {
const cleanType = type.replace(/\s/g, '').slice(1, -1); // remove first lvl () and spaces

Expand All @@ -58,6 +73,13 @@ function extractCairo0Tuple(type: string) {
return recomposed;
}

/**
* Get the offset of the closure in a string.
* @param input - The input string.
* @param open - The opening character (e.g., '(', '{').
* @param close - The closing character (e.g., ')', '}').
* @returns The offset of the closing character.
*/
function getClosureOffset(input: string, open: string, close: string): number {
for (let i = 0, counter = 0; i < input.length; i++) {
if (input[i] === open) {
Expand All @@ -69,6 +91,11 @@ function getClosureOffset(input: string, open: string, close: string): number {
return Number.POSITIVE_INFINITY;
}

/**
* Extract and parse a Cairo 1 tuple into its components.
RuneRogue marked this conversation as resolved.
Show resolved Hide resolved
* @param type - The Cairo 1 tuple string.
* @returns An array of tuple components as strings.
*/
function extractCairo1Tuple(type: string): string[] {
// un-named tuples support
const input = type.slice(1, -1); // remove first lvl ()
Expand Down Expand Up @@ -104,9 +131,29 @@ function extractCairo1Tuple(type: string): string[] {
}

/**
* Convert tuple string definition into object like definition
* @param type tuple string definition
* @returns object like tuple
* Convert a tuple string definition into an object-like definition.
* Supports both Cairo 0 and Cairo 1 tuple formats.
*
* @param type - The tuple string definition (e.g., "(u8, u8)" or "(x:u8, y:u8)").
* @returns An array of strings or objects representing the tuple components.
*
* @example
* // Cairo 0 Tuple
* const cairo0Tuple = "(u8, u8)";
* const result = extractTupleMemberTypes(cairo0Tuple);
* // result: ["u8", "u8"]
*
* @example
* // Named Cairo 0 Tuple
* const namedCairo0Tuple = "(x:u8, y:u8)";
* const namedResult = extractTupleMemberTypes(namedCairo0Tuple);
* // namedResult: [{ name: "x", type: "u8" }, { name: "y", type: "u8" }]
*
* @example
* // Cairo 1 Tuple
* const cairo1Tuple = "(core::result::Result::<u8, u8>, u8)";
* const cairo1Result = extractTupleMemberTypes(cairo1Tuple);
* // cairo1Result: ["core::result::Result::<u8, u8>", "u8"]
*/
export default function extractTupleMemberTypes(type: string): (string | object)[] {
if (isCairo1Type(type)) {
Expand Down