Spicy
mime.h
1 // Copyright (c) 2020-2021 by the Zeek Project. See LICENSE for details.
2 
3 #pragma once
4 
5 #include <string>
6 #include <string_view>
7 
8 #include <hilti/rt/exception.h>
9 #include <hilti/rt/extension-points.h>
10 #include <hilti/rt/types/result.h>
11 #include <hilti/rt/util.h>
12 
13 namespace spicy::rt {
14 
18 HILTI_EXCEPTION(InvalidMIMEType, UsageError)
19 
20 namespace mime {
21 
22 constexpr char INVALID_NAME[] = "";
23 
24 } // namespace mime
25 
29 class MIMEType {
30 public:
38  MIMEType(std::string_view main, std::string_view sub) : _main(main), _sub(sub) {}
39 
47  MIMEType(const std::string& type) {
48  if ( type == "*" ) {
49  _main = _sub = "*";
50  return;
51  }
52 
53  auto x = hilti::rt::split1(type, "/");
54  _main = hilti::rt::trim(x.first);
55  _sub = hilti::rt::trim(x.second);
56 
57  if ( _main.empty() || _sub.empty() )
58  throw InvalidMIMEType(hilti::rt::fmt("cannot parse MIME type '%s'", type));
59  }
60 
61  MIMEType() = default;
62 
64  std::string mainType() const {
65  ensureValid();
66  return _main;
67  };
68 
70  std::string subType() const {
71  ensureValid();
72  return _sub;
73  };
74 
76  bool isWildcard() const { return _main == "*" || _sub == "*"; }
77 
78  ~MIMEType() = default;
79  MIMEType(const MIMEType&) = default;
80  MIMEType(MIMEType&&) noexcept = default;
81  MIMEType& operator=(const MIMEType&) = default;
82  MIMEType& operator=(MIMEType&&) noexcept = default;
83 
84  operator std::string() const { return mainType() + "/" + subType(); }
85 
93  std::string asKey() const {
94  ensureValid();
95 
96  if ( _main == "*" )
97  return "";
98 
99  if ( _sub == "*" )
100  return _main;
101 
102  return *this;
103  }
104 
111  static hilti::rt::Result<MIMEType> parse(const std::string& s) {
112  try {
113  return MIMEType(s);
114  } catch ( const InvalidMIMEType& e ) {
115  return hilti::rt::result::Error(e.description());
116  }
117  }
118 
119  friend bool operator==(const MIMEType& a, const MIMEType& b) { return a._main == b._main && a._sub == b._sub; }
120  friend bool operator!=(const MIMEType& a, const MIMEType& b) { return ! (a == b); }
121 
122 private:
132  void ensureValid() const {
133  if ( _main == mime::INVALID_NAME || _sub == mime::INVALID_NAME )
134  throw InvalidMIMEType("MIME type is uninitialized");
135  }
136 
137  std::string _main = mime::INVALID_NAME;
138  std::string _sub = mime::INVALID_NAME;
139 };
140 
141 } // namespace spicy::rt
142 
143 namespace hilti::rt::detail::adl {
144 extern inline std::string to_string(const spicy::rt::MIMEType& x, adl::tag /*unused*/) { return x; }
145 } // namespace hilti::rt::detail::adl
MIMEType(std::string_view main, std::string_view sub)
Definition: mime.h:38
Definition: result.h:18
static hilti::rt::Result< MIMEType > parse(const std::string &s)
Definition: mime.h:111
std::string mainType() const
Definition: mime.h:64
std::pair< std::string, std::string > split1(std::string s)
Definition: util.cc:146
Definition: mime.h:29
bool isWildcard() const
Definition: mime.h:76
std::string asKey() const
Definition: mime.h:93
MIMEType(const std::string &type)
Definition: mime.h:47
Definition: deferred-expression.h:41
std::string_view trim(std::string_view s, const std::string &chars) noexcept
Definition: util.h:143
std::string subType() const
Definition: mime.h:70
Definition: result.h:67
std::string fmt(const char *fmt, const Args &... args)
Definition: fmt.h:13