text: from urllib import parse
  import email
  
  
  def parse_multipart(content_type: str, data: bytes, decode: bool = False):
      post_data = f"""Content-Type: {content_type}
          MIME-Version: 1.0
  
          {data.decode()}"""
      msg = email.message_from_string(post_data)
      files = TypedMultiMap({})
      body = TypedMultiMap({})
      if msg.is_multipart():
          for part in msg.get_payload():
              name = part.get_param(
                  'name', header='content-disposition', decode=decode)
              filename = part.get_param(
                  'filename', header='content-disposition', decode=decode)
              payload = part.get_payload(decode=True)
              if filename is not None:
                  files[name] = FileObject(
                      payload,
                      **part.get_params(header='content-disposition', decode=decode)
                  )
              else:
                  body[name] = payload
      return body, files
  
  
  class TypedMultiMap(dict):
  
      def __init__(self, mapping=None):
          if isinstance(mapping, TypedMultiMap):
              dict.__init__(self, ((k, l[:]) for k, l in mapping.lists()))
          elif isinstance(mapping, dict):
              temp = dict()
              for key, value in mapping.items():
                  if isinstance(value, (tuple, list)):
                      if len(value) == 0:
                          continue
                      value = list(value)
                  else:
                      value = [value]
                  temp[key] = value
              dict.__init__(self, temp)
          else:
              temp = {}
              for key, value in mapping or ():
                  temp.setdefault(key, []).append(value)
              dict.__init__(self, temp)
  
      def __iter__(self):
          return dict.__iter__(self)
  
      def __getitem__(self, key):
          """
          Returns only the first item and None, if key does not exist.
          """
  
          if key in self:
              lst = dict.__getitem__(self, key)
              if len(lst) > 0:
                  return lst[0]
              else:
                  return lst
          return None
  
      def __setitem__(self, key, value):
          """
          Used for assigning the value to an index.
          .. code-block :: python
  
              a = TypedMultiMap()
              a["key"] = "value"
  
          """
          dict.__setitem__(self, key, [value])
  
      def add(self, key, value):
          """
          Inserts a key for the value given.
          """
          dict.setdefault(self, key, []).append(value)
  
      def to_dict(self, flat=True):
          """
          Return the contents as regular dict.
  
          Args:
              Flat: If set to ``True``, only first item is present. Else, a list is present.\
              Defaults to ``False``
          """
  
          if flat:
              return dict(self.items())
          return dict(self.lists())
  
      def get_all(self, key, type_=None):
          """
          Fetches the list of all the items present.
          """
          try:
              rv = dict.__getitem__(self, key)
          except KeyError:
              return []
          if type is None:
              return list(rv)
          result = []
          for item in rv:
              try:
                  result.append(type_(item))
              except ValueError:
                  pass
          return result
  
      def get(self, key, default=None, type_=None):
          if key in self:
              lst = dict.__getitem__(self, key)
              if len(lst) > 0:
                  rv = lst[0]
              else:
                  rv = lst
              if type_ is not None:
                  try:
                      rv = type_(rv)
                  except ValueError:
                      return rv
              return rv
          return default
  
      def items(self, multi=False):
          '''
          Args:
              multi: When set to ``True``, you get a list. Else, a value.
          '''
          for key, values in dict.items(self):
              if multi:
                  for value in values:
                      yield key, value
              else:
                  yield key, values[0]
  
  
  class Response:
      '''
  
  
      This class contains the Response data to be sent,
      in a manageable format.
      The `response` argument of the functions defined,
      objects of this class.
  
  
      The response object does not require external parameters,
      but has some attributes which can be set:
      Args:
        headers(dict[str,str]):\
        It is the HTTP headers set as a dict. Only [content-type] =  text/html is set by default.
        cookies(dict[str,maglev.Structure.Cookie])
        body(str)
        status(int)
  
      '''
  
      def __init__(
              self,
              status=200,
              content_type="text/html",
              body='',
              headers=TypedMultiMap({}),
              cookies=dict()):
          self.headers = headers
          self.cookies = cookies
          self.content_type = content_type
          self.headers['content-type'] = self.content_type
          self.body = body
          self.status = status
  
  
  class Request:
      '''
  
  
      This class contains the information requested by the user.
      The functions called by ``maglev.Router.handle`` take this as the first argument.
  
      Args:
        headers(list[list[bytes,bytes]]): Array of headers passed by the server, and converts them to a dict.
        method(str): It is the HTTP request method.
        path(str):  It is the HTTP request path.
        query(dict[str,list[str]]): It is obtained from the server as a string and is then parsed into the dictionary with `urllib.parse.parse_qs`
  
  
      '''
      params, cookies = {}, {}
  
      def __init__(self, method: str, path: str, raw_body: bytes, raw_query: bytes, headers, *args):
          '''
  
          Args:
            self: The class ``maglev.structure.Request``
            method(str): The HTTP method used by the client.
            path(str): The path requested by the client.
            headers(list): The HTTP headers obtained from the ASGI scope, of send.
            query(str): The ``GET`` query string, obtained from ASGI scope of send.
            body(str): The HTTP request body.
  
          '''
          self.headers = TypedMultiMap({})
          self.method = method
          self.path = path
          self.raw_query = raw_query
          self.raw_body = raw_body
          self.query = TypedMultiMap(
              parse.parse_qs(raw_query.decode())
          )
          for header_pair in headers:
              self.headers[header_pair[0].decode()] = header_pair[1].decode()
  
          if self.headers.get("content-type") == "multipart/form-data":
              self.body, self.files = parse_multipart(
                  self.headers["content_type"],
                  raw_body
              )
          else:
              self.body = TypedMultiMap(
                  parse.parse_qs(raw_body.decode())
              )
              self.files = TypedMultiMap({})
  
          if 'cookie' in self.headers.keys():
              [self.cookies.update({_.split('=')[0]:_.split('=')[1]})
               for _ in self.headers['cookie'].split(';')]
  
  
  class Response404(Response):
      def __init__(self):
          super().__init__()
          self.headers['content-type'] = 'text/html'
          self.body = 'Not found'
          self.status = 404
  
  
  class Response405(Response):
      def __init__(self):
          super().__init__()
          self.headers['content_type'] = 'text/html'
          self.body = "Method not allowed"
          self.status = 405
  
  
  class Response500(Response):
      def __init__(self):
          super().__init__()
          self.headers['content_type'] = 'text/html'
          self.body = "Internal Server Error"
          self.status = 500
  
  
  class Cookie:
      '''
      This class is used to send cookies to the user.
  
      Args:
          value(str): Cookie value
          max_age(int): Max age of the cookie (default = 0)
          same_site(str): Same-site attribute value (default = "Lax")
          secure(bool):Secure attribute of the cookie. (default=True)
          http_only(bool): If True, cookie cannot be accesed from JavaScript. (default = True)
  
  
      It is not a callable class.
  
      .. note ::
          Try to keep the http_only to True as it prevents XSS attacks.
          Attackers cannot steal cookies from users through Cross-Site scripting if it is set.
          However, it requires an HTTPS connection, so you can disable it during development.
  
      '''
  
      __slots__ = ('value', 'max_age', 'cookie_str',
                   'same_site', 'secure', 'http_only')
  
      def __init__(
              self,
              value: str,
              max_age: int = 0,
              same_site: str = "Lax",
              secure: bool = True,
              http_only: bool = True):
          '''
  
          Args:
              value(str): The value of cookie.
              max_age(int): The max_age of the cookie. Defaults to zero.
              same_site(str): The value of the same_site attribute. Defaults to Lax. Find more about same_site in https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite
              secure(bool): Is the cookie a secure cookie or not. Defaults to True
              http_only(bool): States if the cookie is HttpOnly cookie.
  
          '''
          self.value = value.encode()
          self.max_age = str(max_age).encode()
          self.same_site = same_site.encode()
          self.secure = secure
          self.http_only = http_only
          self.cookie_str = self.value + b'; Max-Age=' + \
              self.max_age + b'; SameSite=' + same_site.encode()
          if secure is True:
              self.cookie_str += b'; Secure'
          if http_only is True:
              self.cookie_str += b'; HttpOnly'
  
  
  class FileObject:
      __slots__ = ("payload", "name", "filename")
  
      def __init__(self, payload, name, filename, **kwargs):
          self.payload = payload
          self.name = name
          self.filename = filename
          del kwargs
  
  
  class HTTPException(Exception, Response):
      def __init__(
              self,
              status: int = 404,
              body: str = "Not found",
              content_type="text/html"
      ):
          # Do not use super() here. Makes a mess of multiple inheritances.
          Response.__init__(self)
          self.status = 404
          self.content_type = content_type
          self.body = body
  