git.lukeshu.com/go/lowmemjson@v0.3.9-0.20230723050957-72f6d13f6fb2/internal/fastio/allwriter.go (about)

     1  // Copyright (C) 2023  Luke Shumaker <lukeshu@lukeshu.com>
     2  //
     3  // SPDX-License-Identifier: GPL-2.0-or-later
     4  
     5  package fastio
     6  
     7  import (
     8  	"io"
     9  	"unicode/utf8"
    10  
    11  	"git.lukeshu.com/go/lowmemjson/internal/fastio/noescape"
    12  )
    13  
    14  // interfaces /////////////////////////////////////////////////////////////////
    15  
    16  type RuneWriter interface {
    17  	WriteRune(rune) (int, error)
    18  }
    19  
    20  // An AllWriter is the union of several common writer interfaces.
    21  type AllWriter interface {
    22  	io.Writer
    23  	io.ByteWriter
    24  	RuneWriter
    25  	io.StringWriter
    26  }
    27  
    28  // implementations ////////////////////////////////////////////////////////////
    29  
    30  func WriteByte(w io.Writer, b byte) error {
    31  	var buf [1]byte
    32  	buf[0] = b
    33  	_, err := noescape.Write(w, buf[:])
    34  	return err
    35  }
    36  
    37  func WriteRune(w io.Writer, r rune) (int, error) {
    38  	var buf [utf8.UTFMax]byte
    39  	n := utf8.EncodeRune(buf[:], r)
    40  	return noescape.Write(w, buf[:n])
    41  }
    42  
    43  func WriteString(w io.Writer, s string) (int, error) {
    44  	return noescape.Write(w, []byte(s))
    45  }
    46  
    47  // wrappers ///////////////////////////////////////////////////////////////////
    48  
    49  // NNN
    50  
    51  type (
    52  	writerNNN        interface{ io.Writer }
    53  	writerNNNWrapper struct{ writerNNN }
    54  )
    55  
    56  func (w writerNNNWrapper) WriteByte(b byte) error            { return WriteByte(w, b) }
    57  func (w writerNNNWrapper) WriteRune(r rune) (int, error)     { return WriteRune(w, r) }
    58  func (w writerNNNWrapper) WriteString(s string) (int, error) { return WriteString(w, s) }
    59  
    60  // NNY
    61  
    62  type (
    63  	writerNNY interface {
    64  		io.Writer
    65  		io.StringWriter
    66  	}
    67  	writerNNYWrapper struct{ writerNNY }
    68  )
    69  
    70  func (w writerNNYWrapper) WriteByte(b byte) error        { return WriteByte(w, b) }
    71  func (w writerNNYWrapper) WriteRune(r rune) (int, error) { return WriteRune(w, r) }
    72  
    73  // NYN
    74  
    75  type (
    76  	writerNYN interface {
    77  		io.Writer
    78  		RuneWriter
    79  	}
    80  	writerNYNWrapper struct{ writerNYN }
    81  )
    82  
    83  func (w writerNYNWrapper) WriteByte(b byte) error            { return WriteByte(w, b) }
    84  func (w writerNYNWrapper) WriteString(s string) (int, error) { return WriteString(w, s) }
    85  
    86  // NYY
    87  
    88  type (
    89  	writerNYY interface {
    90  		io.Writer
    91  		RuneWriter
    92  		io.StringWriter
    93  	}
    94  	writerNYYWrapper struct{ writerNYY }
    95  )
    96  
    97  func (w writerNYYWrapper) WriteByte(b byte) error { return WriteByte(w, b) }
    98  
    99  // YNN
   100  
   101  type (
   102  	writerYNN interface {
   103  		io.Writer
   104  		io.ByteWriter
   105  	}
   106  	writerYNNWrapper struct{ writerYNN }
   107  )
   108  
   109  func (w writerYNNWrapper) WriteRune(r rune) (int, error)     { return WriteRune(w, r) }
   110  func (w writerYNNWrapper) WriteString(s string) (int, error) { return WriteString(w, s) }
   111  
   112  // YNY
   113  
   114  type (
   115  	writerYNY interface {
   116  		io.Writer
   117  		io.ByteWriter
   118  		io.StringWriter
   119  	}
   120  	writerYNYWrapper struct{ writerYNY }
   121  )
   122  
   123  func (w writerYNYWrapper) WriteRune(r rune) (int, error) { return WriteRune(w, r) }
   124  
   125  // YYN
   126  
   127  type (
   128  	writerYYN interface {
   129  		io.Writer
   130  		io.ByteWriter
   131  		RuneWriter
   132  	}
   133  	writerYYNWrapper struct{ writerYYN }
   134  )
   135  
   136  func (w writerYYNWrapper) WriteString(s string) (int, error) { return WriteString(w, s) }
   137  
   138  // NewAllWriter wraps an io.Writer turning it in to an AllWriter.  If
   139  // the io.Writer already has any of the other write methods, then its
   140  // native version of those methods are used.
   141  func NewAllWriter(inner io.Writer) AllWriter {
   142  	if inner == io.Discard {
   143  		return Discard
   144  	}
   145  	switch inner := inner.(type) {
   146  	// 3 Y bits
   147  	case AllWriter: // YYY:
   148  		return inner
   149  	// 2 Y bits
   150  	case writerNYY:
   151  		return writerNYYWrapper{writerNYY: inner}
   152  	case writerYNY:
   153  		return writerYNYWrapper{writerYNY: inner}
   154  	case writerYYN:
   155  		return writerYYNWrapper{writerYYN: inner}
   156  	// 1 Y bit
   157  	case writerNNY:
   158  		return writerNNYWrapper{writerNNY: inner}
   159  	case writerNYN:
   160  		return writerNYNWrapper{writerNYN: inner}
   161  	case writerYNN:
   162  		return writerYNNWrapper{writerYNN: inner}
   163  	// 0 Y bits
   164  	default: // NNN:
   165  		return writerNNNWrapper{writerNNN: inner}
   166  	}
   167  }
   168  
   169  // discard /////////////////////////////////////////////////////////////////////
   170  
   171  // Discard is like io.Discard, but implements AllWriter.
   172  var Discard = discard{}
   173  
   174  type discard struct{}
   175  
   176  func (discard) Write(p []byte) (int, error)       { return len(p), nil }
   177  func (discard) WriteByte(b byte) error            { return nil }
   178  func (discard) WriteRune(r rune) (int, error)     { return 0, nil }
   179  func (discard) WriteString(s string) (int, error) { return len(s), nil }