Skip to content

Commit

Permalink
FIX: better struct! initialization; empty struct not allowed
Browse files Browse the repository at this point in the history
  • Loading branch information
Oldes committed Nov 9, 2023
1 parent 7aaa058 commit 821a5a9
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 5 deletions.
18 changes: 13 additions & 5 deletions src/core/t-struct.c
Expand Up @@ -686,7 +686,7 @@ static REBOOL parse_field_type(struct Struct_Field *field, REBVAL *spec, REBVAL
/*
* Format:
* make struct! [
* field1 [type1]
* field1 [type1]
* field2: [type2] field2-init-value
* field3: [struct [field1 [type1]]] field3-init-struct-value
* field4: [type1[3]] field4-init-block-value
Expand All @@ -695,10 +695,17 @@ static REBOOL parse_field_type(struct Struct_Field *field, REBVAL *spec, REBVAL
***********************************************************************/
{
//RL_Print("%s\n", __func__);
REBINT max_fields = 16;

if (!IS_BLOCK(data)) return FALSE; // validate early!

VAL_STRUCT_FIELDS(out) = Make_Series(max_fields, sizeof(struct Struct_Field), FALSE);

/* Using spec block length as a prediction of fields number
(each field requires at least 2 spec values) */
REBCNT num_spec_values = VAL_TAIL(data) - VAL_INDEX(data);
REBCNT min_fileds = num_spec_values >> 1;
/* Don't allow empty struct! */
if (min_fileds == 0) Trap_Arg(data);

VAL_STRUCT_FIELDS(out) = Make_Series(min_fileds, sizeof(struct Struct_Field), FALSE);
BARE_SERIES(VAL_STRUCT_FIELDS(out));

//Reduce_Block_No_Set(VAL_SERIES(data), 0, NULL);
Expand All @@ -718,7 +725,8 @@ static REBOOL parse_field_type(struct Struct_Field *field, REBVAL *spec, REBVAL
EXPAND_SERIES_TAIL(VAL_STRUCT_DATA(out), 1);
BARE_SERIES(VAL_STRUCT_DATA(out));

VAL_STRUCT_DATA_BIN(out) = Make_Series(max_fields << 2, 1, FALSE);
/* one byte per field as a minimum (expands when needed) */
VAL_STRUCT_DATA_BIN(out) = Make_Series(min_fileds, 1, FALSE);
BARE_SERIES(VAL_STRUCT_DATA_BIN(out));
VAL_STRUCT_OFFSET(out) = 0;

Expand Down
27 changes: 27 additions & 0 deletions src/tests/units/struct-test.r3
Expand Up @@ -133,6 +133,15 @@ Rebol [
--assert all [s2/a = 1 s2/b = 20]
--assert all [s3/a = 10 s3/b = 20]

--test-- "Struct with many fields"
blk: copy []
repeat i 32 [repend blk [to word! join 'a i [int8!]]]
--assert all [
not error? try [s: make struct! blk]
[a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19 a20 a21 a22 a23 a24 a25 a26 a27 a28 a29 a30 a31 a32] = words-of s
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] = values-of s
]

===end-group===


Expand Down Expand Up @@ -177,6 +186,24 @@ s: make struct! spec: [a: [uint16!] 1 b: [int32!] -1 c: [word!] foo d [uint8! [2
error? e: try [ make struct! [a: [int8! [2]] 1] ] ;- No crash!
e/id = 'expect-val
]

--test-- "Empty struct not allowed"
--assert all [
error? e: try [make struct! []]
e/id = 'invalid-arg
]
--assert all [
error? e: try [make struct! [a]]
e/id = 'invalid-arg
]
--assert all [
error? e: try [make struct! [[]]]
e/id = 'invalid-arg
]
--assert all [
error? e: try [make struct! [[] a]]
e/id = 'invalid-arg
]
===end-group===


Expand Down

0 comments on commit 821a5a9

Please sign in to comment.