k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/pkg/proxy/util/linebuffer.go (about)

     1  /*
     2  Copyright 2023 The Kubernetes 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 util
    18  
    19  import (
    20  	"bytes"
    21  	"fmt"
    22  	"strings"
    23  
    24  	"github.com/go-logr/logr"
    25  )
    26  
    27  // LineBuffer is an interface for writing lines of input to a bytes.Buffer
    28  type LineBuffer interface {
    29  	// Write takes a list of arguments, each a string or []string, joins all the
    30  	// individual strings with spaces, terminates with newline, and writes them to the
    31  	// buffer. Any other argument type will panic.
    32  	Write(args ...interface{})
    33  
    34  	// WriteBytes writes bytes to the buffer, and terminates with newline.
    35  	WriteBytes(bytes []byte)
    36  
    37  	// Reset clears the buffer
    38  	Reset()
    39  
    40  	// Bytes returns the contents of the buffer as a []byte
    41  	Bytes() []byte
    42  
    43  	// String returns the contents of the buffer as a string
    44  	String() string
    45  
    46  	// Lines returns the number of lines in the buffer. Note that more precisely, this
    47  	// returns the number of times Write() or WriteBytes() was called; it assumes that
    48  	// you never wrote any newlines to the buffer yourself.
    49  	Lines() int
    50  }
    51  
    52  var _ logr.Marshaler = &realLineBuffer{}
    53  
    54  type realLineBuffer struct {
    55  	b     bytes.Buffer
    56  	lines int
    57  }
    58  
    59  // NewLineBuffer returns a new "real" LineBuffer
    60  func NewLineBuffer() LineBuffer {
    61  	return &realLineBuffer{}
    62  }
    63  
    64  // Write is part of LineBuffer
    65  func (buf *realLineBuffer) Write(args ...interface{}) {
    66  	for i, arg := range args {
    67  		if i > 0 {
    68  			buf.b.WriteByte(' ')
    69  		}
    70  		switch x := arg.(type) {
    71  		case string:
    72  			buf.b.WriteString(x)
    73  		case []string:
    74  			for j, s := range x {
    75  				if j > 0 {
    76  					buf.b.WriteByte(' ')
    77  				}
    78  				buf.b.WriteString(s)
    79  			}
    80  		default:
    81  			panic(fmt.Sprintf("unknown argument type: %T", x))
    82  		}
    83  	}
    84  	buf.b.WriteByte('\n')
    85  	buf.lines++
    86  }
    87  
    88  // WriteBytes is part of LineBuffer
    89  func (buf *realLineBuffer) WriteBytes(bytes []byte) {
    90  	buf.b.Write(bytes)
    91  	buf.b.WriteByte('\n')
    92  	buf.lines++
    93  }
    94  
    95  // Reset is part of LineBuffer
    96  func (buf *realLineBuffer) Reset() {
    97  	buf.b.Reset()
    98  	buf.lines = 0
    99  }
   100  
   101  // Bytes is part of LineBuffer
   102  func (buf *realLineBuffer) Bytes() []byte {
   103  	return buf.b.Bytes()
   104  }
   105  
   106  // String is part of LineBuffer
   107  func (buf *realLineBuffer) String() string {
   108  	return buf.b.String()
   109  }
   110  
   111  // Lines is part of LineBuffer
   112  func (buf *realLineBuffer) Lines() int {
   113  	return buf.lines
   114  }
   115  
   116  // Implements the logs.Marshaler interface
   117  func (buf *realLineBuffer) MarshalLog() any {
   118  	return strings.Split(buf.b.String(), "\n")
   119  }
   120  
   121  type discardLineBuffer struct {
   122  	lines int
   123  }
   124  
   125  // NewDiscardLineBuffer returns a dummy LineBuffer that counts the number of writes but
   126  // throws away the data. (This is used for iptables proxy partial syncs, to keep track of
   127  // how many rules we managed to avoid having to sync.)
   128  func NewDiscardLineBuffer() LineBuffer {
   129  	return &discardLineBuffer{}
   130  }
   131  
   132  // Write is part of LineBuffer
   133  func (buf *discardLineBuffer) Write(args ...interface{}) {
   134  	buf.lines++
   135  }
   136  
   137  // WriteBytes is part of LineBuffer
   138  func (buf *discardLineBuffer) WriteBytes(bytes []byte) {
   139  	buf.lines++
   140  }
   141  
   142  // Reset is part of LineBuffer
   143  func (buf *discardLineBuffer) Reset() {
   144  	buf.lines = 0
   145  }
   146  
   147  // Bytes is part of LineBuffer
   148  func (buf *discardLineBuffer) Bytes() []byte {
   149  	return []byte{}
   150  }
   151  
   152  // String is part of LineBuffer
   153  func (buf *discardLineBuffer) String() string {
   154  	return ""
   155  }
   156  
   157  // Lines is part of LineBuffer
   158  func (buf *discardLineBuffer) Lines() int {
   159  	return buf.lines
   160  }