@@ -96,3 +96,348 @@ pub fn ArrayBasicTreeView(comptime ST: type) type {
9696 }
9797 };
9898}
99+
100+ const UintType = @import ("../type/uint.zig" ).UintType ;
101+ const FixedVectorType = @import ("../type/vector.zig" ).FixedVectorType ;
102+
103+ test "TreeView vector element roundtrip" {
104+ const allocator = std .testing .allocator ;
105+ var pool = try Node .Pool .init (allocator , 128 );
106+ defer pool .deinit ();
107+
108+ const Uint64 = UintType (64 );
109+ const VectorType = FixedVectorType (Uint64 , 4 );
110+
111+ const original : VectorType.Type = [_ ]u64 { 11 , 22 , 33 , 44 };
112+
113+ const root_node = try VectorType .tree .fromValue (& pool , & original );
114+ var view = try VectorType .TreeView .init (allocator , & pool , root_node );
115+ defer view .deinit ();
116+
117+ try std .testing .expectEqual (@as (u64 , 11 ), try view .get (0 ));
118+ try std .testing .expectEqual (@as (u64 , 44 ), try view .get (3 ));
119+
120+ try view .set (1 , 77 );
121+ try view .set (2 , 88 );
122+
123+ try view .commit ();
124+
125+ var expected = original ;
126+ expected [1 ] = 77 ;
127+ expected [2 ] = 88 ;
128+
129+ var expected_root : [32 ]u8 = undefined ;
130+ try VectorType .hashTreeRoot (& expected , & expected_root );
131+
132+ var actual_root : [32 ]u8 = undefined ;
133+ try view .hashTreeRoot (& actual_root );
134+
135+ try std .testing .expectEqualSlices (u8 , & expected_root , & actual_root );
136+
137+ var roundtrip : VectorType.Type = undefined ;
138+ try VectorType .tree .toValue (view .base_view .data .root , & pool , & roundtrip );
139+ try std .testing .expectEqualSlices (u64 , & expected , & roundtrip );
140+ }
141+
142+ test "TreeView vector getAll fills provided buffer" {
143+ const allocator = std .testing .allocator ;
144+ var pool = try Node .Pool .init (allocator , 256 );
145+ defer pool .deinit ();
146+
147+ const Uint32 = UintType (32 );
148+ const VectorType = FixedVectorType (Uint32 , 8 );
149+
150+ const values = [_ ]u32 { 9 , 8 , 7 , 6 , 5 , 4 , 3 , 2 };
151+ const root_node = try VectorType .tree .fromValue (& pool , & values );
152+ var view = try VectorType .TreeView .init (allocator , & pool , root_node );
153+ defer view .deinit ();
154+
155+ const out = try allocator .alloc (u32 , values .len );
156+ defer allocator .free (out );
157+
158+ const filled = try view .getAllInto (out );
159+ try std .testing .expectEqual (out .ptr , filled .ptr );
160+ try std .testing .expectEqual (out .len , filled .len );
161+ try std .testing .expectEqualSlices (u32 , values [0.. ], filled );
162+
163+ const wrong = try allocator .alloc (u32 , values .len - 1 );
164+ defer allocator .free (wrong );
165+ try std .testing .expectError (error .InvalidSize , view .getAllInto (wrong ));
166+ }
167+
168+ test "TreeView vector getAllAlloc roundtrip" {
169+ const allocator = std .testing .allocator ;
170+ var pool = try Node .Pool .init (allocator , 256 );
171+ defer pool .deinit ();
172+
173+ const Uint16 = UintType (16 );
174+ const VectorType = FixedVectorType (Uint16 , 5 );
175+ const values = [_ ]u16 { 3 , 1 , 4 , 1 , 5 };
176+
177+ const root_node = try VectorType .tree .fromValue (& pool , & values );
178+ var view = try VectorType .TreeView .init (allocator , & pool , root_node );
179+ defer view .deinit ();
180+
181+ const filled = try view .getAll (allocator );
182+ defer allocator .free (filled );
183+
184+ try std .testing .expectEqualSlices (u16 , values [0.. ], filled );
185+ }
186+
187+ test "TreeView vector getAllAlloc repeat reflects updates" {
188+ const allocator = std .testing .allocator ;
189+ var pool = try Node .Pool .init (allocator , 256 );
190+ defer pool .deinit ();
191+
192+ const Uint32 = UintType (32 );
193+ const VectorType = FixedVectorType (Uint32 , 6 );
194+ var values = [_ ]u32 { 10 , 20 , 30 , 40 , 50 , 60 };
195+
196+ const root_node = try VectorType .tree .fromValue (& pool , & values );
197+ var view = try VectorType .TreeView .init (allocator , & pool , root_node );
198+ defer view .deinit ();
199+
200+ const first = try view .getAll (allocator );
201+ defer allocator .free (first );
202+ try std .testing .expectEqualSlices (u32 , values [0.. ], first );
203+
204+ try view .set (3 , 99 );
205+
206+ const second = try view .getAll (allocator );
207+ defer allocator .free (second );
208+ values [3 ] = 99 ;
209+ try std .testing .expectEqualSlices (u32 , values [0.. ], second );
210+ }
211+
212+ test "TreeView vector clone isolates subsequent updates" {
213+ const allocator = std .testing .allocator ;
214+ var pool = try Node .Pool .init (allocator , 1024 );
215+ defer pool .deinit ();
216+
217+ const Uint16 = UintType (16 );
218+ const Vec4 = FixedVectorType (Uint16 , 4 );
219+
220+ const value : Vec4.Type = [_ ]u16 { 0 , 0 , 0 , 0 };
221+ const root = try Vec4 .tree .fromValue (& pool , & value );
222+
223+ var v1 = try Vec4 .TreeView .init (allocator , & pool , root );
224+ defer v1 .deinit ();
225+
226+ var v2 = try v1 .clone (.{});
227+ defer v2 .deinit ();
228+
229+ try v2 .set (1 , @as (u16 , 9 ));
230+ try v2 .commit ();
231+
232+ try std .testing .expectEqual (@as (u16 , 0 ), try v1 .get (1 ));
233+ try std .testing .expectEqual (@as (u16 , 9 ), try v2 .get (1 ));
234+ }
235+
236+ test "TreeView vector clone reads committed state" {
237+ const allocator = std .testing .allocator ;
238+ var pool = try Node .Pool .init (allocator , 1024 );
239+ defer pool .deinit ();
240+
241+ const Uint16 = UintType (16 );
242+ const Vec4 = FixedVectorType (Uint16 , 4 );
243+
244+ const value : Vec4.Type = [_ ]u16 { 0 , 0 , 0 , 0 };
245+ const root = try Vec4 .tree .fromValue (& pool , & value );
246+
247+ var v1 = try Vec4 .TreeView .init (allocator , & pool , root );
248+ defer v1 .deinit ();
249+
250+ try v1 .set (2 , @as (u16 , 7 ));
251+ try v1 .commit ();
252+
253+ var v2 = try v1 .clone (.{});
254+ defer v2 .deinit ();
255+
256+ try std .testing .expectEqual (@as (u16 , 7 ), try v2 .get (2 ));
257+ }
258+
259+ test "TreeView vector clone drops uncommitted changes" {
260+ const allocator = std .testing .allocator ;
261+ var pool = try Node .Pool .init (allocator , 1024 );
262+ defer pool .deinit ();
263+
264+ const Uint16 = UintType (16 );
265+ const Vec4 = FixedVectorType (Uint16 , 4 );
266+
267+ const value : Vec4.Type = [_ ]u16 { 1 , 2 , 3 , 4 };
268+ const root = try Vec4 .tree .fromValue (& pool , & value );
269+
270+ var v = try Vec4 .TreeView .init (allocator , & pool , root );
271+ defer v .deinit ();
272+
273+ try v .set (0 , @as (u16 , 9 ));
274+ try std .testing .expectEqual (@as (u16 , 9 ), try v .get (0 ));
275+
276+ var dropped = try v .clone (.{});
277+ defer dropped .deinit ();
278+
279+ try std .testing .expectEqual (@as (u16 , 1 ), try v .get (0 ));
280+ try std .testing .expectEqual (@as (u16 , 1 ), try dropped .get (0 ));
281+ }
282+
283+ test "TreeView vector clone(true) does not transfer cache" {
284+ const allocator = std .testing .allocator ;
285+ var pool = try Node .Pool .init (allocator , 1024 );
286+ defer pool .deinit ();
287+
288+ const Uint16 = UintType (16 );
289+ const Vec4 = FixedVectorType (Uint16 , 4 );
290+
291+ const value : Vec4.Type = [_ ]u16 { 1 , 2 , 3 , 4 };
292+ const root = try Vec4 .tree .fromValue (& pool , & value );
293+
294+ var v = try Vec4 .TreeView .init (allocator , & pool , root );
295+ defer v .deinit ();
296+
297+ _ = try v .get (0 );
298+ try std .testing .expect (v .base_view .data .children_nodes .count () > 0 );
299+
300+ var cloned_no_cache = try v .clone (.{ .transfer_cache = false });
301+ defer cloned_no_cache .deinit ();
302+
303+ try std .testing .expect (v .base_view .data .children_nodes .count () > 0 );
304+ try std .testing .expectEqual (@as (usize , 0 ), cloned_no_cache .base_view .data .children_nodes .count ());
305+ }
306+
307+ test "TreeView vector clone(false) transfers cache and clears source" {
308+ const allocator = std .testing .allocator ;
309+ var pool = try Node .Pool .init (allocator , 1024 );
310+ defer pool .deinit ();
311+
312+ const Uint16 = UintType (16 );
313+ const Vec4 = FixedVectorType (Uint16 , 4 );
314+
315+ const value : Vec4.Type = [_ ]u16 { 1 , 2 , 3 , 4 };
316+ const root = try Vec4 .tree .fromValue (& pool , & value );
317+
318+ var v = try Vec4 .TreeView .init (allocator , & pool , root );
319+ defer v .deinit ();
320+
321+ _ = try v .get (0 );
322+ try std .testing .expect (v .base_view .data .children_nodes .count () > 0 );
323+
324+ var cloned = try v .clone (.{});
325+ defer cloned .deinit ();
326+
327+ try std .testing .expectEqual (@as (usize , 0 ), v .base_view .data .children_nodes .count ());
328+ try std .testing .expect (cloned .base_view .data .children_nodes .count () > 0 );
329+ }
330+
331+ // Tests ported from TypeScript ssz packages/ssz/test/unit/byType/vector/tree.test.ts
332+ test "ArrayBasicTreeView - serialize (uint64 vector)" {
333+ const allocator = std .testing .allocator ;
334+
335+ const Uint64 = UintType (64 );
336+ const VecU64Type = FixedVectorType (Uint64 , 4 );
337+
338+ var pool = try Node .Pool .init (allocator , 1024 );
339+ defer pool .deinit ();
340+
341+ const TestCase = struct {
342+ id : []const u8 ,
343+ values : [4 ]u64 ,
344+ expected_serialized : []const u8 ,
345+ expected_root : [32 ]u8 ,
346+ };
347+
348+ const test_cases = [_ ]TestCase {
349+ .{
350+ .id = "4 values" ,
351+ .values = [4 ]u64 { 100000 , 200000 , 300000 , 400000 },
352+ // 0xa086010000000000400d030000000000e093040000000000801a060000000000
353+ .expected_serialized = &[_ ]u8 { 0xa0 , 0x86 , 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x40 , 0x0d , 0x03 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0xe0 , 0x93 , 0x04 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x80 , 0x1a , 0x06 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 },
354+ // For VectorBasic, the root is the same as the serialized bytes (fits in one chunk)
355+ .expected_root = [_ ]u8 { 0xa0 , 0x86 , 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x40 , 0x0d , 0x03 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0xe0 , 0x93 , 0x04 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x80 , 0x1a , 0x06 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 },
356+ },
357+ };
358+
359+ for (test_cases ) | tc | {
360+ const value = tc .values ;
361+
362+ var value_serialized : [VecU64Type .fixed_size ]u8 = undefined ;
363+ _ = VecU64Type .serializeIntoBytes (& value , & value_serialized );
364+
365+ const tree_node = try VecU64Type .tree .fromValue (& pool , & value );
366+ var view = try VecU64Type .TreeView .init (allocator , & pool , tree_node );
367+ defer view .deinit ();
368+
369+ var view_serialized : [VecU64Type .fixed_size ]u8 = undefined ;
370+ const written = try view .serializeIntoBytes (& view_serialized );
371+ try std .testing .expectEqual (view_serialized .len , written );
372+
373+ try std .testing .expectEqualSlices (u8 , tc .expected_serialized , & view_serialized );
374+ try std .testing .expectEqualSlices (u8 , & value_serialized , & view_serialized );
375+
376+ const view_size = view .serializedSize ();
377+ try std .testing .expectEqual (tc .expected_serialized .len , view_size );
378+
379+ var hash_root : [32 ]u8 = undefined ;
380+ try view .hashTreeRoot (& hash_root );
381+ try std .testing .expectEqualSlices (u8 , & tc .expected_root , & hash_root );
382+ }
383+ }
384+
385+ test "ArrayBasicTreeView - serialize (uint8 vector)" {
386+ const allocator = std .testing .allocator ;
387+
388+ const Uint8 = UintType (8 );
389+ const VecU8Type = FixedVectorType (Uint8 , 8 );
390+
391+ var pool = try Node .Pool .init (allocator , 1024 );
392+ defer pool .deinit ();
393+
394+ const value = [8 ]u8 { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 };
395+
396+ var value_serialized : [VecU8Type .fixed_size ]u8 = undefined ;
397+ _ = VecU8Type .serializeIntoBytes (& value , & value_serialized );
398+
399+ const tree_node = try VecU8Type .tree .fromValue (& pool , & value );
400+ var view = try VecU8Type .TreeView .init (allocator , & pool , tree_node );
401+ defer view .deinit ();
402+
403+ var view_serialized : [VecU8Type .fixed_size ]u8 = undefined ;
404+ const written = try view .serializeIntoBytes (& view_serialized );
405+ try std .testing .expectEqual (view_serialized .len , written );
406+
407+ try std .testing .expectEqualSlices (u8 , & value , & view_serialized );
408+
409+ const view_size = view .serializedSize ();
410+ try std .testing .expectEqual (@as (usize , 8 ), view_size );
411+ }
412+
413+ test "ArrayBasicTreeView - get and set" {
414+ const allocator = std .testing .allocator ;
415+
416+ const Uint64 = UintType (64 );
417+ const VecU64Type = FixedVectorType (Uint64 , 4 );
418+
419+ var pool = try Node .Pool .init (allocator , 1024 );
420+ defer pool .deinit ();
421+
422+ const value = [4 ]u64 { 100 , 200 , 300 , 400 };
423+ const tree_node = try VecU64Type .tree .fromValue (& pool , & value );
424+ var view = try VecU64Type .TreeView .init (allocator , & pool , tree_node );
425+ defer view .deinit ();
426+
427+ try std .testing .expectEqual (@as (u64 , 100 ), try view .get (0 ));
428+ try std .testing .expectEqual (@as (u64 , 200 ), try view .get (1 ));
429+ try std .testing .expectEqual (@as (u64 , 300 ), try view .get (2 ));
430+ try std .testing .expectEqual (@as (u64 , 400 ), try view .get (3 ));
431+
432+ try view .set (1 , 999 );
433+ try std .testing .expectEqual (@as (u64 , 999 ), try view .get (1 ));
434+
435+ var serialized : [VecU64Type .fixed_size ]u8 = undefined ;
436+ const written = try view .serializeIntoBytes (& serialized );
437+ try std .testing .expectEqual (serialized .len , written );
438+
439+ const expected = [4 ]u64 { 100 , 999 , 300 , 400 };
440+ var expected_serialized : [VecU64Type .fixed_size ]u8 = undefined ;
441+ _ = VecU64Type .serializeIntoBytes (& expected , & expected_serialized );
442+ try std .testing .expectEqualSlices (u8 , & expected_serialized , & serialized );
443+ }
0 commit comments