@@ -102,9 +102,104 @@ void parseErrorThrows() {
102102 }
103103
104104 @ Test
105- void dumpsRejectsNonObjectTopLevel () {
106- Value arr = new Value .Arr (List .of (new Value .Str ("x" )));
107- assertThrows (KtavException .class , () -> Ktav .dumps (arr ));
105+ void dumpsRejectsScalarTopLevel () {
106+ // Top-level Array is now valid (spec 0.1.1) — only bare scalars
107+ // are still rejected by the native side.
108+ assertThrows (KtavException .class , () -> Ktav .dumps (new Value .Str ("just a string" )));
109+ }
110+
111+ @ Test
112+ void loadsTopLevelArrayBareScalars () {
113+ // spec 0.1.1: first content line decides Object vs Array.
114+ String src = """
115+ alpha
116+ beta
117+ gamma
118+ """ ;
119+ Value v = Ktav .loads (src );
120+ Value .Arr arr = assertInstanceOf (Value .Arr .class , v );
121+ assertEquals (List .of (
122+ new Value .Str ("alpha" ),
123+ new Value .Str ("beta" ),
124+ new Value .Str ("gamma" )), arr .items ());
125+ }
126+
127+ @ Test
128+ void loadsTopLevelArrayTypedItems () {
129+ String src = """
130+ :i 1
131+ :i 2
132+ :f 3.5
133+ """ ;
134+ Value v = Ktav .loads (src );
135+ Value .Arr arr = assertInstanceOf (Value .Arr .class , v );
136+ assertEquals (3 , arr .items ().size ());
137+ assertEquals (new Value .Int ("1" ), arr .items ().get (0 ));
138+ assertEquals (new Value .Int ("2" ), arr .items ().get (1 ));
139+ Value .Flt third = assertInstanceOf (Value .Flt .class , arr .items ().get (2 ));
140+ assertEquals (3.5 , third .toDouble ());
141+ }
142+
143+ @ Test
144+ void roundTripTopLevelArray () {
145+ Value .Arr arr = new Value .Arr (List .of (
146+ new Value .Str ("one" ),
147+ new Value .Str ("two" ),
148+ Value .Int .of (3 )));
149+ String out = Ktav .dumps (arr );
150+ assertNotNull (out );
151+ Value back = Ktav .loads (out );
152+ Value .Arr bArr = assertInstanceOf (Value .Arr .class , back );
153+ assertEquals (3 , bArr .items ().size ());
154+ assertEquals (new Value .Str ("one" ), bArr .items ().get (0 ));
155+ assertEquals (new Value .Str ("two" ), bArr .items ().get (1 ));
156+ assertEquals (new Value .Int ("3" ), bArr .items ().get (2 ));
157+ }
158+
159+ @ Test
160+ void toStringForceStringsCoercesScalars () {
161+ LinkedHashMap <String , Value > entries = new LinkedHashMap <>();
162+ entries .put ("count" , Value .Int .of (42 ));
163+ entries .put ("ratio" , Value .Flt .of (0.5 ));
164+ entries .put ("flag" , Value .Bool .TRUE );
165+ entries .put ("nothing" , Value .Null .NULL );
166+ entries .put ("name" , new Value .Str ("demo" ));
167+
168+ String out = Ktav .toStringForceStrings (new Value .Obj (entries ));
169+ assertNotNull (out );
170+
171+ // Round-trip — every leaf scalar must come back as Value.Str.
172+ Value back = Ktav .loads (out );
173+ Value .Obj b = assertInstanceOf (Value .Obj .class , back );
174+ assertInstanceOf (Value .Str .class , b .entries ().get ("count" ));
175+ assertInstanceOf (Value .Str .class , b .entries ().get ("ratio" ));
176+ assertInstanceOf (Value .Str .class , b .entries ().get ("flag" ));
177+ assertInstanceOf (Value .Str .class , b .entries ().get ("nothing" ));
178+ assertInstanceOf (Value .Str .class , b .entries ().get ("name" ));
179+
180+ assertEquals (new Value .Str ("42" ), b .entries ().get ("count" ));
181+ assertEquals ("true" , ((Value .Str ) b .entries ().get ("flag" )).value ());
182+ assertEquals ("null" , ((Value .Str ) b .entries ().get ("nothing" )).value ());
183+ assertEquals ("demo" , ((Value .Str ) b .entries ().get ("name" )).value ());
184+ }
185+
186+ @ Test
187+ void toStringForceStringsAcceptsTopLevelArray () {
188+ Value .Arr arr = new Value .Arr (List .of (
189+ Value .Int .of (1 ),
190+ Value .Bool .FALSE ,
191+ Value .Null .NULL ));
192+ String out = Ktav .toStringForceStrings (arr );
193+ assertNotNull (out );
194+ Value back = Ktav .loads (out );
195+ Value .Arr bArr = assertInstanceOf (Value .Arr .class , back );
196+ assertEquals (3 , bArr .items ().size ());
197+ for (Value item : bArr .items ()) {
198+ assertInstanceOf (Value .Str .class , item );
199+ }
200+ assertEquals ("1" , ((Value .Str ) bArr .items ().get (0 )).value ());
201+ assertEquals ("false" , ((Value .Str ) bArr .items ().get (1 )).value ());
202+ assertEquals ("null" , ((Value .Str ) bArr .items ().get (2 )).value ());
108203 }
109204
110205 @ Test
0 commit comments