96 lines
2.3 KiB
Go
96 lines
2.3 KiB
Go
// 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),
|
|
}
|
|
}
|