// internal/adapter/buffer.go package adapter import ( "sync" "time" ) // RingBuffer - потокобезопасный кольцевой буфер для байт GPIO type RingBuffer struct { mu sync.RWMutex data []byte writePtr int count int // сколько байт записано (до заполнения буфера) lastWrite time.Time } // NewRingBuffer создает буфер заданного размера func NewRingBuffer(size int) *RingBuffer { return &RingBuffer{ data: make([]byte, size), lastWrite: time.Now(), } } // Write добавляет байт в буфер func (rb *RingBuffer) Write(b byte) { rb.mu.Lock() defer rb.mu.Unlock() rb.data[rb.writePtr] = b rb.writePtr = (rb.writePtr + 1) % len(rb.data) if rb.count < len(rb.data) { rb.count++ } rb.lastWrite = time.Now() } // GetLatest возвращает последний записанный байт func (rb *RingBuffer) GetLatest() (byte, bool) { rb.mu.RLock() defer rb.mu.RUnlock() if rb.count == 0 { return 0, false } idx := rb.writePtr - 1 if idx < 0 { idx += len(rb.data) } return rb.data[idx], true } // GetLast возвращает последние N байт func (rb *RingBuffer) GetLast(n int) []byte { rb.mu.RLock() defer rb.mu.RUnlock() if n > rb.count { n = rb.count } if n == 0 { return []byte{} } result := make([]byte, n) start := rb.writePtr - n if start < 0 { start += len(rb.data) copy(result, rb.data[start:]) copy(result[len(rb.data)-start:], rb.data[:rb.writePtr]) } else { copy(result, rb.data[start:rb.writePtr]) } return result } // GetAll возвращает все данные из буфера func (rb *RingBuffer) GetAll() []byte { return rb.GetLast(rb.count) } // Stats возвращает статистику буфера func (rb *RingBuffer) Stats() map[string]interface{} { rb.mu.RLock() defer rb.mu.RUnlock() return map[string]interface{}{ "total_bytes": rb.count, "buffer_size": len(rb.data), "last_write": rb.lastWrite.Format(time.RFC3339), "is_full": rb.count == len(rb.data), } }