// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details1#pragma once23#include <type_traits>4#include <string>5#include <optional>6#include <unordered_map>7#include <vector>89#include "Luau/NotNull.h"1011namespace Luau::Json12{1314struct JsonEmitter;1516/// Writes a value to the JsonEmitter. Note that this can produce invalid JSON17/// if you do not insert commas or appropriate object / array syntax.18template<typename T>19void write(JsonEmitter&, T) = delete;2021/// Writes a boolean to a JsonEmitter.22/// @param emitter the emitter to write to.23/// @param b the boolean to write.24void write(JsonEmitter& emitter, bool b);2526/// Writes an integer to a JsonEmitter.27/// @param emitter the emitter to write to.28/// @param i the integer to write.29void write(JsonEmitter& emitter, int i);3031/// Writes an integer to a JsonEmitter.32/// @param emitter the emitter to write to.33/// @param i the integer to write.34void write(JsonEmitter& emitter, long i);3536/// Writes an integer to a JsonEmitter.37/// @param emitter the emitter to write to.38/// @param i the integer to write.39void write(JsonEmitter& emitter, long long i);4041/// Writes an integer to a JsonEmitter.42/// @param emitter the emitter to write to.43/// @param i the integer to write.44void write(JsonEmitter& emitter, unsigned int i);4546/// Writes an integer to a JsonEmitter.47/// @param emitter the emitter to write to.48/// @param i the integer to write.49void write(JsonEmitter& emitter, unsigned long i);5051/// Writes an integer to a JsonEmitter.52/// @param emitter the emitter to write to.53/// @param i the integer to write.54void write(JsonEmitter& emitter, unsigned long long i);5556/// Writes a double to a JsonEmitter.57/// @param emitter the emitter to write to.58/// @param d the double to write.59void write(JsonEmitter& emitter, double d);6061/// Writes a string to a JsonEmitter. The string will be escaped.62/// @param emitter the emitter to write to.63/// @param sv the string to write.64void write(JsonEmitter& emitter, std::string_view sv);6566/// Writes a character to a JsonEmitter as a single-character string. The67/// character will be escaped.68/// @param emitter the emitter to write to.69/// @param c the string to write.70void write(JsonEmitter& emitter, char c);7172/// Writes a string to a JsonEmitter. The string will be escaped.73/// @param emitter the emitter to write to.74/// @param str the string to write.75void write(JsonEmitter& emitter, const char* str);7677/// Writes a string to a JsonEmitter. The string will be escaped.78/// @param emitter the emitter to write to.79/// @param str the string to write.80void write(JsonEmitter& emitter, const std::string& str);8182/// Writes null to a JsonEmitter.83/// @param emitter the emitter to write to.84void write(JsonEmitter& emitter, std::nullptr_t);8586/// Writes null to a JsonEmitter.87/// @param emitter the emitter to write to.88void write(JsonEmitter& emitter, std::nullopt_t);8990struct ObjectEmitter;91struct ArrayEmitter;9293struct JsonEmitter94{95JsonEmitter();9697/// Converts the current contents of the JsonEmitter to a string value. This98/// does not invalidate the emitter, but it does not clear it either.99std::string str();100101/// Returns the current comma state and resets it to false. Use popComma to102/// restore the old state.103/// @returns the previous comma state.104bool pushComma();105106/// Restores a previous comma state.107/// @param c the comma state to restore.108void popComma(bool c);109110/// Writes a raw sequence of characters to the buffer, without escaping or111/// other processing.112/// @param sv the character sequence to write.113void writeRaw(std::string_view sv);114115/// Writes a character to the buffer, without escaping or other processing.116/// @param c the character to write.117void writeRaw(char c);118119/// Writes a comma if this wasn't the first time writeComma has been120/// invoked. Otherwise, sets the comma state to true.121/// @see pushComma122/// @see popComma123void writeComma();124125/// Begins writing an object to the emitter.126/// @returns an ObjectEmitter that can be used to write key-value pairs.127ObjectEmitter writeObject();128129/// Begins writing an array to the emitter.130/// @returns an ArrayEmitter that can be used to write values.131ArrayEmitter writeArray();132133private:134bool comma = false;135std::vector<std::string> chunks;136137void newChunk();138};139140/// An interface for writing an object into a JsonEmitter instance.141/// @see JsonEmitter::writeObject142struct ObjectEmitter143{144ObjectEmitter(NotNull<JsonEmitter> emitter);145~ObjectEmitter();146147NotNull<JsonEmitter> emitter;148bool comma;149bool finished;150151/// Writes a key-value pair to the associated JsonEmitter. Keys will be escaped.152/// @param name the name of the key-value pair.153/// @param value the value to write.154template<typename T>155void writePair(std::string_view name, T value)156{157if (finished)158{159return;160}161162emitter->writeComma();163write(*emitter, name);164emitter->writeRaw(':');165write(*emitter, value);166}167168/// Finishes writing the object, appending a closing `}` character and169/// resetting the comma state of the associated emitter. This can only be170/// called once, and once called will render the emitter unusable. This171/// method is also called when the ObjectEmitter is destructed.172void finish();173};174175/// An interface for writing an array into a JsonEmitter instance. Array values176/// do not need to be the same type.177/// @see JsonEmitter::writeArray178struct ArrayEmitter179{180ArrayEmitter(NotNull<JsonEmitter> emitter);181~ArrayEmitter();182183NotNull<JsonEmitter> emitter;184bool comma;185bool finished;186187/// Writes a value to the array.188/// @param value the value to write.189template<typename T>190void writeValue(T value)191{192if (finished)193{194return;195}196197emitter->writeComma();198write(*emitter, value);199}200201/// Finishes writing the object, appending a closing `]` character and202/// resetting the comma state of the associated emitter. This can only be203/// called once, and once called will render the emitter unusable. This204/// method is also called when the ArrayEmitter is destructed.205void finish();206};207208/// Writes a vector as an array to a JsonEmitter.209/// @param emitter the emitter to write to.210/// @param vec the vector to write.211template<typename T>212void write(JsonEmitter& emitter, const std::vector<T>& vec)213{214ArrayEmitter a = emitter.writeArray();215216for (const T& value : vec)217a.writeValue(value);218219a.finish();220}221222/// Writes an optional to a JsonEmitter. Will write the contained value, if223/// present, or null, if no value is present.224/// @param emitter the emitter to write to.225/// @param v the value to write.226template<typename T>227void write(JsonEmitter& emitter, const std::optional<T>& v)228{229if (v.has_value())230write(emitter, *v);231else232emitter.writeRaw("null");233}234235template<typename T>236void write(JsonEmitter& emitter, const std::unordered_map<std::string, T>& map)237{238ObjectEmitter o = emitter.writeObject();239240for (const auto& [k, v] : map)241o.writePair(k, v);242243o.finish();244}245246} // namespace Luau::Json247248249