...

Source file src/github.com/cloudwego/base64x/base64x.go

Documentation: github.com/cloudwego/base64x

     1  /*
     2   * Copyright 2024 CloudWeGo Authors
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package base64x
    18  
    19  import (
    20      `encoding/base64`
    21  )
    22  
    23  // An Encoding is a radix 64 encoding/decoding scheme, defined by a
    24  // 64-character alphabet. The most common encoding is the "base64"
    25  // encoding defined in RFC 4648 and used in MIME (RFC 2045) and PEM
    26  // (RFC 1421).  RFC 4648 also defines an alternate encoding, which is
    27  // the standard encoding with - and _ substituted for + and /.
    28  type Encoding int
    29  
    30  const (
    31      _MODE_URL  = 1 << 0
    32      _MODE_RAW  = 1 << 1
    33      _MODE_AVX2 = 1 << 2
    34      _MODE_JSON = 1 << 3
    35  )
    36  
    37  // StdEncoding is the standard base64 encoding, as defined in
    38  // RFC 4648.
    39  const StdEncoding Encoding = 0
    40  
    41  // URLEncoding is the alternate base64 encoding defined in RFC 4648.
    42  // It is typically used in URLs and file names.
    43  const URLEncoding Encoding = _MODE_URL
    44  
    45  // RawStdEncoding is the standard raw, unpadded base64 encoding,
    46  // as defined in RFC 4648 section 3.2.
    47  //
    48  // This is the same as StdEncoding but omits padding characters.
    49  const RawStdEncoding Encoding = _MODE_RAW
    50  
    51  // RawURLEncoding is the unpadded alternate base64 encoding defined in RFC 4648.
    52  // It is typically used in URLs and file names.
    53  //
    54  // This is the same as URLEncoding but omits padding characters.
    55  const RawURLEncoding Encoding = _MODE_RAW | _MODE_URL
    56  
    57  // JSONStdEncoding is the StdEncoding and encoded as JSON string as RFC 8259.
    58  const JSONStdEncoding Encoding = _MODE_JSON;
    59  
    60  var (
    61      archFlags = 0
    62  )
    63  
    64  /** Encoder Functions **/
    65  
    66  // Encode encodes src using the specified encoding, writing
    67  // EncodedLen(len(src)) bytes to out.
    68  //
    69  // The encoding pads the output to a multiple of 4 bytes,
    70  // so Encode is not appropriate for use on individual blocks
    71  // of a large data stream.
    72  //
    73  // If out is not large enough to contain the encoded result,
    74  // it will panic.
    75  func (self Encoding) Encode(out []byte, src []byte) {
    76      if len(src) != 0 {
    77          if buf := out[:0:len(out)]; self.EncodedLen(len(src)) <= len(out) {
    78              self.EncodeUnsafe(&buf, src)
    79          } else {
    80              panic("encoder output buffer is too small")
    81          }
    82      }
    83  }
    84  
    85  // EncodeUnsafe behaves like Encode, except it does NOT check if
    86  // out is large enough to contain the encoded result.
    87  //
    88  // It will also update the length of out.
    89  func (self Encoding) EncodeUnsafe(out *[]byte, src []byte) {
    90      b64encode(out, &src, int(self) | archFlags)
    91  }
    92  
    93  // EncodeToString returns the base64 encoding of src.
    94  func (self Encoding) EncodeToString(src []byte) string {
    95      nbs := len(src)
    96      ret := make([]byte, 0, self.EncodedLen(nbs))
    97  
    98      /* encode in native code */
    99      self.EncodeUnsafe(&ret, src)
   100      return mem2str(ret)
   101  }
   102  
   103  // EncodedLen returns the length in bytes of the base64 encoding
   104  // of an input buffer of length n.
   105  func (self Encoding) EncodedLen(n int) int {
   106      if (self & _MODE_RAW) == 0 {
   107          return (n + 2) / 3 * 4
   108      } else {
   109          return (n * 8 + 5) / 6
   110      }
   111  }
   112  
   113  /** Decoder Functions **/
   114  
   115  // Decode decodes src using the encoding enc. It writes at most
   116  // DecodedLen(len(src)) bytes to out and returns the number of bytes
   117  // written. If src contains invalid base64 data, it will return the
   118  // number of bytes successfully written and base64.CorruptInputError.
   119  //
   120  // New line characters (\r and \n) are ignored.
   121  //
   122  // If out is not large enough to contain the encoded result,
   123  // it will panic.
   124  func (self Encoding) Decode(out []byte, src []byte) (int, error) {
   125      if len(src) == 0 {
   126          return 0, nil
   127      } else if buf := out[:0:len(out)]; self.DecodedLen(len(src)) <= len(out) {
   128          return self.DecodeUnsafe(&buf, src)
   129      } else {
   130          panic("decoder output buffer is too small")
   131      }
   132  }
   133  
   134  // DecodeUnsafe behaves like Decode, except it does NOT check if
   135  // out is large enough to contain the decoded result.
   136  //
   137  // It will also update the length of out.
   138  func (self Encoding) DecodeUnsafe(out *[]byte, src []byte) (int, error) {
   139      if n := b64decode(out, mem2addr(src), len(src), int(self) | archFlags); n >= 0 {
   140          return n, nil
   141      } else {
   142          return 0, base64.CorruptInputError(-n - 1)
   143      }
   144  }
   145  
   146  // DecodeString returns the bytes represented by the base64 string s.
   147  func (self Encoding) DecodeString(s string) ([]byte, error) {
   148      src := str2mem(s)
   149      ret := make([]byte, 0, self.DecodedLen(len(s)))
   150  
   151      /* decode into the allocated buffer */
   152      if _, err := self.DecodeUnsafe(&ret, src); err != nil {
   153          return nil, err
   154      } else {
   155          return ret, nil
   156      }
   157  }
   158  
   159  // DecodedLen returns the maximum length in bytes of the decoded data
   160  // corresponding to n bytes of base64-encoded data.
   161  func (self Encoding) DecodedLen(n int) int {
   162      if (self & _MODE_RAW) == 0 {
   163          return n / 4 * 3
   164      } else {
   165          return n * 6 / 8
   166      }
   167  }
   168  

View as plain text