No worries - happy to help. One last thing base64 coding is fairly trivial - a cursory shows that the padded version uses = signs. I suspect you could write a decoder that handled either during the decoding.
> On Jan 12, 2025, at 3:29 PM, Rory Campbell-Lange <r...@campbell-lange.net> > wrote: > > Thanks very much for the links, pointers and possible solution. > > Trying to read base64 standard (padded) encoded data with > base64.RawStdEncoding can produce an error such as > > illegal base64 data at input byte <n> > > Reading base64 raw (unpadded) encoded data produces the EOF error. > > I'll go with trying to read the standard encoded data up to maybe 1MB and > then switch to base64.RawStdEncoding if I hit the "illegal base64 data" > problem, maybe with reference to bufio.Reader which has most of the methods > suggested below. > > Yes, the use of a "Rewind" method would be crucial. I guess this would need > to: > 1. error if more than one buffer of data has been read > 2. else re-read from byte 0 > > Thanks again very much for these suggestions. > > Rory > >> On 12/01/25, robert engels (reng...@ix.netcom.com) wrote: >> Also, see this >> https://stackoverflow.com/questions/69753478/use-base64-stdencoding-or-base64-rawstdencoding-to-decode-base64-string-in-go >> as I expected the error should be reported earlier than the end of stream >> if the chosen format is wrong. >> >>>> On Jan 12, 2025, at 2:57 PM, robert engels <reng...@ix.netcom.com> wrote: >>> >>> Also, this is what Gemini provided which looks basically correct - but I >>> think encapsulating it with a Rewind() method would be easier to understand. >>> >>> >>> >>> While Go doesn't have a built-in PushbackReader like some other languages >>> (e.g., Java), you can implement similar functionality using a custom struct >>> and a buffer. >>> >>> Here's an example implementation: >>> >>> package main >>> >>> import ( >>> "bytes" >>> "io" >>> ) >>> >>> type PushbackReader struct { >>> reader io.Reader >>> buffer *bytes.Buffer >>> } >>> >>> func NewPushbackReader(r io.Reader) *PushbackReader { >>> return &PushbackReader{ >>> reader: r, >>> buffer: new(bytes.Buffer), >>> } >>> } >>> >>> func (p *PushbackReader) Read(b []byte) (n int, err error) { >>> if p.buffer.Len() > 0 { >>> return p.buffer.Read(b) >>> } >>> return p.reader.Read(b) >>> } >>> >>> func (p *PushbackReader) UnreadByte() error { >>> if p.buffer.Len() == 0 { >>> return io.EOF >>> } >>> lastByte := p.buffer.Bytes()[p.buffer.Len()-1] >>> p.buffer.Truncate(p.buffer.Len() - 1) >>> p.buffer.WriteByte(lastByte) >>> return nil >>> } >>> >>> func (p *PushbackReader) Unread(buf []byte) error { >>> if p.buffer.Len() == 0 { >>> return io.EOF >>> } >>> p.buffer.Write(buf) >>> return nil >>> } >>> >>> func main() { >>> // Example usage >>> r := NewPushbackReader(bytes.NewBufferString("Hello, World!")) >>> buf := make([]byte, 5) >>> r.Read(buf) >>> r.UnreadByte() >>> r.Read(buf) >>> } >>> >>> Explanation: >>> PushbackReader struct: This struct holds the underlying io.Reader and a >>> buffer to store the pushed-back bytes. >>> NewPushbackReader: This function creates a new PushbackReader from an >>> existing io.Reader. >>> Read method: This method reads bytes from either the buffer (if it contains >>> data) or the underlying reader. >>> UnreadByte method: This method pushes back a single byte into the buffer. >>> Unread method: This method pushes back a slice of bytes into the buffer. >>> Important Considerations: >>> The buffer size is not managed automatically. You may need to adjust the >>> buffer size based on your use case. >>> This implementation does not handle pushing back beyond the initially read >>> data. If you need to support arbitrary pushback, you'll need a more complex >>> solution. >>> >>> Generative AI is experimental. >>> >>>> On Jan 12, 2025, at 2:53 PM, Robert Engels <reng...@ix.netcom.com> wrote: >>>> >>>> You can see the two pass reader here >>>> https://stackoverflow.com/questions/20666594/how-can-i-push-bytes-into-a-reader-in-go >>>> >>>> But yea, the basic premise is that you buffer the data so you can rewind >>>> if needed >>>> >>>> Are you certain it is reading to the end to return EOF? It may be >>>> returning eof once the parsing fails. >>>> >>>> Otherwise I would expect this is being decoded wrong - eg the mime type or >>>> encoding type should tell you the correct format before you start decoding. >>>> >>>>> On Jan 12, 2025, at 2:46 PM, Rory Campbell-Lange >>>>> <r...@campbell-lange.net> wrote: >>>>> >>>>> Thanks for the suggestion of a ReadSeeker to wrap an io.Reader. >>>>> >>>>> My google fu must be deserting me. I can find PushbackReader >>>>> implementations in Java, but the only similar thing for Go I could find >>>>> was https://gitlab.com/osaki-lab/iowrapper. If you have a specific >>>>> recommendation for a ReadSeeker wrapper to an io.Reader that would be >>>>> great to know. >>>>> >>>>> Since the base64 decoding error I'm looking for is an EOF, I guess the >>>>> wrapper approach will not work when the EOF byte position is > than the >>>>> io.ReadSeeker buffer size. >>>>> >>>>> Rory >>>>> >>>>> On 12/01/25, robert engels (reng...@ix.netcom.com) wrote: >>>>>> create a ReadSeeker that wraps the Reader providing the buffering (mark >>>>>> & reset) - normally the buffer only needs to be large enough to detect >>>>>> the format contained in the Reader. >>>>>> >>>>>> You can search Google for PushbackReader in Go and you’ll get a basic >>>>>> implementation. >>>>>> >>>>>>> On Jan 12, 2025, at 12:52 PM, Rory Campbell-Lange >>>>>>> <r...@campbell-lange.net> wrote: >>>>> ... >>>>>>> I'm attempting to rationalise the process [of avoiding reading email >>>>>>> parts into byte slices] by simply wrapping the provided io.Reader with >>>>>>> the necessary decoders to reduce memory usage and unnecessary >>>>>>> processing. >>>>>>> >>>>>>> The wrapping strategy seems to work ok. However there is a particular >>>>>>> issue in detecting base64.StdEncoding versus base64.RawStdEncoding, >>>>>>> which requires draining the io.Reader using base64.StdEncoding and >>>>>>> (based on the current implementation) switching to >>>>>>> base64.RawStdEncoding if an io.ErrUnexpectedEOF is found. >>>>>>> >>>> >>>> >>>> -- >>>> You received this message because you are subscribed to the Google Groups >>>> "golang-nuts" group. >>>> To unsubscribe from this group and stop receiving emails from it, send an >>>> email to golang-nuts+unsubscr...@googlegroups.com >>>> <mailto:golang-nuts+unsubscr...@googlegroups.com>. >>>> To view this discussion visit >>>> https://groups.google.com/d/msgid/golang-nuts/DD0C1480-D237-447A-B978-78FC8951FE05%40ix.netcom.com >>>> >>>> <https://groups.google.com/d/msgid/golang-nuts/DD0C1480-D237-447A-B978-78FC8951FE05%40ix.netcom.com?utm_medium=email&utm_source=footer>. >>> >> -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/golang-nuts/90FBDABA-BFEF-4C88-A305-2485866B35C1%40ix.netcom.com.