2929import java .io .File ;
3030import java .io .IOException ;
3131import java .io .InputStream ;
32+ import java .nio .charset .Charset ;
33+ import java .nio .file .Files ;
34+ import java .nio .file .Paths ;
35+ import java .nio .file .StandardOpenOption ;
3236import java .util .ArrayList ;
3337import java .util .Arrays ;
3438import java .util .HashMap ;
3539import java .util .List ;
3640import java .util .Map ;
3741
42+ import tla2sany .semantic .ExprOrOpArgNode ;
3843import tlc2 .output .EC ;
44+ import tlc2 .tool .EvalControl ;
3945import tlc2 .tool .EvalException ;
46+ import tlc2 .tool .TLCState ;
47+ import tlc2 .tool .coverage .CostModel ;
48+ import tlc2 .tool .impl .Tool ;
49+ import tlc2 .util .Context ;
4050import tlc2 .value .IValue ;
4151import tlc2 .value .ValueInputStream ;
4252import tlc2 .value .ValueOutputStream ;
5262public class IOUtils {
5363
5464 @ TLAPlusOperator (identifier = "IODeserialize" , module = "IOUtils" , warn = false )
55- public static final IValue deserialize (final StringValue absolutePath , final BoolValue compress )
65+ public static final IValue ioDeserialize (final StringValue absolutePath , final BoolValue compress )
5666 throws IOException {
5767 final ValueInputStream vis = new ValueInputStream (new File (absolutePath .val .toString ()), compress .val );
5868 try {
@@ -63,7 +73,7 @@ public static final IValue deserialize(final StringValue absolutePath, final Boo
6373 }
6474
6575 @ TLAPlusOperator (identifier = "IOSerialize" , module = "IOUtils" , warn = false )
66- public static final IValue serialize (final IValue value , final StringValue absolutePath , final BoolValue compress )
76+ public static final IValue ioSerialize (final IValue value , final StringValue absolutePath , final BoolValue compress )
6777 throws IOException {
6878 final ValueOutputStream vos = new ValueOutputStream (new File (absolutePath .val .toString ()), compress .val );
6979 try {
@@ -74,6 +84,123 @@ public static final IValue serialize(final IValue value, final StringValue absol
7484 return BoolValue .ValTrue ;
7585 }
7686
87+ /* Writes a String as plain text to a file.
88+ * Operator should be called as Serialize(payload, filepath, [format |-> "TXT", charset |-> charset, openOptions |-> openOptions])
89+ * String payload: is the string that will be written
90+ * String filepath: is the file where the string will be written
91+ * String charset: string with a java standard charset
92+ * String openOptions: sequence of strings of java StandardOpenOptions
93+ *
94+ * Example:
95+ * Serialize("test payload", "test.txt", [format |-> "TXT", charset |-> "UTF-8", openOptions |-> <<"WRITEA", "CREATE", "TRUNCATE_EXISTING">>])
96+ */
97+ @ Evaluation (definition = "Serialize" , module = "IOUtils" , warn = false , silent = true , priority = 50 )
98+ public synchronized static Value textSerialize (final Tool tool , final ExprOrOpArgNode [] args , final Context c ,
99+ final TLCState s0 , final TLCState s1 , final int control , final CostModel cm ) {
100+
101+ final String msgInvalidParam = "Serialize error invalid parameters: " ;
102+ final String successmsg = "Finish writting to the file with success!" ;
103+
104+ final RecordValue opts ;
105+
106+ try {
107+ opts = (RecordValue ) tool .eval (args [2 ], c , s0 , s1 , control , cm );
108+ } catch (Exception e ){
109+ return new RecordValue (EXEC_NAMES , new Value [] { IntValue .ValOne , new StringValue ("" ), new StringValue (msgInvalidParam + e .toString ()) }, false );
110+ }
111+
112+ final StringValue serializer = (StringValue ) opts .apply (new StringValue ("format" ), EvalControl .Clear );
113+ if ("TXT" .equals (serializer .getVal ().toString ())) {
114+
115+ final StringValue payload ;
116+ final StringValue filepath ;
117+ final StringValue [] openOptions ;
118+ final StringValue charset ;
119+
120+ try {
121+ payload = (StringValue ) tool .eval (args [0 ], c , s0 , s1 , control , cm );
122+ filepath = (StringValue ) tool .eval (args [1 ], c , s0 , s1 , control , cm );
123+ final TupleValue openOptionstv = (TupleValue ) opts .apply (new StringValue ("openOptions" ), EvalControl .Clear );
124+ charset = (StringValue ) opts .apply (new StringValue ("charset" ), EvalControl .Clear );
125+
126+ openOptions = Arrays .asList (openOptionstv .getElems ()).stream ()
127+ .map (e -> (StringValue ) e )
128+ .toArray (size -> new StringValue [size ]);
129+ } catch (Exception e ) {
130+ return new RecordValue (EXEC_NAMES , new Value [] { IntValue .ValOne , new StringValue ("" ), new StringValue (msgInvalidParam + e .toString ()) }, false );
131+ }
132+
133+ try {
134+ Files .writeString (
135+ Paths .get (filepath .getVal ().toString ()),
136+ payload .getVal ().toString (),
137+ Charset .forName (charset .getVal ().toString ()),
138+ Arrays .asList (openOptions ).stream ()
139+ .map (e -> StandardOpenOption .valueOf (e .getVal ().toString ()) )
140+ .toArray (size -> new StandardOpenOption [size ]));
141+
142+ return new RecordValue (EXEC_NAMES , new Value [] { IntValue .ValZero , new StringValue (successmsg ), new StringValue ("" ) }, false );
143+
144+ } catch (Exception e ) {
145+ final StringValue errormsg = new StringValue ("Serialize error writting to the file: " +e .toString ());
146+ return new RecordValue (EXEC_NAMES , new Value [] { IntValue .ValOne , new StringValue ("" ), errormsg }, false );
147+ }
148+ }
149+
150+ return null ;
151+ }
152+
153+ /* Reads a String from a plain text file.
154+ * Operator should be called as Deserialize(filepath, [format |-> "TXT", charset |-> charset])
155+ * String filepath: is the file to be read
156+ * String charset: string with a java standard charset
157+ *
158+ * Example:
159+ * Deserialize("test.txt", [format |-> "TXT", charset |-> "UTF-8"])
160+ */
161+ @ Evaluation (definition = "Deserialize" , module = "IOUtils" , warn = false , silent = true , priority = 50 )
162+ public synchronized static Value textDeserialize (final Tool tool , final ExprOrOpArgNode [] args , final Context c ,
163+ final TLCState s0 , final TLCState s1 , final int control , final CostModel cm ) {
164+
165+ final String msgInvalidParam = "Deserialize error invalid parameters: " ;
166+
167+ final RecordValue opts ;
168+
169+ try {
170+ opts = (RecordValue ) tool .eval (args [1 ], c , s0 , s1 , control , cm );
171+ } catch (Exception e ){
172+ return new RecordValue (EXEC_NAMES , new Value [] { IntValue .ValOne , new StringValue ("" ), new StringValue (msgInvalidParam + e .toString ()) }, false );
173+ }
174+
175+ final StringValue serializer = (StringValue ) opts .apply (new StringValue ("format" ), EvalControl .Clear );
176+ if ("TXT" .equals (serializer .getVal ().toString ())) {
177+
178+ final StringValue filepath ;
179+ final StringValue charset ;
180+
181+ try {
182+ filepath = (StringValue ) tool .eval (args [0 ], c , s0 , s1 , control , cm );
183+ charset = (StringValue ) opts .apply (new StringValue ("charset" ), EvalControl .Clear );
184+ } catch (Exception e ) {
185+ return new RecordValue (EXEC_NAMES , new Value [] { IntValue .ValOne , new StringValue ("" ), new StringValue (msgInvalidParam + e .toString ()) }, false );
186+ }
187+
188+ try {
189+ final String result = Files .readString (
190+ Paths .get (filepath .getVal ().toString ()),
191+ Charset .forName (charset .getVal ().toString ()));
192+
193+ return new RecordValue (EXEC_NAMES , new Value [] { IntValue .ValZero , new StringValue (result ), new StringValue ("" ) }, false );
194+
195+ } catch (Exception e ) {
196+ final StringValue errormsg = new StringValue ("Deserialize error reading from the file: " +e .toString ());
197+ return new RecordValue (EXEC_NAMES , new Value [] { IntValue .ValOne , new StringValue ("" ), errormsg }, false );
198+ }
199+ }
200+
201+ return null ;
202+ }
203+
77204 static {
78205 // Eagerly lookup the environment, which is not going to change while the Java
79206 // process executes.
0 commit comments