1

We have a case where we need to peek certain amount of incoming characters. The length for which is not fixed. bufio.Reader.Peek can only peek up to the maximum size of its initialized buffer. Any attempt to Peek larger results in ErrBufferFull

Problem:

package main

import (
    "bufio"
    "fmt"
    "strings"
)

func main() {
    data := "In publishing and graphic design, Lorem ipsum is a placeholder text commonly used to demonstrate the visual form of a document or a typeface without relying on meaningful content."
    dataLen := len([]rune(data))
    fmt.Printf("Length of data: %d\n", dataLen)

    r := bufio.NewReaderSize(strings.NewReader(data), 16)
    bufferSize := r.Size()
    fmt.Printf("buffer size: %d\n", bufferSize)

    GetPeekedCharacters(r, dataLen)
}

func GetPeekedCharacters(r *bufio.Reader, dataLen int) {
    b, err := r.Peek(dataLen)
    if err != nil {
        fmt.Println(err)
    } else {
        fmt.Printf("peeked: %s\n", b)
    }
}

I have been trying to see if we could maybe kind of swap the Peek with our own implementation but we require the internal fields of bufio.Reader like buf/r/w

// Reader implements buffering for an io.Reader object.
type Reader struct {
    buf          []byte
    rd           io.Reader // reader provided by the client
    r, w         int       // buf read and write positions
    err          error
    lastByte     int // last byte read for UnreadByte; -1 means invalid
    lastRuneSize int // size of last rune read for UnreadRune; -1 means invalid
}

My approaches:

package main

import (
    "fmt"
    "strings"

    "mybufio/mybufio"
)

func main() {
    rd := mybufio.NewMyBufio(strings.NewReader("In publishing and graphic design, Lorem ipsum is a placeholder text commonly used to demonstrate the visual form of a document or a typeface without relying on meaningful content."), 16)

    if _, err := rd.Peek(179); err != nil {
        fmt.Printf("Got error in Peek: %s\n", err)
    }

}
-- go.mod --
module mybufio
-- mybufio/mybufio.go --
package mybufio

import (
    "bufio"
    "io"
)

type MyReader interface {
    Peek(n int) ([]byte, error)
}

type MyBufio struct {
    *bufio.Reader
}

func NewMyBufio(rd io.Reader, size int) *MyBufio {
    return &MyBufio{bufio.NewReaderSize(rd, size)}
}

func (b *MyBufio) Peek(n int) ([]byte, error) {
    // inaccessible b.buf
    // comment below to run program
    fmt.Println(b.buf)

    return []byte{}, nil
}

I am new to go and not sure how to achieve this. Any pointers would be helpful.

D3XT3R
  • 181
  • 2
  • 15
  • you can't access non-exported fields, period. your options are: a) copy the source code and change it - it's BSD-3 licensed, so as long as you stick to the terms of the license, that's fine. b) write a new implementation from scratch ( or c) first do a), then make a pull-request on the Go github repository, and convince the maintainers to get it merged. not sure what your chances are.) – Erwin Bolwidt Apr 12 '23 at 06:50

1 Answers1

0

A simple solution using the bufio package

package main

import (
    "bufio"
    "fmt"
    "strings"
)

func GetPeekedBytes(r *bufio.Reader, dataLen int) (*bufio.Reader, []byte, error) {
    r = bufio.NewReaderSize(r, dataLen)
    p, err := r.Peek(dataLen)
    if err != nil {
        return r, nil, err
    }
    return r, p, nil
}

func main() {
    data := "In publishing and graphic design, Lorem ipsum is a placeholder text commonly used to demonstrate the visual form of a document or a typeface without relying on meaningful content."
    dataLen := len(data)
    fmt.Printf("Length of data: %d\n", dataLen)

    r := bufio.NewReaderSize(strings.NewReader(data), 16)
    fmt.Println("buffer size", r.Size())
    r, peeked, err := GetPeekedBytes(r, dataLen)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println("peeked data:", len(peeked), string(peeked))
    fmt.Println("buffer size", r.Size())
}

https://go.dev/play/p/moUsrLn7GL4

Length of data: 179
buffer size 16
peeked data: 179 In publishing and graphic design, Lorem ipsum is a placeholder text commonly used to demonstrate the visual form of a document or a typeface without relying on meaningful content.
buffer size 179

rocka2q
  • 2,473
  • 4
  • 11