11 type FlatNews struct {
17 readOffset int // Internal offset to track read progress
20 func NewFlatNews(path string) (*FlatNews, error) {
21 data, err := os.ReadFile(path)
23 return &FlatNews{}, err
32 func (f *FlatNews) Reload() error {
36 data, err := os.ReadFile(f.filePath)
45 // It returns the number of bytes read and any error encountered.
46 func (f *FlatNews) Read(p []byte) (int, error) {
50 if f.readOffset >= len(f.data) {
51 return 0, io.EOF // All bytes have been read
54 n := copy(p, f.data[f.readOffset:])
61 // Write implements io.Writer for flat news.
62 // p is guaranteed to contain the full data of a news post.
63 func (f *FlatNews) Write(p []byte) (int, error) {
67 f.data = slices.Concat(p, f.data)
69 tempFilePath := f.filePath + ".tmp"
71 if err := os.WriteFile(tempFilePath, f.data, 0644); err != nil {
72 return 0, fmt.Errorf("write to temporary file: %v", err)
75 // Atomically rename the temporary file to the final file path.
76 if err := os.Rename(tempFilePath, f.filePath); err != nil {
77 return 0, fmt.Errorf("rename temporary file to final file: %v", err)
80 return len(p), os.WriteFile(f.filePath, f.data, 0644)
83 func (f *FlatNews) Seek(offset int64, _ int) (int64, error) {
84 f.readOffset = int(offset)