feat: improve get_args functions

This commit is contained in:
max_richter 2024-04-23 03:41:28 +02:00
parent c87d4b8dda
commit 98cf2e8369
20 changed files with 270 additions and 147 deletions

View File

@ -241,7 +241,7 @@ export class GraphManager extends EventEmitter<{ "save": Graph, "result": any, "
let settingId = nodeType.inputs[key].setting; let settingId = nodeType.inputs[key].setting;
if (settingId) { if (settingId) {
settingTypes[settingId] = nodeType.inputs[key]; settingTypes[settingId] = nodeType.inputs[key];
if (settingValues[settingId] === undefined && "value" in type.inputs[key]) { if (settingValues[settingId] === undefined && "value" in nodeType.inputs[key]) {
settingValues[settingId] = nodeType.inputs[key].value; settingValues[settingId] = nodeType.inputs[key].value;
} }
} }

View File

@ -1,11 +1,13 @@
<script lang="ts"> <script lang="ts">
import { T } from "@threlte/core"; import { T } from "@threlte/core";
import { Text } from "@threlte/extras"; import { MeshLineGeometry, MeshLineMaterial, Text } from "@threlte/extras";
import type { BufferGeometry } from "three"; import type { BufferGeometry, Vector3 } from "three";
import { OrbitControls } from "@threlte/extras"; import { OrbitControls } from "@threlte/extras";
import { AppSettings } from "../settings/app-settings"; import { AppSettings } from "../settings/app-settings";
export let geometry: BufferGeometry[]; export let geometries: BufferGeometry[];
export let lines: Vector3[][];
$: console.log({ geometries, lines });
function getPosition(geo: BufferGeometry, i: number) { function getPosition(geo: BufferGeometry, i: number) {
const pos = [ const pos = [
@ -21,6 +23,16 @@
<T.GridHelper args={[20, 20]} /> <T.GridHelper args={[20, 20]} />
{/if} {/if}
{#if lines}
{#each lines as line}
<T.Mesh>
<MeshLineGeometry points={line} />
<MeshLineMaterial width={0.1} depthTest={false} />
</T.Mesh>
{/each}
{/if}
<T.PerspectiveCamera position={[-10, 10, 10]} makeDefault fov={50}> <T.PerspectiveCamera position={[-10, 10, 10]} makeDefault fov={50}>
<OrbitControls /> <OrbitControls />
</T.PerspectiveCamera> </T.PerspectiveCamera>
@ -28,7 +40,7 @@
<T.DirectionalLight position={[0, 10, 10]} /> <T.DirectionalLight position={[0, 10, 10]} />
<T.AmbientLight intensity={0.5} /> <T.AmbientLight intensity={0.5} />
{#each geometry as geo} {#each geometries as geo}
{#if $AppSettings.showIndices} {#if $AppSettings.showIndices}
{#each geo.attributes.position.array as _, i} {#each geo.attributes.position.array as _, i}
{#if i % 3 === 0} {#if i % 3 === 0}

View File

@ -1,11 +1,13 @@
<script lang="ts"> <script lang="ts">
import { Canvas } from "@threlte/core"; import { Canvas } from "@threlte/core";
import Scene from "./Scene.svelte"; import Scene from "./Scene.svelte";
import { BufferGeometry, Float32BufferAttribute } from "three"; import { BufferGeometry, Float32BufferAttribute, Vector3 } from "three";
import { decodeFloat } from "@nodes/utils";
export let result: Int32Array; export let result: Int32Array;
let geometries: BufferGeometry[] = []; let geometries: BufferGeometry[] = [];
let lines: Vector3[][] = [];
function createGeometryFromEncodedData( function createGeometryFromEncodedData(
encodedData: Int32Array, encodedData: Int32Array,
@ -90,9 +92,34 @@
return res; return res;
} }
globalThis.parse_args = parse_args;
function createLineGeometryFromEncodedData(encodedData: Int32Array) {
const positions: Vector3[] = [];
const amount = (encodedData.length - 1) / 4;
for (let i = 0; i < amount; i++) {
const x = decodeFloat(encodedData[1 + i * 4 + 0]);
const y = decodeFloat(encodedData[1 + i * 4 + 1]);
const z = decodeFloat(encodedData[1 + i * 4 + 2]);
positions.push(new Vector3(x, y, z));
}
return positions;
}
$: if (result) { $: if (result) {
const inputs = parse_args(result); const inputs = parse_args(result);
lines = inputs
.map((input) => {
if (input[0] === 0) {
return createLineGeometryFromEncodedData(input);
}
})
.filter(Boolean) as Vector3[][];
geometries = inputs geometries = inputs
.map((input) => { .map((input) => {
if (input[0] === 1) { if (input[0] === 1) {
@ -101,9 +128,11 @@
} }
}) })
.filter(Boolean) as BufferGeometry[]; .filter(Boolean) as BufferGeometry[];
console.log(lines);
} }
</script> </script>
<Canvas> <Canvas>
<Scene geometry={geometries} /> <Scene {geometries} {lines} />
</Canvas> </Canvas>

View File

@ -150,7 +150,12 @@ export class MemoryRuntimeExecutor implements RuntimeExecutor {
} }
// if the input is not connected to another node, we use the value from the node itself // if the input is not connected to another node, we use the value from the node itself
inputs[key] = node.props?.[key] ?? input?.value; let value = node.props?.[key] ?? input?.value;
if (Array.isArray(value)) {
inputs[key] = [0, value.length + 1, ...value, 1, 1];
} else {
inputs[key] = value;
}
} }
@ -191,10 +196,6 @@ export class MemoryRuntimeExecutor implements RuntimeExecutor {
return encodeFloat(value as number); return encodeFloat(value as number);
} }
if (Array.isArray(value)) {
return encodeNestedArray(value);
}
return value; return value;
}); });
@ -204,13 +205,14 @@ export class MemoryRuntimeExecutor implements RuntimeExecutor {
// console.log(`${a2 - a1}ms TRANSFORMED_INPUTS`); // console.log(`${a2 - a1}ms TRANSFORMED_INPUTS`);
const encoded_inputs = encodeNestedArray(transformed_inputs); const encoded_inputs = concatEncodedArrays(transformed_inputs);
const a3 = performance.now(); const a3 = performance.now();
console.groupCollapsed(`executing ${node_type.id || node.id}`); console.groupCollapsed(`executing ${node_type.id || node.id}`);
console.log(`Inputs:`, transformed_inputs); console.log(`Inputs:`, transformed_inputs);
console.log(`Encoded Inputs:`, encoded_inputs); console.log(`Encoded Inputs:`, encoded_inputs);
results[node.id] = node_type.execute(encoded_inputs); results[node.id] = node_type.execute(encoded_inputs);
console.log("Result:", decodeNestedArray(results[node.id])); console.log("Result:", results[node.id]);
console.log("Result (decoded):", decodeNestedArray(results[node.id]));
console.groupEnd(); console.groupEnd();
const duration = performance.now() - a3; const duration = performance.now() - a3;
if (duration > 5) { if (duration > 5) {

View File

@ -14,7 +14,7 @@
<div class="command-wrapper"> <div class="command-wrapper">
<div class="command"> <div class="command">
{#if key.ctrl} {#if key.ctrl}
<span>Ctrl + </span> <span>Ctrl</span>
{/if} {/if}
{#if key.shift} {#if key.shift}
<span>Shift</span> <span>Shift</span>
@ -22,7 +22,7 @@
{#if key.alt} {#if key.alt}
<span>Alt</span> <span>Alt</span>
{/if} {/if}
<span>{key.key}</span> {key.key}
</div> </div>
</div> </div>
<p>{key.description}</p> <p>{key.description}</p>
@ -69,4 +69,9 @@
display: flex; display: flex;
align-items: center; align-items: center;
} }
span::after {
content: " +";
opacity: 0.5;
}
</style> </style>

View File

@ -1,4 +1,5 @@
<script lang="ts"> <script lang="ts">
import localStore from "$lib/helpers/localStore";
import type { NodeInput } from "@nodes/types"; import type { NodeInput } from "@nodes/types";
import Input from "@nodes/ui"; import Input from "@nodes/ui";
import type { Writable } from "svelte/store"; import type { Writable } from "svelte/store";
@ -7,6 +8,13 @@
[key: string]: Nested | NodeInput; [key: string]: Nested | NodeInput;
} }
export let id: string;
$: expandedDetails = localStore<Record<string, boolean>>(
`nodes.settings.expanded.${id}`,
{},
);
export let settings: Nested; export let settings: Nested;
export let store: Writable<Record<string, any>>; export let store: Writable<Record<string, any>>;
export let depth = 0; export let depth = 0;
@ -36,7 +44,11 @@
{/if} {/if}
</div> </div>
{:else} {:else}
<details> {#if depth > 0}
<hr />
{/if}
<details bind:open={$expandedDetails[key]}>
<summary>{settings[key]?.__title || key}</summary> <summary>{settings[key]?.__title || key}</summary>
<div class="content"> <div class="content">
<svelte:self settings={settings[key]} {store} depth={depth + 1} /> <svelte:self settings={settings[key]} {store} depth={depth + 1} />
@ -50,11 +62,11 @@
summary { summary {
cursor: pointer; cursor: pointer;
user-select: none; user-select: none;
margin-bottom: 1em;
} }
details { details {
padding: 1rem; padding: 1em;
box-sizing: border-box; padding-bottom: 0;
border-bottom: solid thin var(--outline);
} }
.input { .input {
@ -69,6 +81,7 @@
.input-boolean { .input-boolean {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center;
} }
.input-boolean > label { .input-boolean > label {
order: 2; order: 2;
@ -84,4 +97,12 @@
.first-level > details { .first-level > details {
border: none; border: none;
} }
hr {
position: absolute;
margin: 0;
left: 0;
right: 0;
border: none;
border-bottom: solid thin var(--outline);
}
</style> </style>

View File

@ -90,6 +90,7 @@
{:else} {:else}
<div class="flex flex-col"> <div class="flex flex-col">
<NestedSettings <NestedSettings
id={$activePanel}
settings={constructNested(panels[$activePanel])} settings={constructNested(panels[$activePanel])}
store={panels[$activePanel].settings} store={panels[$activePanel].settings}
/> />
@ -125,6 +126,7 @@
.content { .content {
background: var(--layer-1); background: var(--layer-1);
position: relative;
} }
.tabs { .tabs {

View File

@ -47,22 +47,6 @@ export const AppSettingTypes = {
value: true value: true
} }
}, },
stressTest: {
__title: "Stress Test",
amount: {
type: "integer",
min: 2,
max: 15
},
loadGrid: {
type: "button",
label: "Load Grid"
},
loadTree: {
type: "button",
label: "Load Tree"
},
},
debug: { debug: {
wireframe: { wireframe: {
type: "boolean", type: "boolean",
@ -74,6 +58,22 @@ export const AppSettingTypes = {
label: "Show Indices", label: "Show Indices",
value: false, value: false,
}, },
stressTest: {
__title: "Stress Test",
amount: {
type: "integer",
min: 2,
max: 15
},
loadGrid: {
type: "button",
label: "Load Grid"
},
loadTree: {
type: "button",
label: "Load Tree"
},
},
} }
} }

View File

@ -14,12 +14,13 @@
import NodeStore from "$lib/node-store/NodeStore.svelte"; import NodeStore from "$lib/node-store/NodeStore.svelte";
import type { GraphManager } from "$lib/graph-interface/graph-manager"; import type { GraphManager } from "$lib/graph-interface/graph-manager";
import { setContext } from "svelte"; import { setContext } from "svelte";
import { decodeNestedArray } from "@nodes/utils"; import { decodeNestedArray, encodeNestedArray } from "@nodes/utils";
const nodeRegistry = new RemoteNodeRegistry(""); const nodeRegistry = new RemoteNodeRegistry("");
const runtimeExecutor = new MemoryRuntimeExecutor(nodeRegistry); const runtimeExecutor = new MemoryRuntimeExecutor(nodeRegistry);
globalThis.decode = decodeNestedArray; globalThis.decode = decodeNestedArray;
globalThis.encode = encodeNestedArray;
let res: Int32Array; let res: Int32Array;
@ -82,15 +83,17 @@
types: Record<string, unknown>; types: Record<string, unknown>;
}>, }>,
) { ) {
settings.general.definition.stressTest.loadGrid.callback = function () { settings.general.definition.debug.stressTest.loadGrid.callback =
const store = get(settings.general.settings); function () {
graph = templates.grid(store.amount, store.amount); const store = get(settings.general.settings);
}; graph = templates.grid(store.amount, store.amount);
};
settings.general.definition.stressTest.loadTree.callback = function () { settings.general.definition.debug.stressTest.loadTree.callback =
const store = get(settings.general.settings); function () {
graph = templates.tree(store.amount); const store = get(settings.general.settings);
}; graph = templates.tree(store.amount);
};
settings.graph = { settings.graph = {
icon: "i-tabler-chart-bar", icon: "i-tabler-chart-bar",

View File

@ -1,18 +1,12 @@
use macros::include_definition_file; use macros::include_definition_file;
use utils::{concat_args, get_args, set_panic_hook};
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
include_definition_file!("src/input.json"); include_definition_file!("src/input.json");
#[wasm_bindgen] #[wasm_bindgen]
pub fn execute(args: &[i32]) -> Vec<i32> { pub fn execute(args: &[i32]) -> Vec<i32> {
let mut result = Vec::with_capacity(args.len() + 3); set_panic_hook();
result.push(0); // encoding the [ bracket let args = get_args(args);
result.push(args[1] + 1); concat_args(vec![&[0], args[0], args[1], args[2]])
result.push(0); // adding the node-type, math: 0
result.extend_from_slice(&args[2..]);
result.push(1);
result.push(1); // closing bracket
result
} }

View File

@ -13,13 +13,14 @@ include_definition_file!("src/inputs.json");
pub fn execute(input: &[i32]) -> Vec<i32> { pub fn execute(input: &[i32]) -> Vec<i32> {
utils::set_panic_hook(); utils::set_panic_hook();
log!("output input: {:?}", input);
let args = get_args(input); let args = get_args(input);
log!("output args: {:?}", args); log!("output args: {:?}", args);
let inputs = get_args(args[0]); let inputs = get_args(args[0]);
log!("output inputs: {:?}", inputs);
let resolution = evaluate_int(args[1]) as usize; let resolution = evaluate_int(args[1]) as usize;
log!("inputs: {}, resolution: {}", inputs.len(), resolution); log!("inputs: {}, resolution: {}", inputs.len(), resolution);
@ -30,16 +31,14 @@ pub fn execute(input: &[i32]) -> Vec<i32> {
continue; continue;
} }
let arg_type = arg[0]; let arg_type = arg[2];
log!("arg: {:?}", arg);
if arg_type == 0 { if arg_type == 0 {
// this is stem // this is stem
let _arg = &arg[3..]; let stem = &arg[2..arg.len() - 2];
let mut geometry = extrude_path(_arg, resolution); output.push(arg.to_vec());
let matrix = Mat4::from_translation(Vec3::new(0.0, 0.0, 0.0)); let geometry = extrude_path(stem, resolution);
geometry = transform_geometry(geometry, matrix); log!("geometry: {:?}", geometry);
output.push(geometry); output.push(geometry);
} else if arg_type == 1 { } else if arg_type == 1 {
// this is geometry // this is geometry
@ -47,5 +46,5 @@ pub fn execute(input: &[i32]) -> Vec<i32> {
} }
} }
concat_args(output) concat_args(output.iter().map(|v| v.as_slice()).collect())
} }

View File

@ -10,27 +10,40 @@ pub fn execute(input: &[i32]) -> Vec<i32> {
let args = get_args(input); let args = get_args(input);
log!("node-stem: {:?}", args); log!("stem args: {:?}", args);
let origin = evaluate_vec3(args[0]); let origin = evaluate_vec3(args[0]);
let length = evaluate_float(args[1]); let length = evaluate_float(args[1]);
let thickness = evaluate_float(args[2]); let thickness = evaluate_float(args[2]);
let res_curve = evaluate_int(args[3]) as usize; let res_curve = evaluate_int(args[3]) as usize;
log!("origin: {:?}", origin); log!(
"origin: {:?} length: {} thickness: {} res_curve: {}",
origin,
length,
thickness,
res_curve
);
let amount_points = res_curve * 4; let amount_points = res_curve * 4;
// +4 for opening and closing brackets and +1 node-type // +4 for opening and closing brackets and +1 node-type
let output_size = amount_points + 5; let output_size = amount_points + 9;
// because we could potentially return multiple stems
// we need to encode two pairs of brackets
//
let mut path: Vec<i32> = vec![0; output_size]; let mut path: Vec<i32> = vec![0; output_size];
path[0] = 0; // encode opening bracket path[0] = 0; // encode opening bracket
path[1] = res_curve as i32 * 4 + 4; // encode opening bracket path[1] = 1; // encode opening bracket
path[2] = 0; // encode node-type, stem: 0 path[2] = 0; // encode opening bracket
path[3] = res_curve as i32 * 4 + 2; // encode opening bracket
path[4] = 0; // encode node-type, stem: 0
path[output_size - 4] = 1; // encode closing bracket
path[output_size - 3] = 1; // encode closing bracket
path[output_size - 2] = 1; // encode closing bracket path[output_size - 2] = 1; // encode closing bracket
path[output_size - 1] = 1; // encode closing bracket path[output_size - 1] = 1; // encode closing bracket
let slice = &mut path[3..output_size - 2]; let slice = &mut path[5..5 + amount_points];
let path_p: &mut [f32] = unsafe { let path_p: &mut [f32] = unsafe {
assert_eq!(slice.len() % 4, 0); assert_eq!(slice.len() % 4, 0);

View File

@ -1,9 +1,13 @@
use macros::include_definition_file; use macros::include_definition_file;
use utils::{concat_args, get_args, log};
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
include_definition_file!("src/input.json"); include_definition_file!("src/input.json");
#[wasm_bindgen] #[wasm_bindgen]
pub fn execute(input: &[i32]) -> Vec<i32> { pub fn execute(input: &[i32]) -> Vec<i32> {
input.to_vec() let args = get_args(input);
log!("vec3 input: {:?}", input);
log!("vec3 args: {:?}", args);
concat_args(args)
} }

View File

@ -32,7 +32,7 @@ export const NodeInputIntegerSchema = z.object({
export const NodeInputBooleanSchema = z.object({ export const NodeInputBooleanSchema = z.object({
...DefaultOptionsSchema.shape, ...DefaultOptionsSchema.shape,
type: z.literal("boolean"), type: z.literal("boolean"),
vale: z.boolean().optional(), value: z.boolean().optional(),
}); });
export const NodeInputSelectSchema = z.object({ export const NodeInputSelectSchema = z.object({

View File

@ -9,11 +9,23 @@ test("it correctly concats nested arrays", () => {
const output = concatEncodedArrays([input_a, input_b, input_c]); const output = concatEncodedArrays([input_a, input_b, input_c]);
console.log("Output", output);
const decoded = decodeNestedArray(output); const decoded = decodeNestedArray(output);
expect(decoded[0]).toEqual([1, 2, 3]); expect(decoded[0]).toEqual([1, 2, 3]);
expect(decoded[1]).toEqual(2);
expect(decoded[2]).toEqual([4, 5, 6]);
});
test("it correctly concats nested arrays with nested arrays", () => {
const input_c = encodeNestedArray([1, 2, 3]);
const output = concatEncodedArrays([42, 12, input_c]);
const decoded = decodeNestedArray(output);
expect(decoded[0]).toEqual(42);
expect(decoded[1]).toEqual(12);
expect(decoded[2]).toEqual([1, 2, 3]);
}); });
// Original test case // Original test case

View File

@ -14,11 +14,6 @@ export function concatEncodedArrays(input: (number | number[])[]): number[] {
const item = input[i]; const item = input[i];
if (Array.isArray(item)) { if (Array.isArray(item)) {
result.push(...item); result.push(...item);
if (item.length > 2) {
if (item[item.length - 2] !== 1 && item[item.length - 1] !== 1) {
result.push(1, 1); // add closing bracket if missing
}
}
last_closing_bracket = result.length - 1; last_closing_bracket = result.length - 1;
} else { } else {
result[last_closing_bracket]++; result[last_closing_bracket]++;
@ -46,8 +41,10 @@ export function encodeNestedArray(array: SparseArray): number[] {
encoded.push(0, 1, 1, 1); encoded.push(0, 1, 1, 1);
} else { } else {
// Recursively encode non-empty arrays // Recursively encode non-empty arrays
console.log("recursing", item);
const child = encodeNestedArray(item); const child = encodeNestedArray(item);
encoded.push(...child, 1, 0); console.log("recursed", child);
encoded.push(...child);
} }
// Update missingBracketIndex to the position of the newly added bracket // Update missingBracketIndex to the position of the newly added bracket
missingBracketIndex = encoded.length - 1; missingBracketIndex = encoded.length - 1;
@ -57,8 +54,10 @@ export function encodeNestedArray(array: SparseArray): number[] {
// Update the distance for the last opened bracket // Update the distance for the last opened bracket
if (missingBracketIndex) encoded[missingBracketIndex] = index + 2; if (missingBracketIndex) encoded[missingBracketIndex] = index + 2;
} }
console.log(encoded, item);
} }
return encoded;
return [...encoded, 1, 1];
}; };
function decode_recursive(dense: number[] | Int32Array, index = 0) { function decode_recursive(dense: number[] | Int32Array, index = 0) {

View File

@ -1,5 +1,3 @@
use crate::log;
use super::{create_geometry_data, wrap_geometry_data}; use super::{create_geometry_data, wrap_geometry_data};
use glam::{Mat4, Quat, Vec3}; use glam::{Mat4, Quat, Vec3};

View File

@ -15,6 +15,12 @@ pub fn create_geometry_data(vertex_amount: usize, face_amount: usize) -> Vec<i32
let mut geo = vec![0; amount]; let mut geo = vec![0; amount];
log!(
"create_geometry_data: vertices: {} faces: {}",
vertex_amount,
face_amount
);
geo[0] = 0; // opening bracket geo[0] = 0; // opening bracket
geo[1] = amount as i32 - 2; // opening bracket geo[1] = amount as i32 - 2; // opening bracket
geo[2] = 1; // type: geometry geo[2] = 1; // type: geometry
@ -44,13 +50,6 @@ pub fn wrap_geometry_data(geometry: &mut [i32]) -> GeometryData {
let (positions_slice, rest) = rest.split_at_mut(vertices_amount * 3); let (positions_slice, rest) = rest.split_at_mut(vertices_amount * 3);
let (normals_slice, _) = rest.split_at_mut(vertices_amount * 3); let (normals_slice, _) = rest.split_at_mut(vertices_amount * 3);
log!(
"Vertices: {}, normals: {}, Total floats: {}",
positions_slice.len(),
normals_slice.len(),
total_floats
);
assert!( assert!(
positions_slice.len() + normals_slice.len() == total_floats, positions_slice.len() + normals_slice.len() == total_floats,
"Slices do not match the expected sizes." "Slices do not match the expected sizes."

View File

@ -0,0 +1,18 @@
use utils::get_args;
#[rustfmt::skip]
fn main() {
let inputs = vec![
vec![0, 1, 0, 4, 1056964608, 1065353216, 1056964608, 1, 4, 1080872141, 1054951342, 32, 1, 1 ],
vec![0, 4, 1056964608, 1065353216, 1056964608, 1, 4],
vec![0, 1, 0, 3, 0, 0, 0, 5, 0, 0, 1073741824, 1073741824, 1, 1, 1, 1, 1, 4, 1065353216, 1054615798, 5, 1, 1 ],
vec![ 0, 1, 0, 3, 0, 0, 0, 1, 4, 1073741824, 1073741824, 32, 1, 1 ],
vec![0, 1, 0, 1, 0, 14, 0, 1056964608, 1056964608, 1056964608, 1058810102, 1056964608, 1069547520, 1056964608, 1050421494, 1056964608, 1075838976, 1056964608, 0, 1, 1, 1, 2, 13, 1, 1],
vec![ 0, 1, 0, 2, 0, 0, 5, 0, 0, 1073741824, 1073741824, 1, 2, 0, 1, 4, 1088212173, 1083388723, 20, 1, 1 ]
];
for input in inputs {
println!("RESULT: {:?}", get_args(&input));
}
}

View File

@ -1,90 +1,103 @@
use crate::decode_float; use crate::decode_float;
pub fn get_args(args: &[i32]) -> Vec<&[i32]> { pub fn get_args(args: &[i32]) -> Vec<&[i32]> {
let mut idx: usize = 0; println!("-------------------");
let mut depth = -1; println!("{:?}", args);
let mut next_bracket_index = 0;
let mut out_args: Vec<&[i32]> = Vec::new(); let mut out_args: Vec<&[i32]> = Vec::new();
let mut depth = 0;
let mut i = 0;
let mut start_index = 0;
let mut nbi = 0;
let len = args.len();
let length = args.len(); while i < len {
print!("{:2} ", i);
let mut arg_start_index = 2; let val = args[i];
let is_bracket = i == nbi;
while idx < length { let is_opening_bracket = val == 0;
let is_bracket = idx == next_bracket_index; if i >= len - 1 {
let value = args[idx];
// if we are at a bracket
if is_bracket {
// if we are at the end of the args
if idx >= length - 1 {
break;
}
next_bracket_index = 1 + idx + args[idx + 1] as usize;
if value == 0 {
depth += 1;
} else if value == 1 {
depth -= 1;
}
if depth == 0 {
if value == 1 {
out_args.push(&args[arg_start_index..idx]);
arg_start_index = idx + 2;
}
// skip over the bracket encoding
idx += 2;
} else {
// skip to the next bracket if we are at depth > 0
idx = next_bracket_index;
}
continue;
}
out_args.push(&args[arg_start_index..=idx]);
arg_start_index = idx + 1;
// this is at the end of args where normally multiple ] are encoded
if depth < 0 {
break; break;
} }
if is_bracket {
nbi = i + args[i + 1] as usize + 1;
if !is_opening_bracket {
depth -= 1;
}
}
idx += 1; for _ in 0..depth {
print!("-");
}
if is_bracket {
if is_opening_bracket {
if depth == 1 {
start_index = i;
}
println!("[ {}", start_index);
depth += 1;
} else {
println!("] {}", start_index);
if depth == 1 {
out_args.push(&args[start_index..i + 2]);
println!("-> {:?}", &args[start_index..i + 2]);
start_index = i + 2;
}
}
i += 2;
continue;
} else {
if depth == 1 {
out_args.push(&args[i..i + 1]);
println!("-> {:?}", &args[i..i + 1]);
start_index = i + 1;
} else {
println!("{}", val);
}
}
i += 1;
} }
out_args out_args
} }
pub fn concat_args(mut data: Vec<Vec<i32>>) -> Vec<i32> { pub fn concat_args(mut data: Vec<&[i32]>) -> Vec<i32> {
let mut total_length = 4; // Start with 4 to account for [0, 1] at the start and [1, 1] at the end let mut total_length = 4; // Start with 4 to account for [0, 1] at the start and [1, 1] at the end
// Calculate the total length first to avoid reallocations // Calculate the total length first to avoid reallocations
for vec in &data { for vec in &data {
total_length += vec.len(); // +4 for [0, 1] and [1, 1] per inner vec if vec.len() == 1 {
total_length += 1;
} else {
total_length += vec.len(); // +4 for [0, 1] and [1, 1] per inner vec
}
} }
let mut result = Vec::with_capacity(total_length); let mut result = Vec::with_capacity(total_length);
// Add [0, 1] initially // Add [0, 1] initially
// result.push(0); result.push(0);
// result.push(1); result.push(1);
let mut last_closing_bracket = 1;
// Process each vector // Process each vector
for vec in data.iter_mut() { for vec in data.iter_mut() {
result.push(0); if vec.len() == 1 {
result.push(1); result.push(vec[0]);
result.append(vec); result[last_closing_bracket] += 1;
result.push(1); continue;
result.push(1); } else {
result.extend_from_slice(vec);
last_closing_bracket = result.len() - 1;
result[last_closing_bracket] = 1;
}
} }
// Add [1, 1] at the end // Add [1, 1] at the end
// result.push(1); result.push(1);
result.push(1); result.push(1);
result result