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 }