1 //===- MsgPackTypes.h - MsgPack Types ---------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 /// \file
11 /// This is a data structure for representing MessagePack "documents", with
12 /// methods to go to and from MessagePack. The types also specialize YAMLIO
13 /// traits in order to go to and from YAML.
14 //
15 //===----------------------------------------------------------------------===//
16 
17 #include "llvm/ADT/Optional.h"
18 #include "llvm/BinaryFormat/MsgPackReader.h"
19 #include "llvm/BinaryFormat/MsgPackWriter.h"
20 #include "llvm/Support/Casting.h"
21 #include "llvm/Support/YAMLTraits.h"
22 #include <vector>
23 
24 #ifndef LLVM_BINARYFORMAT_MSGPACKTYPES_H
25 #define LLVM_BINARYFORMAT_MSGPACKTYPES_H
26 
27 namespace llvm {
28 namespace msgpack {
29 
30 class Node;
31 
32 /// Short-hand for a Node pointer.
33 using NodePtr = std::shared_ptr<Node>;
34 
35 /// Short-hand for an Optional Node pointer.
36 using OptNodePtr = Optional<NodePtr>;
37 
38 /// Abstract base-class which can be any MessagePack type.
39 class Node {
40 public:
41   enum NodeKind {
42     NK_Scalar,
43     NK_Array,
44     NK_Map,
45   };
46 
47 private:
48   virtual void anchor() = 0;
49   const NodeKind Kind;
50 
51   static Expected<OptNodePtr> readArray(Reader &MPReader, size_t Length);
52   static Expected<OptNodePtr> readMap(Reader &MPReader, size_t Length);
53 
54 public:
getKind()55   NodeKind getKind() const { return Kind; }
56 
57   /// Construct a Node. Used by derived classes to track kind information.
Node(NodeKind Kind)58   Node(NodeKind Kind) : Kind(Kind) {}
59 
60   virtual ~Node() = default;
61 
62   /// Read from a MessagePack reader \p MPReader, returning an error if one is
63   /// encountered, or None if \p MPReader is at the end of stream, or some Node
64   /// pointer if some type is read.
65   static Expected<OptNodePtr> read(Reader &MPReader);
66 
67   /// Write to a MessagePack writer \p MPWriter.
68   virtual void write(Writer &MPWriter) = 0;
69 };
70 
71 /// A MessagePack scalar.
72 class ScalarNode : public Node {
73 public:
74   enum ScalarKind {
75     SK_Int,
76     SK_UInt,
77     SK_Nil,
78     SK_Boolean,
79     SK_Float,
80     SK_String,
81     SK_Binary,
82   };
83 
84 private:
85   void anchor() override;
86 
87   void destroy();
88 
89   ScalarKind SKind;
90 
91   union {
92     int64_t IntValue;
93     uint64_t UIntValue;
94     bool BoolValue;
95     double FloatValue;
96     std::string StringValue;
97   };
98 
99 public:
100   /// Construct an Int ScalarNode.
101   ScalarNode(int64_t IntValue);
102   /// Construct an Int ScalarNode.
103   ScalarNode(int32_t IntValue);
104   /// Construct an UInt ScalarNode.
105   ScalarNode(uint64_t UIntValue);
106   /// Construct an UInt ScalarNode.
107   ScalarNode(uint32_t UIntValue);
108   /// Construct a Nil ScalarNode.
109   ScalarNode();
110   /// Construct a Boolean ScalarNode.
111   ScalarNode(bool BoolValue);
112   /// Construct a Float ScalarNode.
113   ScalarNode(double FloatValue);
114   /// Construct a String ScalarNode.
115   ScalarNode(StringRef StringValue);
116   /// Construct a String ScalarNode.
117   ScalarNode(const char *StringValue);
118   /// Construct a String ScalarNode.
119   ScalarNode(std::string &&StringValue);
120   /// Construct a Binary ScalarNode.
121   ScalarNode(MemoryBufferRef BinaryValue);
122 
123   ~ScalarNode();
124 
125   ScalarNode &operator=(const ScalarNode &RHS) = delete;
126   /// A ScalarNode can only be move assigned.
127   ScalarNode &operator=(ScalarNode &&RHS);
128 
129   /// Change the kind of this ScalarNode, zero initializing it to the new type.
setScalarKind(ScalarKind SKind)130   void setScalarKind(ScalarKind SKind) {
131     switch (SKind) {
132     case SK_Int:
133       *this = int64_t(0);
134       break;
135     case SK_UInt:
136       *this = uint64_t(0);
137       break;
138     case SK_Boolean:
139       *this = false;
140       break;
141     case SK_Float:
142       *this = 0.0;
143       break;
144     case SK_String:
145       *this = StringRef();
146       break;
147     case SK_Binary:
148       *this = MemoryBufferRef("", "");
149       break;
150     case SK_Nil:
151       *this = ScalarNode();
152       break;
153     }
154   }
155 
156   /// Get the current kind of ScalarNode.
getScalarKind()157   ScalarKind getScalarKind() { return SKind; }
158 
159   /// Get the value of an Int scalar.
160   ///
161   /// \warning Assumes getScalarKind() == SK_Int
getInt()162   int64_t getInt() {
163     assert(SKind == SK_Int);
164     return IntValue;
165   }
166 
167   /// Get the value of a UInt scalar.
168   ///
169   /// \warning Assumes getScalarKind() == SK_UInt
getUInt()170   uint64_t getUInt() {
171     assert(SKind == SK_UInt);
172     return UIntValue;
173   }
174 
175   /// Get the value of an Boolean scalar.
176   ///
177   /// \warning Assumes getScalarKind() == SK_Boolean
getBool()178   bool getBool() {
179     assert(SKind == SK_Boolean);
180     return BoolValue;
181   }
182 
183   /// Get the value of an Float scalar.
184   ///
185   /// \warning Assumes getScalarKind() == SK_Float
getFloat()186   double getFloat() {
187     assert(SKind == SK_Float);
188     return FloatValue;
189   }
190 
191   /// Get the value of a String scalar.
192   ///
193   /// \warning Assumes getScalarKind() == SK_String
getString()194   StringRef getString() {
195     assert(SKind == SK_String);
196     return StringValue;
197   }
198 
199   /// Get the value of a Binary scalar.
200   ///
201   /// \warning Assumes getScalarKind() == SK_Binary
getBinary()202   StringRef getBinary() {
203     assert(SKind == SK_Binary);
204     return StringValue;
205   }
206 
classof(const Node * N)207   static bool classof(const Node *N) { return N->getKind() == NK_Scalar; }
208 
209   void write(Writer &MPWriter) override;
210 
211   /// Parse a YAML scalar of the current ScalarKind from \p ScalarStr.
212   ///
213   /// \returns An empty string on success, otherwise an error message.
214   StringRef inputYAML(StringRef ScalarStr);
215 
216   /// Output a YAML scalar of the current ScalarKind into \p OS.
217   void outputYAML(raw_ostream &OS) const;
218 
219   /// Determine which YAML quoting type the current value would need when
220   /// output.
221   yaml::QuotingType mustQuoteYAML(StringRef ScalarStr) const;
222 
223   /// Get the YAML tag for the current ScalarKind.
224   StringRef getYAMLTag() const;
225 
226   /// Flag which affects how the type handles YAML tags when reading and
227   /// writing.
228   ///
229   /// When false, tags are used when reading and writing. When reading, the tag
230   /// is used to decide the ScalarKind before parsing. When writing, the tag is
231   /// output along with the value.
232   ///
233   /// When true, tags are ignored when reading and writing. When reading, the
234   /// ScalarKind is always assumed to be String. When writing, the tag is not
235   /// output.
236   bool IgnoreTag = false;
237 
238   static const char *IntTag;
239   static const char *NilTag;
240   static const char *BooleanTag;
241   static const char *FloatTag;
242   static const char *StringTag;
243   static const char *BinaryTag;
244 };
245 
246 class ArrayNode : public Node, public std::vector<NodePtr> {
247   void anchor() override;
248 
249 public:
ArrayNode()250   ArrayNode() : Node(NK_Array) {}
classof(const Node * N)251   static bool classof(const Node *N) { return N->getKind() == NK_Array; }
252 
write(Writer & MPWriter)253   void write(Writer &MPWriter) override {
254     MPWriter.writeArraySize(this->size());
255     for (auto &N : *this)
256       N->write(MPWriter);
257   }
258 };
259 
260 class MapNode : public Node, public StringMap<NodePtr> {
261   void anchor() override;
262 
263 public:
MapNode()264   MapNode() : Node(NK_Map) {}
classof(const Node * N)265   static bool classof(const Node *N) { return N->getKind() == NK_Map; }
266 
write(Writer & MPWriter)267   void write(Writer &MPWriter) override {
268     MPWriter.writeMapSize(this->size());
269     for (auto &N : *this) {
270       MPWriter.write(N.first());
271       N.second->write(MPWriter);
272     }
273   }
274 };
275 
276 } // end namespace msgpack
277 
278 namespace yaml {
279 
280 template <> struct PolymorphicTraits<msgpack::NodePtr> {
281   static NodeKind getKind(const msgpack::NodePtr &N) {
282     if (isa<msgpack::ScalarNode>(*N))
283       return NodeKind::Scalar;
284     if (isa<msgpack::MapNode>(*N))
285       return NodeKind::Map;
286     if (isa<msgpack::ArrayNode>(*N))
287       return NodeKind::Sequence;
288     llvm_unreachable("NodeKind not supported");
289   }
290   static msgpack::ScalarNode &getAsScalar(msgpack::NodePtr &N) {
291     if (!N || !isa<msgpack::ScalarNode>(*N))
292       N.reset(new msgpack::ScalarNode());
293     return *cast<msgpack::ScalarNode>(N.get());
294   }
295   static msgpack::MapNode &getAsMap(msgpack::NodePtr &N) {
296     if (!N || !isa<msgpack::MapNode>(*N))
297       N.reset(new msgpack::MapNode());
298     return *cast<msgpack::MapNode>(N.get());
299   }
300   static msgpack::ArrayNode &getAsSequence(msgpack::NodePtr &N) {
301     if (!N || !isa<msgpack::ArrayNode>(*N))
302       N.reset(new msgpack::ArrayNode());
303     return *cast<msgpack::ArrayNode>(N.get());
304   }
305 };
306 
307 template <> struct TaggedScalarTraits<msgpack::ScalarNode> {
308   static void output(const msgpack::ScalarNode &S, void *Ctxt,
309                      raw_ostream &ScalarOS, raw_ostream &TagOS) {
310     if (!S.IgnoreTag)
311       TagOS << S.getYAMLTag();
312     S.outputYAML(ScalarOS);
313   }
314 
315   static StringRef input(StringRef ScalarStr, StringRef Tag, void *Ctxt,
316                          msgpack::ScalarNode &S) {
317     if (Tag == msgpack::ScalarNode::IntTag) {
318       S.setScalarKind(msgpack::ScalarNode::SK_UInt);
319       if (S.inputYAML(ScalarStr) == StringRef())
320         return StringRef();
321       S.setScalarKind(msgpack::ScalarNode::SK_Int);
322       return S.inputYAML(ScalarStr);
323     }
324 
325     if (S.IgnoreTag || Tag == msgpack::ScalarNode::StringTag ||
326         Tag == "tag:yaml.org,2002:str")
327       S.setScalarKind(msgpack::ScalarNode::SK_String);
328     else if (Tag == msgpack::ScalarNode::NilTag)
329       S.setScalarKind(msgpack::ScalarNode::SK_Nil);
330     else if (Tag == msgpack::ScalarNode::BooleanTag)
331       S.setScalarKind(msgpack::ScalarNode::SK_Boolean);
332     else if (Tag == msgpack::ScalarNode::FloatTag)
333       S.setScalarKind(msgpack::ScalarNode::SK_Float);
334     else if (Tag == msgpack::ScalarNode::StringTag)
335       S.setScalarKind(msgpack::ScalarNode::SK_String);
336     else if (Tag == msgpack::ScalarNode::BinaryTag)
337       S.setScalarKind(msgpack::ScalarNode::SK_Binary);
338     else
339       return "Unsupported messagepack tag";
340 
341     return S.inputYAML(ScalarStr);
342   }
343 
344   static QuotingType mustQuote(const msgpack::ScalarNode &S, StringRef Str) {
345     return S.mustQuoteYAML(Str);
346   }
347 };
348 
349 template <> struct CustomMappingTraits<msgpack::MapNode> {
350   static void inputOne(IO &IO, StringRef Key, msgpack::MapNode &M) {
351     IO.mapRequired(Key.str().c_str(), M[Key]);
352   }
353   static void output(IO &IO, msgpack::MapNode &M) {
354     for (auto &N : M)
355       IO.mapRequired(N.getKey().str().c_str(), N.getValue());
356   }
357 };
358 
359 template <> struct SequenceTraits<msgpack::ArrayNode> {
360   static size_t size(IO &IO, msgpack::ArrayNode &A) { return A.size(); }
361   static msgpack::NodePtr &element(IO &IO, msgpack::ArrayNode &A,
362                                    size_t Index) {
363     if (Index >= A.size())
364       A.resize(Index + 1);
365     return A[Index];
366   }
367 };
368 
369 } // end namespace yaml
370 } // end namespace llvm
371 
372 #endif //  LLVM_BINARYFORMAT_MSGPACKTYPES_H
373