package svg import ( "bytes" "errors" "io" ) type ( elementReader[T Tag, A Attribute, C MarshalerReader] struct { element Element[T, A, C] buf *bytes.Buffer openTagRead bool numChildrenRead int childrenRead bool childReader io.Reader closeTagRead bool } ) func newElementReader[T Tag, A Attribute, C MarshalerReader](e Element[T, A, C]) *elementReader[T, A, C] { return &elementReader[T, A, C]{ element: e, } } func (e *elementReader[T, A, C]) Read(p []byte) (totalRead int, err error) { if e.buf == nil { // just started reading. // buffer the open tag e.buf = new(bytes.Buffer) // bytes.Buffer never returns an error on Write() e.buf.WriteByte('<') e.buf.WriteString(e.element.PrintTag()) for _, a := range e.element.Attributes { e.buf.WriteByte(' ') e.buf.WriteString(PrintAttribute(a)) } e.buf.WriteByte('>') } if !e.openTagRead { // read the open tag n, err := e.buf.Read(p) totalRead += n if (err != nil && !errors.Is(err, io.EOF)) || n >= len(p) { return totalRead, err } // done reading the open tag e.openTagRead = true e.buf.Reset() p = p[n:] } // read the children for ; e.numChildrenRead < len(e.element.Children); e.numChildrenRead += 1 { if e.childReader == nil { e.childReader = e.element.Children[e.numChildrenRead].GetMarkupReader() } // read the child n, err := e.childReader.Read(p) totalRead += n if (err != nil && !errors.Is(err, io.EOF)) || n >= len(p) { return totalRead, err } // done reading the child e.childReader = nil p = p[n:] } if !e.childrenRead { // done reading the children e.childrenRead = true // buffer the close tag e.buf.Write([]byte("') } if !e.closeTagRead { n, err := e.buf.Read(p) totalRead += n if (err != nil && !errors.Is(err, io.EOF)) || n >= len(p) { return totalRead, err } // done writing the close tag e.closeTagRead = true return totalRead, err } return 0, io.EOF }