// Copyright 2020 The gVisor Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // +build linux // Package iovec provides helpers to interact with vectorized I/O on host // system. package iovec import ( "golang.org/x/sys/unix" ) // MaxIovs is the maximum number of iovecs host platform can accept. var MaxIovs = 1024 // Builder is a builder for slice of unix.Iovec. type Builder struct { iovec []unix.Iovec storage [8]unix.Iovec // overflow tracks the last buffer when iovec length is at MaxIovs. overflow []byte } // Add adds buf to b preparing to be written. Zero-length buf won't be added. func (b *Builder) Add(buf []byte) { if len(buf) == 0 { return } if b.iovec == nil { b.iovec = b.storage[:0] } if len(b.iovec) >= MaxIovs { b.addByAppend(buf) return } b.iovec = append(b.iovec, unix.Iovec{Base: &buf[0]}) b.iovec[len(b.iovec)-1].SetLen(len(buf)) // Keep the last buf if iovec is at max capacity. We will need to append to it // for later bufs. if len(b.iovec) == MaxIovs { n := len(buf) b.overflow = buf[:n:n] } } func (b *Builder) addByAppend(buf []byte) { b.overflow = append(b.overflow, buf...) b.iovec[len(b.iovec)-1] = unix.Iovec{Base: &b.overflow[0]} b.iovec[len(b.iovec)-1].SetLen(len(b.overflow)) } // Build returns the final Iovec slice. The length of returned iovec will not // excceed MaxIovs. func (b *Builder) Build() []unix.Iovec { return b.iovec }