xref: /freebsd/contrib/llvm-project/llvm/include/llvm/BinaryFormat/MsgPackReader.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===- MsgPackReader.h - Simple MsgPack reader ------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 ///  \file
10 ///  This is a MessagePack reader.
11 ///
12 ///  See https://github.com/msgpack/msgpack/blob/master/spec.md for the full
13 ///  standard.
14 ///
15 ///  Typical usage:
16 ///  \code
17 ///  StringRef input = GetInput();
18 ///  msgpack::Reader MPReader(input);
19 ///  msgpack::Object Obj;
20 ///
21 ///  while (true) {
22 ///    Expected<bool> ReadObj = MPReader.read(&Obj);
23 ///    if (!ReadObj)
24 ///      // Handle error...
25 ///    if (!ReadObj.get())
26 ///      break; // Reached end of input
27 ///    switch (Obj.Kind) {
28 ///    case msgpack::Type::Int:
29 //       // Use Obj.Int
30 ///      break;
31 ///    // ...
32 ///    }
33 ///  }
34 ///  \endcode
35 ///
36 //===----------------------------------------------------------------------===//
37 
38 #ifndef LLVM_BINARYFORMAT_MSGPACKREADER_H
39 #define LLVM_BINARYFORMAT_MSGPACKREADER_H
40 
41 #include "llvm/Support/Compiler.h"
42 #include "llvm/Support/Error.h"
43 #include "llvm/Support/MemoryBufferRef.h"
44 #include <cstdint>
45 
46 namespace llvm {
47 namespace msgpack {
48 
49 /// MessagePack types as defined in the standard, with the exception of Integer
50 /// being divided into a signed Int and unsigned UInt variant in order to map
51 /// directly to C++ types.
52 ///
53 /// The types map onto corresponding union members of the \c Object struct.
54 enum class Type : uint8_t {
55   Int,
56   UInt,
57   Nil,
58   Boolean,
59   Float,
60   String,
61   Binary,
62   Array,
63   Map,
64   Extension,
65   Empty, // Used by MsgPackDocument to represent an empty node
66 };
67 
68 /// Extension types are composed of a user-defined type ID and an uninterpreted
69 /// sequence of bytes.
70 struct ExtensionType {
71   /// User-defined extension type.
72   int8_t Type;
73   /// Raw bytes of the extension object.
74   StringRef Bytes;
75 };
76 
77 /// MessagePack object, represented as a tagged union of C++ types.
78 ///
79 /// All types except \c Type::Nil (which has only one value, and so is
80 /// completely represented by the \c Kind itself) map to a exactly one union
81 /// member.
82 struct Object {
83   Type Kind;
84   union {
85     /// Value for \c Type::Int.
86     int64_t Int;
87     /// Value for \c Type::Uint.
88     uint64_t UInt;
89     /// Value for \c Type::Boolean.
90     bool Bool;
91     /// Value for \c Type::Float.
92     double Float;
93     /// Value for \c Type::String and \c Type::Binary.
94     StringRef Raw;
95     /// Value for \c Type::Array and \c Type::Map.
96     size_t Length;
97     /// Value for \c Type::Extension.
98     ExtensionType Extension;
99   };
100 
ObjectObject101   Object() : Kind(Type::Int), Int(0) {}
102 };
103 
104 /// Reads MessagePack objects from memory, one at a time.
105 class Reader {
106 public:
107   /// Construct a reader, keeping a reference to the \p InputBuffer.
108   LLVM_ABI Reader(MemoryBufferRef InputBuffer);
109   /// Construct a reader, keeping a reference to the \p Input.
110   LLVM_ABI Reader(StringRef Input);
111 
112   Reader(const Reader &) = delete;
113   Reader &operator=(const Reader &) = delete;
114 
115   /// Read one object from the input buffer, advancing past it.
116   ///
117   /// The \p Obj is updated with the kind of the object read, and the
118   /// corresponding union member is updated.
119   ///
120   /// For the collection objects (Array and Map), only the length is read, and
121   /// the caller must make and additional \c N calls (in the case of Array) or
122   /// \c N*2 calls (in the case of Map) to \c Read to retrieve the collection
123   /// elements.
124   ///
125   /// \param [out] Obj filled with next object on success.
126   ///
127   /// \returns true when object successfully read, false when at end of
128   /// input (and so \p Obj was not updated), otherwise an error.
129   LLVM_ABI Expected<bool> read(Object &Obj);
130 
131 private:
132   MemoryBufferRef InputBuffer;
133   StringRef::iterator Current;
134   StringRef::iterator End;
135 
remainingSpace()136   size_t remainingSpace() {
137     // The rest of the code maintains the invariant that End >= Current, so
138     // that this cast is always defined behavior.
139     return static_cast<size_t>(End - Current);
140   }
141 
142   template <class T> Expected<bool> readRaw(Object &Obj);
143   template <class T> Expected<bool> readInt(Object &Obj);
144   template <class T> Expected<bool> readUInt(Object &Obj);
145   template <class T> Expected<bool> readLength(Object &Obj);
146   template <class T> Expected<bool> readExt(Object &Obj);
147   Expected<bool> createRaw(Object &Obj, uint32_t Size);
148   Expected<bool> createExt(Object &Obj, uint32_t Size);
149 };
150 
151 } // end namespace msgpack
152 } // end namespace llvm
153 
154 #endif // LLVM_BINARYFORMAT_MSGPACKREADER_H
155